o
    ia-                     @  s   d Z ddlmZ ddl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mZmZmZ erFddlmZ eeZ			ddddZG dd deZdS )a   Enhanced authorization handler with improved error responses.

This module provides an enhanced authorization handler that wraps the MCP SDK's
AuthorizationHandler to provide better error messages when clients attempt to
authorize with unregistered client IDs.

The enhancement adds:
- Content negotiation: HTML for browsers, JSON for API clients
- Enhanced JSON responses with registration endpoint hints
- Styled HTML error pages with registration links/forms
- Link headers pointing to registration endpoints
    )annotationsN)TYPE_CHECKING)AuthorizationHandler)
AnyHttpUrl)Request)Response)
get_logger)INFO_BOX_STYLESTOOLTIP_STYLEScreate_logocreate_pagecreate_secure_html_response) OAuthAuthorizationServerProviderClient Not Registered	client_idstrregistration_endpointdiscovery_endpointserver_name
str | Noneserver_icon_urltitlereturnc                 C  sp   ddl }|| }d| d}d}	d}
dt||pdd	 d
| d| d|	 d|
 d}tt d }t|||dS )a  Create styled HTML error page for unregistered client attempts.

    Args:
        client_id: The unregistered client ID that was provided
        registration_endpoint: URL of the registration endpoint
        discovery_endpoint: URL of the OAuth metadata discovery endpoint
        server_name: Optional server name for branding
        server_icon_url: Optional server icon URL
        title: Page title

    Returns:
        HTML string for the error page
    r   NzI
        <div class="info-box error">
            <p>The client ID <code>zN</code> was not found in the server's client registry.</p>
        </div>
    a  
        <div class="info-box warning">
            <p>Your MCP client opened this page to complete OAuth authorization,
            but the server did not recognize its client ID. To fix this:</p>
            <ul>
                <li>Close this browser window</li>
                <li>Clear authentication tokens in your MCP client (or restart it)</li>
                <li>Try connecting again - your client should automatically re-register</li>
            </ul>
        </div>
    a  
        <div class="help-link-container">
            <span class="help-link">
                Why am I seeing this?
                <span class="tooltip">
                    OAuth 2.0 requires clients to register before authorization.
                    This server returned a 400 error because the provided client
                    ID was not found.
                    <br><br>
                    In browser-delegated OAuth flows, your application cannot
                    detect this error automatically; it's waiting for a
                    callback that will never arrive. You must manually clear
                    auth tokens and reconnect.
                </span>
            </span>
        </div>
    z-
        <div class="container">
            FastMCP)icon_urlalt_textz
            <h1>z</h1>
            z
            z
        </div>
        z
    aU  
        /* Error variant for info-box */
        .info-box.error {
            background: #fef2f2;
            border-color: #f87171;
        }
        .info-box.error strong {
            color: #991b1b;
        }
        /* Warning variant for info-box (yellow) */
        .info-box.warning {
            background: #fffbeb;
            border-color: #fbbf24;
        }
        .info-box.warning strong {
            color: #92400e;
        }
        .info-box code {
            background: rgba(0, 0, 0, 0.05);
            padding: 2px 6px;
            border-radius: 3px;
            font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
            font-size: 0.9em;
        }
        .info-box ul {
            margin: 10px 0;
            padding-left: 20px;
        }
        .info-box li {
            margin: 6px 0;
        }
        )contentr   additional_styles)htmlescaper   r	   r
   r   )r   r   r   r   r   r   html_moduleclient_id_escaped	error_boxwarning_box	help_linkr   r    r%   l/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/fastmcp/server/auth/handlers/authorize.pycreate_unregistered_client_html)   s:   
