
    "<iO%                        d Z ddlmZ ddlmZ ddlZddlmZmZ ddl	m
Z
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mZ ddlmZ ddlmZ ddlmZmZ  ee          Z G d de
          Z  G d de          Z!dS )a  Descope authentication provider for FastMCP.

This module provides DescopeProvider - a complete authentication solution that integrates
with Descope's OAuth 2.1 and OpenID Connect services, supporting Dynamic Client Registration (DCR)
for seamless MCP client authentication.
    )annotations)urlparseN)
AnyHttpUrlfield_validator)BaseSettingsSettingsConfigDict)JSONResponse)Route)RemoteAuthProviderTokenVerifier)JWTVerifier)ENV_FILEparse_scopes)
get_logger)NotSetNotSetTc                      e Zd ZU  eded          ZdZded<   dZded<   dZ	d	ed
<   ded<   dZ
ded<    edd          ed                         ZdS )DescopeProviderSettings$FASTMCP_SERVER_AUTH_DESCOPEPROVIDER_ignore)
env_prefixenv_fileextraNzAnyHttpUrl | None
config_url
str | None
project_idzAnyHttpUrl | str | Nonedescope_base_urlr   base_urlzlist[str] | Nonerequired_scopesbefore)modec                     t          |          S Nr   )clsvs     /Users/kimhansen/Desktop/03 Workspace/ceo-agents/chl-effectiveness/mcp-servers/whoop/.venv/lib/python3.11/site-packages/fastmcp/server/auth/providers/descope.py_parse_scopesz%DescopeProviderSettings._parse_scopes)   s     A    )__name__
__module____qualname__r   r   model_configr   __annotations__r   r   r    r   classmethodr(    r)   r'   r   r      s         %%9  L %)J((((!J!!!!044444(,O,,,,_&X666  [ 76  r)   r   c                  D     e Zd ZdZeeeeeddd fdZ	 dd fdZ xZS )DescopeProvidera  Descope metadata provider for DCR (Dynamic Client Registration).

    This provider implements Descope integration using metadata forwarding.
    This is the recommended approach for Descope DCR
    as it allows Descope to handle the OAuth flow directly while FastMCP acts
    as a resource server.

    IMPORTANT SETUP REQUIREMENTS:

    1. Create an MCP Server in Descope Console:
       - Go to the [MCP Servers page](https://app.descope.com/mcp-servers) of the Descope Console
       - Create a new MCP Server
       - Ensure that **Dynamic Client Registration (DCR)** is enabled
       - Note your Well-Known URL

    2. Note your Well-Known URL:
       - Save your Well-Known URL from [MCP Server Settings](https://app.descope.com/mcp-servers)
       - Format: ``https://.../v1/apps/agentic/P.../M.../.well-known/openid-configuration``

    For detailed setup instructions, see:
    https://docs.descope.com/identity-federation/inbound-apps/creating-inbound-apps#method-2-dynamic-client-registration-dcr

    Example:
        ```python
        from fastmcp.server.auth.providers.descope import DescopeProvider

        # Create Descope metadata provider (JWT verifier created automatically)
        descope_auth = DescopeProvider(
            config_url="https://.../v1/apps/agentic/P.../M.../.well-known/openid-configuration",
            base_url="https://your-fastmcp-server.com",
        )

        # Use with FastMCP
        mcp = FastMCP("My App", auth=descope_auth)
        ```
    N)r   r   r   r   r    token_verifierr   AnyHttpUrl | str | NotSetTr   str | NotSetTr   r   r    list[str] | NotSetT | Noner3   TokenVerifier | Nonec          	        t                               d |||||d                                D                       }t          t	          |j                                      d                    | _        |j        t	          |j                  }|                    d          r|dt          d                    }t          |          }	|	j                            d                              d          }
d|
v rN|
                    d          }|dz   t          |
          k     r|
|dz            | _        n$t!          d|           t!          d	|           |	j         d
|	j                             d          | _        n|j        m|j        f|j        | _        t	          |j                                      d          }|                    d          sd| }|| _        | j         d| j         }nt!          d          |.t+          | j         d| j         d|d| j        |j                  }t/                                          |t          |          g| j                   dS )az  Initialize Descope metadata provider.

        Args:
            config_url: Your Descope Well-Known URL (e.g., "https://.../v1/apps/agentic/P.../M.../.well-known/openid-configuration")
                This is the new recommended way. If provided, project_id and descope_base_url are ignored.
            project_id: Your Descope Project ID (e.g., "P2abc123"). Used with descope_base_url for backwards compatibility.
            descope_base_url: Your Descope base URL (e.g., "https://api.descope.com"). Used with project_id for backwards compatibility.
            base_url: Public URL of this FastMCP server
            required_scopes: Optional list of scopes that must be present in validated tokens.
                These scopes will be included in the protected resource metadata.
            token_verifier: Optional token verifier. If None, creates JWT verifier for Descope
        c                ,    i | ]\  }}|t           u||S r0   )r   ).0kr&   s      r'   
