feat(auth): Implement /refresh endpoint and update login/register
This commit is contained in:
@@ -59,7 +59,8 @@ async def register(user_in: UserCreate, response: Response):
|
||||
)
|
||||
|
||||
access_token = create_access_token(data={"sub": str(user.id)})
|
||||
set_auth_cookie(response, access_token)
|
||||
refresh_token = create_refresh_token(data={"sub": str(user.id)})
|
||||
set_auth_cookie(response, access_token, refresh_token)
|
||||
|
||||
return {
|
||||
"id": str(user.id),
|
||||
@@ -80,15 +81,64 @@ async def login(response: Response, form_data: OAuth2PasswordRequestForm = Depen
|
||||
)
|
||||
|
||||
access_token = create_access_token(data={"sub": str(user.id)})
|
||||
set_auth_cookie(response, access_token)
|
||||
refresh_token = create_refresh_token(data={"sub": str(user.id)})
|
||||
set_auth_cookie(response, access_token, refresh_token)
|
||||
return {"access_token": access_token, "token_type": "bearer"}
|
||||
|
||||
@router.post("/logout")
|
||||
async def logout(response: Response):
|
||||
"""Logout by clearing the auth cookie."""
|
||||
response.delete_cookie(key="access_token")
|
||||
"""Logout by clearing the auth cookies."""
|
||||
clear_auth_cookies(response)
|
||||
return {"detail": "Successfully logged out"}
|
||||
|
||||
@router.post("/refresh", response_model=Token)
|
||||
async def refresh(request: Request, response: Response):
|
||||
"""Refresh the access token using a valid refresh token."""
|
||||
refresh_token = request.cookies.get("refresh_token")
|
||||
if not refresh_token:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Refresh token missing"
|
||||
)
|
||||
|
||||
from ea_chatbot.api.utils import decode_access_token # Using decode_access_token for both
|
||||
payload = decode_access_token(refresh_token)
|
||||
|
||||
if not payload:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid refresh token"
|
||||
)
|
||||
|
||||
if payload.get("type") != "refresh":
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid token type"
|
||||
)
|
||||
|
||||
user_id = payload.get("sub")
|
||||
if not user_id:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid token payload"
|
||||
)
|
||||
|
||||
# Check if user still exists
|
||||
user = history_manager.get_user_by_id(user_id)
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="User not found"
|
||||
)
|
||||
|
||||
# Issue new tokens (Rotation)
|
||||
new_access_token = create_access_token(data={"sub": str(user.id)})
|
||||
new_refresh_token = create_refresh_token(data={"sub": str(user.id)})
|
||||
|
||||
set_auth_cookie(response, new_access_token, new_refresh_token)
|
||||
|
||||
return {"access_token": new_access_token, "token_type": "bearer"}
|
||||
|
||||
@router.get("/oidc/login")
|
||||
async def oidc_login(response: Response):
|
||||
"""Get the OIDC authorization URL and set temporary session cookie."""
|
||||
@@ -158,9 +208,10 @@ async def oidc_callback(request: Request, response: Response, code: str, state:
|
||||
# 4. Sync user and establish session
|
||||
user = history_manager.sync_user_from_oidc(email=email, display_name=name)
|
||||
access_token = create_access_token(data={"sub": str(user.id)})
|
||||
refresh_token = create_refresh_token(data={"sub": str(user.id)})
|
||||
|
||||
redirect_response = RedirectResponse(url=settings.frontend_url, status_code=status.HTTP_302_FOUND)
|
||||
set_auth_cookie(redirect_response, access_token)
|
||||
set_auth_cookie(redirect_response, access_token, refresh_token)
|
||||
redirect_response.delete_cookie("oidc_session") # Cleanup
|
||||
|
||||
return redirect_response
|
||||
|
||||
Reference in New Issue
Block a user