✨ SSO 로그인용 이벤트 훅

✨ SSO 로그인용 이벤트 훅 (Event Hooks for SSO Login)

Enterprise 기능

SSO에는 LiteLLM Enterprise 라이선스가 필요해요. 무료 30일 체험판을 시작하거나 데모를 예약하세요. Enterprise에 포함된 것 보기. SSO는 최대 5명의 사용자에게 무료예요. 그 이상은 엔터프라이즈 라이선스가 필요해요.

LiteLLM은 인증 설정에 따라 두 가지 다른 SSO 훅을 제공해요.

출처: 문서

본문

훅 유형 사용 시기 동작
커스텀 UI SSO 로그인 핸들러 (Custom UI SSO Sign-in Handler) LiteLLM 앞에 OAuth 프록시(oauth2-proxy, Gatekeeper, Vouch 등)가 있음 요청 헤더에서 사용자 정보를 파싱해 UI에 로그인
커스텀 SSO 핸들러 (Custom SSO Handler) 직접 SSO 제공자(Google, Microsoft, SAML)를 사용하고 커스텀 사후 인증 로직을 원함 표준 OAuth 플로우 후 커스텀 코드를 실행해 사용자 권한/팀 설정

빠른 결정 가이드:

  • ✅ 사용자 인증이 LiteLLM 밖(헤더 통해)에서 일어나면 Custom UI SSO Sign-in Handler 사용
  • ✅ LiteLLM이 OAuth 플로우를 처리 + 이후 커스텀 로직을 실행하게 하려면 Custom SSO Handler 사용

옵션 1: 커스텀 UI SSO 로그인 핸들러 (Custom UI SSO Sign-in Handler)

LiteLLM 앞에 이미 사용자를 인증하고 요청 헤더를 통해 사용자 정보를 전달하는 OAuth 프록시가 있을 때 사용해요.

동작 방식 (How it works)

  1. 사용자가 Admin UI에 도착
  2. 👉 커스텀 SSO 로그인 핸들러가 호출되어 요청 헤더를 파싱하고 사용자 정보 반환
  3. LiteLLM이 커스텀 핸들러에서 사용자 정보를 검색
  4. 사용자가 UI에 로그인

사용법 (Usage)

1. 커스텀 UI SSO 핸들러 파일 생성

이 핸들러는 요청 헤더를 파싱하고 OpenID 객체로 사용자 정보를 반환해요:

from fastapi import Request
from fastapi_sso.sso.base import OpenID
from litellm.integrations.custom_sso_handler import CustomSSOLoginHandler

class MyCustomSSOLoginHandler(CustomSSOLoginHandler):
    """
    Custom handler for parsing OAuth proxy headers

    Use this when you have an OAuth proxy (like oauth2-proxy, Vouch, etc.)
    in front of LiteLLM that adds user info to request headers
    """
    async def handle_custom_ui_sso_sign_in(
        self,
        request: Request,
    ) -> OpenID:
        # Parse headers from your OAuth proxy
        request_headers = dict(request.headers)

        # Extract user info from headers (adjust header names for your proxy)
        user_id = request_headers.get("x-forwarded-user") or request_headers.get("x-user")
        user_email = request_headers.get("x-forwarded-email") or request_headers.get("x-email")
        user_name = request_headers.get("x-forwarded-preferred-username") or request_headers.get("x-preferred-username")

        # Return OpenID object with user information
        return OpenID(
            id=user_id or "unknown",
            email=user_email or "[email protected]",
            first_name=user_name or "Unknown",
            last_name="User",
            display_name=user_name or "Unknown User",
            picture=None,
            provider="oauth-proxy",
        )

# Create an instance to be used by LiteLLM
custom_ui_sso_sign_in_handler = MyCustomSSOLoginHandler()

2. config.yaml에서 구성

model_list:
  - model_name: "openai-model"
    litellm_params:
      model: "gpt-5.6-luna"
