I am currently implementing login using jwt.
I stored access token and refresh token in cookies, verify the validity of refresh token, and reissue the access token.
Once logged in, a new access token and refresh token are issued and stored on the client side.
Here, the refresh token is stored in the server-side redis, and if it turns out to be a different token compared to the refresh token held by the client, the login is requested again.
I implemented it in this way considering the possibility that refresh token might be stolen, but there is one problem with this method. If the same user logs in from another browser or from another device, he or she must log in again with the browser he or she previously logged in with. Because whenever a new login occurs, the refresh token stored on the server is replaced by this.
What should I do in this case? It seems that there are cases where refresh tokens are stored on the client without saving them on the server, but in that case, did you not consider the possibility that refresh tokens might be stolen? We set HTTP only when saving to cookies. Is this enough to be safe? I'm looking forward to hearing from you.
The solution I came up with is to provide the refresh token of the server and save it to the client if you log in from another device and do not have the refresh token. In this way, you can use the same refresh token while using the existing refresh token comparison method, so you can ensure that you are the same user on multiple devices. Is that a good idea?
Related
i'm having a diffculty with Access Token.
And i'm new in web dev, taking a role in front-end.
So far, my web site is connected with server for log in API, and i can verify user infomation after logged in at console.
However, i'm wondering the way to get access to Access Token which is issued from the server.
So, the logic is as follows,
When i sucess logged in with correct user information, AccessToken and Refresh Tokens are issued.
I needed a code to access to Access Token, so if i have, i can access to prevented pages (such as, MyPage)
The Access Token has 30min of expires, so after logged in 30min,the issued Access Token must be expired and lost its access rigth to private pages.
Summary !
I'm wondering the way to code the AccessToken in Client side to server side after logged in. Found some of informations that saying include Access Token in headers request in Client side.
How can i code whether the Access Token is expired after 30 min and reqesting again to issue the access-token when i access to private pages with access-token expired state.
Then, if server can find there is a refresh-token in Client side, then issues access token very easily.
Wondering should i put all of the pages that check wether AccessToken is alive?
Normally, it handle by token middle-ware between front-end to IdP(ID provider) server.
It automatically refresh the access token by refresh-token.
The middle-ware's roles
refresh token together with the access token when the user login is processed.
access token and refresh token are re-issued when the refresh is executed
saved the access token and refresh token into local storage (usually called cookies)
If an access token is expired when you execute an API, it will be able to execute the API with a new access token if a refresh token is valid
If an refresh token is expired when you execute an API, it will be able to execute the API with a new access token if a refresh token is expired after got new refresh token.
Popular IdP is Keycloak provides middle-ware for multiple languages.
Java, Javascript, Python, Spring Boot, Angular, React
sorry, I missed your question
I'm wondering the way to code the AccessToken in Client side to server side after logged in. Found some of informations that saying include Access Token in headers request in Client side.
The front-end access an access token and decode it for getting user's information, role and expires time
How can i code whether the Access Token is expired after 30 min and reqesting again to issue the access-token when i access to private pages with access-token expired state.
middle-ware takes care the life time of access token
Then, if server can find there is a refresh-token in Client side, then issues access token very easily.
Yes,
Wondering should i put all of the pages that check wether AccessToken is alive?
It stored in local storage in single place and use it from mutiple pages
There are a few things I might not agree with in #BenchVue answer:
Client should retrieve user data from ID-tokens only. Access-tokens audience are resource-server(s), can be opaque and should be used only as authorisation headers.
Authorization-server (middle-ware in the answer) defines tokens expiries. It does not refresh it auto-magically. Clients must handle tokens refreshing, which can be done pro-actively as OAuth2 token responses contain expiry in adition to the token itself (even for opaque token).
Do not code a gripped weel. Pick a lib. You're very very likely to make security breaches otherwize. Plus you'll waste a lot of time implementing stuff like:
redirection to authorization-server for login / logout when user tries to access a protected route
silent access-token refreshing (just before it expires) using refresh-token
JWT adding as Bearer Authorization header to secured resource-server
etc.
In the last few days I've been reading on Authentication with refresh and access tokens, but this is one thing I can't find the answer to. Let's say an expired access token is sent. Should the backend automatically refresh it (if a refresh token was provided), or the refreshing should only be done at a refresh endpoint?
As an example, consider the two following auth flows:
Automatically Refreshing
User authenticates with username and password. The API sends back a short lived access token containing his data, and a long lived refresh token.
For every request that requires authentication/authorization, the user will send both tokens on the request headers.
If the access token is expired, the API will check if a valid refresh token was sent, if it is active and if it belongs to the same user as the access token. If everything looks good then it will sign a new access token and update the response headers with it.
Front-end doesn't have to worry about refreshing the token, but it still has to look up response headers after each request to check if a new token was sent.
Manually Refreshing
User authenticates with username and password. The API sends back a short lived access token containing his data, and a long lived refresh token.
For every request that requires authentication/authorization, the user will send his access token.
When the access token expires, the user will send his refresh token to the refresh/ route. The API checks if the token is valid. If everything looks good, it returns a new access token.
After every request, the client has to check if the token expired, and if it did it will have to perform a new request to refresh the token. More requests are being made to the server, but on the other hand responsibilities are better separated, since auth route is only responsible for handling access tokens, while the refresh token handling lives in another route.
I've had some hard time finding resources on the subject, so I'm not quite about sure which solution is better, or even if the solutions I described are correct at all. If I had to pick one, I would go with Automatically Refreshing, since less requests are made, and the client side usability looks better, but as I said, I'm not 100% on this, and thus I'm making that thread.
How should access tokens be refreshed?
It feels to me that you are missing a role here, which is that of the Authorization Server (AS):
UI redirects to AS to authenticate the user via password
AS issues an access token and refresh token, then returns them to the UI
UI calls the API for a while with the access token
Eventually the access token expires and the API returns a 401 response
The UI then calls the AS with the refresh the token to get a new access token
The UI then retries the API call with the new access token
Eventually the refresh token expires and the refresh attempt will fail
The UI then redirects the user to sign in again and the cycle repeats
It is always the client's responsibility to refresh tokens and only the access token should be sent to the API. The API's only OAuth job is verify the access token and authorize based on its contents.
It is possible that you have an API that is doing the job of the Authorization Server. I would aim to separate these roles. If it helps my Messages Blog Post has a lot of detail on the messages in a full UI and API solution.
The implementations of the OAuth2-protocol I know use the flow you are describing under "Manual Refreshing". The client has to care himself about the refreshing.
The client can either check the access_token if it is still valid before every request or do a refresh after a failed request due to an invalid token response.
The access_token is short lived and so the risk sending it with every request and having it eavesdropped and misused is limited. The refresh_token is long lived. If you send the refresh_token with every request an attacker has a much greater chance to get hold of it.
If you send both token with every request you would not need the distinction between these two types. You would work with one long lived token only.
Following is the Main Disadvantage of using Automatic Refresh Token Rotation Scheme :-
Let's say the Client makes 2 API calls (API A and API B) at the same time. At the time of triggering these two API calls, the access token was expired. Both of these API calls are carrying the same expired access token and the refresh token (let's assume this refresh token is valid).
Let's assume API A gets handled by the server first. According to the Automatically Refreshing Scheme, the server will check the API A's access token, if that token is expired, server will check the refresh token and if that refresh token is verified (this refresh token is present in the database too), the server will create a new access token and a new refresh token (the refresh token that came with the API will be deleted from the database and will be updated with this new refresh token). These new tokens will be returned to the Client.
API B will follow the same flow. BUT its Refresh Token will be invalid because during the handling of API A, the refresh token was replaced in the database by a new token. API B's Refresh Token is not present in the Database and thus this request will fail.
If you have multiple APIs being called at the same time, Automatic Refresh Token Rotation Scheme will fail as the First API request will replace the Refresh Token when renewing the tokens and the remaining API requests will be coming with a Refresh Token which is not present in the Database !
My experience has been that the OAuth2 access_token requests dont like extra data meaning that you wont be able to send both the access_token and the refresh_token. That would lead to the Manual Refreshing scenario youve described as the only option
Background
I'm implementing an authentication system based on JWT and Refresh tokens but I had an hard time searching for serious documentation about the refresh token generation and handling.
The common scenarios I've found expect:
A short-live token JWT that is stateless and not stored on the server-side
A long-live refresh token that is stored somewhere on the client side and on the server-side and that allows to get new authorized JWTs.
Refresh token generation
My first question is about the refresh token generation. I've seen two main scenarios:
The refresh token is a simple random string or a uuid that it is stored (with its expiring time) on the server side and represent a long user session
The refresh token is itself a JWT containing the not-sensitive data of the user that has logged in and has itself an expiration
The first case is the simplest but allows to encapsulate session data only manually, the second case is more complex but allows to encapsulate the session data, the expiration and it is generated only by a secret held in the server (it means more security). In this last case, however, making the JWT persistent is against the JWT phylosophy and more effort is required for validating also this JWT and comparing the data.
Refresh token workflow
Prerequisites
Storing the refresh token on the client side is the only way to persist the session on something like a browser. However it has to been stored securely so there are two scenarios even here:
The refresh token get stored in the browser in something like the localStorage or the sessionStorage (less secure)
The refresh token is passed to the client using a HttpOnly cookie that are less reachable with Javascript.
Question
Assuming that we store the refresh token in an HttpOnly cookie I was wondering: does the endpoint /refresh_token, that returns a new JWT and a new refresh token, need to be authorized?
If the endpoint has to be authorized, I should have a valid JWT for validating my user without requesting username and password again. In a scenario where the user uses the web application in a browser, then he closes it, then after a while he returns to the web application (and the JWT has expired) this is not possible and requires the user to authenticate again.
If the endpoint is not authorized I cannot have, while validating the refresh token, a valid user instance to check the refresh token data against. So, the only thing that I can check is the validity of the refresh token with the store (or with JWT strategies). This solves the above-mentioned scenario but, is this safe enough?
Another scenario is that the endpoint accepts also expired JWTs, validates them and then it checks the refresh token.
How should the refresh token be validated for a secure implementation? What are the best practices about this?
How can I use Google Identity platform as a login / registration system for my own service?
Specifically - how can I do this and support login for same user from different devices?
Using for web service, nodejs without npm modules: passportjs / googleapis / google-auth-library.
My idea:
User opens myClientApp/login page and clicks on GoogleLogIn button which will ask him to authorize my service for specific scopes of his Google account.
I then get the refresh token & access token and save it in DB, then send the refresh token to the client with cookie.
Whenever I make a call to my own service API I send the refresh token from the cookie.
As long as I have valid access token saved in my DB or the refresh token is not expired - I treat the user matching that refresh token as an active session for my service.
Security problems:
cookies attacks, and the refresh token is easily accessed from the browser. Could use https / encryption and more methods to secure the cookie and it's value. Still- someone could copy the cookie from one computer to another!
Multiple login problems:
If the user login on different device, a new refresh token will be created. The previous device the user logged in to will now hold a wrong refresh token in the cookie...
Could the OpenID solve this? Do I need to use JWT?
What is the most secure way to use Google Identity login in my own service while supporting multiple devices login for the same user?
First, make sure that you really understand the security implications for what you want to do.
For example, NEVER send the Refresh Token to a client.
If you want to use the same tokens for the same client on multiple devices, you have a chicken and egg situation. How do you "authenticate" the user at each device. How do you know that user "John" is actually user "John" but on a different device the first time?
Your goal is not to trade convenience for less security. Your goal should always be security first, no matter the inconvenience.
A better approach is to let Google authenticate and authorize a user on each device. They only have to do this once per device. Your backend systems keep track of the Refresh Token issued for each device. You can then generate the Access Tokens and Identity Tokens when needed - they expire after one hour anyways. Store a cookie on the user's device that identifies them to your system so that you can look up who they are, get the Refresh Token, create new Access Tokens, etc.
There is a limit to the number of Refresh Tokens that can be issued before the oldest ones are voided. I think the number is 50. This is usually not a problem. If a Refresh Token is invalid, just put the user back thru the authenticate process and store the new token.
Also provide the user with a sign-out method that removes all stored tokens in your system.
The cookie that you store on the client's devices should be opaque meaning that there is no stored information in the cookie and the cookie is only valid for that device and no other devices. This solves the stolen cookie moved to another device problem.
I will now touch on some of your questions:
My idea: User opens myClientApp/login page and clicks on GoogleLogIn
button which will ask him to authorize my service for specific scopes
of his Google account.
Google OAuth does not work that way. You send the user to a URL, Google manages all display and input with the end user. Once everything is complete a callback URL on your server is called and you are passed a code. The exact details depend on the type of OAuth Flow that you are using.
I then get the refresh token & access token and save it in DB, then
send the refresh token to the client with cookie.
During the OAuth Flow you will request the Access Token, Refresh Token and Identity Token. The Refresh Token is saved in the database. Never send this token to the client. Read my suggestion above about creating an opaque cookie that you send to the client.
Security problems: cookies attacks, and the refresh token is easily
accessed from the browser. Could use https / encryption and more
methods to secure the cookie and it's value. Still- someone could copy
the cookie from one computer to another!
Create an opaque cookie that is only valid for that device and no other devices. If a client sends you a cookie intended for a different device, consider this a problem and invalidate all cookies, tokens, etc for this user on all devices.
Multiple login problems: If the user login on different device, a new
refresh token will be created. The previous device the user logged in
to will now hold a wrong refresh token in the cookie...
I covered this issue above. Store the Refresh Token generated for each device in your DB. Consider each device / Refresh Token / cookie as a set.
Could the OpenID solve this? Do I need to use JWT? What is the most
secure way to use Google Identity login in my own service while
supporting multiple devices login for the same user?
By Open ID I think you mean Open ID Connect (OIDC). This is already integrated into Google OAuth and this is the part that generates the Identity Token.
Do I need to use JWT?
Google OAuth Tokens are generated from Signed JWTs. However for the most part you do not need to worry about the format of tokens. Google provides endpoints that validate and decode Google OAuth tokens.
What is the most secure way to use Google Identity login in my own
service while supporting multiple devices login for the same user?
I covered this question in the first part of my answer above.
I'm working on an application that uses a token-based authentication system, where the user provides their username / password and receives a token in return (the token gets saved to the database as well). Then subsequent requests will include this token as a custom header and we can use this to identify the user. This all works fine.
Right now if the user doesn't login for 3 days, we expire the token. I was reading a little about refresh tokens in OAuth and I was wondering if I could somehow implement something similar. i.e. when providing the auth token, I also provide a refresh token which can be used later to request a new auth token. In terms of security though, it seems quite similar to just never expiring the user's auth token in the first place. Should I be sending additional information with the refresh token to validate the user?
In OAuth2, the resource server and authorization server are often not the same.
The refresh token is sent back to the client when the access token is issued and when the token is refreshed. The client needs to authenticate itself (using client id and client secret) to use the refresh token. The resource server never sees the refresh token.
Also, access tokens are not stored at the server side as they have a limited lifetime. Refresh tokens are stored and can therefore be revoked.