
    ib              
         S SK Jr  S SKrS SKrS SKJrJr  S SKJrJ	r	  \R                  " S\	R                  S9r\R                  " S\	R                  S9r " S S	5      r\R                  " S
SS9r " S S\R"                  \   5      r\R                  " SSS9r " S S\R(                  \   5      r\R                  " SSS9r\R                  " SSS9r\R                  " SSS9r\R                  " SSS9r\R                  " SSS9r " S S\R(                  \\\\\4   5      r " S S\\	R8                  \	R:                  \	R<                  \	R>                  \	R@                  4   5      r! " S S\\	RD                  \	RF                  \	RH                  \	RJ                  \	RL                  4   5      r' " S S\\	RP                  \	RR                  \	RT                  \	RV                  \	RX                  4   5      r- " S  S!5      r.\R                  " S"\\/\0\Rb                  4      S9r2 " S# S$5      r3          S)S% jr4S*S& jr5    S+S' jr6/ S(Qr7g),    )annotationsN)CallableSequence)
exceptionstypesTH)boundAHc                  <    \ rS rSrSrSr\r \r SS jrS	S jr	Sr
g)
Auth   a
  Add custom authentication and authorization management to your LangGraph application.

The Auth class provides a unified system for handling authentication and
authorization in LangGraph applications. It supports custom user authentication
protocols and fine-grained authorization rules for different resources and
actions.

To use, create a separate python file and add the path to the file to your
LangGraph API configuration file (`langgraph.json`). Within that file, create
an instance of the Auth class and register authentication and authorization
handlers as needed.

Example `langgraph.json` file:

```json
{
  "dependencies": ["."],
  "graphs": {
    "agent": "./my_agent/agent.py:graph"
  },
  "env": ".env",
  "auth": {
    "path": "./auth.py:my_auth"
  }
```

Then the LangGraph server will load your auth file and run it server-side whenever a request comes in.

???+ example "Basic Usage"
    ```python
    from langgraph_sdk import Auth

    my_auth = Auth()

    async def verify_token(token: str) -> str:
        # Verify token and return user_id
        # This would typically be a call to your auth server
        return "user_id"

    @auth.authenticate
    async def authenticate(authorization: str) -> str:
        # Verify token and return user_id
        result = await verify_token(authorization)
        if result != "user_id":
            raise Auth.exceptions.HTTPException(
                status_code=401, detail="Unauthorized"
            )
        return result

    # Global fallback handler
    @auth.on
    async def authorize_default(params: Auth.on.value):
        return False # Reject all requests (default behavior)

    @auth.on.threads.create
    async def authorize_thread_create(params: Auth.on.threads.create.value):
        # Allow the allowed user to create a thread
        assert params.get("metadata", {}).get("owner") == "allowed_user"

    @auth.on.store
    async def authorize_store(ctx: Auth.types.AuthContext, value: Auth.types.on):
        assert ctx.user.identity in value["namespace"], "Not authorized"
    ```

???+ note "Request Processing Flow"
    1. Authentication (your `@auth.authenticate` handler) is performed first on **every request**
    2. For authorization, the most specific matching handler is called:
        * If a handler exists for the exact resource and action, it is used (e.g., `@auth.on.threads.create`)
        * Otherwise, if a handler exists for the resource with any action, it is used (e.g., `@auth.on.threads`)
        * Finally, if no specific handlers match, the global handler is used (e.g., `@auth.on`)
        * If no global handler is set, the request is accepted

    This allows you to set default behavior with a global handler while
    overriding specific routes as needed.
)on	_handlers_global_handlers_authenticate_handler_handler_cachec                ^    [        U 5      U l         0 U l        / U l        S U l        0 U l        g N)_Onr   r   r   r   r   )selfs    U/home/james-whalen/.local/lib/python3.13/site-packages/langgraph_sdk/auth/__init__.py__init__Auth.__init__n   s6    d)=	@ FH57AE"DF    c                B    U R                   b  [        S5      eXl         U$ )a6	  Register an authentication handler function.

