
    hl                     `   d Z ddlZddlZddlZddlmZmZmZmZm	Z	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 ddlmZ ddlmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z- ddl.m/Z/ ddl0m1Z1m2Z2 ddl3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<  G d d      Z= G d d      Z>y)z
Supports using JWT's for authenticating into the proxy.

Currently only supports admin.

JWT token must have 'litellm_proxy_admin' in scope.
    N)AnyListLiteralOptionalSetTuplecast)x509)default_backend)serializationHTTPException)verbose_proxy_logger)	DualCache)get_nested_value)HTTPHandler)
RBAC_ROLESJWKKeyValueJWTAuthBuilderResult
JWTKeyItemLiteLLM_EndUserTableLiteLLM_JWTAuthLiteLLM_OrganizationTableLiteLLM_TeamTableLiteLLM_UserTableLitellmUserRolesMemberProxyErrorTypesProxyExceptionScopeMappingSpanTeamMemberAddRequestUserAPIKeyAuth)can_team_access_model)PrismaClientProxyLogging   )	_allowed_routes_checkallowed_routes_checkget_actual_routesget_end_user_objectget_org_objectget_role_based_modelsget_role_based_routesget_team_objectget_user_objectc                      e Zd ZU dZee   ed<   eed<   	 	 d*dZ	 d+dee   dede	de
ddf
d	Zed
efd       Zd
edee   fdZd
edee   fdZdedefdZd
edee   fdZd
edee   dee   fdZdefdZdefdZd
edee   dee   fdZd,dee   defdZd
edee   dee   fdZd
edeee      deee      fdZd
edee   fdZ d
edeee      deee      fdZ!deee      defdZ"d
edee   dee   fdZ#d
edee   dee   fdZ$d
edee   dee   fd Z%d
edee   fd!Z&d"ee   defd#Z'd$e(d"ee   dee)   fd%Z*d&edefd'Z+d
edefd(Z,d) Z-y)-
JWTHandlerz
    - treat the sub id passed in as the user id
    - return an error if id making request doesn't exist in proxy user table
    - track spend against the user id
    - if role="litellm_proxy_user" -> allow making calls + info. Can not edit budgets
    prisma_clientuser_api_key_cachereturnNc                 0    t               | _        d| _        y )Nr   )r   http_handlerleewayselfs    Y/var/www/Befach/backend/env/lib/python3.12/site-packages/litellm/proxy/auth/handle_jwt.py__init__zJWTHandler.__init__E   s     (M    litellm_jwtauthr8   c                 <    || _         || _        || _        || _        y N)r3   r4   r>   r8   )r:   r3   r4   r>   r8   s        r;   update_environmentzJWTHandler.update_environmentK   s#     +"4.r=   tokenc                 @    | j                  d      }t        |      dk(  S )N.   )splitlen)rB   partss     r;   is_jwtzJWTHandler.is_jwtW   s    C 5zQr=   c                     | j                   j                  y| j                  |d      }|syt        |      }| j                   j                  D ]  }|j                  |v s|j
                  c S  y)a  
        Returns the RBAC role the token 'belongs' to based on role mappings.

        Args:
            token (dict): The JWT token containing role information

        Returns:
            Optional[RBAC_ROLES]: The mapped internal RBAC role if a mapping exists,
                                None otherwise

        Note:
            The function handles both single string roles and lists of roles from the JWT.
            If multiple mappings match the JWT roles, the first matching mapping is returned.
        NrB   default_value)r>   role_mappingsget_jwt_rolesetroleinternal_role)r:   rB   jwt_rolejwt_role_setrole_mappings        r;   _rbac_role_from_role_mappingz'JWTHandler._rbac_role_from_role_mapping\   sr     --5$$5$E8} 00>>L  L0#111 ?
 r=   c                    | j                  |      }| j                  |      }| j                  |d      }|rt        j                  S | j                  |d      t        j                  S | j                  |d      t        j                  S |"| j                  |      rt        j                  S | j                  |      x}r|S y)a^  
        Returns the RBAC role the token 'belongs' to.

        RBAC roles allowed to make requests:
        - PROXY_ADMIN: can make requests to all routes
        - TEAM: can make requests to routes associated with a team
        - INTERNAL_USER: can make requests to routes associated with a user

        Resolves: https://github.com/BerriAI/litellm/issues/6793

        Returns:
        - PROXY_ADMIN: if token is admin
        - TEAM: if token is associated with a team
        - INTERNAL_USER: if token is associated with a user
        - None: if token is not associated with a team or user
        rB   scopesNrK   )
user_roles)
get_scopesis_adminget_user_rolesr   PROXY_ADMINget_team_idTEAMget_user_idINTERNAL_USERis_allowed_user_rolerU   )r:   rB   rY   r\   rZ   	rbac_roles         r;   get_rbac_rolezJWTHandler.get_rbac_role{   s    " u-===/((uD(I
#///E>J#(((E>J#111#(A(A! )B )
 $111;;%;HHYHr=   rY   c                 6    | j                   j                  |v ryy)NTF)r>   admin_jwt_scope)r:   rY   s     r;   r\   zJWTHandler.is_admin   s    //69r=   c                     | j                   j                  >|j                  | j                   j                        || j                   j                     S g S r@   )r>   team_ids_jwt_fieldget)r:   rB   s     r;   get_team_ids_from_jwtz JWTHandler.get_team_ids_from_jwt   sM      33?		$..AABN --@@AA	r=   rL   c                     	 | j                   j                  || j                   j                     }|S d }	 |S # t        $ r |}Y |S w xY wr@   )r>   end_user_id_jwt_fieldKeyErrorr:   rB   rL   user_ids       r;   get_end_user_idzJWTHandler.get_end_user_id   s_    	$##99E 4 4 J JK 	    	$#G	$   /8 8 AAc                 2    | j                   j                  yy)z`
        Returns:
        - True: if 'team_id_jwt_field' is set
        - False: if not
        FT)r>   team_id_jwt_fieldr9   s    r;   is_required_team_idzJWTHandler.is_required_team_id   s     119r=   c                 z    | j                   j                  %t        | j                   j                  t              ryy)z
        Returns:
        - True: if 'user_allowed_email_domain' is set
        - False: if 'user_allowed_email_domain' is None
        TF)r>   user_allowed_email_domain
