Fix OAuth callback redirect and deps import

- Discord OAuth callback now redirects to frontend with tokens in URL fragment
  (more secure than query params - fragment not sent to server)
- Error responses also redirect with error in query params
- Fix deps.py import: get_session_dependency -> get_session

Part of Phase 2 Authentication completion.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2026-01-28 00:17:27 -06:00
parent 5cf2198542
commit f82bc8aa1f
2 changed files with 19 additions and 9 deletions

View File

@ -246,17 +246,18 @@ async def discord_auth_callback(
db: DbSession,
code: str = Query(..., description="Authorization code from Discord"),
state: str = Query(..., description="State parameter for CSRF validation"),
) -> TokenResponse:
) -> RedirectResponse:
"""Handle Discord OAuth callback.
Exchanges the authorization code for tokens and creates/fetches the user.
Redirects to the frontend with tokens in URL fragment.
Args:
code: Authorization code from Discord.
state: State parameter for CSRF validation.
Returns:
JWT access and refresh tokens.
Redirect to frontend with access and refresh tokens.
Raises:
HTTPException: 400 if state is invalid or OAuth fails.
@ -281,13 +282,22 @@ async def discord_auth_callback(
await user_service.update_last_login(db, user)
# Create tokens
return await _create_tokens_for_user(user.id)
tokens = await _create_tokens_for_user(user.id)
# Redirect to frontend with tokens in URL fragment (not query params for security)
# Fragment is not sent to server, only accessible by frontend JavaScript
fragment = f"access_token={tokens.access_token}&refresh_token={tokens.refresh_token}&expires_in={tokens.expires_in}"
return RedirectResponse(
url=f"{redirect_uri}#{fragment}",
status_code=status.HTTP_302_FOUND,
)
except DiscordOAuthError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Discord OAuth failed: {e}",
) from None
# Redirect to frontend with error
return RedirectResponse(
url=f"{redirect_uri}?error=oauth_failed&message={e}",
status_code=status.HTTP_302_FOUND,
)
# =============================================================================

View File

@ -26,7 +26,7 @@ from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.ext.asyncio import AsyncSession
from app.db import get_session_dependency
from app.db import get_session
from app.db.models import User
from app.services.jwt_service import verify_access_token
from app.services.user_service import user_service
@ -55,7 +55,7 @@ async def get_db() -> AsyncSession:
async def get_items(db: AsyncSession = Depends(get_db)):
...
"""
async with get_session_dependency() as session:
async with get_session() as session:
yield session