Approve sign-in
A NexaMFA push request was sent to your enrolled Android device.
This request expires in {settings.challenge_ttl_seconds} seconds.
import json from uuid import UUID from fastapi import APIRouter, Depends, Form, HTTPException, Request from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse from sqlalchemy.ext.asyncio import AsyncSession from app.core.config import Settings from app.core.deps import get_app_settings, get_db from app.models.challenge import Challenge from app.models.oidc import AuthorizationCode from app.services.challenges import create_challenge, expire_if_needed from app.services.oidc import ( build_token_response, consume_authorization_code, is_approved, issue_authorization_code, jwks, redirect_with_code, redirect_with_error, validate_authorize_request, ) from app.services.push import PushService router = APIRouter(tags=["oidc"]) OIDC_PRIVATE_KEY = None def set_oidc_private_key(key) -> None: global OIDC_PRIVATE_KEY OIDC_PRIVATE_KEY = key @router.get("/.well-known/openid-configuration") async def openid_configuration(settings: Settings = Depends(get_app_settings)): issuer = settings.oidc_issuer.rstrip("/") return { "issuer": issuer, "authorization_endpoint": f"{issuer}/oauth/authorize", "token_endpoint": f"{issuer}/oauth/token", "userinfo_endpoint": f"{issuer}/oauth/userinfo", "jwks_uri": f"{issuer}/oauth/jwks", "response_types_supported": ["code"], "subject_types_supported": ["public"], "id_token_signing_alg_values_supported": ["RS256"], "scopes_supported": ["openid", "profile", "email"], "token_endpoint_auth_methods_supported": ["client_secret_post", "client_secret_basic"], "claims_supported": ["sub", "name", "preferred_username", "email", "amr"], } @router.get("/oauth/jwks") async def jwks_endpoint(): return jwks(OIDC_PRIVATE_KEY) @router.get("/oauth/authorize") async def authorize( request: Request, response_type: str, client_id: str, redirect_uri: str, scope: str = "openid profile email", state: str | None = None, nonce: str | None = None, login_hint: str | None = None, session: AsyncSession = Depends(get_db), settings: Settings = Depends(get_app_settings), ): error = validate_authorize_request(settings, client_id, redirect_uri, response_type) if error: return RedirectResponse(redirect_with_error(redirect_uri, error, state)) if not login_hint: return HTMLResponse("
authentik must send login_hint with the username.
", status_code=400) challenge = await create_challenge( session, settings, PushService(settings), username=login_hint, relying_party="authentik", requester_ip=request.client.host if request.client else "unknown", location=None, ttl_seconds=settings.challenge_ttl_seconds, oidc_state=state, ) if not challenge: return RedirectResponse(redirect_with_error(redirect_uri, "access_denied", state)) await session.commit() html = f"""A NexaMFA push request was sent to your enrolled Android device.
This request expires in {settings.challenge_ttl_seconds} seconds.