feat: Update JWT refresh token endpoint to include user manager dependency

This commit enhances the JWT refresh token functionality by introducing a user manager dependency for loading user instances from the database. It also adds detailed documentation for the refresh token process, ensuring clarity on the expected request format and error handling for invalid tokens. These changes aim to improve security and maintainability of the authentication flow.
This commit is contained in:
mohamad 2025-06-22 12:46:01 +02:00
parent 0207c175ba
commit 1897d48188

View File

@ -4,7 +4,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.database import get_transactional_session
from app.models import User
from app.auth import oauth, fastapi_users, auth_backend, get_jwt_strategy, get_refresh_jwt_strategy
from app.auth import oauth, fastapi_users, auth_backend, get_jwt_strategy, get_refresh_jwt_strategy, get_user_manager
from app.config import settings
from fastapi.security import OAuth2PasswordRequestForm
@ -88,16 +88,33 @@ async def apple_callback(request: Request, db: AsyncSession = Depends(get_transa
return RedirectResponse(url=redirect_url)
@router.post('/jwt/refresh')
async def refresh_jwt_token(request: Request):
async def refresh_jwt_token(
request: Request,
user_manager=Depends(get_user_manager),
):
"""Refresh the JWT access token using a valid refresh token.
The incoming request must provide a JSON body with a ``refresh_token`` field.
A new access and refresh token pair will be returned when the provided refresh
token is valid. If the token is invalid or expired, a *401* error is raised.
"""
data = await request.json()
refresh_token = data.get('refresh_token')
if not refresh_token:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Missing refresh token")
refresh_strategy = get_refresh_jwt_strategy()
try:
user = await refresh_strategy.read_token(refresh_token, None)
# ``read_token`` needs a callback capable of loading the *User* from the
# database. We therefore pass the user manager obtained via dependency
# injection so that the strategy can hydrate the full *User* instance.
user = await refresh_strategy.read_token(refresh_token, user_manager)
except Exception:
# Any error during decoding or lookup should result in an unauthorized
# response to avoid leaking information about token validity.
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid refresh token")
if not user:
@ -106,6 +123,7 @@ async def refresh_jwt_token(request: Request):
access_strategy = get_jwt_strategy()
access_token = await access_strategy.write_token(user)
new_refresh_token = await refresh_strategy.write_token(user)
return JSONResponse({
"access_token": access_token,
"refresh_token": new_refresh_token,