
    Ki~0                        d Z ddlmZ ddlZddlmZ ddlmZ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 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 G d de      Z y)aT  GitHub OAuth provider for FastMCP.

This module provides a complete GitHub OAuth integration that's ready to use
with just a client ID and client secret. It handles all the complexity of
GitHub's OAuth flow, token validation, and user management.

Example:
    ```python
    from fastmcp import FastMCP
    from fastmcp.server.auth.providers.github import GitHubProvider

    # Simple GitHub OAuth protection
    auth = GitHubProvider(
        client_id="your-github-client-id",
        client_secret="your-github-client-secret"
    )

    mcp = FastMCP("My Protected Server", auth=auth)
    ```
    )annotationsN)AsyncKeyValue)
AnyHttpUrl	SecretStrfield_validator)BaseSettingsSettingsConfigDict)TokenVerifier)AccessToken)
OAuthProxy)ENV_FILEparse_scopes)
get_logger)NotSetNotSetTc                      e Zd ZU dZ eded      ZdZded<   dZ	ded	<   dZ
d
ed<   dZd
ed<   dZded<   dZded<   dZded<   dZded<   dZded<    edd      ed               Zy)GitHubProviderSettingsz#Settings for GitHub OAuth provider.FASTMCP_SERVER_AUTH_GITHUB_ignore)
env_prefixenv_fileextraNz
str | None	client_idzSecretStr | Noneclient_secretzAnyHttpUrl | str | Nonebase_url
issuer_urlredirect_pathlist[str] | Nonerequired_scopesz
int | Nonetimeout_secondsallowed_client_redirect_urisjwt_signing_keybefore)modec                    t        |      S )Nr   )clsvs     p/home/jay/workspace/scripts/.codegraph-venv/lib/python3.12/site-packages/fastmcp/server/auth/providers/github.py_parse_scopesz$GitHubProviderSettings._parse_scopes;   s     A    )__name__
__module____qualname____doc__r	   r   model_configr   __annotations__r   r   r   r   r    r!   r"   r#   r   classmethodr*    r+   r)   r   r   (   s    -%0L !Iz &*M#*(,H%,*.J'. $M:$(,O%,"&OZ&59 "29"&OZ&&X6  7r+   r   c                  :     e Zd ZdZddd	 	 	 d fdZddZ xZS )	GitHubTokenVerifierzToken verifier for GitHub OAuth tokens.

    GitHub OAuth tokens are opaque (not JWTs), so we verify them
    by calling GitHub's API to check if they're valid and get user info.
    N
   r    r!   c               4    t         |   |       || _        y)zInitialize the GitHub token verifier.

        Args:
            required_scopes: Required OAuth scopes (e.g., ['user:email'])
            timeout_seconds: HTTP request timeout
        )r    N)super__init__r!   )selfr    r!   	__class__s      r)   r:   zGitHubTokenVerifier.__init__H   s     	9.r+   c                n  K   	 t        j                  | j                        4 d{   }|j                  dd| ddd       d{   }|j                  d	k7  r@t
        j                  d
|j                  |j                  dd	        	 ddd      d{    y|j                         }|j                  dd| ddd       d{   }|j                  j                  dd      }|j                  d      D cg c]"  }|j                         r|j                         $ }}|sdg}| j                  rlt        |      }	t        | j                        }
|
j                  |	      s;t
        j                  dt        |	      t        |
             	 ddd      d{    yt!        |t#        |j                  dd            |dt#        |d         |j                  d      |j                  d      |j                  d      |j                  d      |d      cddd      d{    S 7 7 7 7 lc c}w 7 7 # 1 d{  7  sw Y   yxY w# t         j$                  $ r }t
        j                  d|       Y d}~yd}~wt&        $ r }t
        j                  d|       Y d}~yd}~ww xY ww)z0Verify GitHub OAuth token by calling GitHub API.)timeoutNzhttps://api.github.com/userzBearer zapplication/vnd.github.v3+jsonzFastMCP-GitHub-OAuth)AuthorizationAcceptz
User-Agent)headers   z)GitHub token verification failed: %d - %sz!https://api.github.com/user/reposzx-oauth-scopes ,userz6GitHub token missing required scopes. Has %d, needs %didunknownloginnameemail
avatar_url)subrH   rI   rJ   rK   github_user_data)tokenr   scopes
expires_atclaimsz!Failed to verify GitHub token: %sz#GitHub token verification error: %s)httpxAsyncClientr!   getstatus_codeloggerdebugtextjsonrA   splitstripr    setissubsetlenr   strRequestError	Exception)r;   rN   clientresponse	user_datascopes_responseoauth_scopes_headerscopetoken_scopestoken_scopes_setrequired_scopes_setes               r)   verify_tokenz GitHubTokenVerifier.verify_tokenW   s    N	((1E1EF F F&!'1+25'):"B&< ", "  ''3.LLC ,, ds+
  #F F F& %MMO	 )/

7+25'):"B&< )3 ) # '6&=&=&A&ABRTV&W# "5!:!:3!? {{} KKM    $$*8L '''*<'8$*-d.B.B*C'.778HIT 01 34
  $mF F Fr #!)--i"@A'#"9T?3!*w!7 )f 5!*w!7&/mmL&A,5sF F FF.# EF F F F FP !! 	LL<a@ 	LL>B	s  J5$I H.I I
