There are a lot of various topics on that already but I want to be very explicit here:
I'm aware that Cognito API flows (also used by Amplify) return tokens with aws.cognito.signin.user.admin scope. And I'm also aware that I can't use those to call any of the OIDC endpoints (like /userinfo). But this is leaving me with quite a problem: how do you solve a case when user performs a global logout? Without calling endpoints like /userinfo, how can I verify that incoming access_token is indeed revoked?
Especially when one's using Amplify with it's client storing tokens approach, those can be easily stolen, and with an hour of expiry on access_token, someone can cause a lot of mayhem... I'm struggling with this very much, tried consulting AWS directly about this, but they don't seem to have any solution in mind, so maybe the community can help... I need my app to be as secure as possible. I'd prefer to use authorization_code flow with PKCE but doing it with custom UI is a journey on its own...
Thanks everyone in advance
Related
I am using Amazon Cognito and its hosted UI to help create a web application. I am able to use to log in using the hosted UI and the redirect link successfully points me to where I want it to go. I also recieve a correctly formatted JWT token on redirect.
I've also successfully parsed that JWT token into a JS object and am able to verify its validity. With the correct username, expiration time, issue time, etc., etc.
The problem I'm having now is that I simply don't know where to go from here. Is the fact that I have that JWT enough to continue on and assume that the user is valid? If I want to be able to persist the user across different webpages on the site, is it safe to store the JWT -- or, at least, parts of it -- in session storage and act as if that is valid user?
If not, then what am I supposed to do next with the JWT? I have looked through many of the various articles on using the JWT with Cognito and they all seem to be about decoding the JWT, but not about what I'm supposed to do with the JWT once I have it decoded.
For context, all I am really trying to get from the JWT is the correct user name, I am planning on storing a lot of other important user details elsewhere.
I'm sorry if there is something very obvious I'm missing about where to go next, but I'm very new to all this AWS stuff and a lot the of documentation is confusing, and not beginner friendly. Thank you for your time, any help at all is greatly appreciated.
EDIT: I wanted to include that I am writing the log in / verification / redirect code on vanilla, client-side javascript. I am using the standard aws SDK, the aws-cognito SDK, and the amazon-cognito-identity SDK. My imports look like this:
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.686.0.min.js"</script>
<script src="../../aws-cognito/dist/amazon-cognito-auth.min.js" type="text/javascript"></script>
<script src="../../amazon-cognito-identity-js/dist/amazon-cognito-identity.min.js"></script>
my advise for you would be to look into the AWS Client Side SDK which handle the storing, refreshing and other nice functionality for you.
https://docs.amplify.aws/start/q/integration/js - Main Client side SDK.
https://github.com/amazon-archives/amazon-cognito-auth-js - older SDK used for Cognito Oauth endpoints/ Hosted UI.
Both SDK's will store the result from your HostedUI authentication is local storage in the browser. There you can check if the tokens are valid and even access them if you require to send them to an authorized resource server.
This of course can all be implemented without the use of those SDK's but they help and can give you poinnters. Additionally, the AWS SDK and Cognito identity SDK do not have any functionality that will help you integrate with the HostedUI and Oauth endpoints. That can be done using the SDK's provided above.
Hey I am getting started with the serverless framework, apigateway, lambdas and authorizers.
Here my questions:
In order to verify a proper JWT token (which seems nowadays the best solution for serverless authentication), I would need a client id. Since the authorizer lambda is not capable(?) of reaching any other parameters of the request into the lambda except for the token itself, this is a difficult task to do. How can I achieve this?
Since with every authenticated call, an additional lambda is called, my costs are doubled?! May be I am misunderstanding something here, but it seems to me like implementing a method for verifying my token without using the authorizer is cheaper and I don't need to implement the authorizer lambda itself.
The whole point of OAuth2 is that at the point of authorization you don't care who the bearer presenting you with a token is or which client they are using (web app, Postman, etc.), only that the token is valid for whatever the token bearer is trying to do. You trust that the authentication has happened because the token issuer has done the authentication.
When you talk about the aud(audience) (from comments) in JWTs, which may or may not be included dependent on the JWT issuer, this is intended to reflect the service or services that the JWT is valid for.
This could for example have a value of 'myAPIName' or 'myAPIName/test' or even ['myAPIName/test1', 'myAPIName/test2'].
If you need to validate an individual aud claim you have two choices, you can either have different Lambdas authorizing different api routes and methods with hardcoded aud variables or you can get the name of the api being called and map it back to something that would match an aud claim.
For example the method arn for the incoming request can be found in event.methodArn. This looks like arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/ potentially with [{resource}/[{child-resources}]] dependent on your implementation. With a bit of string manipulation, you could map this back to the format of an audience claim (whatever that looks like for you).
If you would rather work an api name instead of an api name you can use the apigateway.getrestapi method for whatever sdk you are using. Documentation on this method for the JavaScript sdk can be found here.
The JWT may have a sub(subject claim), again dependent on implementation of the JWT issuer, this could relate to any of your users (or at least the users the JWT issuer knows about). Validating this beyond checking the signature of the JWT is pointless. The best you could do is check if that user exists and only if you have access to the same user database that the JWT issuer does. Although this can be used to ensure that UserA only has access to UserA's data. Again, you are trusting that the fact a bearer has a token is proof that they have authenticated (proved who they are).
I hope that answers part one of your question.
In regards to part 2, the advantage of using a Lambda Authorizer over doing the authorization in the target Lambda is caching.
So envisage I have a token valid for one hour and I call your API once every second for 30 minutes (1,800 calls). You have a Lambda authorizer with a response cache time of 10 minutes. That means you check the JWT 3 times for 1800 api calls.
But if you do the validation of that token in your target Lambda, you are doing that processing 1,800 times.
There is authentication with AWS Cognito which will allow you to use authentication outside your application and still being able to let your application divide the users into subgroups based on custom roles or similar.
If for some reason you cannot use AWS Cognito (Why not?) there is both the possibility of custom authentication (the same for each function with SLS) or even authenticating with custom code inside each lambda function.
I would recommend to use Cognito, and only custom if you know you need it.
I am starting to work on an authentication system for an angular 2 Single Page Application using django-rest framework as back-end. I'd also like to have some kind of "remember me" functionality that is going to keep users logged in for a certain amount of time.
From what I have read so far, it seems that the best authentication method for this kind of Angular 2 SPA/REST API is using jwt (json web token). For jwt authentication, I looked at the django-rest-framework-jwt (https://github.com/GetBlimp/django-rest-framework-jwt).
The problem that I see is that the token needs to have a short life span (few minutes to a few hours...) in order to minimize security issues if the token get stolen. The token now needs to be refreshed frequently to avoid the user from being disconnected while using the application. In this case, a "remember me" functionality is posing problem since the token have a short life span.
I thought about a solution involving a second token that would serve as a refresh token. It would be opaque, have a longer life span and would contain information specific to the user (ip address or something like that) so that if it get stolen, the information specific to the user being different would render this refresh token invalid.
So here are my questions:
1- I would like to know if they are existing solutions addressing this problem. As any security/authentication issues, I prefer to rely on well tested solutions to avoid getting my API compromised.
2- Would the refresh token based on specific user infos be a good idea?
3- Any other ideas how I could implement what I want?
For your situation, you really need a way to store issued tokens.
I always use an OAuth2.0 server setup that manages the auth and returns tokens the OAuth setup uses a database to manage everything so it's easy to manage and revoke tokens.
The database schema would be like this http://imgur.com/a/oRbP2 the problem with using just JWT without any management over the issued tokens with long expiration you have that security issue of not being able to revoke easily.
I would advise against including any such thing as a password in the JWT and requiring them to change it what if they use that password everywhere, then they would have to change that everywhere.
Updated from comments
Sessions Authentication use session_id which most the time is stored in a cookie and this is attached to every outgoing request. It is stateful. It is nothing more than a unique identifier that associates a user account that the server has in memory/database. For example, this can course problems when running multiple servers/instances when scaling your infrastructure.
Token Authentication no session is persisted on the server so this means it is stateless. It normally uses the header Authorization: Bearer REPLACE-WITH-TOKEN . This means that this token can be passed to multiple different servers/instances because the authentication is not limited to the server that you initiated the authentication on. This helps with scaling your infrastructure. Tokens can also be passed to other clients.
RESTful API's are stateless so there must not be a session state stored on the server. Instead, it must the handled entirely by the client so that's why token authentication is used.
I had the exact problem when trying to use JWT with an application that needed a lot more than JWT was designed for. OAuth2.0 has a lot more options that I believe are necessary to meet your requirement in the safest manner possible and even features that you may find very useful in the future as your Application may grow and need more features with regards authentication.
Here is my little API with two URL :
/api/location/list -> GET
/api/location/detail -> GET
I'm looking for a process to secure this service with authentication. For now, it can be accessed by only one user (me).
I think oAuth is too complex in my case and I found this resource for designing a simple API.
I understand the principle of private/public key and HMAC but I have a big concern about this :
Say my webservice is consumed by an ajax request with GET verb. I have something like /api/location/list?apikkey=userid&hash=abcde.
A end user can easily sniffed the network during the request (via a simple chrome console), capture full url and access directly to the service multiple times (I think it's a case of replay attacks).
Differents resources talk about timestamp or nonce to make a request unique but I'm a bit lost with implementation.
Any ideas ?
You can try JWToken auth specs, simpler than Oauth, but avoid authorization data as url parameter if possible and use Header's request instead.
If needed consider also ssl encryption at tcp level.
Perhaps you could try to use a token-based approach for security, as described in this blog post:
Implementing authentication with tokens for RESTful applications - https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
The idea is to authenticate to an authentication resource (that can be part of your application) to get temporary token that can be refreshed with a refresh token when expired.
With the use of HTTPS, it seems to be appropriate.
I think that it depends on the security level you expect. Signature-based authentication (the AWS approach) is great but is a bit complex to implement by hand.
Hope it helps you,
Thierry
I am building a web application with a services layer. The services layer is going to be built using a RESTful design. The thinking is that some time in the future we may build other applications (iPhone, Android, etc.) that use the same services layer as the web application. My question is this - how do I implement login? I think I am having trouble moving from a more traditional verb based design to a resource based design. If I was building this with SOAP I would probably have a method called Login. In REST I should have a resource. I am having difficulty understanding how I should construct my URI for a login. Should it be something like this:
http://myservice/{username}?p={password}
EDIT: The front end web application uses the traditional ASP.NET framework for authentication. However at some point in the authentication process I need to validate the supplied credentials. In a traditional web application I would do a database lookup. But in this scenario I am calling a service instead of doing a database lookup. So I need something in the service that will validate the supplied credentials. And in addition to validating the supplied credentials I probably also need some sort of information about the user after they have successfully authenticated - things like their full name, their ID, etc. I hope this makes the question clearer.
Or am I not thinking about this the right way? I feel like I am having difficulty describing my question correctly.
Corey
As S.Lott pointed out already, we have a two folded things here: Login and authentication
Authentication is out-of-scope here, as this is widely discussed and there is common agreement. However, what do we actually need for a client successfully authenticate itself against a RESTful web service? Right, some kind of token, let's call it access-token.
Client) So, all I need is an access-token, but how to get such RESTfully?
Server) Why not simply creating it?
Client) How comes?
Server) For me an access-token is nothing else than a resource. Thus, I'll create one for you in exchange for your username and password.
Thus, the server could offer the resource URL "/accesstokens", for POSTing the username and password to, returning the link to the newly created resource "/accesstokens/{accesstoken}".
Alternatively, you return a document containing the access-token and a href with the resource's link:
<access-token
id="{access token id goes here; e.g. GUID}"
href="/accesstokens/{id}"
/>
Most probably, you don't actually create the access-token as a subresource and thus, won't include its href in the response.
However, if you do so, the client could generate the link on its behalf or not? No!
Remember, truly RESTful web services link resources together in a way that the client can navigate itself without the need for generating any resource links.
The final question you probably have is if you should POST the username and password as a HTML form or as a document, e.g. XML or JSON - it depends... :-)
You don't "login". You "authenticate". World of difference.
You have lots of authentication alternatives.
HTTP Basic, Digest, NTLM and AWS S3 Authentication
HTTP Basic and Digest authentication. This uses the HTTP_AUTHORIZATION header. This is very nice, very simple. But can lead to a lot of traffic.
Username/Signature authentication. Sometimes called "ID and KEY" authentication. This can use a query string.
?username=this&signature=some-big-hex-digest
This is what places like Amazon use. The username is the "id". The "key" is a digest, similar to the one used for HTTP Digest authentication. Both sides have to agree on the digest to proceed.
Some kind of cookie-based authentication. OpenAM, for example, can be configured as an agent to authenticate and provide a cookie that your RESTful web server can then use. The client would authenticate first, and then provide the cookie with each RESTful request.
Great question, well posed. I really like Patrick's answer. I use something like
-/users/{username}/loginsession
With POST and GET being handled. So I post a new login session with credentials and I can then view the current session as a resource via the GET.
The resource is a login session, and that may have an access token or auth code, expiry, etc.
Oddly enough, my MVC caller must itself present a key/bearer token via a header to prove that it has the right to try and create new login sessions since the MVC site is a client of the API.
Edit
I think some other answers and comments here are solving the issue with an out-of-band shared secret and just authenticating with a header. That's fine in many situations or for service-to-service calls.
The other solution is to flow a token, OAuth or JWT or otherwise, which means the "login" has already taken place by another process, probably a normal login UI in a browser which is based around a form POST.
My answer is for the service that sits behind that UI, assuming you want login and auth and user management placed in a REST service and not in the site MVC code. It IS the user login service.
It also allows other services to "login" and get an expiring token, instead of using a pre-shared key, as well as test scripts in a CLI or Postman.
Since quite a bit has changed since 2011...
If you're open to using a 3rd party tool, and slightly deviating from REST slightly for the web UI, consider http://shiro.apache.org.
Shiro basically gives you a servlet filter purposed for authentication as well as authorization. You can utilize all of the login methods listed by #S.Lott, including a simple form based authentication.
Filter the rest URLs that require authentication, and Shiro will do the rest.
I'm currently using this in my own project and it has worked pretty well for me thus far.
Here's something else people may be interested in.
https://github.com/PE-INTERNATIONAL/shiro-jersey#readme
The first thing to understand about REST is that its a Token based resource access.Unlike traditional ways, access is granted based on token validation. In simple words if you have right token, you can access resources.Now there is lot of whole other stuff for token creation and manipulation.
For your first question, you can design a Restfull API. Credentials(Username and password) will be passed to your service layer.Service layer then validates these credentials and grant a token.Credentials can be either simple username/password or can be SSL certificates. SSL certificates uses the OAUTH protocol and are more secure.
You can design your URI like this-
URI for token request-> http://myservice/some-directory/token?
(You can pass Credentilals in this URI for Token)
To use this token for resource access you can add this [Authorization:Bearer (token)] to your http header.
This token can be utilized by the customer to access different component of your service layer. You can also change the expiry period of this token to prevent misuse.
For your second question one thing you can do is that you grant different token to access different resource components of your service layer. For this you can specify resource parameter in your token, and grand permission based on this field.
You can also follow these links for more information-
http://www.codeproject.com/Articles/687647/Detailed-Tutorial-for-Building-ASP-NET-WebAPI-REST
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
I have faced the same problem before. Login does not translate nicely to resource based design.
The way I usually handle it is by having Login resource and passing username and password on the parameter string, basically doing
GET on http://myservice/login?u={username}&p={password}
The response is some kind of session or auth string that can then be passed to other APIs for validation.
An alternative to doing GET on the login resource is doing a POST, REST purists will probably not like me now :), and passing in the creds in the body. The response would be the same.