%r'   c                      s@   e Zd ZdZ		dd fd
dZd fddZdddZ  ZS )r   a;  Authorization handler with enhanced error responses for unregistered clients.

    This handler extends the MCP SDK's AuthorizationHandler to provide better UX
    when clients attempt to authorize without being registered. It implements
    content negotiation to return:

    - HTML error pages for browser requests
    - Enhanced JSON with registration hints for API clients
    - Link headers pointing to registration endpoints

    This maintains OAuth 2.1 compliance (returns 400 for invalid client_id)
    while providing actionable guidance to fix the error.
    Nproviderr   base_urlAnyHttpUrl | strr   r   r   c                   s,   t  | t|d| _|| _|| _dS )aJ  Initialize the enhanced authorization handler.

        Args:
            provider: OAuth authorization server provider
            base_url: Base URL of the server for constructing endpoint URLs
            server_name: Optional server name for branding
            server_icon_url: Optional server icon URL for branding
        /N)super__init__r   rstrip	_base_url_server_name_server_icon_url)selfr(   r)   r   r   	__class__r%   r&   r-      s   
zAuthorizationHandler.__init__requestr   r   r   c                   s   t  |I dH }|jdkrrd}|jdkr|jd}n| I dH }|d}t|tr0|}|rrz5t	|dr_t
t|j}|ddkrbd|d	d
 v re| |||dI dH W S W |S W |S W |S  tyq   Y |S w |S )a  Handle authorization request with enhanced error responses.

        This method extends the SDK's authorization handler and intercepts
        errors for unregistered clients to provide better error responses
        based on the client's Accept header.

        Args:
            request: The authorization request

        Returns:
            Response (redirect on success, error response on failure)
        N  GETr   bodyerrorinvalid_requestz	not founderror_description state)r,   handlestatus_codemethodquery_paramsgetform
isinstancer   hasattrjsonloadsbytesr8   lower_create_enhanced_error_response	Exception)r2   r5   responser   rC   client_id_valuer8   r3   r%   r&   r>      s<   





	zAuthorizationHandler.handler   r   r=   c                   s4  | j  d}| j  d}ddlm} t|jjdd}t||r0|j}|j}	|	r-|	d j	nd}
n| j
}| j}
|jdd}d	|v rQt|||||
d
}t|dd}n.ddlm} |dd| d|d}|jdd}||d< ||d< ddlm} |d|ddid}d| d|jd< td|d	|v rd |S d |S ) a5  Create enhanced error response with content negotiation.

        Args:
            request: The original request
            client_id: The unregistered client ID
            state: The state parameter from the request

        Returns:
            HTML or JSON error response based on Accept header
        z	/registerz'/.well-known/oauth-authorization-serverr   )r   fastmcp_serverNacceptr<   z	text/html)r   r   r   r   r   r6   )r?   )AuthorizationErrorResponser:   zClient ID 'z' is not registered with this server. MCP clients should automatically re-register by sending a POST request to the registration_endpoint and retry authorization. If this persists, clear cached authentication tokens and reconnect.)r9   r;   r=   T)exclude_noner   authorization_server_metadata)JSONResponsezCache-Controlzno-store)r?   r   headers<z0>; rel="http://oauth.net/core/2.1/#registration"Linkz5Unregistered client_id=%s, returned %s error responseHTMLJSON)r/   fastmcp.server.serverr   getattrappr=   rD   nameiconssrcr0   r1   rT   rB   r'   r   "mcp.server.auth.handlers.authorizerP   
model_dumpstarlette.responsesrS   loggerinfo)r2   r5   r   r=   r   r   r   fastmcpr   r]   r   rO   r   rL   rP   
error_data
error_dictrS   r%   r%   r&   rJ      s^   



z4AuthorizationHandler._create_enhanced_error_response)NN)r(   r   r)   r*   r   r   r   r   )r5   r   r   r   )r5   r   r   r   r=   r   r   r   )__name__
__module____qualname____doc__r-   r>   rJ   __classcell__r%   r%   r3   r&   r      s    1r   )NNr   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rj   
__future__r   rF   typingr   r_   r   SDKAuthorizationHandlerpydanticr   starlette.requestsr   ra   r   fastmcp.utilities.loggingr   fastmcp.utilities.uir	   r
   r   r   r   mcp.server.auth.providerr   rg   rb   r'   r%   r%   r%   r&   <module>   s$    x