The authentication handler is responsible for verifying credentials
and returning user scopes. It can accept any of the following parameters
by name:

    - request (Request): The raw ASGI request object
    - body (dict): The parsed request body
    - path (str): The request path, e.g., "/threads/abcd-1234-abcd-1234/runs/abcd-1234-abcd-1234/stream"
    - method (str): The HTTP method, e.g., "GET"
    - path_params (dict[str, str]): URL path parameters, e.g., {"thread_id": "abcd-1234-abcd-1234", "run_id": "abcd-1234-abcd-1234"}
    - query_params (dict[str, str]): URL query parameters, e.g., {"stream": "true"}
    - headers (dict[bytes, bytes]): Request headers
    - authorization (str | None): The Authorization header value (e.g., "Bearer <token>")

Args:
    fn: The authentication handler function to register.
        Must return a representation of the user. This could be a:
            - string (the user id)
            - dict containing {"identity": str, "permissions": list[str]}
            - or an object with identity and permissions properties
        Permissions can be optionally used by your handlers downstream.

Returns:
    The registered handler function.

Raises:
    ValueError: If an authentication handler is already registered.

???+ example "Examples"
    Basic token authentication:
    ```python
    @auth.authenticate
    async def authenticate(authorization: str) -> str:
        user_id = verify_token(authorization)
        return user_id
    ```

    Accept the full request context:
    ```python
    @auth.authenticate
    async def authenticate(
        method: str,
        path: str,
        headers: dict[str, bytes]
    ) -> str:
        user = await verify_request(method, path, headers)
        return user
    ```

    Return user name and permissions:
    ```python
    @auth.authenticate
    async def authenticate(
        method: str,
        path: str,
        headers: dict[str, bytes]
    ) -> Auth.types.MinimalUserDict:
        permissions, user = await verify_request(method, path, headers)
        # Permissions could be things like ["runs:read", "runs:write", "threads:read", "threads:write"]
        return {
            "identity": user["id"],
            "permissions": permissions,
            "display_name": user["name"],
        }
    ```
zCAuthentication handler already set as {self._authenticate_handler}.)r   
ValueErrorr   fns     r   authenticateAuth.authenticate   s.    H %%1U  &("	r   )r   r   r   r   r   N)returnNone)r   r
   r!   r
   )__name__
__module____qualname____firstlineno____doc__	__slots__r   r   r   r   __static_attributes__ r   r   r   r      s6    JXI E0
 JEGNIr   r   VT)contravariantc                  *    \ rS rSr      SS jrSrg)_ActionHandleri  c                  #    g 7fr   r*   )r   ctxvalues      r   __call___ActionHandler.__call__  s     !s   r*   N)r0   ztypes.AuthContextr1   r+   r!   ztypes.HandlerResult)r#   r$   r%   r&   r2   r)   r*   r   r   r.   r.     s    "'"01"	"r   r.   T)	covariantc                  <    \ rS rSr          SS jrSS jrSrg)_ResourceActionOni  c                4    Xl         X l        X0l        X@l        g r   )authresourceactionr1   )r   r9   r:   r;   r1   s        r   r   _ResourceActionOn.__init__  s     	 
r   c                t    [        U5        [        U R                  U R                  U R                  U5        U$ r   )_validate_handler_register_handlerr9   r:   r;   r   s     r   r2   _ResourceActionOn.__call__  s)    "$))T]]DKKD	r   )r;   r9   r:   r1   N)
r9   r   r:   0typing.Literal['threads', 'crons', 'assistants']r;   zLtyping.Literal['create', 'read', 'update', 'delete', 'search', 'create_run']r1   ztype[T]r!   r"   )r   _ActionHandler[T]r!   rB   )r#   r$   r%   r&   r   r2   r)   r*   r   r   r7   r7     s=     C
	  
