
    kKj!                        d Z ddlmZ ddlZddlZddlmZmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZmZ dd	lmZ ddlZdd
lmZ  ee      ZdZdZedd       Zedd       Zddd	 	 	 	 	 	 	 ddZ G d d      Zy)a"  JWT token issuance and verification for FastMCP OAuth Proxy.

This module implements the token factory pattern for OAuth proxies, where the proxy
issues its own JWT tokens to clients instead of forwarding upstream provider tokens.
This maintains proper OAuth 2.0 token audience boundaries.
    )annotationsN)Anyoverload)hashes)HKDF)
PBKDF2HMAC)jwkjwt)	JoseError)
get_loggeri@B 
   c                     y)zHDerive JWT signing key from a high-entropy key material and server salt.N )high_entropy_materialsalts     o/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/fastmcp/server/auth/jwt_issuer.pyderive_jwt_keyr              c                     y)zGDerive JWT signing key from a low-entropy key material and server salt.Nr   )low_entropy_materialr   s     r   r   r   "   r   r   )r   r   c                   | |t        d      | bt        t        j                         d|j	                         d      j                  | j	                               }t        j                  |      S |t        j                  j                  rt        nt        }t        t        j                         d|j	                         |      j                  |j	                               }t        j                  |      S t        d      )zWDerive JWT signing key from a high-entropy or low-entropy key material and server salt.zSEither high_entropy_material or low_entropy_material must be provided, but not both    s   Fernet)	algorithmlengthr   info)key_material)r   r   r   
iterationszEEither high_entropy_material or low_entropy_material must be provided)
ValueErrorr   r   SHA256encodederivebase64urlsafe_b64encodefastmcpsettings	test_modeKDF_ITERATIONS_TESTKDF_ITERATIONSr   )r   r   r   derived_keyr   pbkdf2s         r   r   r   '   s     (-A-Ma
 	
 (mmo	

 &3::<&
= 	 ''44'#*#3#3#=#=> 	 mmo!	

 &299;&
< 	 ''//
O r   c                      e Zd ZdZ	 	 	 	 	 	 ddZ	 	 d	 	 	 	 	 	 	 	 	 	 	 d	dZ	 d
	 	 	 	 	 	 	 	 	 	 	 d	dZ	 d	 	 	 	 	 ddZy)	JWTIssuera  Issues and validates FastMCP-signed JWT tokens using HS256.

    This issuer creates JWT tokens for MCP clients with proper audience claims,
    maintaining OAuth 2.0 token boundaries. Tokens are signed with HS256 using
    a key derived from the upstream client secret.
    c                d    || _         || _        || _        t        j                  |d      | _        y)zInitialize JWT issuer.

        Args:
            issuer: Token issuer (FastMCP server base URL)
            audience: Token audience (typically {base_url}/mcp)
            signing_key: HS256 signing key (32 bytes)
        octN)issueraudience_signing_keyr	   
import_key_jwt_key)selfr0   r1   signing_keys       r   __init__zJWTIssuer.__init__W   s,      '{E:r   Nc                <   t        t        j                               }ddd}| j                  | j                  |dj	                  |      ||z   ||d}|r||d<   t        j                  ||| j                  dg      }	t        j                  d||d	d
 |d          |	S )aW  Issue a minimal FastMCP access token.

        FastMCP tokens are reference tokens containing only the minimal claims
        needed for validation and lookup. The JTI maps to the upstream token
        which contains actual user identity and authorization data.

        Args:
            client_id: MCP client ID
            scopes: Token scopes
            jti: Unique token identifier (maps to upstream token)
            expires_in: Token lifetime in seconds
            upstream_claims: Optional claims from upstream IdP token to include

        Returns:
            Signed JWT token
        HS256JWTalgtyp )issaud	client_idscopeexpiatjtiupstream_claims
algorithmsz/Issued access token for client=%s jti=%s exp=%dN   rC   
inttimer0   r1   joinr
   r!   r4   loggerdebug
