Our APIs (delivered by a third party) are using Tokens in order to ensure authorized access only. Our new website should not be server-to-server but mostly front end, i.e. the token would be visible in the script. We're now checking how to secure the API for a frontend website and I have to propose ways to my boss. However, I've never had to do something with API securing, could you please help me by telling me where to read / state of the art solutions?
I've already begun to look into OAuth1a, OAuth2, OpenID but can't (yet) really get a direction to further investigate.
You should still use a token, but you have to make sure that the token doesn't grant you full access to the API.
Tokens need to be specific to the user who's using the application, and the token can only grant API access to the specific functions that the user is allowed to do.
For now I would ignore OAuth1 and OpenID and only look at OAuth2. There's enough features there to do what you want, and it's simpler than the rest.
Related
I'm developing a REST API with a tightly coupled SPA as the only client of the mentioned REST API.
Let's say the SPA is available at myservice.com and api is under myservice.com/api. They're basically one service, just split at code level, and deployed at different root paths.
What I'm using for security right now is OAuth2 with ROPC (username/password) grant type.
Here comes the problem. I keep reading everywhere that ROPC is not secure and should not be used. What should I use then?
My REST API acts as an authorization server but it doesn't have any web interface itself. So any flow involving redirect doesn't really make sense. The SPA and API are so tightly coupled that for an end user they're basically one application. There's no 3rd party.
I could add simple login form to the API available at let's say myservice.com/login. But I'm struggling to see the difference that would make.
Security in this application is very important.
Here are my questions:
Is using ROPC really dangerous in this scenario?
What would be the perfect way for authentication and authorization?
Or maybe OAuth2 is completely redundant without a third party?
Technologies used:
Server: Spring Boot
Is using ROPC really dangerous in this scenario?
No, not really providing:
a) You don't store a user's password - maybe only use it to get the initial access and refresh token - although that could be tricky with an SPA.
b) Your SPA client and the resource API are owned by you, so you don't need the user to consent to specific scoped access for the SPA.
What would be the perfect way for authentication and authorization?
It depends on lots of things. Not enough info to try to answer that. OAuth2.0 (with a probably implemented Authorisation server) is a pretty good way for the example you have here.
Or maybe OAuth2 is completely redundant without a third party?
If other applications will use your API in time then OAuth2.0 is probably a good call. Otherwise you could probably use a more simple solution e.g. session cookies as all sits on same domain.
Answer to this can be taken out from OAuth 2.0 specification (RFC6749) itself. It define when ROPC grant is suitable for,
4.3. Resource Owner Password Credentials Grant
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged
application. The authorization server should take special care when
enabling this grant type and only allow it when other flows are not
viabl.
According to your explanation, you have tight coupling with SPA and backend. Also you have both authorization server and resource server built as one. This is completely acceptable implementation.
The authorization server
may be the same server as the resource server or a separate entity.
So what matter now is to clear out why you use OAuth 2.0 in your scenario.
If you are using OAuth 2.0 to obtain tokens, maintain them as defined through OAuth 2.0 specification, then this is completely oaky. But if you are doing this to follow a trend, think twice.
OAuth 2.0 implementation comes with it's own complexity. You have to maintain user identities, maintain tokens and renew them. You are building a complete authorization server by yourself. But this also have some advantages as well.
For example, same authorization server can be used to issue token for future integrations/secondary app. IMO, usage of OAuth 2.0 make integrations easy as it define a protocol for issuing tokens, renew and revoke them.! But in such integration scenario, may be you will require to use a different grant. Still, your API being authorized on token, you only need to worry about how new integration/application obtain tokens. This is better than using authenticated sessions
Going back to your questions,
Q : Is using ROPC really dangerous in this scenario?
As explained, if there is a correct trust relationship between client and authorization server, then it is fine. But be mindful about complexity comes with having a authorization server.
Q : What would be the perfect way for authentication and authorization?
OAuth 2.0 is for authorization. You obtain access token and use them to authorize against your protected APIs. From APIs you do a token validation to detect correct access levels/permissions.
If you want authenticaiton, then you must use OpenID Connect. It is a protocol extended from OAuth 2.0. And allows your application to authenticate the end user based on ID Token. You can use ROPC grant to obtain an ID token.!
Q : Or maybe OAuth2 is completely redundant without a third party?
Not necessarily. It allows you to design your APIs in a modern, standard way. Who know what future hold (again the integration scenario). Following a protocol allows that easy.
Only advice, follow specifications closely. Do not invent your own protocol/adaptation. It makes things harder to maintain.
I am building an API meant to be sold to various clients. These clients will be given an API Key or something similar and they'll use the API in a widget on their website.
The end users of the clients' website must be able to use the widget anonymously (no login).
Workflow:
My current idea is to have the Client's server retrieve a temporary key and use that in the webpage. The End user's browser will use that temporary key to call our API.
Is there any reason why this is not a good practice and/or insecure?
Or is there a better good practice solution? Can I for exmaple use OAuth 2 for this?
You need to secure your API from the clients app. So, for that you can use OAuth 2 with Client Credentials grant type and setup each client as an app so they each get their own set of key/secret credentials.
Since you don't know anything about the end user, but still need to track them, require an endUserId custom header on every request to your API and you'll just have to trust the client to provide you with a valid id for the end user making the request.
To setup OAuth, use an existing library or OAuth service. I don't recommend writing your own. If you can spend some money, Okta and Auth0 are good choices. If your API is written in .net, you can use IdentityServer as a free option.
I'm looking to use API Gateway + Lambda + Cognito User Pools to build a simple REST API.
The API will be used in two ways. The first is to support a basic web app (hosted on CloudFront + S3). Authentication for the web application uses the hosted Cognito sign in / sign up flow and is working fine (with API Gateway setup to use the user pool authenticator).
The second method will be for customers to use the REST API to communicate with the system.
As an example, the client might use the web app to configure a workflow and then use an API to invoke that workflow.
What is the recommended method of authenticating the API for use with backend services?
Traditionally, I'd expect to use an API key + secret token for this purpose. I have no issue creating API keys in the API Gateway interface however I can't see anyway to link that to a specific user, nor can I see any method of specifying a secret token alongside the API key.
And assuming the above is possible, how would I set it up in such a way that I could use the JWT-based approach for the web application and the API key + secret token for customers to use.
EDIT: Additionally, I notice that app clients have an ID and a secret. Are they intended to be used for 3rd API-based-authentication (similar to how other systems make you create an app for API access)? I'm a bit skeptical because there's a limit of 25 per user pool, although it is a soft limit...
I have been searching for an answer to this myself and my searching led me to your question. I will give you my best answer from my research, assuming you want to utilize the well-known key/secret approach. Maybe others can provide a better approach.
Basically, the approach is:
Your REST API accounts are just Cognito users in a (possibly separate) user pool
The management of API accounts is done from the back end
The username and password will be the API key and secret, are administratively created (see the Admin* operations), and can be whatever format you want (within Cognito limits)
The REST API is authorized via Cognito JWT tokens
API account key and secret are only used to retrieve or refresh tokens
This requires the REST API to have a set of endpoints to support token retrieval and refresh using account keys and secrets
Based upon how long you set up the Cognito refresh interval, you can require API accounts to submit their key/secret credentials from very often to almost never
Structuring the authorization of your REST API to use Cognito tokens will allow you to integrate the REST API directly with API Gateway's support for Cognito.
I think the biggest headache of this whole thing is that you will have to create the supporting pieces for, e.g., registered users to request API accounts and for the administration of those accounts, as well as some extra helper REST endpoints for token exchange. Additionally, clients will have to keep track of keys/secrets AND token(s) as well as add client-side logic to know when to supply tokens or credentials.
When i was starting out using API gateway and Congito, i referenced https://github.com/awslabs/aws-serverless-auth-reference-app a lot and found it very helpful in demonstrating the integration between the different AWS components.
If I understand you correctly, you want to create a "long-lived API key + secret" for programmatic access to your API?
I have exactly this need, and am sadly finding that it appears to not be possible. The longest a key can be valid for is 1 hour. You can have a refresh token that's valid for 10 years. https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html
I'm currently looking for an elegant solution to this. I'd be interested to hear if you ever found a solution, or if you rolled your own.
Did anyone ever find a more elegant solution to this problem?
The first answer seems like pushing too much work into the hands of my customers. I don't know the skill level of the developers calling my API, and I wouldn't wish becoming a Cognito developer on anyone lol. More seriously, I don't want them to have to store multiple pieces of information and then have to deal with refreshing tokens.
I might be Ok with giving them a refresh token. Then I could do one of two things:
Give them a refresh method. I'd figure out all the weird Cognito kinks and keep their method to a simple payload of just the refresh token. I'd give them back the access token to use on subsequent calls.
Let them pass me the refresh token as if it was an access token. I would use it on each call to get an access token and then use that to call the interior APIs.
So I want to understand a little more about authentication in an API. I know very little about how security works.
I am using Auth0 for my app and it supports only logging in from a social media site. My API checks if a user is authenticated and checks data that is being sent to avoid wrong stuff to be saved in the database(mongodb). That is all I have currently implemented to secure my API. Is it possible that a user can take his own token that he got from logging in and post information to a different account by simply guessing a different user _id.
For example, an article receives all its content and the id of the article author.
If this is possible what are some solutions on securing my API.
Any other tips on making an API secure are appreciated!
Auth0 supports logins with anything , not just social networks. You can login with username/passwords, LDAP servers, SAML servers, etc.
A token is a secure artifact. An author cannot change the id in a token without compromising the token itself (e.g. the digital signature will fail), so impersonating someone else is not that easy. The very first thing your API would need to do is checking the integrity of the token being added to the request, and reject any that contains an invalid one (bad signature, expired, etc).
It is a question that requires a lot of content, so I would recommend starting here: https://auth0.com/docs/api-auth
I want to add PayPal REST API capabilities to our shop software. Unfortunately it seems there is no way to automate to process of connecting the merchants account to our system. It looks like if you use the REST API you need to ask for client ID and secret. Then you trade that information for an OAuth token. However this is not the normal OAuth flow, which has a step that asks for users permission and does not require credentials to begin with.
These two topics basically cover the same issue, but are rather stale:
paypal rest api credential via oauth
Is it possible to use `Log In with PayPal` to make REST api requests on behalf of the user?
Does anybody know if this is possible in the meantime? I find it rather strange to design a RESTful API with OAuth capabilities and then not using it by allowing people to automatically ask for access rights on behalf of the merchant? This makes is somewhat useless for all shop software doesn't it? Well at least inconvenient.
Or is there maybe a way one could use the old API to obtain an access token that can also be used with the REST API?
Have you looked into the Permissions API?