r   r7   VCreateVUpdateVReadVDeleteVSearchc                      \ rS rSr% SrS\S'   S\S'   S\S'   S	\S
'   S\S'   S\S'         SS jr\R                      SS j5       r	\R                  SS.     SS jj5       r	 SSSS.       SS jjjr	Sr
g)_ResourceOni+  z4
Generic base class for resource-specific handlers.
z3type[VCreate | VUpdate | VRead | VDelete | VSearch]r1   ztype[VCreate]Createztype[VRead]Readztype[VUpdate]Updateztype[VDelete]Deleteztype[VSearch]Searchc                4   Xl         X l        [        XSU R                  5      U l        [        XSU R
                  5      U l        [        XSU R                  5      U l        [        XSU R                  5      U l
        [        XSU R                  5      U l        g )Ncreatereadupdatedeletesearch)r9   r:   r7   rJ   rP   rK   rQ   rL   rR   rM   rS   rN   rT   )r   r9   r:   s      r   r   _ResourceOn.__init__8  s    
 	 2CHdkk3
 /@FDII/
	 3DHdkk3
 3DHdkk3
 3DHdkk3
r   c                    g r   r*   r   s     r   r2   _ResourceOn.__call__O  s	     ILr   Nactionsc                   g r   r*   r   	resourcesrY   s      r   r2   rW   X  s     r   r\   rY   c          	       ^  Ubs  [        U5        [        R                  " [        [        R                  [
        [        [        [        [        4      [        T R                  T R                  SU5      5      $     SU 4S jjnX#4nU$ )N*c           	        > [        U 5        [        R                  " [        [        R                  [
        [        [        [        [        4      [        TR                  TR                  SU 5      5      $ Nr_   r>   typingcastr.   UnionrC   rD   rE   rF   rG   r?   r9   r:   )handlerr   s    r   	decorator'_ResourceOn.__call__.<locals>.decorator{  sP     g&;;v||GWeWg,UVW!$))T]]CI r   )rf   =_ActionHandler[VCreate | VUpdate | VRead | VDelete | VSearch]r!   ri   rb   )r   r   r\   rY   rg   _s   `     r   r2   rW   c  sz    " >b!;;v||GWeWg,UVW!$))T]]CD 
	R	J	 r   )r9   rP   rS   rQ   r:   rT   rR   r9   r   r:   rA   r!   r"   )r   ze_ActionHandler[VCreate | VUpdate | VRead | VDelete | VSearch] | _ActionHandler[dict[str, typing.Any]]r!   ri   )r\   str | Sequence[str]rY   str | Sequence[str] | Noner!   zCallable[[_ActionHandler[VCreate | VUpdate | VRead | VDelete | VSearch]], _ActionHandler[VCreate | VUpdate | VRead | VDelete | VSearch]]r   )r   zl_ActionHandler[VCreate | VUpdate | VRead | VDelete | VSearch] | _ActionHandler[dict[str, typing.Any]] | Noner\   rm   rY   rm   r!   z_ActionHandler[VCreate | VUpdate | VRead | VDelete | VSearch] | Callable[[_ActionHandler[VCreate | VUpdate | VRead | VDelete | VSearch]], _ActionHandler[VCreate | VUpdate | VRead | VDelete | VSearch]])r#   r$   r%   r&   r'   __annotations__r   rc   overloadr2   r)   r*   r   r   rI   rI   +  s     ?>


 C
 
	
. __L4L 
GL L __
 /3	 ' ,	

   # 15.2## .# ,#	
# #r   rI   c                     \ rS rSr\R
                  \R                  \R                  \R                  \R                  \R                  4   r\R                  r\R                  r\R                  r\R                  r\R                  rSrg)_AssistantsOni  r*   N)r#   r$   r%   r&   rc   re   r   AssistantsCreateAssistantsReadAssistantsUpdateAssistantsDeleteAssistantsSearchr1   rJ   rK   rL   rM   rN   r)   r*   r   r   rq   rq     s}     LL		 E ##FD##F##F##Fr   rq   c                    ^  \ rS rSr\R
                  \\R                     \\R                     \\R                     \\R                     \\R                     \\R                     4   r\R                  r\R                  r\R                  r\R                  r\R                  r\R                  r      SU 4S jjrSrU =r$ )
_ThreadsOni  c                \   > [         TU ]  X5        [        XSU R                  5      U l        g )N
create_run)superr   r7   	CreateRunrz   )r   r9   r:   	__class__s      r   r   _ThreadsOn.__init__  s*    
 	(?PL$..@
r   )rz   rk   )r#   r$   r%   r&   rc   re   typer   ThreadsCreateThreadsReadThreadsUpdateThreadsDeleteThreadsSearch
RunsCreater1   rJ   rK   rL   rM   rN   r|   r   r)   __classcell__)r}   s   @r   rx   rx     s     LLU  !UU  !U  !U  !U	 E   FD  F  F  F  I

 C
 
	
 
r   rx   c                     \ rS rSr\\R                  \R                  \R                  \R                  \R                  \R                  4      r\R                  r\R                  r\R                  r\R                  r\R                  rSrg)_CronsOni  r*   N)r#   r$   r%   r&   r   rc   re   r   CronsCreate	CronsReadCronsUpdateCronsDeleteCronsSearchr1   rJ   rK   rL   rM   rN   r)   r*   r   r   r   r     s     OO		
E F??DFFFr   r   c                      \ rS rSrS	S jr\R                  SS.   S
S jj5       r\R                  SS j5       r SSS.     SS jjjrSrg)_StoreOni  c                    Xl         g r   _authr   r9   s     r   r   _StoreOn.__init__  s    
r   NrX   c                   g r   r*   )r   rY   s     r   r2   _StoreOn.__call__  s      #r   c                    g r   r*   r   s     r   r2   r         (+r   c               ^   ^ ^ Ub  [        T R                  SSU5        U$     SUU 4S jjnU$ )au  Register a handler for specific resources and actions.

