o
    ưi                     @   s   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 dZ	eG dd deZ
G d	d
 d
ZG dd dZG dd dZdS )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                   @   s"   e Zd ZU dZeed< eed< dS )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 r   r   U/home/app/Keep/.python/lib/python3.10/site-packages/litellm/proxy_auth/credentials.pyr      s   
 
r   c                   @   s"   e Zd ZdZdedefddZdS )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                 C   s   dS )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   r   r   r   	get_token(   s   
zTokenCredential.get_tokenN)r
   r   r   r   r   r   r   r   r   r   r   r      s    	r   c                   @   s6   e Zd ZdZd
dee fddZdedefdd	Z	dS )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                 C   s   || _ |du| _dS )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   r   r   r   __init__J   s   zAzureADCredential.__init__r   r   c                 C   sX   | j szddlm} | | _d| _ W n ty   tdw | j|}t|j|jdS )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   Zazure.identityr   r   ImportErrorr   r   r   r	   )r   r   r   resultr   r   r   r   U   s   
zAzureADCredential.get_token)N)
r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   5   s    r   c                   @   s8   e Zd ZdZdededefddZdedefd	d
ZdS )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                 C   s   || _ || _|| _d| _dS )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$   r   r   r   r      s   	
z GenericOAuth2Credential.__init__r   r   c                 C   s   | j r| j jt d kr| j S ddl}|j| jd| j| j|dd}|  |	 }t
|d tt |dd	 d
| _ | 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   NZclient_credentials)Z
grant_typer"   r#   r   )dataZaccess_tokenZ
expires_ini  r   )r%   r	   timehttpxpostr$   r"   r#   raise_for_statusjsonr   r   get)r   r   r)   responser'   r   r   r   r      s$   	z!GenericOAuth2Credential.get_tokenN)r
   r   r   r   r   r   r   r   r   r   r   r   r!   r   s    r!   c                   @   s>   e Zd ZdZdedefddZdefddZde	fd	d
Z
dS )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                 C   s   || _ || _d| _dS )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   r%   )r   r   r   r   r   r   r      s   	
zProxyAuthHandler.__init__r   c                 C   s0   | j r| j jt d kr| j| j| _ | j S )z
        Get a valid access token, refreshing if necessary.

        Returns:
            AccessToken that is valid for at least 60 more seconds.
        r&   )r%   r	   r(   r   r   r   )r   r   r   r   r      s   zProxyAuthHandler.get_tokenc                 C   s   |   }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   r   r   r   get_auth_headers   s   z!ProxyAuthHandler.get_auth_headersN)r
   r   r   r   r   r   r   r   r   dictr1   r   r   r   r   r/      s
    r/   )r   r(   dataclassesr   typingr   r   r   r   r   r   r   r!   r/   r   r   r   r   <module>   s    =B