isinstancestrr9   s    r;   is_enforced_email_domainz#JWTHandler.is_enforced_email_domain   s7     99E*  ::CK
 r=   c                     	 | j                   j                  || j                   j                     }|S | j                   j                  | j                   j                  }|S d }	 |S # t        $ r |}Y |S w xY wr@   )r>   rt   team_id_defaultrn   )r:   rB   rL   team_ids       r;   r_   zJWTHandler.get_team_id   s    	$##55A 4 4 F FG  %%55A..>>
     	$#G	$s   /A& ,A& !A& &A54A5valid_user_emailc                 8    |du ry| j                   j                  S )z
        Returns:
        - True: if 'user_id_upsert' is set AND valid_user_email is not False
        - False: if not
        F)r>   user_id_upsert)r:   r~   s     r;   is_upsert_user_idzJWTHandler.is_upsert_user_id   s!     u$##222r=   c                     	 | j                   j                  || j                   j                     }|S |}	 |S # t        $ r |}Y |S w xY wr@   )r>   user_id_jwt_fieldrn   ro   s       r;   ra   zJWTHandler.get_user_id   s_    	$##55A 4 4 F FG
  (   	$#G	$rr   c                     	 | j                   j                  $t        || j                   j                  |      }|S |}	 |S # t        $ r |}Y |S w xY w)zn
        Returns the user role from the token.

        Set via 'user_roles_jwt_field' in the config.
        datakey_pathdefault)r>   user_roles_jwt_fieldr   rn   r:   rB   rL   rZ   s       r;   r]   zJWTHandler.get_user_roles   sk    
	'##88D-!11FF)
  +
   	'&J	'   8A A AAc                    | j                   j                  sy| j                  |g       }|sy| j                   j                  D ]9  }|D ]2  }t        j                  ||j                        s$|j
                  c c S  ; y)z(Map roles from JWT to LiteLLM user rolesNrK   )r>   jwt_litellm_role_maprN   fnmatchrR   litellm_role)r:   rB   	jwt_rolesmappingrP   s        r;   map_jwt_role_to_litellm_rolez'JWTHandler.map_jwt_role_to_litellm_role  su    ##88%%E%D	++@@G!??4)9)9:"/// " A r=   c                     	 | j                   j                  $t        || j                   j                  |      }|S |}	 |S # t        $ r |}Y |S w xY w)z
        Generic implementation of `get_user_roles` that can be used for both user and team roles.

        Returns the jwt role from the token.

        Set via 'roles_jwt_field' in the config.
        r   )r>   roles_jwt_fieldr   rn   r   s       r;   rN   zJWTHandler.get_jwt_role  sk    
	'##33?-!11AA)
  +
   	'&J	'r   rZ   c                 `     |+ j                   j                  t         fd|D              ryy)zl
        Returns the user role from the token.

        Set via 'user_allowed_roles' in the config.
        c              3   N   K   | ]  }|j                   j                  v   y wr@   )r>   user_allowed_roles).0rP   r:   s     r;   	<genexpr>z2JWTHandler.is_allowed_user_role.<locals>.<genexpr>6  s'      DH,,???s   "%TF)r>   r   any)r:   rZ   s   ` r;   rc   zJWTHandler.is_allowed_user_role-  s:     "$$77C LV  r=   c                     	 | j                   j                  || j                   j                     }|S d }	 |S # t        $ r |}Y |S w xY wr@   )r>   user_email_jwt_fieldrn   )r:   rB   rL   
