
    AHj                         d Z ddlZddlmZ ddlmZmZmZmZ e G d d             Z	e G d de             Z
 G d	 d
      Z G d d      Z G d d      Zy)z
Credential providers for proxy authentication.

This module provides a provider-agnostic interface for obtaining OAuth2/JWT tokens.
It follows the same TokenCredential protocol used by Azure SDK.
    N)	dataclass)AnyOptionalProtocolruntime_checkablec                   &    e Zd ZU dZeed<   eed<   y)AccessTokena  
    Represents an OAuth2 access token with expiration.

    This matches the structure used by azure.core.credentials.AccessToken.

    Attributes:
        token: The access token string (typically a JWT).
        expires_on: Unix timestamp when the token expires.
    token
expires_onN)__name__
__module____qualname____doc__str__annotations__int     V/root/tools/cai/cai_env/lib/python3.12/site-packages/litellm/proxy_auth/credentials.pyr	   r	      s     JOr   r	   c                        e Zd ZdZdedefdZy)TokenCredentialz
    Protocol for credential providers.

    This matches the azure.core.credentials.TokenCredential interface,
    allowing any Azure SDK credential to be used directly.

    Any class implementing get_token(scope) -> AccessToken can be used.
    scopereturnc                      y)z
        Get an access token for the specified scope.

        Args:
            scope: The OAuth2 scope to request (e.g., "api://my-app/.default")

        Returns:
            AccessToken with the token string and expiration timestamp.
        Nr   )selfr   s     r   	get_tokenzTokenCredential.get_token(   s     	r   N)r   r   r   r   r   r	   r   r   r   r   r   r      s    
s 
{ 
r   r   c                   4    e Zd ZdZddee   fdZdedefdZ	y)	AzureADCredentiala  
    Wrapper for Azure Identity credentials.

    This wraps any azure-identity credential (DefaultAzureCredential,
    ClientSecretCredential, ManagedIdentityCredential, etc.) and converts
    the token to our AccessToken format.

    If no credential is provided, it will use DefaultAzureCredential
    which tries multiple authentication methods automatically.

    Example:
        # Use default credential chain (env vars, managed identity, CLI, etc.)
        cred = AzureADCredential()

        # Or provide a specific credential
        from azure.identity import ClientSecretCredential
        azure_cred = ClientSecretCredential(tenant_id, client_id, client_secret)
        cred = AzureADCredential(credential=azure_cred)
    N
credentialc                 $    || _         |du| _        y)z
        Initialize with an optional Azure credential.

        Args:
            credential: An azure-identity credential object. If None,
                       DefaultAzureCredential will be used on first token request.
        N)_credential_initialized)r   r   s     r   __init__zAzureADCredential.__init__J   s     !+&d2r   r   r   c                     | j                   s	 ddlm}  |       | _        d| _         | j                  j                  |      }t        |j                  |j                        S # t        $ r t	        d      w xY w)a  
        Get an access token from Azure AD.

        Args:
            scope: The OAuth2 scope (e.g., "api://my-app/.default")

        Returns:
            AccessToken with the JWT and expiration.

        Raises:
            ImportError: If azure-identity is not installed.
        r   )DefaultAzureCredentialTz]azure-identity is required for AzureADCredential. Install it with: pip install azure-identityr
   r   )	r"   azure.identityr%   r!   ImportErrorr   r	   r
   r   )r   r   r%   results       r   r   zAzureADCredential.get_tokenU   s{       	A#9#; $(! !!++E2&:K:KLL  !B s   A# #A8)N)
r   r   r   r   r   r   r#   r   r	   r   r   r   r   r   r   5   s-    (	38C= 	3Ms M{ Mr   r   c                   4    e Zd ZdZdededefdZdedefdZy	)
GenericOAuth2Credentialay  
    Generic OAuth2 client credentials flow.

    This works with any OAuth2 provider (Okta, Auth0, Keycloak, etc.)
    that supports the client_credentials grant type.

    Example:
        cred = GenericOAuth2Credential(
            client_id="my-client-id",
            client_secret="my-client-secret",
            token_url="https://my-idp.com/oauth2/token"
        )
    	client_idclient_secret	token_urlc                 <    || _         || _        || _        d| _        y)z
        Initialize OAuth2 client credentials.

        Args:
            client_id: OAuth2 client ID
            client_secret: OAuth2 client secret
            token_url: Token endpoint URL (e.g., "https://idp.com/oauth2/token")
        N)r,   r-   r.   _cached_token)r   r,   r-   r.   s       r   r#   z GenericOAuth2Credential.__init__   s"     #*"48r   r   r   c                    | j                   r:| j                   j                  t        j                         dz   kD  r| j                   S ddl}|j	                  | j
                  d| j                  | j                  |d      }|j                          |j                         }t        |d   t        t        j                               |j                  dd	      z   
      | _         | j                   S )a  
        Get an access token using OAuth2 client credentials flow.

        Tokens are cached and reused until they expire (with 60s buffer).

        Args:
            scope: The OAuth2 scope to request

        Returns:
            AccessToken with the token and expiration.
        <   r   Nclient_credentials)
