问题
Recently I needed to build a simple REST API and I read different articles on best practices to reduce as far as possible the vulnerabilities of my web app. Searching online I found different tutorials on how to implement JWT tokens, every one different in some aspects, and I couldn't find a well throttled "common approach". In the end, I achieved the solution that seemed most reasonable to me but I wanted to confirm that this is the most efficient way to handle this type of authentication.
Before starting:
- Notice that CORS policy is implemented
- To sign tokens I used "standard" libraries
- Communication between clients and server is encrypted (HTTPS)
#STEP 1: Generating tokens after authentication:
- I generate a short-lived access token (15 mins) and a "longer-lived" refresh token (7 days) signed with the HS256 algorithm (key-length used: 512-bit)
- Furthermore I store the id of the refresh token in the cache.
- I send the access token back in the response (and on the client-side I keep it only in memory [Redux]) while I set the refresh token in an HTTPOnly cookie to make XSS attacks more difficult (not impossible, I know: the goal is to avoid/reduce the possibilities to steal the cookie)
#STEP 2: Authorizing requests
To authorize requests, I only use the access token that is sent in a field in the header of the requests. Requests are allowed only if the token is valid.
#STEP 3: Refreshing access token
To refresh the token I send a refresh request to the server. The server:
- Check if the refresh token signature is valid
- Check if the refresh token is in the cache (to check if expired and put another layer of defense against forged tokens)
- Generates both a new access token and a new refresh token, while the previous refresh token is revoked (and update cache accordingly)
- Send back the access token in the response and the refresh token in an HTTP only cookie
MORE INFORMATION on the refresh process
Refresh is called:
- Before the expiration of the access token
- At the exact moment the user opens/refresh the web app. In this way, if the refresh token is still valid, the user is automatically authenticated and ready to use the app. Notice that the refresh token can be used only to refresh the access token and not perform other requests (to avoid CSRF attacks the cookie can't be used to authenticate requests, but the user needs to load the website to get an access token)
FURTHER PRECAUTIONS: CRITICAL OPERATIONS
Refresh tokens have two expiration times. The first, for non-critical operations, is refreshed every time a new token is issued. In this way, if the user continues to use the app, he/she can stay logged potentially forever. The second (that lasts 3 hours), for critical operations, is "absolute". This means that, at every refresh, the "timer" for critical operations isn't refreshed.
//To make it simpler:
nextToken.criticalExpiration=previousToken.criticalExpiration
When the refresh request is called after the expiration of the "critical" timer, the access token generated has a field to false that symbolize the option to perform critical operations. If false, critical operations are not allowed (and so users have to re-authenticate to perform these requests)
Summary:
I'd like to understand if this process is executed correctly or if it generates vulnerabilities. I understand that vulnerabilities can be always possible in other parts of the app and/or in external libraries, however, I'd like to minimize the possibility of leaving something that can be exploited.
回答1:
You have to create controllers, middlewares for login, generating the jwt token and also for the refresh token. See: https://stackabuse.com/authentication-and-authorization-with-jwts-in-express-js/ for more detail.
来源:https://stackoverflow.com/questions/65946041/guidelines-to-build-a-secure-jwt-authentication-process