user_emails       r;   get_user_emailzJWTHandler.get_user_email=  sb    	'##88D"4#7#7#L#LM

  "
   	'&J	'rr   c                     	 | j                   j                  || j                   j                     }|S |}	 |S # t        $ r |}Y |S w xY wr@   )r>   object_id_jwt_fieldrn   )r:   rB   rL   	object_ids       r;   get_object_idzJWTHandler.get_object_idI  sb    	&##77C!$"6"6"J"JK	
  *	   	&%I	&rr   c                     	 | j                   j                  || j                   j                     }|S d }	 |S # t        $ r |}Y |S w xY wr@   )r>   org_id_jwt_fieldrn   )r:   rB   rL   org_ids       r;   
get_org_idzJWTHandler.get_org_idS  s_    	###44@t33DDE
     	#"F	#rr   c                     	 t        |d   t              r|d   j                         }|S t        |d   t              r|d   }|S t	        dt        |d          d      # t        $ r g }Y |S w xY w)NscopezUnmapped scope type - z. Supported types - list, str.)rx   ry   rF   list	Exceptiontypern   )r:   rB   rY   s      r;   r[   zJWTHandler.get_scopes]  s    	%.#.w--/  E'ND1w   ,T%.-A,BB`a   	F	s   &A A A A.-A.kidc                   K   t        j                  d      }|t        d      |j                  d      D cg c]  }|j	                          }}|D ]  }d| }| j
                  j                  |       d {   }|| j                  j                  |       d {   }|j                         }	d|	v r|j                         d   }
n|	}
| j
                  j                  ||