Can be used as a decorator or with explicit resource/action parameters:

@auth.on.store
async def handler(): ... # Handle all store ops

@auth.on.store(actions=("put", "get", "search", "delete"))
async def handler(): ... # Handle specific store ops

@auth.on.store.put
async def handler(): ... # Handle store.put ops
Nstorec                   > [        T[        5      (       a  T/nOTb  [        T5      OS/nU H  n[        TR                  SX 5        M     U $ )Nr_   r   
isinstancestrlistr?   r   )rf   action_listr;   rY   r   s      r   rg   $_StoreOn.__call__.<locals>.decorator  sJ     '3''&i/6/Bd7m%!$**gvG &Nr   rf   AHOr!   r   r?   r   )r   r   rY   rg   s   ` ` r   r2   r     sC    2 >djj'4<I						 		 r   r   r9   r   r!   r"   )rY   typing.Literal['put', 'get', 'search', 'list_namespaces', 'delete'] | Sequence[typing.Literal['put', 'get', 'search', 'list_namespaces', 'delete']] | Noner!   Callable[[AHO], AHO]r   r   r!   r   r   )r   
AHO | NonerY   r   r!   AHO | Callable[[AHO], AHO])	r#   r$   r%   r&   r   rc   ro   r2   r)   r*   r   r   r   r     s     __ 
#	
# 

# 
# __+ + * **
* 
$* *r   r   r   c                      \ rS rSrSrSrSS jr\R                  SS.     SS jj5       r	\R                  SS j5       r	 SSSS	.       SS
 jjjr	Sr
g)r   i!  am  Entry point for authorization handlers that control access to specific resources.

The _On class provides a flexible way to define authorization rules for different resources
and actions in your application. It supports three main usage patterns:

1. Global handlers that run for all resources and actions
2. Resource-specific handlers that run for all actions on a resource
3. Resource and action specific handlers for fine-grained control

Each handler must be an async function that accepts two parameters:
- ctx (AuthContext): Contains request context and authenticated user info
- value: The data being authorized (type varies by endpoint)

The handler should return one of:
    - None or True: Accept the request
    - False: Reject with 403 error
    - FilterType: Apply filtering rules to the response

???+ example "Examples"

    Global handler for all requests:
    ```python
    @auth.on
    async def log_all_requests(ctx: AuthContext, value: Any) -> None:
        print(f"Request to {ctx.path} by {ctx.user.identity}")
        return True
    ```

    Resource-specific handler:
    ```python
    @auth.on.threads
    async def check_thread_access(ctx: AuthContext, value: Any) -> bool:
        # Allow access only to threads created by the user
        return value.get("created_by") == ctx.user.identity
    ```

    Resource and action specific handler:
    ```python
    @auth.on.threads.delete
    async def prevent_thread_deletion(ctx: AuthContext, value: Any) -> bool:
        # Only admins can delete threads
        return "admin" in ctx.user.permissions
    ```

    Multiple resources or actions:
    ```python
    @auth.on(resources=["threads", "runs"], actions=["create", "update"])
    async def rate_limit_writes(ctx: AuthContext, value: Any) -> bool:
        # Implement rate limiting for write operations
        return await check_rate_limit(ctx.user.identity)
    ```
)r   
assistantsthreadsrunscronsr   r1   c                    Xl         [        US5      U l        [        US5      U l        [        US5      U l        [        U5      U l        [        [        [        R                  4   U l        g )Nr   r   r   )r   rq   r   rx   r   r   r   r   r   dictr   rc   Anyr1   r   s     r   r   _On.__init__a  sP    
'l;!$	2dG,
d^
#vzz/*
r   NrX   c                   g r   r*   r[   s      r   r2   _On.__call__i  s      #r   c                    g r   r*   r   s     r   r2   r   q  r   r   r]   c               b   ^ ^^ Ub  [        T R                  SSU5        U$     SUUU 4S jjnU$ )a  Register a handler for specific resources and actions.

Can be used as a decorator or with explicit resource/action parameters:

@auth.on
async def handler(): ...  # Global handler

@auth.on(resources="threads")
async def handler(): ...  # types.Handler for all thread actions

@auth.on(resources="threads", actions="create")
async def handler(): ...  # types.Handler for thread creation
Nc                  > [        T[        5      (       a  T/nOTb  [        T5      OS/n[        T[        5      (       a  T/nOTb  [        T5      OS/nU H#  nU H  n[        TR                  X4U 5        M     M%     U $ ra   r   )rf   resource_listr   r:   r;   rY   r\   r   s        r   rg   _On.__call__.<locals>.decorator  s|     )S))!*3<3HYse'3''&i/6/Bd7m))F%djj(GL * * Nr   r   r   )r   r   r\   rY   rg   s   ` `` r   r2   r   t  sC    ( >djj$b9I			 	" r   )r   r   r   r   r   r1   r   )r\   rl   rY   rm   r!   r   r   r   )r   r   r\   rm   rY   rm   r!   r   )r#   r$   r%   r&   r'   r(   r   rc   ro   r2   r)   r*   r   r   r   r   !  s    3jI+ __
 /3	# '# ,	#
 
# # __+ + + 15.2++ .	+
 ,+ 
$+ +r   r   c                V   [        U5        U=(       d    SnU=(       d    SnUS:X  a?  US:X  a9  U R                  (       a  [        S5      eU R                  R                  U5        U$ Ub  UOSnUb  UOSnXE4U R                  ;   a  [        SU SU S35      eU/U R                  XE4'   U$ )Nr_   zGlobal handler already set.ztypes.Handler already set for z, .)r>   r   r   appendr   )r9   r:   r;   r   ras         r   r?   r?     s     b3H]sF36S=  :;;$$R( I !,H#(Fc6T^^#=aS1#QGHH"$vIr   c                B   [         R                  " U 5      (       d  [        S[        U SU 5       S35      e[         R                  " U 5      nSUR
                  ;  a  [        S[        U SU 5       S35      eSUR
                  ;  a  [        S[        U SU 5       S35      eg)	zValidates that an auth handler function meets the required signature.

Auth handlers must:
1. Be async functions
2. Accept a ctx parameter of type AuthContext
3. Accept a value parameter for the data being authorized
zAuth handler 'r#   z|' must be an async function. Add 'async' before 'def' to make it asynchronous and ensure any IO operations are non-blocking.r0   zm' must have a 'ctx: AuthContext' parameter. Update the function signature to include this required parameter.r1   z' must have a 'value' parameter.  The value contains the mutable data being sent to the endpoint.Update the function signature to include this required parameter.N)inspectiscoroutinefunctionr   getattr	signature
parameters)r   sigs     r   r>   r>     s     &&r**WRR89 :3 3
 	
 

B
CCNN"WRR89 :P P
 	
 cnn$WRR89 :P P
 	
 %r   c                    [        U [        R                  5      =(       d+    [        U [        5      =(       a    U R	                  S5      S:H  $ )Nkind
StudioUser)r   r   r   r   get)users    r   is_studio_userr     s>     	4))* 	-dD! -HHV,r   )r   r   r   )
r9   r   r:   
str | Noner;   r   r   types.Handlerr!   r   )r   zCallable[..., typing.Any]r!   r"   )r   z:types.MinimalUser | types.BaseUser | types.MinimalUserDictr!   bool)8
__future__r   r   rc   collections.abcr   r   langgraph_sdk.authr   r   TypeVarHandlerr   Authenticatorr
   r   r+   Protocolr.   r4   Genericr7   rC   rD   rE   rF   rG   rI   rr   rs   rt   ru   rv   rq   r   r   r   r   r   rx   r   r   r   r   r   r   r   r   r   r   r   r   r?   r>   r   __all__r*   r   r   <module>r      si   "   . 0^^D.^^D 3 34q ql NN3d+"V__Q' " NN3$'q) * ..d
3
..d
3w$/
..d
3
..d
3[&..%'7!JK [|$		 $. 
		 
F		4> >B nnU.c6::o1F"GH~ ~B
  		
 ,
:
D	 *r   