For example, suppose I want to determine if a user is still "logged in"... AKA their token is not yet expired.
I store my JWT access_token in localStorage when I am first issued the access_token. I know it isn't enough to simply check the localStorage to see if the access_token is there or not. I read about the introspection end point but that seems like it is for API's - not JS clients. Is the best approach to use a client side library for JWT validation? I don't like this because there is a chance I may need to switch to reference tokens. I would like to make a call to the server side for this.
What is the correct way to validate an access_token with a JavaScript client?
Update:
Upon further investigation and with advice from leastprivilege I will be using the OIDC JavaScript client so I don't need to worry about this.
Client applications are not supposed to "decode" an access token. The exact format is an implementation detail between issuer and API.
When requesting an access token, the token response contains an 'expires_in' parameter that tell the client for how many seconds the token is valid.
Most jwt tokens come with an expiry date field for expiration time(depending on the server though). You can use a library like this to decode a JWT token before saving it into your local storage and then save the expiration time inside with the token so that you can just check the local storage and the expiry time and if the current day is grater than the expiry time, you discard the previous token and get a new one.
This library might be useful to you: oidc-client-js. Some documentation is available here.
Related
Reference token as an identifier to the access token stored in identity server. What is the best practice to manage it?
There was a claim changed, how to update the access token to reflect
the change. I found that the current access token doesn't get updated automatically for that case so would like to know how to achieve that claim update on the access token.
What is the suitable lifetime it should have (15 days or more?), once expired to
re-issue it with a refresh token or just getting the end user to
login again?
Does it need to be validated through the introspection endpoint from
the javascript client (Angular) at all? I know the API needs to have a back
channel to validate it just unsure about the javascript side.
To get automatic refresh token management, I would recommend that you use the IdentityModel library from the authors of IdentityServer.
You can set the UpdateAccessTokenClaimsOnRefresh flag to true in the client definition, then you will get updated claims when you refresh the access token.
For dealing with tokens in the browser, I would recommend watchin this video
alert‘OAuth 2 0’; // The impact of XSS on OAuth 2 0 in SPAs
then visit the Backend for Frontend (BFF) Security Framework library.
I've been provided with a REST API which has authentication type bearer (Security Scheme Type: API Key, Header parameter name: Authorization) and which i use to authenticate the user and then fetch other data (i will only create the front end using react).
As a first step the user logs in and i sent his/her username-password to the prementioned REST API and get back an access and a refresh token.
Is anything wrong with storing these 2 tokens in a cookie in order to use them in subsequent requests? How does JWT comes into play regarding these 2 tokens? Is JWT of any use to me in this situation?
There's nothing wrong in storing the tokens in cookies, but if you're planning to have a Single Page Application with React it should be enough to store these tokens in memory. Once the user refreshes the page you can either make them sign in again or perform a silent login in the background to get a new set of tokens. In both cases the session kept on the Authorization Server should kick in and you should get new tokens without the need of user interaction.
Your tokens will be much safer if you don't keep them in cookies.
JWTs are not a requirement for access and refresh tokens. If you don't have to use them I would recommend going with opaque tokens. That said, since you do not have control over the API you might be limited to the format required by the API. If you don't want to be limited by this format you can set up your own gateway which you can use to perform token exchange or introspection and forward requests to the API with proper tokens (something which is called a Phantom Token pattern.
From my understanding of the question, you are using an identity provider which provides you with access token and refresh token for the users. That means it is a authentication as a service REST API at works here.
The REST API requires an authorisation header to be passed along with the username-password to exchange for access token and refresh token for the users. (correct me if I'm wrong) In this case, you might want to keep the authorisation header away from the users (consult the authentication as a service documentation).
You call the REST API with payloads (the user-password) along with headers like this:
Authorization: ACCESS_TOKEN
However the ACCESS_TOKEN is the one provided by the vendor for you to use the REST API. On success call of the REST API, it should return you with a set of access token and refresh token. You can then use this access token and refresh token to safe guard your own API, API that you control to provide service to your users.
The access token and refresh token might just be JWT tokens (again consult the vendor documentation).
Also if you are using an authentication as a service REST API, check the documentation if they provide a client sdk. In that case, it should show you the best practise of handling the access token and refresh token it returned.
In a WebApp development with AngularJS which uses token validation for authentication purposes, what's the best way to do this validation? For example:
Validate the Token every time I have a route transition. For this I have to make a rest call for everytime I want to validate.
Validate the token just one time, with one rest call, and then store the token in local storage. (The token itself just have a boolean telling if it is authenticated or not)
My concern is to not make a rest call in every route transaction, I don't want to consume that much of http traffic. But, if there isn't another way, I will do that.
If we look into what a JSON Web Token (JWT) is (although you're not specifically referring to JWT, but simply to "token"), you will realize that once you got a JWT you do not need to validate it every time you make a transition in the client app (Angular). This is because JWT are usually signed, so the server can be sure the senders (in this case the Angular app) are who they say they are when they make a request.
What you need to do is to send the JWT on every request in a header to the API server every time you try to consume a resource. The server is in charge of checking that you are sending a valid JWT and to assign the proper permissions to that request in order to get access to the resources.
Concluding (and answering your questions)
1.Validate the Token every time I have a route transition. For this I
have to make a rest call for every time I want to validate.
No, this is useless, since the given token is already signed by the server. If the token is manipulated in the client in any way the resource server will know it and will answer with the proper HTTP Status Code (usually a 401 HTTP Status).
What you can do is, in case the server respond with a 401, you can use a Refresh Token (if the server provides it) in order to get a new access token and use it again on every request. This way the final user will never know what's going on behind scenes (and won't see a login form again) because you won't ask him/her again about the username and password.
2.Validate the token just one time, with one rest call, and then store the token in local storage. (The token itself just have a boolean
telling if it is authenticated or not)
This is a correct approach (and used by most people), this way you do not overload the traffic with unnecessary requests. Actually, when you get the access token, you do not need to validate it because as I said before the token itself is Self-contained (it contains all the required information about the user and other necessary data the token provider considers important).
If I were you I would read a lot about this since there is much more to get to know than what any answerer can put together in a single answer here on SO (I put some links to sources I've used and which describe pretty well these topics).
Bear in mind that all theses behaviors can be modified according to your needs and not all of them have to be the way I just described. I just put some examples of how it could be.
The image below will give you a big picture about all these matters I just described.
I'm using JWT for authentication in my Angular.js application, with Express.js on the server side.
Basically, when user logs in, a new token is created (using https://github.com/auth0/node-jsonwebtoken) and send back to the client. If token is valid also on the client side (angular.js part, using https://github.com/auth0/angular-jwt), a new user is created and the token gets stored in a cookie.
So, each request to certain path on the server is protected by a token validation. However, my token has an expiration time. Now let's say for the sake of argument that expiration time is 30 seconds; user can actively use my application for 30 seconds and after that, he gets logged out. That's not exactly user friendly.
So what I did was that with each request to the server, I create a NEW token and send it back in the head of response. When I receive the response in my Angular.js client-side, I read the token and overwrite the token in the cookie. That way, as long as client is active (or rather, makes requests to the server side), the token gets refreshed.
Now I'd like to know the following:
Is such an approach correct? The downside is, that token gets created at each request and send back in each head of response. Cookies get overwritten quite often (performance issues?)
What would be the correct approach?
Is it OK that the token expires if there are no requests to the server? Client might still be using the application, however, if he's only writing on client side something (or reading), the token does not get refreshed.
Thanks for your time and responses!
Yes, that is a valid approach. It is the same approach many take,
including the popular Angular module ng-token-auth. You might
consider saving the tokens to local storage, with a fall back to
cookie storage if the browser doesn't support it (see
http://caniuse.com/#feat=namevalue-storage for coverage).
I would do what you describe.
One solution is to use $interval to basically ping the API. All you need to do is send in a token a get a new one back (i.e., in headers like you are now). Keep track of how many "pings" you've sent. You can reset the number of "pings" upon certain actions like on ui-router's $stateChangeSuccess (i.e., navigating to a new view) or anything you like, including submitting a form or other non-ping requests. When the number of "pings" reaches your threshold, warn the user that their session is expiring, and after a delay, erase the stored token and log them out. Check your ping responses for authentication errors from the API, indicating that the user might need to be logged out and/or redirected.
Perhaps you just gave 30 seconds as an example token lifespan. I would recommend getting closer to the browsing session timeout that you want. As points of reference, consider that the Ruby gem devise_token_auth defaults to 2 weeks and that .NET defaults to 10 hours. Your needs may vary.
The problem is also addressed by using refresh tokens. Your access token has a short life and is verified by signature. The refresh token has a longer life and is used to get new access tokens.
When the refresh token is used to get a new access token, that is a good time to do extra checks: has the refresh token been revoked? Is this user account still valid?
Both tokens can be stored in secure cookies and supplied on every request. Doing this allows your server to transparently use the refresh token when needed and set new access tokens in cookie responses.
This is the approach we've taken for Express-Stormpath and is documented in our Authentication section of the documentation. If you'd like to offload your authentication layer, I'd suggest Stormpath. (Disclaimer: I work there, and wrote that module).
I am developing an app on Google AppEngine, and utilizing Google+ SignIn with server-side flow method as documented here.
I can get the token as above, and stores it in session.
However, i want to check at login, if the token is valid or has expired. How can i do that?
Note: I use Google API client libs for java.
You can call the tokeninfo API method to get info about a token, including how long before it expires (if < 0, token is expired)
https://developers.google.com/resources/api-libraries/documentation/oauth2/v2/java/latest/com/google/api/services/oauth2/model/Tokeninfo.html
In addition to Jason's answer:
You could also estimate if the token is still good by setting another session cookie with the timestamp of when you acquired the token. They expire approximately hourly (there is some variability).
Since the tokeninfo endpoint requires a request, you could also skip hitting the tokeninfo endpoint unless you have other reasons, such as needing to verify that the token matches the app and user, and just make normal requests until they you get a bad request error. When you get that attempt to refresh your token.