initial commit
This commit is contained in:
118
backend/src/main.py
Normal file
118
backend/src/main.py
Normal file
@@ -0,0 +1,118 @@
|
||||
from fastapi import FastAPI, Depends, Request
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
from fastapi.responses import RedirectResponse
|
||||
from src.models import TokenResponse, UserInfo
|
||||
from src.controller import AuthController
|
||||
from src.config import get_openid, get_settings
|
||||
|
||||
# Initialize the FastAPI app
|
||||
app = FastAPI(title="Keycloak Auth API", version="1.0.0")
|
||||
|
||||
# Get settings
|
||||
settings = get_settings()
|
||||
|
||||
# Configure CORS
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=[settings.frontend_url],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# Initialize the HTTPBearer scheme for authentication
|
||||
bearer_scheme = HTTPBearer()
|
||||
|
||||
# Configure client
|
||||
keycloak_openid = get_openid()
|
||||
|
||||
|
||||
# Define the root endpoint
|
||||
@app.get("/api")
|
||||
async def read_root():
|
||||
"""
|
||||
Root endpoint that provides a welcome message and documentation link.
|
||||
"""
|
||||
return AuthController.read_root()
|
||||
|
||||
|
||||
# Define the login endpoint
|
||||
@app.get("/api/login", response_class=RedirectResponse)
|
||||
async def login(request: Request):
|
||||
"""
|
||||
Login endpoint to authenticate the user and return an access token.
|
||||
|
||||
Returns:
|
||||
RedirectResponse: Contains the redirect URL upon successful authentication.
|
||||
"""
|
||||
# Build the callback URI using the frontend URL (accessible from browser)
|
||||
# This ensures the redirect works correctly through nginx proxy
|
||||
redirect_uri = f"{settings.frontend_url}/api/callback"
|
||||
|
||||
# Construct the authorization URL with external Keycloak URL
|
||||
auth_url = (
|
||||
f"{settings.keycloak_external_url}realms/{settings.keycloak_realm}"
|
||||
f"/protocol/openid-connect/auth"
|
||||
f"?client_id={settings.keycloak_client_id}"
|
||||
f"&response_type=code"
|
||||
f"&redirect_uri={redirect_uri}"
|
||||
f"&scope=openid%20profile%20email"
|
||||
)
|
||||
|
||||
return RedirectResponse(auth_url)
|
||||
|
||||
|
||||
# Define the callback endpoint
|
||||
@app.get("/api/callback", include_in_schema=False)
|
||||
async def callback(request: Request):
|
||||
"""
|
||||
OAuth callback endpoint that exchanges the authorization code for a token
|
||||
and sets it as an HTTP-only cookie.
|
||||
"""
|
||||
# Extract the code from the URL
|
||||
keycode = request.query_params.get('code')
|
||||
|
||||
return AuthController.login(str(keycode), request)
|
||||
|
||||
|
||||
# Define the auth/me endpoint to get current user from cookie
|
||||
@app.get("/api/auth/me", response_model=UserInfo)
|
||||
async def get_current_user(request: Request):
|
||||
"""
|
||||
Get the current authenticated user from the session cookie.
|
||||
|
||||
Returns:
|
||||
UserInfo: Information about the authenticated user.
|
||||
"""
|
||||
return AuthController.get_current_user(request)
|
||||
|
||||
|
||||
# Define the logout endpoint
|
||||
@app.post("/api/auth/logout")
|
||||
async def logout(request: Request):
|
||||
"""
|
||||
Logout endpoint that clears the authentication cookie.
|
||||
|
||||
Returns:
|
||||
dict: Success message.
|
||||
"""
|
||||
return AuthController.logout()
|
||||
|
||||
|
||||
# Define the protected endpoint (kept for API token-based access)
|
||||
@app.get("/api/protected", response_model=UserInfo)
|
||||
async def protected_endpoint(
|
||||
credentials: HTTPAuthorizationCredentials = Depends(bearer_scheme),
|
||||
):
|
||||
"""
|
||||
Protected endpoint that requires a valid token for access.
|
||||
|
||||
Args:
|
||||
credentials (HTTPAuthorizationCredentials):
|
||||
Bearer token provided via HTTP Authorization header.
|
||||
|
||||
Returns:
|
||||
UserInfo: Information about the authenticated user.
|
||||
"""
|
||||
return AuthController.protected_endpoint(credentials)
|
||||
Reference in New Issue
Block a user