| j                  j                         d {    n|}
| j                  |
|      }|t        t        |      c S  t        d| d	|       c c}w 7 7 7 Jw)
NJWT_PUBLIC_KEY_URLz,Missing JWT Public Key URL from environment.,litellm_jwt_auth_keys_keys)keyvaluettl)r   r   z#No matching public key found. keys=z, kid=)osgetenvr   rF   stripr4   async_get_cacher7   rj   jsonasync_set_cacher>   public_key_ttl
parse_keysr	   dict)r:   r   keys_urlurlkeys_url_listkey_url	cache_keycached_keysresponseresponse_jsonr   
public_keys               r;   get_public_keyzJWTHandler.get_public_keyl  s[    9912JKK08s0CDDD$G0	:I $ 7 7 G G	 RRK"!%!2!2!6!6w!?? (]*(0(?D(D--==!,,;; >    #d<J%D*--1 %4 1-seL
 	
9 E
 S @sG   6EE*E9E	:$EEA#EEE *EEEr   c                    d }t        |      dk(  r\t        |t              r|j                  dd       |k(  s||}|S t        |t              r|d   j                  dd       |k(  s||d   }|S t        |      dkD  rK|D ]F  }t        |t              r|j                  dd       }nd }|+t        |t              s<|?||k(  sE|}H |S )Nr'   r   r   )rG   rx   r   rj   r   )r:   r   r   r   r   key_kids         r;   r   zJWTHandler.parse_keys  s    +/
t9>$%488E4+@C+G3;!
& % D$'QE4(C/3;!!W
  Y]c4(!ggeT2G"GO"3-+3!$J  r=   r   c                     | j                   j                  y|j                  d      d   }|| j                   j                  k(  ryy)NT@F)r>   rw   rF   )r:   r   email_domains      r;   is_allowed_domainzJWTHandler.is_allowed_domain  sF    99A!'',R04//IIIr=   c                   K   g d}t        j                  d      }d }|ddi}dd l}ddlm} |j                  |      }t        j                  d|       |j                  dd       }| j                  |	       d {   }	|	t        |	t              rzi }
d
|	v r|	d
   |
d
<   d|	v r|	d   |
d<   d|	v r|	d   |
d<   d|	v r|	d   |
d<   |j                  t        j                  |
            }	 |j                  |||||| j                         }|S |	t        |	t&              r	 t)        j*                  |	j-                         t/                     }|j1                         j3                  t4        j6                  j8                  t4        j:                  j<                        }|j                  |||||      }|S t%        d      7 C# |j"                  $ r t%        d      t$        $ r}t%        dt'        |             d }~ww xY w# |j"                  $ r t%        d      t$        $ r}t%        dt'        |             d }~ww xY ww)N)RS256RS384RS512PS256PS384PS512JWT_AUDIENCE
verify_audFr   )RSAAlgorithmz
header: %sr   )r   ktyne)
algorithmsoptionsaudiencer8   zToken ExpiredzValidation fails: )r   r   r   zInvalid JWT Submitted)r   r   jwtjwt.algorithmsr   get_unverified_headerr   debugrj   r   rx   r   from_jwkr   dumpsdecoder8   ExpiredSignatureErrorr   ry   r
   load_pem_x509_certificateencoder   r   public_bytesr   EncodingPEMPublicFormatSubjectPublicKeyInfo)r:   rB   r   r   decode_optionsr   r   headerr   r   jwkpublic_key_rsapayloadr   certr   s                   r;   auth_jwtzJWTHandler.auth_jwt  sc     L
