
    iT,                        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mZ ddlmZmZ ddlmZ dd	lmZmZmZ dd
lmZ ddlmZmZmZ ddlmZmZ  ej@                  e!      Z" G d de      Z#y)a  Authorization middleware for FastMCP.

This module provides middleware-based authorization using callable auth checks.
AuthMiddleware applies auth checks globally to all components on the server.

Example:
    ```python
    from fastmcp import FastMCP
    from fastmcp.server.auth import require_scopes, restrict_tag
    from fastmcp.server.middleware import AuthMiddleware

    # Require specific scope for all components
    mcp = FastMCP(middleware=[
        AuthMiddleware(auth=require_scopes("api"))
    ])

    # Tag-based: components tagged "admin" require "admin" scope
    mcp = FastMCP(middleware=[
        AuthMiddleware(auth=restrict_tag("admin", scopes=["admin"]))
    ])
    ```
    )annotationsN)Sequence)AuthorizationError)PromptPromptResult)ResourceResourceResult)ResourceTemplate)	AuthCheckAuthContextrun_auth_checks)get_access_token)CallNext
MiddlewareMiddlewareContext)Tool
ToolResultc                      e Zd ZdZddZ	 	 	 	 	 	 ddZ	 	 	 	 	 	 ddZ	 	 	 	 	 	 ddZ	 	 	 	 	 	 ddZ	 	 	 	 	 	 ddZ		 	 	 	 	 	 ddZ
	 	 	 	 	 	 dd	Zy
)AuthMiddlewarea  Global authorization middleware using callable checks.

    This middleware applies auth checks to all components (tools, resources,
    prompts) on the server. It uses the same callable API as component-level
    auth checks.

    The middleware:
    - Filters tools/resources/prompts from list responses based on auth checks
    - Checks auth before tool execution, resource read, and prompt render
    - Skips all auth checks for STDIO transport (no OAuth concept)

    Args:
        auth: A single auth check function or list of check functions.
            All checks must pass for authorization to succeed (AND logic).

    Example:
        ```python
        from fastmcp import FastMCP
        from fastmcp.server.auth import require_scopes

        # Require specific scope for all components
        mcp = FastMCP(middleware=[AuthMiddleware(auth=require_scopes("api"))])

        # Multiple scopes (AND logic)
        mcp = FastMCP(middleware=[
            AuthMiddleware(auth=require_scopes("read", "api"))
        ])
        ```
    c                    || _         y )N)auth)selfr   s     w/Users/bowang/.openclaw/workspace/ChatDev/.venv/lib/python3.12/site-packages/fastmcp/server/middleware/authorization.py__init__zAuthMiddleware.__init__R   s	    	    c                *  K    ||       d{   }ddl m} |j                         dk(  r|S t               }g }|D ]?  }t	        ||      }	 t        | j                  |       d{   r|j                  |       A |S 7 q7 # t        $ r Y Sw xY ww)z0Filter tools/list response based on auth checks.Nr   _current_transportstdiotoken	component	fastmcp.server.contextr   getr   r   r   r   appendr   )	r   context	call_nexttoolsr   r!   authorized_toolstoolctxs	            r   on_list_toolszAuthMiddleware.on_list_toolsU   s       (( 	>!!#w.L "')DET:C(C888$++D1	   ) ) 9% E   BB =BB&B'B<BB	BBBBc                  K   ddl m} |j                         dk(  r ||       d{   S |j                  j                  }|j
                  }|(t        j                  d| d       t        d| d      |j                  j                  |       d{   }|t        d| d	      t               }t        ||
      }t        | j                  |       d{   st        d| d       ||       d{   S 7 7 k7 '7 
w)z!Check auth before tool execution.r   r   r   Nz2AuthMiddleware: fastmcp_context is None for tool ''. Denying access for security.zAuthorization failed for tool '': missing contextz': tool not foundr    ': insufficient permissions)r$   r   r%   messagenamefastmcp_contextloggerwarningr   fastmcpget_toolr   r   r   r   )	r   r'   r(   r   	tool_namer8   r+   r!   r,   s	            r   on_call_toolzAuthMiddleware.on_call_toolq   s(     	>!!#w."7+++ OO((	))?NNDYK P/ / %1)<NO 
 __--i88<$1)<MN 
 !"6$TYY444$1)<WX  w'''= ,  9 5
 (G   %DD A.DDADDD;D<DDDDc                *  K    ||       d{   }ddl m} |j                         dk(  r|S t               }g }|D ]?  }t	        ||      }	 t        | j                  |       d{   r|j                  |       A |S 7 q7 # t        $ r Y Sw xY ww)z4Filter resources/list response based on auth checks.Nr   r   r   r    r#   )	r   r'   r(   	resourcesr   r!   authorized_resourcesresourcer,   s	            r   on_list_resourcesz AuthMiddleware.on_list_resources   s      $G,,	 	>!!#w. "/1!HEX>C(C888(//9	 " $#' - 9% r.   c                  K   ddl m} |j                         dk(  r ||       d{   S |j                  j                  }|j
                  }|(t        j                  d| d       t        d| d      |j                  j                  t        |             d{   }|,|j                  j                  t        |             d{   }|t        d| d	      t               }t        ||
      }t        | j                   |       d{   st        d| d       ||       d{   S 7 7 7 n7 *7 w)z Check auth before resource read.r   r   r   Nz6AuthMiddleware: fastmcp_context is None for resource 'r0   z#Authorization failed for resource 'r1   z': resource not foundr    r2   )r$   r   r%   r3   urir5   r6   r7   r   r8   get_resourcestrget_resource_templater   r   r   r   )	r   r'   r(   r   rC   r8   r"   r!   r,   s	            r   on_read_resourcezAuthMiddleware.on_read_resource   sS     	>!!#w."7+++ oo!!))?NNH N/ / %5cU:LM 
 "//66s3x@@	%ooCCCHMMI$5cU:OP 
 !";$TYY444$5cU:UV  w'''? , AM 5
 (sY   %ED7A7ED: -ED<AED>E2E 3E:E<E>E Ec                *  K    ||       d{   }ddl m} |j                         dk(  r|S t               }g }|D ]?  }t	        ||      }	 t        | j                  |       d{   r|j                  |       A |S 7 q7 # t        $ r Y Sw xY ww)z=Filter resource templates/list response based on auth checks.Nr   r   r   r    r#   )	r   r'   r(   	templatesr   r!   authorized_templatestemplater,   s	            r   on_list_resource_templatesz)AuthMiddleware.on_list_resource_templates   s      $G,,	 	>!!#w. "79!HEX>C(C888(//9	 " $#' - 9% r.   c                *  K    ||       d{   }ddl m} |j                         dk(  r|S t               }g }|D ]?  }t	        ||      }	 t        | j                  |       d{   r|j                  |       A |S 7 q7 # t        $ r Y Sw xY ww)z2Filter prompts/list response based on auth checks.Nr   r   r   r    r#   )	r   r'   r(   promptsr   r!   authorized_promptspromptr,   s	            r   on_list_promptszAuthMiddleware.on_list_prompts   s      "'** 	>!!#w.N "+-FEV<C(C888&--f5	  "!' + 9% r.   c                  K   ddl m} |j                         dk(  r ||       d{   S |j                  j                  }|j
                  }|(t        j                  d| d       t        d| d      |j                  j                  |       d{   }|t        d| d	      t               }t        ||
      }t        | j                  |       d{   st        d| d       ||       d{   S 7 7 k7 '7 
w)z Check auth before prompt render.r   r   r   Nz4AuthMiddleware: fastmcp_context is None for prompt 'r0   z!Authorization failed for prompt 'r1   z': prompt not foundr    r2   )r$   r   r%   r3   r4   r5   r6   r7   r   r8   
get_promptr   r   r   r   )	r   r'   r(   r   prompt_namer8   rP   r!   r,   s	            r   on_get_promptzAuthMiddleware.on_get_prompt  s(     	>!!#w."7+++ oo**))?NNF{m T/ / %3K=@RS 
 11+>>>$3K=@ST 
 !"8$TYY444$3K=@[\  w'''; , ? 5
 (r<   N)r   zAuthCheck | list[AuthCheck]returnNone)r'   z&MiddlewareContext[mt.ListToolsRequest]r(   z-CallNext[mt.ListToolsRequest, Sequence[Tool]]rV   zSequence[Tool])r'   z+MiddlewareContext[mt.CallToolRequestParams]r(   z.CallNext[mt.CallToolRequestParams, ToolResult]rV   r   )r'   z*MiddlewareContext[mt.ListResourcesRequest]r(   z5CallNext[mt.ListResourcesRequest, Sequence[Resource]]rV   zSequence[Resource])r'   z/MiddlewareContext[mt.ReadResourceRequestParams]r(   z6CallNext[mt.ReadResourceRequestParams, ResourceResult]rV   r	   )r'   z2MiddlewareContext[mt.ListResourceTemplatesRequest]r(   zECallNext[mt.ListResourceTemplatesRequest, Sequence[ResourceTemplate]]rV   zSequence[ResourceTemplate])r'   z(MiddlewareContext[mt.ListPromptsRequest]r(   z1CallNext[mt.ListPromptsRequest, Sequence[Prompt]]rV   zSequence[Prompt])r'   z,MiddlewareContext[mt.GetPromptRequestParams]r(   z1CallNext[mt.GetPromptRequestParams, PromptResult]rV   r   )__name__
__module____qualname____doc__r   r-   r;   rA   rG   rL   rQ   rU    r   r   r   r   3   s    < 7  A  
	 8)(<)( B)( 
	)(V$;$ I$ 
	$6)(@)( J)( 
	)(V$C$
$ 
$$:"9" E" 
	"6'(='( E'( 
	'(r   r   )$r[   
__future__r   loggingcollections.abcr   	mcp.typestypesmtfastmcp.exceptionsr   fastmcp.prompts.promptr   r   fastmcp.resources.resourcer   r	   fastmcp.resources.templater
   !fastmcp.server.auth.authorizationr   r   r   fastmcp.server.dependenciesr   $fastmcp.server.middleware.middlewarer   r   r   fastmcp.tools.toolr   r   	getLoggerrX   r6   r   r\   r   r   <module>rl      sb   . #  $  1 7 ? 7 
 9 
 0			8	$N(Z N(r   