initial commit

This commit is contained in:
gulimabr
2025-11-28 12:33:37 -03:00
commit 5da54393ff
42 changed files with 3251 additions and 0 deletions

118
backend/src/main.py Normal file
View 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)