if auth_header:
access_token = auth_header.split(" ")[1]
# Get refresh token from httponly cookie
refresh_token = request.cookies.get('refresh_token')
if not access_token or not refresh_token:
return jsonify({'message': 'Tokens are missing'}), 400
Once I have confirmed that both tokens are present, I decode the JWT access token and extract the user_id and access_level. If decoding fails due to expiration, the access_token is automatically refreshed, but only if the refresh_token has not expired as well
try:
# Decode access token and get user ID and access level
payload = jwt.decode(access_token, current_app.config['SECRET_KEY'], algorithms=['HS256'])
user_id = payload['sub']
access_level = payload['role']
except jwt.ExpiredSignatureError:
# If access token is expired, try to refresh it
try:
token = Account.verify_refresh_token(refresh_token)
if not token:
return jsonify({'error': 'Refresh token expired'}), 401
user = db_session.query(Account).options(selectinload(Account.token)).filter_by(token=token).first()
access_token = user.generate_access_token()
resp = make_response(jsonify({'message': 'Access token refreshed'}), 202)
resp.headers['Authorization'] = f'Bearer {access_token}'
resp.set_cookie('refresh_token', token.refresh_token, samesite='lax', httponly=True)
return resp
except Exception as e:
return jsonify({'error': str(e)}), 401
except jwt.InvalidTokenError:
return jsonify({'error': 'Invalid access token'}), 401
return f(user_id=user_id, access_level=access_level, *args, **kwargs)
I have read several articles about token authentication, and most of them suggest that when the access_token expires and the backend responds with an authorization error code, the frontend should send another request to the /refresh URI on the backend to obtain a new access_token.
The frontend can then use the new access_token to try to access the protected URI again.
Please advise which approach is more secure and provides smoother performance, and also point out any potential issues with my approach.
The standard approach is to send only the jwt
and not the refresh one. This is also the most correct method since, jwt
, is specifically introduced to not send credentials within each http request to make communication more secure.
if with the jwt
we also send the refresh token
with each request, in case someone manages to steal the contents of the http packets directed to your server they would be able to take possession of both the authentication token and the login token, thus allowing him to be able to authenticate himself at any time.
If, on the other hand, you send only the jwt
with each request and someone steals the information, they will only be able to register until the jwt
expires.