I'm trying to wrap my head around JWT (JSON Web Token) based authentication for securing API endpoints using access tokens. I'm protecting these endpoints by requiring the user to have a valid access token in order to obtain said resources.
I'm struggling, however, understanding the use a refresh tokens.
I have a /auth/login endpoint which accepts POST
requests:
class UserLogin(Resource):
def post(self):
data = parser.parse_args()
current_user = User.find_by_username(data['username'])
if not current_user:
return {'message': 'Unsuccessful. You do not have an account'}
if User.verify_hash(data['password'], current_user.password):
access_token = create_access_token(current_user)
refresh_token = create_refresh_token(current_user)
return {
'message': 'Login successful {}'.format(current_user.username),
'roles': 'Role: {}'.format(current_user.role),
'access token': access_token,
'refresh token': refresh_token
}
else:
return {'message': 'Something went wrong'}
The end point essentially checks the incoming credentials to ensure that the user exists in my User store. If they do, I'll return an access and refresh token. Otherwise, an error message to be handled client side.
Now, assume that the user has logged in and tries accessing a private resource from another end point secured by requiring an access token. The client will make a request and the protected end point will return some error message stating they do not have an access token. The client will then attempt to generate a new access token using the refresh token obtained on login:
class TokenRefresh(Resource):
@jwt_refresh_token_required
def post(self):
current_user = get_jwt_identity()
access_token = create_access_token(identity=current_user)
return {'access token': access_token}
Hitting the above resource will generate a new access token with some defined expiration time. This is my current flow.
My question is, how should I store refresh tokens to ensure they are being accessed by the authenticated user? Should I have some additional logic in my login requests which store the generated refresh token to that specific user?
If so, should I then generate a new refresh token and overwrite the existing refresh token attached to the user each time the client tries to refresh their access token?
At present, I feel my process can be compromised if an attacker manages to obtain the refresh token.