99^,*E2N/**51""<8jj%..3.77
!jT&BC
"'.E

"'.E
j %c?Cj %c?C)224::c?CN?**")*%;; %   #
:s(C?55%%'):
 oo'44!**..!..CC **)%* %   /00y 86 ,, 100 ?"4SVH =>>?0 ,, 100 ?"4SVH =>>?s\   A:I<F?=A,I*"G I BH 3I"H $G;;H  I"I%H<<IIc                 T   K   | j                   j                          d {    y 7 wr@   )r7   closer9   s    r;   r   zJWTHandler.close  s     %%'''s   (&()r5   N)r   r@   ).__name__
__module____qualname____doc__r   r%   __annotations__r   r<   r   intrA   staticmethodry   rI   r   r   rU   re   r   boolr\   r   rk   rq   ru   rz   r_   r   ra   r]   r   r   rN   rc   r   r   r   r[   r   r   r   r   r   r   r    r=   r;   r2   r2   :   s    L))!!	 
-
 &
 )	

 
 

 c  $ 8J;O >"4 "HZ,@ "Ht  
4 DI *23-	#T $ 
 
hsm 
QT 
3(4. 3D 3 hsm QT *249*=	$s)	*$ 8DT;U *249*=	$s)	.xS	/B t  

*23-
	#
4  (SV-  Xc] xPS}  c $
 $
$ $
L{ # 8JCW 2C D P1C P1D P1d(r=   r2   c                   |   e Zd ZdZededededed   fd       Z	ededede
e   ded   fd	       Zed
ee   dee   dededdf
d       Zedededededede
e   ddfd       Zedededede
e   de
e   dede
e   fd       Zededede
e   dede
e   dedee
e   e
e   f   fd       Zedededee   fd       Zedee   de
e   dedede
e   dede
e   dedee
e   e
e   f   fd       Zedededee
e   e
e   e
e   f   fd       Zede
e   d e
e   de
e   d!e
e   d"e
e   dede
e   dede
e   dedee
e    e
e!   e
e"   f   fd#       Z#ede
e   d$e
e   d%ed&eded   f
d'       Z$ed(e
e    d)e
e   fd*       Z%ededed(e
e    de
e   ddf
d+       Z&edededededede
e   dede
e   dedefd,       Z'y)-JWTAuthManagerz7Manages JWT authentication and authorization operationsrd   general_settingsrouter5   Tc           	      r    t        | |      }||yt        ||      }|st        dd|  d| d|       y)	zU
        Checks if user is allowed to access the route, based on their role.
        rd   r  T)
user_routeallowed_routes  Role=z not allowed to call route=z. Allowed routes=status_codedetail)r.   r(   r   )rd   r  r  role_based_routes
is_alloweds        r;   can_rbac_role_call_routez'JWTAuthManager.can_rbac_role_call_route  sh     22B
 $*,


 yk)DUGK\]n\op 
 r=   modelc           	      \    t        | |      }||y||vrt        dd|  d| d|       y)zU
        Checks if user is allowed to access the model, based on their role.
        r  Tr  r	  z not allowed to call model=z. Allowed models=r
  )r-   r   )rd   r  r  role_based_modelss       r;   can_rbac_role_call_modelz'JWTAuthManager.can_rbac_role_call_model+  s\     22B
 $))yk)DUGK\]n\op 
 r=   scope_mappingsrY   request_dataNc                     | syg }| D ]9  }|j                   |v s|j                  s|j                  |j                         ; |j                  d      }|sy||vrt	        dddj                  ||      i      y)zE
        Check if scope allows access to the requested model
        Nr  r  errorz'model={} not allowed. Allowed_models={}r
  )r   modelsextendrj   r   format)r  rY   r  r  allowed_modelssmrequested_models          r;   check_scope_based_accessz'JWTAuthManager.check_scope_based_accessB  s      Bxx6!bii%%bii0 ! '**73.0FMM'  r=   jwt_handlerjwt_valid_tokenc                    K   | j                   j                  du rO|t        dd      t        j	                  |||j                  d             t        j                  |||       yyw)	z/Validate RBAC role and model access permissionsTNr  zjUnmatched token passed in. enforce_rbac is set to True. Token must belong to a proxy admin, team, or user.r
  r  )rd   r  r  )rd   r  r  )r>   enforce_rbacr   r  r  rj   r  )r  r   r  r  r  rd   s         r;   check_rbac_rolezJWTAuthManager.check_rbac_roled  s      &&33t; # # H  33#!1"&&w/ 4 
 33#!1 4  <s   A)A+rp   r   api_keyc                   K   | j                  |      syt        t        j                  || j                        }|s3| j                  j
                  }t        |      }t        d| d|       t        ddddd|d|d|
      S w)	z/Check admin status and route access permissionsrX   N	user_roler  litellm_proxy_roles)r  z.Admin not allowed to access this route. Route=z, Allowed Routes=T)
is_proxy_adminteam_objectuser_objectend_user_object
org_objectrB   r}   rp   end_user_idr   )	r\   r)   r   r^   r>   admin_allowed_routesr*   r   r   )	r  rY   r  rp   r   r$  r  r  actual_routess	            r;   check_admin_accessz!JWTAuthManager.check_admin_access  s      ##6#2)&22 + ; ;


 (3(C(C(X(XN-^LM@GXYfXgh  $ 
 	
s   BBr3   r4   parent_otel_spanproxy_logging_objc                   K   | j                  |d      }|s5| j                         du r#t        d| j                  j                   d      d}|r-t        |||||| j                  j                         d{   }||fS 7 w)z"Find and validate specific team IDNrK   Tz2No team id found in token. Checked team_id field '')r}   r3   r4   r2  r3  team_id_upsert)r_   ru   r   r>   rt   r/   r6  )r  r   r3   r4   r2  r3  individual_team_idr*  s           r;   "find_and_validate_specific_team_idz1JWTAuthManager.find_and_validate_specific_team_id  s      )44! 5 
 "k&E&E&G4&OD[E`E`ErErDsstu 
 48 /*+#5!1"3*::II! K ";..s   A7B9B:	Bc                 @    | j                  |      }t        |      }|S )z8Get combined team IDs from groups and individual team_idrW   )rk   rO   )r  r   team_ids_from_groupsall_team_idss       r;   get_all_team_idszJWTAuthManager.get_all_team_ids  s)      +@@@W/0r=   team_idsr  c                   K   | s$|j                   j                  rt        dd      y| D ]  }	 t        |||||       d{   }	|	rg|	j                  [|	j                  }
t        |
t              r?|rt        ||	dd      r.t        t        j                  ||j                         }|r||	fc S  |rt        dd	| d
|  d      y7 # t        $ r Y w xY ww)z2Find first team with access to the requested modelr  zgNo teams found in token. `enforce_team_based_model_access` is set to True. Token must belong to a team.r
  )NN)r}   r3   r4   r2  r3  N)r  r*  
llm_routerteam_model_aliasesr&  z+No team has access to the requested model: z. Checked teams=z.. Check `/models` to see all available models.)r>   enforce_team_based_model_accessr   r/   r  rx   r   r$   r)   r   r`   r   )r=  r  r  r  r3   r4   r2  r3  r}   r*  team_modelsr  s               r;   find_team_with_model_accessz*JWTAuthManager.find_team_with_model_access  s!     **JJ# # E  G$3#"/'9%5&7%  ;#5#5#A"-"4"4K!+t4+0"1(3'+/3	 &:&6&;&;',0;0K0K&

 &#*K#777  > D_DUUefneo  p^  _ 
 G4  s;   ,CCC	A*C-C	C	CCCCc                    K   | j                  |d      }d}| j                         r|dn| j                  |      }| j                  ||      }|||fS w)z$Get user email and validation statusNrK   F)r   )r   rz   r   ra   )r  r   r   r~   rp   s        r;   get_user_infozJWTAuthManager.get_user_info  s      !//! 0 

  //1 %  22j2I 
 ))! * 
 
$444s   AAr   r.  r~   c
           
        K   d}
|r|rt        |||||	       d{   nd}
d}| r/| r+t        | |||j                  |      ||	||        d{   nd}d}|r|rt        |||||	       d{   nd}||
|fS 7 ^7 -7 w)z#Get user, org, and end user objectsN)r   r3   r4   r2  r3  )r~   )rp   r3   r4   r   r2  r3  r   sso_user_id)r.  r3   r4   r2  r3  )r,   r0   r   r+   )rp   r   r   r.  r~   r  r3   r4   r2  r3  r-  r+  r,  s                r;   get_objectszJWTAuthManager.get_objects   s     $ ;?
  %!"/'9%5&7     48  &#"/'9#.#@#@)9 $A $ &6&7) '    " ;?  * +"/'9%5&7     J77Y&s3   BA;2BA=B/A?0B=B?Br}   r"  r)  c                 .    |r|s| s|st        dd      y)zUIf enforce_rbac is true, validate that a valid rbac id is returned for spend trackingr  zrNo user or team id found in token. enforce_rbac is set to True. Token must belong to a proxy admin, team, or user.r
  Tr   rp   r}   r"  r)  s       r;   validate_object_idz!JWTAuthManager.validate_object_idc  s(     ww L  r=   r+  r*  c                 n  K   ddl m} | sy|sy|j                  D ]*  }|j                  s|j                  | j                  k(  s* y t	        t        | j                  d      |j                        }	  ||t        t        j                               d{    t        j                  d	| j                   d
|j                          y7 4# t        $ rX}|j                  t        j                  k(  r4t        j                  d| j                   d|j                          Y d}~y|d}~ww xY ww)z
        Map user to teams.
        - If user is not in team, add them to the team
        - If user is in team, do nothing
        r   )team_member_addNuser)rp   rP   )memberr}   )r'  )r   user_api_key_dictzSuccessfully added user z	 to team zUser z is already a member of team )1litellm.proxy.management_endpoints.team_endpointsrM  members_with_rolesrp   r"   r   r}   r#   r   r^   r   r   r   r   r   team_member_already_in_team)r+  r*  rM  rO  r   r   s         r;   map_user_to_teamsz JWTAuthManager.map_user_to_teamsr  s-     	V "44F~~&..K4G4G"G 5 $#++  ''
	!"0.::#   !&&*;+>+>*?yI\I\H]^ #  	vvDDD$**K//00MkNaNaMbc 	sS   (D5D5/D55%C C3C D5C 	D2AD-&D5+D--D22D5c                 `  K   | j                   j                  sy||y| j                  |      }|rq|j                  |j                  k7  rX|j
                  j                  j                  d|j                  id|j                  i       d{    |j                  |_        t        | j                  |            }t        |j                  xs g       }||z
  }||z
  }|s|rEddlm}	  |	|j                  t        |      t        |             d{    t        |      |_        y7 7 w)ak  
        Sync user role and team memberships with JWT claims

        The goal of this method is to ensure:
        1. The user role on LiteLLM DB is in sync with the IDP provider role
        2. The user is a member of the teams specified in the JWT token

        This method is only called if sync_user_role_and_teams is set to True in the JWT config.
        Nrp   r'  )wherer   r   )patch_team_membership)rp   teams_ids_to_add_user_toteams_ids_to_remove_user_from)r>   sync_user_role_and_teamsr   r'  r   dblitellm_usertableupdaterp   rO   rk   teams/litellm.proxy.management_endpoints.scim.scim_v2rW  r   )
r  r   r+  r3   new_rolejwt_team_idsexisting_teamsteams_to_addteams_to_removerW  s
             r;   rZ  z'JWTAuthManager.sync_user_role_and_teams  s3      **CC-"7 ;;OL--?""44;; +"5"56!8>>2 <    %-NNK! ;<<_MN[..4"5#n4(<7? (#++)-l);.2?.C  
 !%\ 2K- s%   BD.D*BD.D,D.,D.c	                 b  K   |j                  |        d{   }	|j                  j                  r(|j                  j                  |	      st        dd      |j	                  |	      }
t
        j                  ||	||||
       d{    |j                  |	      }|j                  j                  rC|j                  j                  r-t
        j                  |j                  j                  |||       |j                  |	d      }|j                  |	      }t
        j                  ||	       d{   \  }}}|j                  |	d      }|j                  |	d      }d}d}|j                  |	d      }|
r-|r+|
t        j                   k(  r|}n|
t        j"                  k(  r|}t
        j%                  ||||||        d{   }|r|S |s%t
        j'                  ||	||||       d{   \  }}|sO|sMt
        j)                  ||	      }t
        j+                  ||j-                  d      ||||||	       d{   \  }}t
        j/                  ||||||||||

       d{   \  }}}t
        j1                  ||	||       d{    t
        j3                  ||       d{    t
        j5                  |||j-                  dd      d       |r |j6                  t        j8                  k(  rd}nd}t;        |||||||||| 
      S 7  7 7 7 W7 27 7 7 7 {w)z-Main authentication and authorization builderrW   Nr  zInvalid JWT tokenr
  )r  rY   r  r  rK   r  )r=  r  r  r  r3   r4   r2  r3  )
rp   r   r   r.  r~   r  r3   r4   r2  r3  )r  r   r+  r3   )r+  r*  r"  FrJ  T)
r)  r}   r*  rp   r+  r   r-  r.  r,  rB   )r   r>   custom_validater   re   r  r#  r[   enforce_scope_based_accessr  r  r   rE  r   rq   r   r`   rb   r1  r8  r<  rC  rj   rH  rZ  rT  rK  r'  r^   r   )r$  r  r  r  r  r3   r4   r2  r3  r   rd   rY   r   rp   r   r~   r   r.  r}   r*  admin_resultr;  r+  r-  r,  r)  s                             r;   auth_builderzJWTAuthManager.auth_builder  s     '2&:&:&:&I I &&66..>>O# #.   --O-D	,,
 	
 	
 ''o'>''BB++::33*::II)!1	 4   --OSW-X	 ''o'>6D6R6R7
 1
--
 ''oT'R!11! 2 
 "&37--OSW-X	,111#.<<<# ,>>
 
 
  %GG" !  7)::;XL)7)S)S% , 0 0 9'+#5!1"3 *T 	* 	$ G[ :H9S9S!#-#'1-/ :T :
 4
0Z 55#+#'	 6 
 	
 	
 ..## / 
 	
 	
 	)))--neD 	 	* 	
 ;004D4P4PP!N"N#)##!#+
 	
O !J	
41
(
	$4
	
	
s   L/LA1L/
LB-L/8L9BL/
L!'L/2L$3AL/L')L/-L).$L/L+L/1L-2A'L/L/L/!L/$L/'L/)L/+L/-L/)(r   r   r   r   r   r   r   ry   r   r  r   r  r   r    r  r2   r#  r   r   r1  r%   r   r!   r&   r   r   r8  r   r<  rC  r   rE  r   r   r   rH  rK  rT  rZ  ri  r   r=   r;   r  r    s'   A  
	 8  } 
	 , \*S	  	
 
 B   	
  J' 
 4 #
#
#
 #
 #	#

 #
 #
 
&	'#
 #
J ///  -/ &	/
 #4./ (/ 
x}h'899	:/ /@ j 4 CPSH   9c(9!#9 9  	9
  -9 &9 #4.9 (9 
x}h'899	:9 9v 555 
x}hsmXd^;	<5 5( @8#@8SM@8 @8 c]	@8
 #4.@8  @8  -@8 &@8 #4.@8 (@8 
"#*+%&	(
@8 @8D ##  	
 
  0/00/00 0d ... /0.  -	.
 
. .` ^
^
^
 ^
 	^

 ^
  -^
 &^
 #4.^
 (^
 
^
 ^
r=   r  )?r   r   r   r   typingr   r   r   r   r   r   r	   cryptographyr
   cryptography.hazmat.backendsr   cryptography.hazmat.primitivesr   fastapir   litellm._loggingr   litellm.caching.cachingr   0litellm.litellm_core_utils.dot_notation_indexingr   'litellm.llms.custom_httpx.httpx_handlerr   litellm.proxy._typesr   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   litellm.proxy.auth.auth_checksr$   litellm.proxy.utilsr%   r&   auth_checksr(   r)   r*   r+   r,   r-   r.   r/   r0   r2   r  r   r=   r;   <module>rw     s      	 A A A  8 8 ! 1 - M ?    & A :
 
 
N( N(bj	
 j	
r=   