diff --git a/src/oidc_test/main.py b/src/oidc_test/main.py index 42e1245..e4a00f2 100644 --- a/src/oidc_test/main.py +++ b/src/oidc_test/main.py @@ -9,16 +9,13 @@ import logging from urllib.parse import urlencode from httpx import HTTPError -from fastapi import Depends, FastAPI, HTTPException, Request, Response, status +from fastapi import Depends, FastAPI, HTTPException, Request, status from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.templating import Jinja2Templates from fastapi.security import OpenIdConnect from starlette.middleware.sessions import SessionMiddleware from authlib.integrations.starlette_client.apps import StarletteOAuth2App -from authlib.integrations.starlette_client import OAuth, OAuthError - -# authlib startlette integration does not support revocation: using requests -# from authlib.integrations.requests_client import OAuth2Session +from authlib.integrations.starlette_client import OAuthError from .settings import settings from .models import User @@ -58,11 +55,13 @@ for provider in settings.oidc.providers: name=provider.id, server_metadata_url=provider.openid_configuration, client_kwargs={ - "scope": "openid email offline_access profile", + "scope": "openid email", # offline_access profile", }, client_id=provider.client_id, client_secret=provider.client_secret, api_base_url=provider.url, + # For PKCE (not implemented yet): + # code_challenge_method="S256", # fetch_token=fetch_token, # update_token=update_token, # client_id="some-client-id", # if enabled, authlib will also check that the access token belongs to this client id (audience) @@ -80,9 +79,8 @@ for provider in settings.oidc.providers: async def login(request: Request, oidc_provider_id: str) -> RedirectResponse: """Login with the provider id, by giving the browser a redirect to its authorize page. - After successful authentification, the provider replies with an encrypted - auth token that only we can decode and contains userinfo, - and a redirect to our own /auth/{oidc_provider_id} url + The provider is expected to send the browser back to our own /auth/{oidc_provider_id} url + with the token. """ redirect_uri = request.url_for("auth", oidc_provider_id=oidc_provider_id) try: @@ -125,14 +123,11 @@ async def auth(request: Request, oidc_provider_id: str) -> RedirectResponse: sub = userinfo["sub"] # Get additional data from userinfo endpoint try: - user_info_url = oidc_provider.server_metadata["userinfo_endpoint"] - user_info_from_endpoint = ( - await oidc_provider.get( - user_info_url, token=token, follow_redirects=True - ) - ).json() + user_info_from_endpoint = await oidc_provider.userinfo( + token=token, follow_redirects=True + ) except Exception as err: - logger.info(f"Cannot get userinfo from endpoint: {err}") + logger.warn(f"Cannot get userinfo from endpoint: {err}") user_info_from_endpoint = {} # Build and remember the user in the session request.session["user_sub"] = sub diff --git a/src/oidc_test/settings.py b/src/oidc_test/settings.py index d01e19f..d2d9c55 100644 --- a/src/oidc_test/settings.py +++ b/src/oidc_test/settings.py @@ -19,6 +19,8 @@ class OIDCProvider(BaseModel): url: str client_id: str client_secret: str = "" + # For PKCE (not implemented yet) + # code_challenge_method: str | None = None hint: str = "No hint" @computed_field