r5   rA   scopesrE   
expires_inrF   nowheaderpayloadtokens
             r   issue_access_tokenzJWTIssuer.issue_access_tokeni   s    0 $))+ /;;=="XXf%##
 )8G%&

MMy	
 	=GEN		
 r   c           	     >   t        t        j                               }ddd}| j                  | j                  |dj	                  |      ||z   ||dd}|r||d<   t        j                  ||| j                  dg      }	t        j                  d	||d
d |d          |	S )a  Issue a minimal FastMCP refresh token.

        FastMCP refresh tokens are reference tokens containing only the minimal
        claims needed for validation and lookup. The JTI maps to the upstream
        token which contains actual user identity and authorization data.

        Args:
            client_id: MCP client ID
            scopes: Token scopes
            jti: Unique token identifier (maps to upstream token)
            expires_in: Token lifetime in seconds (should match upstream refresh expiry)
            upstream_claims: Optional claims from upstream IdP token to include

        Returns:
            Signed JWT token
        r9   r:   r;   r>   refresh)r?   r@   rA   rB   rC   rD   rE   	token_userF   rG   z0Issued refresh token for client=%s jti=%s exp=%dNrI   rC   rJ   rP   s
             r   issue_refresh_tokenzJWTIssuer.issue_refresh_token   s    0 $))+ /;;=="XXf%#"	#
 )8G%&

MMy	
 	>GEN		
 r   c                   	 t        j                  || j                  dg      j                  }|j	                  dd      }||k7  r(t
        j                  d||       t        d| d|       |j	                  d      }|7|t        j                         k  r t
        j                  d
       t        d      |j	                  d      | j                  k7  r t
        j                  d       t        d      |j	                  d      | j                  k7  r t
        j                  d       t        d      t
        j                  d|j	                  d             |S # t        $ r}t
        j                  d|        d	}~ww xY w)a  Verify and decode a FastMCP token.

        Validates JWT signature, expiration, issuer, audience, and token type.

        Args:
            token: JWT token to verify
            expected_token_use: Expected token type ("access" or "refresh").
                Defaults to "access", which rejects refresh tokens.

        Returns:
            Decoded token payload

        Raises:
            JoseError: If token is invalid, expired, or has wrong claims
        r9   rG   rZ   accessz(Token type mismatch: expected %s, got %szToken type mismatch: expected z, got rC   NzToken expiredzToken has expiredr?   zToken has invalid issuerzInvalid token issuerr@   zToken has invalid audiencezInvalid token audiencez*Token verified successfully for subject=%ssubzToken validation failed: %s)r
   decoder4   claimsgetrN   rO   r   rL   r0   r1   )r5   rV   expected_token_userU   rZ   rC   es          r   verify_tokenzJWTIssuer.verify_token   sc   (,	jj#9 f	   K:I..>&
  45G4H I$+'  ++e$C3#4_- 344 {{5!T[[078 677 {{5!T]]29: 899LL<gkk%>P N 	LL6:	s   EE 	F $E;;F )r0   strr1   re   r6   bytes)i  N)rA   re   rQ   z	list[str]rE   re   rR   rK   rF   zdict[str, Any] | Nonereturnre   )N)r]   )rV   re   rb   re   rg   zdict[str, Any])__name__
__module____qualname____doc__r7   rW   r[   rd   r   r   r   r-   r-   O   s    ;; ; 	;. 1566 6 	6
 6 /6 
6| 2677 7 	7
 7 /7 
7x #+@@  @ 
	@r   r-   )r   re   r   re   rg   rf   )r   re   r   re   rg   rf   )r   
str | Noner   rl   r   re   rg   rf   )rk   
__future__r   r#   rL   typingr   r   cryptography.hazmat.primitivesr   'cryptography.hazmat.primitives.kdf.hkdfr   )cryptography.hazmat.primitives.kdf.pbkdf2r   joserfcr	   r
   joserfc.errorsr   r%   fastmcp.utilities.loggingr   rh   rN   r)   r(   r   r-   r   r   r   <module>ru      s    #     1 8 @  $  0	H	  
S 
S 
R 
R )-'+%%% %% 	%
 %PK Kr   