Cosmetic
Some checks failed
/ build (push) Failing after 14s
/ test (push) Successful in 5s

This commit is contained in:
phil 2025-01-16 05:43:26 +01:00
parent a597a444b5
commit 21ccdad953
2 changed files with 13 additions and 16 deletions

View file

@ -9,16 +9,13 @@ import logging
from urllib.parse import urlencode from urllib.parse import urlencode
from httpx import HTTPError 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.responses import HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from fastapi.security import OpenIdConnect from fastapi.security import OpenIdConnect
from starlette.middleware.sessions import SessionMiddleware from starlette.middleware.sessions import SessionMiddleware
from authlib.integrations.starlette_client.apps import StarletteOAuth2App from authlib.integrations.starlette_client.apps import StarletteOAuth2App
from authlib.integrations.starlette_client import OAuth, OAuthError from authlib.integrations.starlette_client import OAuthError
# authlib startlette integration does not support revocation: using requests
# from authlib.integrations.requests_client import OAuth2Session
from .settings import settings from .settings import settings
from .models import User from .models import User
@ -58,11 +55,13 @@ for provider in settings.oidc.providers:
name=provider.id, name=provider.id,
server_metadata_url=provider.openid_configuration, server_metadata_url=provider.openid_configuration,
client_kwargs={ client_kwargs={
"scope": "openid email offline_access profile", "scope": "openid email", # offline_access profile",
}, },
client_id=provider.client_id, client_id=provider.client_id,
client_secret=provider.client_secret, client_secret=provider.client_secret,
api_base_url=provider.url, api_base_url=provider.url,
# For PKCE (not implemented yet):
# code_challenge_method="S256",
# fetch_token=fetch_token, # fetch_token=fetch_token,
# update_token=update_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) # 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: async def login(request: Request, oidc_provider_id: str) -> RedirectResponse:
"""Login with the provider id, """Login with the provider id,
by giving the browser a redirect to its authorize page. by giving the browser a redirect to its authorize page.
After successful authentification, the provider replies with an encrypted The provider is expected to send the browser back to our own /auth/{oidc_provider_id} url
auth token that only we can decode and contains userinfo, with the token.
and a redirect to our own /auth/{oidc_provider_id} url
""" """
redirect_uri = request.url_for("auth", oidc_provider_id=oidc_provider_id) redirect_uri = request.url_for("auth", oidc_provider_id=oidc_provider_id)
try: try:
@ -125,14 +123,11 @@ async def auth(request: Request, oidc_provider_id: str) -> RedirectResponse:
sub = userinfo["sub"] sub = userinfo["sub"]
# Get additional data from userinfo endpoint # Get additional data from userinfo endpoint
try: try:
user_info_url = oidc_provider.server_metadata["userinfo_endpoint"] user_info_from_endpoint = await oidc_provider.userinfo(
user_info_from_endpoint = ( token=token, follow_redirects=True
await oidc_provider.get( )
user_info_url, token=token, follow_redirects=True
)
).json()
except Exception as err: 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 = {} user_info_from_endpoint = {}
# Build and remember the user in the session # Build and remember the user in the session
request.session["user_sub"] = sub request.session["user_sub"] = sub

View file

@ -19,6 +19,8 @@ class OIDCProvider(BaseModel):
url: str url: str
client_id: str client_id: str
client_secret: str = "" client_secret: str = ""
# For PKCE (not implemented yet)
# code_challenge_method: str | None = None
hint: str = "No hint" hint: str = "No hint"
@computed_field @computed_field