grant_typer,   r-   r   )dataaccess_token
expires_ini  r&   )r0   r   timehttpxpostr.   r,   r-   raise_for_statusjsonr	   r   get)r   r   r9   responser5   s        r   r   z!GenericOAuth2Credential.get_token   s     $"4"4"?"?$))+PRBR"R%%%::NN2!^^!%!3!3	  
 	!!#}}(~&499;'$((<*FF
 !!!r   N)r   r   r   r   r   r#   r	   r   r   r   r   r+   r+   r   s4    9# 9c 9c 9""s ""{ ""r   r+   c                   8    e Zd ZdZdedefdZdefdZde	fdZ
y)	ProxyAuthHandlera{  
    Manages OAuth2/JWT token lifecycle for proxy authentication.

    This handler:
    - Obtains tokens from the configured credential provider
    - Caches tokens to avoid unnecessary requests
    - Automatically refreshes tokens before they expire (60s buffer)
    - Generates Authorization headers for HTTP requests

    Set this as litellm.proxy_auth to automatically inject auth headers
    into all requests to your LiteLLM Proxy.

    Example:
        import litellm
        from litellm.proxy_auth import AzureADCredential, ProxyAuthHandler

        litellm.proxy_auth = ProxyAuthHandler(
            credential=AzureADCredential(),
            scope="api://my-litellm-proxy/.default"
        )
        litellm.api_base = "https://my-proxy.example.com"

        # Auth headers are now automatically injected
        response = litellm.completion(model="gpt-4", messages=[...])
    r   r   c                 .    || _         || _        d| _        y)a  
        Initialize the proxy auth handler.

        Args:
            credential: A TokenCredential implementation (AzureADCredential,
                       GenericOAuth2Credential, or any custom implementation)
            scope: The OAuth2 scope to request tokens for
        N)r   r   r0   )r   r   r   s      r   r#   zProxyAuthHandler.__init__   s     %
48r   r   c                     | j                   r.| j                   j                  t        j                         dz   k  r*| j                  j	                  | j
                        | _         | j                   S )z
        Get a valid access token, refreshing if necessary.

        Returns:
            AccessToken that is valid for at least 60 more seconds.
        r2   )r0   r   r8   r   r   r   )r   s    r   r   zProxyAuthHandler.get_token   sS     !!T%7%7%B%BdiikTVFV%V!%!:!:4::!FD!!!r   c                 D    | j                         }dd|j                   iS )z
        Get HTTP headers for authentication.

        Returns:
            Dict with Authorization header containing Bearer token.
        AuthorizationzBearer )r   r
   )r   r
   s     r   get_auth_headersz!ProxyAuthHandler.get_auth_headers   s&      75;;-!899r   N)r   r   r   r   r   r   r#   r	   r   dictrE   r   r   r   r@   r@      s2    49? 93 9
"; 
":$ :r   r@   )r   r8   dataclassesr   typingr   r   r   r   r	   r   r   r+   r@   r   r   r   <module>rI      sn     ! = =    h  .:M :Mz?" ?"D<: <:r   