H1AII H4I J5-IH73I?'H:&A.II H? I $J5%A7II (I)I -J5.I 1I4I 7I:I?I I I	I
II J5I J2+JJ5J2J-(J5-J22J5)r    r   r!   int)rN   r_   returnzAccessToken | None)r,   r-   r.   r/   r:   rl   __classcell__r<   s   @r)   r5   r5   A   s/     -1!	/ */ 	/Pr+   r5   c                  h     e Zd ZdZeeeeeeeededd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fdZ xZS )GitHubProvidera  Complete GitHub OAuth provider for FastMCP.

    This provider makes it trivial to add GitHub OAuth protection to any
    FastMCP server. Just provide your GitHub OAuth app credentials and
    a base URL, and you're ready to go.

    Features:
    - Transparent OAuth proxy to GitHub
    - Automatic token validation via GitHub API
    - User information extraction
    - Minimal configuration required

    Example:
        ```python
        from fastmcp import FastMCP
        from fastmcp.server.auth.providers.github import GitHubProvider

        auth = GitHubProvider(
            client_id="Ov23li...",
            client_secret="abc123...",
            base_url="https://my-server.com"
        )

        mcp = FastMCP("My App", auth=auth)
        ```
    NT)r   r   r   r   r   r    r!   r"   client_storager#   require_authorization_consentc                  t         j                  |||||||||
d	j                         D ci c]  \  }}|t        ur|| c}}      }|j                  st        d      |j                  st        d      |j                  xs d}|j                  xs dg}|j                  }t        ||      }|j                  r|j                  j                         nd}t        | 5  dd	|j                  |||j                  |j                  |j                   xs |j                  ||	|j"                  |
       t$        j'                  d|j                  |       yc c}}w )a|  Initialize GitHub OAuth provider.

        Args:
            client_id: GitHub OAuth app client ID (e.g., "Ov23li...")
            client_secret: GitHub OAuth app client secret
            base_url: Public URL where OAuth endpoints will be accessible (includes any mount path)
            issuer_url: Issuer URL for OAuth metadata (defaults to base_url). Use root-level URL
                to avoid 404s during discovery when mounting under a path.
            redirect_path: Redirect path configured in GitHub OAuth app (defaults to "/auth/callback")
            required_scopes: Required GitHub scopes (defaults to ["user"])
            timeout_seconds: HTTP request timeout for GitHub API calls
            allowed_client_redirect_uris: List of allowed redirect URI patterns for MCP clients.
                If None (default), all URIs are allowed. If empty list, no URIs are allowed.
            client_storage: Storage backend for OAuth state (client registrations, encrypted tokens).
                If None, a DiskStore will be created in the data directory (derived from `platformdirs`). The
                disk store will be encrypted using a key derived from the JWT Signing Key.
            jwt_signing_key: Secret for signing FastMCP JWT tokens (any string or bytes). If bytes are provided,
                they will be used as is. If a string is provided, it will be derived into a 32-byte key. If not
                provided, the upstream client secret will be used to derive a 32-byte key using PBKDF2.
            require_authorization_consent: Whether to require user consent before authorizing clients (default True).
                When True, users see a consent screen before being redirected to GitHub.
                When False, authorization proceeds directly without user confirmation.
                SECURITY WARNING: Only disable for local development or testing environments.
        )	r   r   r   r   r   r    r!   r"   r#   zQclient_id is required - set via parameter or FASTMCP_SERVER_AUTH_GITHUB_CLIENT_IDzYclient_secret is required - set via parameter or FASTMCP_SERVER_AUTH_GITHUB_CLIENT_SECRETr6   rE   r7   rC   z(https://github.com/login/oauth/authorizez+https://github.com/login/oauth/access_token)upstream_authorization_endpointupstream_token_endpointupstream_client_idupstream_client_secrettoken_verifierr   r   r   r"   rs   r#   rt   z?Initialized GitHub OAuth provider for client %s with scopes: %sN)r   model_validateitemsr   r   
ValueErrorr   r!   r    r"   r5   get_secret_valuer9   r:   r   r   r   r#   rV   rW   )r;   r   r   r   r   r   r    r!   r"   rs   r#   rt   kr(   settingstimeout_seconds_finalrequired_scopes_final"allowed_client_redirect_uris_finalrz   client_secret_strr<   s                       r)   r:   zGitHubProvider.__init__   s   P *88 "+%2 (",%2'6'64P'6
 %'Aq F? 1
& !!c  %%k  !) 8 8 >B ( 8 8 DVH-5-R-R* -11
 :B9O9OH""335UW 	
 	,V$Q'11#4)&&"00** !  )K)$44*G 	 	
  	M!	
{s   E
)r   str | NotSetTr   r   r   AnyHttpUrl | str | NotSetTr   r   r   r   r    list[str] | NotSetTr!   zint | NotSetTr"   r   rs   zAsyncKeyValue | Noner#   zstr | bytes | NotSetTrt   bool)r,   r-   r.   r/   r   r:   ro   rp   s   @r)   rr   rr      s    < $*'-/517'-/5)/<B/317.2j
 !j
 %	j

 -j
 /j
 %j
 -j
 'j
 ':j
 -j
 /j
 (,j
 j
r+   rr   )!r/   
__future__r   rR   key_value.aio.protocolsr   pydanticr   r   r   pydantic_settingsr   r	   fastmcp.server.authr
   fastmcp.server.auth.authr   fastmcp.server.auth.oauth_proxyr   fastmcp.settingsr   fastmcp.utilities.authr   fastmcp.utilities.loggingr   fastmcp.utilities.typesr   r   r,   rV   r   r5   rr   r3   r+   r)   <module>r      sf   * #  1 ; ; > - 0 6 % / 0 3	H	\ 2f- fRF
Z F
r+   