#!/usr/bin/env python3 from typing import Optional from fastapi import FastAPI, Request, Response from fastapi.responses import RedirectResponse from pydantic import BaseModel from contextlib import asynccontextmanager from simple_openid_connect.client import OpenidClient from simple_openid_connect.data import TokenSuccessResponse, IdToken @asynccontextmanager async def lifespan(app: FastAPI): app.extra["oidc_client"] = OpenidClient.from_issuer_url( url="https://id.hamburg.ccc.de/realms/test/", authentication_redirect_uri="http://localhost:8000/auth/login-callback", client_id="dooris", client_secret="dp9HhnvUhAtKm3pRnxfGA7q8Nwrd1td8", ) yield app = FastAPI(lifespan=lifespan) class UserInfo(BaseModel): name: str class UserStatus(BaseModel): is_logged_in: bool user_info: Optional[UserInfo] @app.get("/api/user-info/") async def get_user_info() -> UserStatus: return { "bla": "blub" } @app.get("/auth/login") async def login_init(req: Request): oidc_client = req.app.extra["oidc_client"] # type: OpenidClient return RedirectResponse(oidc_client.authorization_code_flow.start_authentication()) @app.get("/auth/login-callback") async def login_callback(req: Request, resp: Response): oidc_client = req.app.extra["oidc_client"] # type: OpenidClient auth_result = oidc_client.authorization_code_flow.handle_authentication_result(current_url=req.url) if isinstance(auth_result, TokenSuccessResponse): resp.set_cookie("access_token", auth_result.access_token, httponly=True) resp.set_cookie("id_token", auth_result.id_token) return {"authenticated": True} else: return {"authenticated": False} def main(): import uvicorn config = uvicorn.Config(app, port=8000, log_level="info") server = uvicorn.Server(config) server.run() if __name__ == "__main__": main()