<dictcomp>z,DescopeProvider.__init__.<locals>.<dictcomp>l   s3     
 
 
Aq F?? 1 #??r)   )r   r   r   r   r    /Nz!/.well-known/openid-configurationagentic   z.Could not extract project_id from config_url: z-Could not find 'agentic' in config_url path: z://)zhttp://https://r@   	/v1/apps/z^Either config_url (new API) or both project_id and descope_base_url (old API) must be providedz/.well-known/jwks.jsonRS256)jwks_uriissuer	algorithmaudiencer    )r3   authorization_serversr   )r   model_validateitemsr   strr   rstripr   endswithlenr   pathstripsplitindexr   
ValueErrorschemenetlocr   
startswithr   r    super__init__)selfr   r   r   r   r    r3   settings
issuer_url
parsed_url
path_partsagentic_indexdescope_base_url_str	__class__s                r'   rW   zDescopeProvider.__init__U   s   , +99
 
 #-",(8 ('6  %''
 
 

 
 #3x'8#9#9#@#@#E#EFF * X011J""#FGG U'(S3/R+S+S*S(ST
 "*--J#..s3399#>>J J&& * 0 0 ; ; 1$s:66&01B&CDOO$UUU   !PJPP  
 (2'8$P$PZ=N$P$P$W$W% %D!!  ,1J1V&1DO#&x'@#A#A#H#H#M#M '223JKK I'H2F'H'H$$8D! 1MMDOMMJJp  
 !( 1[[DO[[[!! ( 8  N 	)#-j#9#9":] 	 	
 	
 	
 	
 	
r)   mcp_pathr   returnlist[Route]c                     t                                          |          } fd}|                    t          d|dg                     |S )a  Get OAuth routes including Descope authorization server metadata forwarding.

        This returns the standard protected resource routes plus an authorization server
        metadata endpoint that forwards Descope's OAuth metadata to clients.

        Args:
            mcp_path: The path where the MCP endpoint is mounted (e.g., "/mcp")
                This is used to advertise the resource URL in metadata.
        c                  K   	 t          j                    4 d{V }|                    j         dj         d           d{V }|                                 |                                }t          |          cddd          d{V  S # 1 d{V swxY w Y   dS # t          $ r!}t          dd| dd          cY d}~S d}~ww xY w)	zPForward Descope OAuth authorization server metadata with FastMCP customizations.NrA   '/.well-known/oauth-authorization-serverserver_errorz"Failed to fetch Descope metadata: )errorerror_descriptioni  )status_code)	httpxAsyncClientgetr   r   raise_for_statusjsonr	   	Exception)requestclientresponsemetadataerX   s        r'   #oauth_authorization_server_metadatazGDescopeProvider.get_routes.<locals>.oauth_authorization_server_metadata   s      ,.. 2 2 2 2 2 2 2&%+ZZ0ss4?sss& &            H --///'}}H'112 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2    #!/-URS-U-U  !$        sA   B& A"B B& 
BB&  B!B& &
C0CCCre   GET)endpointmethods)rV   
get_routesappendr
   )rX   r`   routesru   r_   s   `   r'   ry   zDescopeProvider.get_routes   sr     ##H--	 	 	 	 	( 	9<  	
 	
 	
 r)   )r   r4   r   r5   r   r4   r   r4   r    r6   r3   r7   r$   )r`   r   ra   rb   )r*   r+   r,   __doc__r   rW   ry   __classcell__)r_   s   @r'   r2   r2   /   s        # #P 28$*7=/56</3b
 b
 b
 b
 b
 b
 b
 b
L  $, , , , , , , , , , ,r)   r2   )"r|   
__future__r   urllib.parser   rj   pydanticr   r   pydantic_settingsr   r   starlette.responsesr	   starlette.routingr
   fastmcp.server.authr   r   !fastmcp.server.auth.providers.jwtr   fastmcp.settingsr   fastmcp.utilities.authr   fastmcp.utilities.loggingr   fastmcp.utilities.typesr   r   r*   loggerr   r2   r0   r)   r'   <module>r      s    # " " " " " ! ! ! ! ! !  0 0 0 0 0 0 0 0 > > > > > > > > , , , , , , # # # # # # A A A A A A A A 9 9 9 9 9 9 % % % % % % / / / / / / 0 0 0 0 0 0 3 3 3 3 3 3 3 3	H		    l   &v v v v v( v v v v vr)   