general_settings:
  custom_ui_sso_sign_in_handler: custom_sso_handler.custom_ui_sso_sign_in_handler
litellm_settings:
  drop_params: True
  set_verbose: True

3. 프록시 시작

$ litellm --config /path/to/config.yaml

4. Admin UI로 이동

사용자가 LiteLLM Admin UI로 이동을 시도하면, 요청이 커스텀 UI SSO 로그인 핸들러로 라우팅돼요.

옵션 2: 커스텀 SSO 핸들러 (사후 인증) (Custom SSO Handler (Post-Authentication))

사용자가 표준 SSO 제공자(Google, Microsoft 등)로 LiteLLM UI에 로그인한 후 자체 코드를 실행하고 싶을 때 사용해요.

동작 방식 (How it works)

  1. 사용자가 Admin UI에 도착
  2. LiteLLM이 사용자를 SSO 제공자(Google, Microsoft 등)로 리다이렉트
  3. SSO 제공자가 사용자를 LiteLLM으로 리다이렉트
  4. LiteLLM이 IDP에서 사용자 정보를 검색
  5. 👉 커스텀 SSO 핸들러가 호출되고 SSOUserDefinedValues 타입의 객체 반환
  6. 사용자가 UI에 로그인

사용법 (Usage)

1. 커스텀 SSO 핸들러 파일 생성

응답 타입이 SSOUserDefinedValues pydantic 객체를 따르도록 하세요. 이는 사용자를 Admin UI에 로그인시키는 데 사용돼요:

from fastapi_sso.sso.base import OpenID
from litellm.proxy._types import LitellmUserRoles, SSOUserDefinedValues
from litellm.proxy import proxy_server
# These imports are available if you need to create users or manage team membership:
# from litellm.proxy.management_endpoints.internal_user_endpoints import new_user
# from litellm.proxy.management_endpoints.team_endpoints import add_new_member

async def custom_sso_handler(userIDPInfo: OpenID) -> SSOUserDefinedValues:
    try:
        print("inside custom sso handler")  # noqa
        print(f"userIDPInfo: {userIDPInfo}")  # noqa
        if userIDPInfo.id is None:
            raise ValueError(
                f"No ID found for user. userIDPInfo.id is None {userIDPInfo}"
            )

        #################################################
        # Access extra fields from SSO provider (requires GENERIC_USER_EXTRA_ATTRIBUTES env var)
        # Example: Set GENERIC_USER_EXTRA_ATTRIBUTES="department,employee_id,groups"
        extra_fields = getattr(userIDPInfo, 'extra_fields', None) or {}
        user_department = extra_fields.get("department")
        employee_id = extra_fields.get("employee_id")
        user_groups = extra_fields.get("groups", [])

        print(f"User department: {user_department}")  # noqa
        print(f"Employee ID: {employee_id}")  # noqa
        print(f"User groups: {user_groups}")  # noqa
        #################################################

        #################################################
        # Run your custom code / logic here
        # check if user exists in litellm proxy DB
        if proxy_server.prisma_client is not None:
            _user_info = await proxy_server.prisma_client.get_data(user_id=userIDPInfo.id)
            print("_user_info from litellm DB ", _user_info)  # noqa
        #################################################

        return SSOUserDefinedValues(
            models=[],                                      # models user has access to
            user_id=userIDPI...

2. config.yaml에서 구성

파일 경로를 config.yaml에 전달하세요.

예를 들어 둘 다 같은 디렉토리에 있다면 - ./config.yaml./custom_sso.py - 다음과 같아요:

model_list:
  - model_name: "openai-model"
    litellm_params:
      model: "gpt-5.6-luna"
general_settings:
  custom_sso: custom_sso.custom_sso_handler
litellm_settings:
  drop_params: True
  set_verbose: True

3. 프록시 시작

$ litellm --config /path/to/config.yaml