diff --git a/containers/auth-gateway/auth_gateway/main.py b/containers/auth-gateway/auth_gateway/main.py index 50256a0..cd4f9d9 100644 --- a/containers/auth-gateway/auth_gateway/main.py +++ b/containers/auth-gateway/auth_gateway/main.py @@ -32,7 +32,13 @@ async def lifespan(app: FastAPI): yield -app = FastAPI(title="Auth Gateway", lifespan=lifespan) +app = FastAPI( + title="Auth Gateway", + lifespan=lifespan, + docs_url=None, + redoc_url=None, + openapi_url=None, +) app.state.limiter = limiter @@ -61,6 +67,19 @@ async def _rate_limit_handler(request: Request, exc: RateLimitExceeded) -> HTMLR app.add_exception_handler(RateLimitExceeded, _rate_limit_handler) +@app.middleware("http") +async def security_headers(request: Request, call_next): + response = await call_next(request) + response.headers["X-Frame-Options"] = "DENY" + response.headers["X-Content-Type-Options"] = "nosniff" + response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin" + response.headers["Content-Security-Policy"] = ( + "default-src 'self'; script-src 'none'; style-src 'self'; " + "img-src 'self' data:; frame-ancestors 'none'" + ) + return response + + @app.middleware("http") async def access_log(request: Request, call_next): start = time.monotonic() diff --git a/containers/auth-gateway/auth_gateway/services/oidc_service.py b/containers/auth-gateway/auth_gateway/services/oidc_service.py index 7de9cd8..54ba6ab 100644 --- a/containers/auth-gateway/auth_gateway/services/oidc_service.py +++ b/containers/auth-gateway/auth_gateway/services/oidc_service.py @@ -38,13 +38,15 @@ class OIDCService: client = self._client(method_name, method) token = await client.authorize_access_token(request) claims = {} + # Always parse and validate the ID token (validates nonce, signature, issuer, audience) + if "id_token" in token: + claims = dict(await client.parse_id_token(request, token, nonce=nonce)) + # Merge userinfo on top for richer claims — core identity is from the validated ID token if "userinfo" in token and isinstance(token["userinfo"], dict): - claims = token["userinfo"] - elif "id_token" in token: - claims = await client.parse_id_token(request, token, nonce=nonce) + claims.update(token["userinfo"]) email = claims.get("email") subject = claims.get("sub") - return OIDCIdentity(subject=subject, email=email, claims=dict(claims)) + return OIDCIdentity(subject=subject, email=email, claims=claims) def is_oidc_identity_allowed(method: OIDCMethodModel, email: str | None) -> bool: