litellm/backend/auth/services/oidc.py
2026-06-11 16:27:52 -07:00

49 lines
1.6 KiB
Python

from __future__ import annotations
import re
from typing import Any, Dict, List
from authlib.integrations.starlette_client import OAuth
from scim2_models import User as ScimUser
from litellm.proxy.auth_v2.config import OIDCProviderConfig
CLAIM_KEYS = ("email", "preferred_username", "name", "groups", "roles")
def provider_key(provider: OIDCProviderConfig) -> str:
return re.sub(r"[^a-z0-9]+", "-", provider.issuer.lower()).strip("-")
def providers_by_key(
providers: List[OIDCProviderConfig],
) -> Dict[str, OIDCProviderConfig]:
return {provider_key(provider): provider for provider in providers}
def user_from_userinfo(userinfo: Dict[str, Any]) -> ScimUser:
return ScimUser(
external_id=userinfo.get("sub"),
user_name=userinfo.get("preferred_username") or userinfo.get("email"),
display_name=userinfo.get("name"),
)
def mapped_claims(userinfo: Dict[str, Any]) -> Dict[str, Any]:
return {key: userinfo[key] for key in CLAIM_KEYS if userinfo.get(key) is not None}
def build_oauth_registry(providers: List[OIDCProviderConfig]) -> OAuth:
oauth = OAuth()
for provider in providers:
oauth.register(
name=provider_key(provider),
server_metadata_url=f"{provider.issuer.rstrip('/')}/.well-known/openid-configuration",
client_id=provider.client_id,
client_secret=(provider.client_secret.get_secret_value() if provider.client_secret else None),
client_kwargs={
"scope": " ".join(provider.login_scopes),
"code_challenge_method": "S256",
},
)
return oauth