Ë
    tPêjX ã                   óT  — U d Z ddlZddlZddlZddlZddlZddlZddlZddl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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m Z m!Z! er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/m0Z0m1Z1m2Z2m3Z3 ddl4Z4ddl5m6Z6 ddl7m8Z8 ddl9m:Z: ddl;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZG ddlHmIZI ddlJmKZKmLZLmMZM ddlNmOZOmPZPmQZQ ddlRmSZSmTZTmUZUmVZVmWZWmXZXmYZYmZZZm[Z[m\Z\m]Z]m^Z^ ddl_m`Z`maZa ddlbmcZcmdZd ddlemfZf ddlgmhZh ddlimjZjmkZk ddllmmZm ddlnmoZo ddlpmqZq ddlrmsZs ddltmuZu ddlvmwZw ddlxmyZymzZz dd l{m|Z|m}Z} dd!l~mZm€Z€m�Z� dd"l‚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�m‘Z‘m’Z’ dd(l“­ dd)l“m”Z”m•Z•m–Z–m—Z—m˜Z˜m™Z™ dd*lšm›Z› erdd+lœm�Z� ndd,lmZ�  e%«       ZžeeŸd-<    e h d.£«      Z¡eeŸd/<   e>› d0�Z¢eeŸd1<   e¢› d2�Z£eeŸd3<   d4Z¤eeŸd5<   d6Z¥eeŸd7<   d8Z¦eeŸd9<    e�jN                  d:«      Z¨eeŸd;<    e�jN                  d<e¦› d=e¦› d>�«      Z©eªe«e¬e­fZ®eeŸd?<    e�jN                  d@«      Z¯eeŸdA<    e h dB£«      Z°eeŸdC<    G dD„ dEe«      Z±dFeŽdGdHfdI„Z² G dJ„ dKe«      Z³dFeŠdGdLfdM„Z´ G dN„ dOe«      ZµdFeŒdGdPfdQ„Z¶ e2e·eªeªf   «      Z¸eeŸdR<    e2e
eªe¹f   «      ZºeeŸdS<   dTe¹dGe¹fdU„Z» G dV„ dWe/«      Z¼ G dX„ dYe/«      Z½ G dZ„ d[e/«      Z¾ e2e¿e¾d\f   «      ZÀeeŸd]<    e¾d^¬_«      ZÁeeŸd`<    G da„ dbe«      ZÂ G dc„ dde«      ZÃ G de„ dfe«      ZÄdTe¹dGe¹fdg„ZÅdheªdGeªfdi„ZÆdjeªdGeªfdk„ZÇdGeªfdl„ZÈdmeªdGeªfdn„ZÉdmeªdz  dGe­fdo„ZÊdjeªdz  dGe­fdp„ZËdGe­fdq„ZÌdmeªdreªdjeªdseªdz  dGe·eªeªe«z  f   f
dt„ZÍ�ddve)dwe­dz  dGeªfdx„ZÎ	 �ddve)dye:dwe­dz  dGdfdz„ZÏdmeªdz  dye:dGe·fd{„ZÐdmeªdye:d|e·dGdfd}„ZÑd|e·dreªdz  dGe­fd~„ZÒdGeÓe¿eªeªf      fd„ZÔd€eªdGe­fd�„ZÕdTe¹dGe­fd‚„ZÖdƒee�z  e·eªe¹f   z  dGe·eªe¹f   fd„„Z×d…e
eªe¹f   d†eªdGe¹fd‡„ZØdƒee�z  e·eªe¹f   z  d†eªdGe¹fdˆ„ZÙd‰e·eªe¹f   dŠeªdTe¹dGdfd‹„ZÚd‰e
eªe¹f   dGe·eªeªe«z  e¬z  e­z  f   fdŒ„ZÛdƒee�z  e·eªe¹f   z  dGe·eªe¹f   fd�„ZÜdŽe·eªe¹f   d�e·eªe¹f   dGe·eªe¹f   fd�„ZÝd‘eƒd’eªd�e·eªe¹f   dGdfd“„ZÞd”e
eªe¹f   dGe·eªeªe«z  e¬z  e­z  f   fd•„Zß	 �dd–eªd—eªd˜eªdz  dGeªfd™„Zàež�jÃ                  dšd›gdu¬œ«      dve)fd�„«       Zâež�jÃ                  džd›gdu¬œ«      dve)dmeªfdŸ„«       Zãd eªdz  dGeªdz  fd¡„ZäeU�jÊ                  eU�jÌ                  eU�jÎ                  eU�jÐ                  fZéeeŸd¢<   d£eÓeª   d¤d¥dGeUdz  fd¦„Zê	 �dd§eªdz  d¨efdz  dƒe�e·z  dz  d¤ed¥   dGe·dz  f
d©„Zëdªeªdz  dGe
eªe¹f   fd«„Zìd¬e
eªe¹f   d­eªdz  d®eªdz  dGe
eªe¹f   fd¯„Zíd°e­d‘eƒdz  dGdfd±„Zîež�jß                  d²d›gdu¬œ«      	 	 	 	 	 �ddve)d³eªdz  d´eªdz  dµeªdz  d¶eªdz  djeªdz  fd·„«       Zð	 	 	 �dd¸efd¨efdz  d¤ed¥   d¹edº   dGef
d»„Zñd¼eªd½eªdGe¿eªeÓeª   eªeªeªe­f   fd¾„ZòdGedº   fd¿„ZódGed¥   fdÀ„ZôdGe·eªeªf   fdÁ„ZõdÂeödÃeªdz  dÄeªdz  dÅe·dGef
dÆ„Z÷dve)d¸efd¨efdz  d¼eªd½eªdGe¿e�e·z  e·dz  e·dz  eOdz  f   fdÇ„ZødÈ„ ZùdÉeYeTz  dÊeÓeª   fdË„ZúdÌ„ Zûd’eªdz  dÍeªdz  d‘eƒdÎeqdÏe„dGeTdz  fdÐ„Zü	 �ddƒee�z  e·z  d‘eƒdÎeqdÏe„dÍeªdz  dÑe\dz  dÒeªdz  dGeTeYz  dz  fdÓ„ZýdÔeªdz  dGe­fdÕ„ZþdƒedÖe�e·f   dz  dÍeªdz  d’eªdz  dGe·eªe¹f   fd×„Zÿd¸efdz  dØe·dz  dÉeTeYz  dz  d‘eƒdÎeqdÑe\dz  dGdfdÙ„�Z dÉeTeYz  dz  dÑe\dz  dGe\dz  fdÚ„�ZdÛeªd’eªd‘eƒdz  fdÜ„�Zež�jß                  dÝd›gdu¬œ«      �ddve)dÞeªdz  fdß„«       �Zež�jß                  dàd›gdu¬œ«      �ddve)d¶eªdz  fdá„«       �Zež�jß                  dâd›gdu¬œ«      dve)fdã„«       �Zež�jÃ                  däd›gdu¬œ«      dve)fdå„«       �Zdƒe�e·z  dæe›dGe\dz  fdç„�Zdèe
eªe¹f   dGe¾fdé„�Zd‘eƒdêeeª   dGe¿e¾d\f   dz  fdë„�Z	dìee¾   dGeÓeª   fdí„�Z
dìe¹dîeªdz  dGe¾dz  fdï„�Zdddðœdve)d´eªd|e·dƒe�e·z  dæe›dÑe\dz  d‘eƒdÎeqdñe:dÏe„d˜eªdz  dòeOdz  fdó„�Z	 	 	 	 	 �ddve)d´eªdz  dƒe�e·z  dz  dØe·dz  d˜eªdz  dòeOdz  fdô„�Zež�jß                  dõd›gdu¬œ«      d e'd¬ö«      fd÷eªdîeªdz  døeªdz  fdù„«       �Z	 �ddúe�e·z  dz  dÑe\dz  dGeYfdû„�Zež�jß                  düd›gdu e&eh«      g¬ý«      dve)fdþ„«       �Zež�jß                  dÿd›g e&eh«      g�¬ «      �d„ «       �Zd¶eªdGe­f�d„�Zd¶eªdz  �deªdGe-dz  f�d„�Z�de*d¶eªdz  dGdf�d„�Z G �d„ �d«      �Z G �d	„ �d
«      �Z G �d„ �d«      �Zež�jß                  �dd›gdu¬œ«      dve)f�d„«       �Zež�jß                  �dd›gdu¬œ«      dve)f�d„«       �Zy(  a^  
Has all /sso/* routes

/sso/key/generate - handles user signing in with SSO and redirects to /sso/callback
/sso/callback - returns JWT Redirect Response that redirects to LiteLLM UI

/sso/debug/login - handles user signing in with SSO and redirects to /sso/debug/callback
/sso/debug/callback - returns the OpenID object returned by the SSO provider
é    N)ÚMappingÚSequence)Údeepcopy©Úescape)ÚMappingProxyType)ÚTYPE_CHECKINGÚ	AnnotatedÚAnyÚFinalÚLiteralÚNoReturnÚOptionalÚProtocolÚUnionÚcastÚoverload)Úparse_qsÚ	urlencodeÚurlparse)Ú	APIRouterÚDependsÚHeaderÚHTTPExceptionÚRequestÚResponseÚstatus)ÚRedirectResponse)Ú	BaseModelÚBeforeValidatorÚ
ConfigDictÚTypeAdapterÚValidationError)Úverbose_proxy_logger)Úuuid)Ú	DualCache)ÚCLI_SSO_CLAIM_MAPÚCLI_SSO_CLAIM_MAX_SCALAR_LENGTHÚ CLI_SSO_SESSION_CACHE_KEY_PREFIXÚCLI_SSO_SESSION_TTL_SECONDSÚLITELLM_CLI_SOURCE_IDENTIFIERÚLITELLM_UI_SESSION_DURATIONÚMAX_SPENDLOG_ROWS_TO_QUERYÚ%MICROSOFT_USER_DISPLAY_NAME_ATTRIBUTEÚMICROSOFT_USER_EMAIL_ATTRIBUTEÚ#MICROSOFT_USER_FIRST_NAME_ATTRIBUTEÚMICROSOFT_USER_ID_ATTRIBUTEÚ"MICROSOFT_USER_LAST_NAME_ATTRIBUTE)Úget_nested_value)ÚAsyncHTTPHandlerÚget_async_httpx_clientÚhttpxSpecialProvider)ÚSSOIdentityAssertionÚassertion_from_sso_loginÚ%retain_sso_identity_assertion_for_ema)ÚCommonProxyErrorsÚLiteLLM_UserTableÚLitellmUserRolesÚMemberÚNewTeamRequestÚNewUserRequestÚNewUserResponseÚProxyErrorTypesÚProxyExceptionÚSSOUserDefinedValuesÚTeamMemberAddRequestÚUserAPIKeyAuth)ÚExperimentalUIJWTTokenÚget_user_object)Ú_get_request_ip_addressÚ_has_user_setup_sso©Ú
JWTHandler)Úuser_api_key_auth)Úadmin_ui_disabledÚshow_missing_vars_in_env)Újwt_display_template)Úbuild_ui_login_form)ÚUserApiKeyCache)Únew_user)ÚCustomMicrosoftSSO)ÚSAMLAuthHandler)Úcheck_is_admin_only_accessÚhas_admin_ui_access)Únew_teamÚteam_member_add)ÚCustomOpenIDÚget_litellm_user_roleÚis_valid_litellm_user_role)ÚPrismaClientÚProxyLoggingÚget_custom_urlÚget_server_root_path)ÚTableActions)ÚSSOConfigRepository)ÚTeamRepository)ÚUserRepository)Úget_secret_boolÚget_secret_strÚstr_to_bool)Ú*)ÚDefaultTeamSSOParamsÚ)MicrosoftGraphAPIUserGroupDirectoryObjectÚ"MicrosoftGraphAPIUserGroupResponseÚMicrosoftServicePrincipalTeamÚRoleMappingsÚTeamMappings)ÚParsedOpenIDResult)ÚOpenID)r   Úrouter>   Úid_tokenÚaccess_tokenÚrefresh_tokenÚ_OAUTH_TOKEN_FIELDSz:flowÚ_CLI_SSO_FLOW_CACHE_KEY_PREFIXz:start_rate_limitÚ*_CLI_SSO_START_RATE_LIMIT_CACHE_KEY_PREFIXé<   Ú(_CLI_SSO_START_RATE_LIMIT_WINDOW_SECONDSé   Ú&_CLI_SSO_START_RATE_LIMIT_MAX_ATTEMPTSÚ ABCDEFGHJKLMNPQRSTUVWXYZ23456789Ú_CLI_SSO_USER_CODE_ALPHABETz^cli-[A-Za-z0-9_-]{12,124}$Ú_CLI_SSO_LOGIN_ID_REz^[z]{4}-[z]{4}$Ú_CLI_SSO_SCALAR_TYPESz^[A-Za-z0-9_.-]+$Ú_CLI_SSO_DEST_KEY_RE>   ÚsecretÚapi_keyrq   ÚpasswordÚprivate_keyrr   Úclient_secretrs   Ú_CLI_SSO_SECRET_KEY_FRAGMENTSc                   ó2   — e Zd Zedeeef   dz  fd„«       Zy)Ú_UserMetadataRowÚreturnNc                  ó   — y ©N© ©Úselfs    ún/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/management_endpoints/ui_sso.pyÚmetadataz_UserMetadataRow.metadata°   s   € Ø7:ó    )Ú__name__Ú
__module__Ú__qualname__Úpropertyr   ÚstrÚobjectr�   r‹   r�   rŽ   r‡   r‡   ¯   s#   „ ØØ:˜' # v +Ñ.°Ñ5Ò:ó Ù:r�   r‡   Úreporˆ   úTableActions[_UserMetadataRow]c                 ó.   — t        d| j                  «      S )Nr˜   ©r   Útable©r—   s    rŽ   Ú_user_meta_dbr�   ´   s   € ÜØ(¨$¯*©*óð r�   c                   ó2   — e Zd Zedeeef   dz  fd„«       Zy)Ú_SsoConfigRowrˆ   Nc                  ó   — y rŠ   r‹   rŒ   s    rŽ   Ússo_settingsz_SsoConfigRow.sso_settings»   s   € Ø;>r�   )r‘   r’   r“   r”   r   r•   r–   r¡   r‹   r�   rŽ   rŸ   rŸ   º   s#   „ ØØ>˜g c¨6 kÑ2°TÑ9Ò>ó Ù>r�   rŸ   úTableActions[_SsoConfigRow]c                 ó.   — t        d| j                  «      S )Nr¢   rš   rœ   s    rŽ   Ú_sso_config_dbr¤   ¿   s   € ÜØ% t§z¡zóð r�   c                   ó"   — e Zd Zdeeef   fd„Zy)Ú_TeamDetailRowrˆ   c                  ó   — y rŠ   r‹   rŒ   s    rŽ   Ú
model_dumpz_TeamDetailRow.model_dumpÆ   ó   � r�   N)r‘   r’   r“   r   r•   r–   r¨   r‹   r�   rŽ   r¦   r¦   Å   s   „ Ø5˜G C¨ KÑ0Ô5r�   r¦   zTableActions[_TeamDetailRow]c                 ó   — | j                   S rŠ   )r›   rœ   s    rŽ   Ú_team_detail_dbr«   É   s   € Ø�:‰:Ðr�   Ú_MODEL_ALIASES_ADAPTERÚ_SSO_TOKEN_CLAIMS_ADAPTERÚvaluec                 óp   — t        | t        «      s| S 	 t        j                  | «      S # t        $ r Y yw xY w)zT``/team/new`` stores team model aliases as a JSON-encoded string in the Json column.N)Ú
isinstancer•   r¬   Úvalidate_jsonr#   ©r®   s    rŽ   Ú_decode_model_aliasesr³   Ñ   s9   € ä�eœSÔ!ØˆðÜ%×3Ñ3°EÓ:Ð:øÜò Ùðús   ”) ©	5´5c                   óT   — e Zd ZU  ed¬«      ZdZeeeef   dz   e	e
«      f   ed<   y)Ú_TeamModelAliasTabler‹   )Úprotected_namespacesNÚmodel_aliases)r‘   r’   r“   r!   Úmodel_configr·   r
   r   r•   r    r³   Ú__annotations__r‹   r�   rŽ   rµ   rµ   Û   s4   … Ù°2Ô6€Làae€M�9˜W S¨# XÑ.°Ñ5±ÐG\Ó7]Ð]Ñ^Ôer�   rµ   c                   óX   — e Zd ZU eed<   dZedz  ed<   dZeedf   ed<   dZe	dz  ed<   y)Ú_TeamRowGrantsÚteam_idNÚ
team_aliasr‹   .ÚmodelsÚlitellm_model_table)
r‘   r’   r“   r•   r¹   r½   r¾   Útupler¿   rµ   r‹   r�   rŽ   r»   r»   á   s8   … ØƒLØ!€J��d‘
Ó!Ø €FˆE�#�s�(‰OÓ Ø7;ÐÐ-°Ñ4Ô;r�   r»   c                   ól   — e Zd ZU dZdZedz  ed<   dZedz  ed<   eedf   ed<   dZ	e
eef   dz  ed<   y)ÚCliSsoTeamDetailzOThe per-team snapshot cached in the CLI SSO flow and echoed to the CLI on poll.Nr¼   r½   .Úteam_modelsÚteam_model_aliases)r‘   r’   r“   Ú__doc__r¼   r•   r¹   r½   rÀ   rÄ   r   r‹   r�   rŽ   rÂ   rÂ   è   sH   … ÙYà€GˆS�4‰ZÓØ!€J��d‘
Ó!Ø�s˜C�x‘Ó Ø37Ð˜  S Ñ)¨DÑ0Ô7r�   rÂ   .Ú_CLI_SSO_TEAM_DETAILS_ADAPTERr‹   )rÃ   Ú_TEAMLESS_CLI_SSO_TEAM_DETAILc                   ó"   — e Zd Zdededz  fd„Zy)Ú_CustomSsoCallÚsso_responserˆ   Nc              ƒ   ó   K  — y ­wrŠ   r‹   )r�   rÊ   s     rŽ   Ú__call__z_CustomSsoCall.__call__ö   s   è ø� ùs   ‚)r‘   r’   r“   r–   rC   rÌ   r‹   r�   rŽ   rÉ   rÉ   õ   s   „ ØV¨6ÐVÐ6JÈTÑ6QÔVr�   rÉ   c                   ó   — e Zd Zdedefd„Zy)Ú_ServicePrincipalAssignmentÚkeyrˆ   c                  ó   — y rŠ   r‹   ©r�   rÏ   s     rŽ   Úgetz_ServicePrincipalAssignment.getú   r©   r�   N)r‘   r’   r“   r•   rÒ   r‹   r�   rŽ   rÎ   rÎ   ù   s   „ Ø'�sÐ'˜sÔ'r�   rÎ   c                   ób   — e Zd Zeded   ded   ded   fd„«       Zeded   dedz  fd	„«       Zy)
Ú_ServicePrincipalPagerÏ   r®   ÚdefaultrÎ   rˆ   c                  ó   — y rŠ   r‹   )r�   rÏ   rÕ   s      rŽ   rÒ   z_ServicePrincipalPage.getþ   s   € ð
 36r�   ú@odata.nextLinkNc                  ó   — y rŠ   r‹   rÑ   s     rŽ   rÒ   z_ServicePrincipalPage.get  s   € ØBEr�   )r‘   r’   r“   r   r   r   rÒ   r•   r‹   r�   rŽ   rÔ   rÔ   ý   se   „ Øð6à�WÑð6ð Ð7Ñ8ð6ð 
Ð/Ñ	0ò	6ó ð6ð ØE�wÐ0Ñ1ÐE°c¸D±jÒEó ÙEr�   rÔ   c                 ó   — | S rŠ   r‹   r²   s    rŽ   Ú
_as_objectrÚ   	  s   € Ø€Lr�   r€   c                 óf   — t        j                  | j                  d«      «      j                  «       S )Núutf-8)ÚhashlibÚsha256ÚencodeÚ	hexdigest)r€   s    rŽ   Ú_hash_cli_sso_secretrá     s#   € Ü�>‰>˜&Ÿ-™-¨Ó0Ó1×;Ñ;Ó=Ð=r�   Ú	user_codec                 óN   — dj                  d„ | j                  «       D «       «      S )NÚ c              3   óB   K  — | ]  }|j                  «       sŒ|–— Œ y ­wrŠ   )Úisalnum©Ú.0Úchs     rŽ   ú	<genexpr>z/_normalize_cli_sso_user_code.<locals>.<genexpr>  s   è ø€ ÒB˜"°R·Z±Zµ\”2ÑBùs   ‚˜)ÚjoinÚupper©râ   s    rŽ   Ú_normalize_cli_sso_user_coderî     s   € Ø�7‰7ÑB 	§¡Ó 1ÔBÓBÐBr�   c                  ó^   — dj                  d„ t        d«      D «       «      } | d d › d| dd  › �S )Nrä   c              3   óN   K  — | ]  }t        j                  t        «      –— Œ y ­wrŠ   )ÚsecretsÚchoicer|   )rè   Ú_s     rŽ   rê   z._generate_cli_sso_user_code.<locals>.<genexpr>  s   è ø€ Ò]ÈqœwŸ~™~Ô.I×JÑ]ùó   ‚#%é   é   ú-)rë   Úrangerí   s    rŽ   Ú_generate_cli_sso_user_coderù     s:   € Ø—w‘wÑ]ÔTYÐZ[ÓT\Ô]Ó]€IØ˜˜ˆmˆ_˜A˜i¨¨˜m˜_Ð-Ð-r�   Úlogin_idc                 ó   — t         › d| › �S )Nú:)ru   ©rú   s    rŽ   Ú_get_cli_sso_flow_cache_keyrþ     s   € Ü,Ð-¨Q¨x¨jÐ9Ð9r�   c                 ób   — t        | t        «      xr t        t        j	                  | «      «      S rŠ   )r°   r•   Úboolr}   Ú	fullmatchrý   s    rŽ   Ú_is_valid_cli_sso_login_idr    s%   € Ü�h¤Ó$ÒW¬Ô.B×.LÑ.LÈXÓ.VÓ)WÐWr�   c                 ób   — t        | t        «      xr t        t        j	                  | «      «      S rŠ   )r°   r•   r   Ú_CLI_SSO_USER_CODE_REr  rí   s    rŽ   Ú_is_valid_cli_sso_user_coder  "  s%   € Ü�i¤Ó%ÒZ¬$Ô/D×/NÑ/NÈyÓ/YÓ*ZÐZr�   c                  óD   — ddl m}  t        | j                  dd«      «      S )Nr   ©Úgeneral_settingsÚ'allow_cli_sso_verification_uri_completeF)Úlitellm.proxy.proxy_serverr  r   rÒ   r  s    rŽ   Ú*_cli_sso_verification_uri_complete_enabledr  &  s    € Ý;äÐ ×$Ñ$Ð%NÐPUÓVÓWÐWr�   Úpoll_secretÚverification_uri_completec                 ó4   — |€| ||t         dœS | |||t         dœS )N)rú   r  râ   Ú
expires_in)rú   r  râ   r  r  )r*   ©rú   r  râ   r  s       rŽ   Ú_cli_sso_start_response_bodyr  ,  s;   € ð !Ð(à Ø&Ø"Ü5ñ	
ð 	
ð Ø"ØØ%>Ü1ñð r�   FÚrequestÚuse_x_forwarded_forc                 óP   — t        | |¬«      xs d}t        |«      }t        › d|› �S )N©r  r  Úunknownrü   )rH   rá   rv   )r  r  Ú	client_ipÚclient_ip_hashs       rŽ   Ú'_get_cli_sso_start_rate_limit_cache_keyr  C  s2   € Ü.°wÐTgÔhÒuÐlu€IÜ0°Ó;€NÜ8Ð9¸¸>Ð:JÐKÐKr�   Úcachec                 óz   — t        | |¬«      }|j                  |dt        ¬«      }|t        kD  rt	        dd¬«      ‚y )Nr  é   ©rÏ   r®   Úttli­  z-Too many CLI login attempts. Try again later.©Ústatus_codeÚdetail)r  Úincrement_cacherx   rz   r   )r  r  r  Úrate_limit_cache_keyÚcurrent_attemptss        rŽ   Ú_check_cli_sso_start_rate_limitr%  I  s[   € ô
 #JØÐ-@ô#Ðð $×3Ñ3Ø ØÜ4ð 4ó Ðð
 Ô@Ò@ÜØØBô
ð 	
ð Ar�   c                 ó  — t        | t        «      r| j                  d«      rt        dd¬«      ‚t	        | «      st        dd¬«      ‚t        t        t        | «      «      }|j                  }|�|j                  |¬«      }n|j                  |¬«      }t        |t        «      r	 t        t        j                  |«      «      }t        |t        «      rd|vr#t        j                  d| «       t        dd	¬«      ‚|S # t        $ r d }Y ŒFw xY w)
Nzsk-é�  z«Your litellm CLI is out of date and uses a login flow this proxy no longer supports. Upgrade it with `pip install -U 'litellm[proxy]'` and run `litellm-proxy login` again.r  zInvalid CLI login session id©rÏ   Úpoll_secret_hashz–CLI SSO login session not found in cache for login_id=%s. If the proxy runs multiple replicas, a shared Redis cache is required for CLI login to work.a  CLI login session not found or expired. Run `litellm-proxy login` again. If this happens immediately after starting a login, the proxy is likely running multiple replicas without a shared cache; configure a Redis cache so every replica can see the login session.)r°   r•   Ú
startswithr   r  rþ   r   Úredis_cacheÚ	get_cacherÚ   ÚjsonÚloadsÚ
ValueErrorÚdictr$   Úwarning)rú   r  Ú	cache_keyr+  Úflows        rŽ   Ú_get_cli_sso_flow_or_raiser4  ]  s  € Ü�(œCÔ  X×%8Ñ%8¸Ô%?ÜØðiô
ð 	
ô & hÔ/Ü¨Ð4RÔSÐSä2´4¼¸XÓ3FÓG€IØ×*Ñ*€KØÐØ×$Ñ$¨Ð$Ó3‰à�‰ 9ˆÓ-ˆÜ�$œÔð	ÜœdŸj™j¨Ó.Ó/ˆDô �dœDÔ!Ð%7¸tÑ%CÜ×$Ñ$ðFàô	
ô
 Øð>ô
ð 	
ð €Køô# ò 	ØŠDð	ús   Â$C; Ã;D	ÄD	r3  c                 ó¾   — t        | «      }|j                  }|�,|j                  |t        j                  |«      t
        ¬«       y |j                  ||t
        ¬«       y )Nr  )rþ   r+  Ú	set_cacher-  Údumpsr*   )rú   r  r3  r2  r+  s        rŽ   Ú_set_cli_sso_flowr8  †  sO   € Ü2°8Ó<€IØ×*Ñ*€KØÐØ×Ñ )´4·:±:¸dÓ3CÔIdÐÕeà�‰˜I¨TÔ7RˆÕSr�   c                 ó¨   — | j                  d«      }t        |t        «      rt        |t        «      syt        |«      }t	        j
                  ||«      S )Nr)  F)rÒ   r°   r•   rá   rñ   Úcompare_digest)r3  r  Úexpected_poll_secret_hashÚsupplied_poll_secret_hashs       rŽ   Ú_verify_cli_sso_poll_secretr=  �  sJ   € Ø'+§x¡xÐ0BÓ'CÐÜÐ/´Ô5¼ZÈÔUXÔ=YØÜ';¸KÓ'HÐÜ×!Ñ!Ð";Ð=VÓWÐWr�   c                  óR  — t        j                  «       } | sg S g }| j                  d«      D ]x  }|j                  «       }|rd|vrŒ|j                  dd«      \  }}|j                  «       }|j                  «       }|j                  d«      }|sŒc|sŒf|j	                  ||f«       Œz |S )aZ  
    Parse CLI_SSO_CLAIM_MAP / LITELLM_CLI_SSO_CLAIM_MAP.

    Format: comma-separated ``source_claim->metadata_key`` pairs, e.g.
    ``employment_type->acme_employment_type,org_info.department->department``.
    Destination keys may use an optional ``metadata.`` prefix; values are stored
    on the LiteLLM user's ``metadata`` JSON column.
    ú,z->r  z	metadata.)r'   ÚstripÚsplitÚremoveprefixÚappend)Úclaim_map_rawÚparsedÚentryÚsource_claimÚdest_keys        rŽ   Ú_parse_cli_sso_claim_maprI  —  s­   € ô -×2Ñ2Ó4€MÙØˆ	à+-€FØ×$Ñ$ SÓ)ò 	4ˆØ—‘“ˆÙ˜ EÑ)ØØ!&§¡¨T°1Ó!5Ñˆ�hØ#×)Ñ)Ó+ˆØ—>‘>Ó#ˆØ×(Ñ(¨Ó5ˆÚšHØ�M‰M˜<¨Ð2Õ3ð	4ð €Mr�   rH  c                 ó†   ‡— | rt         j                  | «      sy| j                  «       Št        ˆfd„t        D «       «       S )NFc              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrŠ   r‹   )rè   ÚfragmentÚlowereds     €rŽ   rê   z5_is_safe_cli_sso_metadata_dest_key.<locals>.<genexpr>¶  s   øè ø€ ÒU¨8�8˜wÔ&ÑUùs   ƒ)r   r  ÚlowerÚanyr…   )rH  rM  s    @rŽ   Ú"_is_safe_cli_sso_metadata_dest_keyrP  ²  s8   ø€ ÙÔ/×9Ñ9¸(ÔCØØ—^‘^Ó%€GÜÓUÔ7TÔUÓUÐUÐUr�   c                 ó¸   — t        | t        «      syt        | t        «      r9t        | «      t        kD  ry| j                  d«      r| j                  d«      dk\  ryy)NFÚeyJú.é   T)r°   r~   r•   Úlenr(   r*  Úcountr²   s    rŽ   Ú#_is_safe_cli_sso_scalar_claim_valuerW  ¹  sN   € Ü�eÔ2Ô3ØÜ�%œÔÜˆu‹:Ô7Ò7ØØ×Ñ˜EÔ" u§{¡{°3Ó'7¸1Ò'<ØØr�   Úresultc                 ó†   — t        | t        «      r| S t        | d«      r"| j                  «       }t        |t        «      r|S i S )Nr¨   )r°   r0  Úhasattrr¨   )rX  Údumpeds     rŽ   Ú_sso_result_to_dictr\  Ä  s=   € Ü�&œ$ÔØˆÜˆv�|Ô$Ø×)Ñ)Ó+ˆÜ�fœdÔ#ØˆMØ€Ir�   ÚdataÚ
claim_pathc                 óô   — |sy|| v r| |   S d}|j                  d|«      j                  d«      }|D �cg c]  }|j                  |d«      ‘Œ }}| }|D ]  }t        |t        «      r
||v r||   }Œ y |S c c}w )zèResolve a dot-notation claim path against an SSO result dict.

    Unlike ``get_nested_value``, this does not strip a leading ``metadata.``
    prefix, since OIDC claims may legitimately use ``metadata`` as a top-level
    key.
    Nú ú\.rS  )ÚreplacerA  r°   r0  )r]  r^  ÚplaceholderÚpartsÚpÚcurrentÚparts          rŽ   Ú_get_nested_claim_valuerh  Î  s™   € ñ ØØ�TÑØ�JÑÐØ€KØ×Ñ˜u kÓ2×8Ñ8¸Ó=€EØ27Ö8¨QˆQ�Y‰Y�{ CÕ(Ð8€EÐ8Ø€GØò ˆÜ�gœtÔ$¨°©Ø˜d‘m‰Gáð	ð
 €Nùò 9s   ´A5c                 óÔ   — t        | dd «      }t        |t        «      r||v r||   S t        ||«      }|�|S t        | t        «      rt        | |«      S t	        | «      }t        ||«      S )NÚextra_fields)Úgetattrr°   r0  rh  r\  )rX  r^  rj  ÚnestedÚresult_dicts        rŽ   Ú_extract_sso_claim_valuern  å  sr   € Ü! &¨.¸$Ó?€LÜ�,¤Ô%Ø˜Ñ%Ø 
Ñ+Ð+Ü/°¸jÓIˆØÐØˆMä�&œ$ÔÜ& v¨zÓ:Ð:ä,¨VÓ4€KÜ" ;°
Ó;Ð;r�   r�   Úkey_pathc                 ó  — d}|j                  d|«      j                  d«      }|D �cg c]  }|j                  |d«      ‘Œ }}| }|d d D ],  }|j                  |«      }t        |t        «      si }|||<   |}Œ. |||d   <   y c c}w )Nr`  ra  rS  éÿÿÿÿ)rb  rA  rÒ   r°   r0  )	r�   ro  r®   rc  rd  re  rf  rg  Úexistings	            rŽ   Ú_set_nested_metadata_valuers  õ  sœ   € Ø€KØ×Ñ˜U KÓ0×6Ñ6°sÓ;€EØ27Ö8¨QˆQ�Y‰Y�{ CÕ(Ð8€EÐ8Ø€GØ�c�r�
ò ˆØ—;‘;˜tÓ$ˆÜ˜(¤DÔ)ØˆHØ$ˆG�D‰MØ‰ðð €GˆE�"‰IÒùò 9s   ¨Bc                 ó6  — i }d| fg}|r�|j                  «       \  }}t        |t        «      r9|}|j                  «       D ]#  \  }}|r|› d|› �n|}|j	                  ||f«       Œ% n0t        |t
        t        t        t        f«      rt        |«      r|||<   |rŒ�|S )zIExpose scalar attribution metadata as a flat dict for CLI poll responses.rä   rS  )
Úpopr°   r0  ÚitemsrC  r•   ÚintÚfloatr   rW  )	r�   Ú	flattenedÚstackÚprefixr®   Únested_itemsrÏ   rl  Únested_prefixs	            rŽ   Ú"_flatten_cli_sso_metadata_for_pollr~    s¬   € ð =?€IØ/1°8¨nÐ-=€EÙ
ØŸ	™	›‰ˆ�Ü�eœTÔ"Ø16ˆLØ+×1Ñ1Ó3ò 6‘��VÙ5; 6 (¨!¨C¨5Ñ 1À�Ø—‘˜m¨VÐ4Õ5ñ6ô ˜¤¤S¬%´Ð6Ô7Ô<_Ð`eÔ<fØ %ˆI�fÑò ð Ðr�   c                 óÌ   — t        «       }|si S i }|D ]N  \  }}t        |«      st        j                  d|«       Œ(t	        | |¬«      }t        |«      sŒAt        |||¬«       ŒP |S )zû
    Build allowlisted, non-secret scalar attribution metadata from an SSO result.

    Sources are configured via CLI_SSO_CLAIM_MAP / LITELLM_CLI_SSO_CLAIM_MAP and
    may include claims captured by GENERIC_USER_EXTRA_ATTRIBUTES on CustomOpenID.
    z4Skipping unsafe CLI SSO metadata destination key: %s)rX  r^  )r�   ro  r®   )rI  rP  r$   Údebugrn  rW  rs  )rX  Ú	claim_mapr�   rG  rH  Ú	raw_values         rŽ   Ú"build_cli_sso_attribution_metadatarƒ    sv   € ô 0Ó1€IÙØˆ	à)+€HØ"+ò 	ZÑˆ�hÜ1°(Ô;Ü ×&Ñ&Ð']Ð_gÔhØä,°FÀ|ÔTˆ	Ü2°9Ô=Øä"¨H¸xÈyÖYð	Zð €Or�   Úexisting_metadataÚattribution_metadatac                 ó
  — | |fg}|r{|j                  «       \  }}|j                  «       D ]R  \  }}|€Œ	|j                  |«      }t        |t        «      r$t        |t        «      r|j                  ||f«       ŒN|||<   ŒT |rŒ{| S )aK  Merge attribution metadata into existing user metadata in-place.

    Preserves original value types (in particular, string claim values that
    happen to look numeric are NOT coerced to ``int``/``float``). Nested dicts
    are merged iteratively so attribution claims do not clobber unrelated keys
    under the same parent.
    )ru  rv  rÒ   r°   r0  rC  )r„  r…  ÚpendingÚtargetÚsourcerÏ   r®   Úexisting_values           rŽ   Ú#_merge_cli_sso_attribution_metadatar‹  1  sŽ   € ð K\Ð]qÐIrÐHs€GÙ
Ø Ÿ™›‰ˆ�Ø Ÿ,™,›.ò 	$‰JˆC�Øˆ}ØØ#ŸZ™Z¨›_ˆNÜ˜%¤Ô&¬:°nÄdÔ+KØ—‘ °Ð6Õ7à#��s’ð	$ò ð Ðr�   Úprisma_clientÚuser_idc           	   ƒ   ó  K  — |sy 	 t        t        | «      «      j                  d|i¬«      ƒ d {  –—† }i }|�'|j                  }t	        |t
        «      rt        |«      }t        ||¬«      }t        t        | «      «      j                  d|id|i¬«      ƒ d {  –—†  t        j                  d|t        t        |«      j                  «       «      «       y 7 Œ¥7 Œ># t        $ r!}t        j                  d||«       Y d }~y d }~ww xY w­w)Nr�  ©Úwhere)r„  r…  r�   ©r�  r]  z6Persisted CLI SSO attribution metadata for user %s: %sz>Failed to persist CLI SSO attribution metadata for user %s: %s)r�   rc   Úfind_uniquer�   r°   r0  r   r‹  Úupdate_manyr$   ÚinfoÚlistr~  ÚkeysÚ	ExceptionÚerror)rŒ  r�  r…  Úuser_rowr„  Úrow_metadataÚmerged_metadataÚes           rŽ   Ú_persist_cli_sso_user_metadatar�  I  s  è ø€ ñ
  ØðqÜ -¬n¸]Ó.KÓ L× XÑ XÐ`iÐkrÐ_sÐ XÓ t×tˆØ/1ÐØÐØ"*×"3Ñ"3ˆLÜ˜,¬Ô-Ü$,¨\Ó$:Ð!ä!DØ/Ø!5ô"
ˆô œN¨=Ó9Ó:×FÑFØ˜gÐ&Ø˜oÐ.ð Gó 
÷ 	
ð 	
ô 	×!Ñ!ØDØÜÔ3Ð4HÓI×NÑNÓPÓQõ	
ð uøð	
ùô ò qÜ×"Ñ"Ð#cÐelÐno×pÑpûðqüsQ   ‚D‡)C °C±A(C ÂCÂ;C ÃDÃC ÃC Ã	DÃ#C?Ã:DÃ?DÄDÚsession_datac                 ó^   — | j                  d«      }t        |t        «      rt        |«      S i S )Nr…  )rÒ   r°   r0  r~  )rž  Ústoreds     rŽ   Ú+_cli_poll_attribution_metadata_from_sessionr¡  j  s/   € ð !×$Ñ$Ð%;Ó<€FÜ�&œ$ÔÜ1°&Ó9Ð9Ø€Ir�   Ú
verify_urlÚbrowser_complete_tokenÚprefill_user_codec           	      óŠ   — t        | d¬«      }t        |d¬«      }|rdt        |d¬«      › d�nd}|rdnd}d|› d	|› d
|› d|› d�	S )NT)Úquotez value="ú"rä   z9Confirm the verification code below to finish this login.zHEnter the verification code shown in your terminal to finish this login.a/  
    <!doctype html>
    <html>
      <head>
        <title>LiteLLM CLI Login</title>
        <style>
          body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
            margin: 0;
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            background: #f8fafc;
            color: #0f172a;
          }
          main {
            width: min(420px, calc(100vw - 32px));
            background: #ffffff;
            border: 1px solid #e2e8f0;
            border-radius: 8px;
            padding: 28px;
            box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08);
          }
          h1 { font-size: 22px; margin: 0 0 12px; }
          p { line-height: 1.5; margin: 0 0 18px; color: #334155; }
          label { display: block; font-weight: 600; margin-bottom: 8px; }
          input {
            box-sizing: border-box;
            width: 100%;
            padding: 12px;
            border: 1px solid #cbd5e1;
            border-radius: 6px;
            font-size: 20px;
            letter-spacing: 0.08em;
            text-transform: uppercase;
          }
          button {
            margin-top: 16px;
            width: 100%;
            padding: 12px;
            border: 0;
            border-radius: 6px;
            background: #0f172a;
            color: #ffffff;
            font-weight: 600;
            cursor: pointer;
          }
        </style>
      </head>
      <body>
        <main>
          <h1>Complete CLI Login</h1>
          <p>z+</p>
          <form method="post" action="zI">
            <input type="hidden" name="browser_complete_token" value="z‘" />
            <label for="user_code">Verification code</label>
            <input id="user_code" name="user_code" autocomplete="one-time-code"z‹ required autofocus />
            <button type="submit">Continue</button>
          </form>
        </main>
      </body>
    </html>
    r   )r¢  r£  r¤  Úescaped_verify_urlÚescaped_browser_complete_tokenÚuser_code_value_attrÚinstructionss          rŽ   Ú!_render_cli_sso_verification_pager¬  s  s“   € ô
 !' z¸Ô >ÐÜ,2Ð3IÐQUÔ,VÐ"ÙYj H¬VÐ4EÈTÔ-RÐ,SÐSTÑ"UÐprÐñ ñ 	DàWð ð
5ðj ˆ^ð 'Ø'9Ð&:ð ;GØGeÐFfð gPàPdÐOeð fðs?ð ?r�   z/sso/cli/startÚexperimental)ÚtagsÚinclude_in_schemac           
   ƒ   óä  K  — ddl m}m} t        | |t	        |xs i j                  dd«      «      ¬«       dt        j                  d«      › �}t        j                  d«      }t        «       }t        |«      t        t        |«      «      ddd d	œ}t        |||¬
«       t        «       r7t        t        | j                  «      d¬«      dz   t!        t"        ||dœ«      z   nd }t%        ||||¬«      S ­w)Nr   )Úcli_sso_session_cacher  r  F)r  r  r  zcli-é   é    )r)  Úuser_code_hashÚsso_completeÚuser_code_verifiedrž  ©rú   r  r3  zsso/key/generate©Úrequest_base_urlÚrouteú?©r‰  rÏ   râ   r  )r
  r±  r  r%  r   rÒ   rñ   Útoken_urlsaferù   rá   rî   r8  r  r^   r•   Úbase_urlr   r+   r  )r  r±  r  rú   r  râ   r3  r  s           rŽ   Úcli_sso_startr¿  Â  s  è ø€ çRä#ØØ#Ü Ð"2Ò"8°b×!=Ñ!=Ð>SÐUZÓ![Ó\õð œW×2Ñ2°2Ó6Ð7Ð8€HÜ ×.Ñ.¨rÓ2€KÜ2Ó4€Iô 1°Ó=Ü.Ô/KÈIÓ/VÓWØØ#Øñ€Dô ˜xÐ/DÈ4ÕPô 6Ô7ô ¬C°×0@Ñ0@Ó,AÐI[Ô\Øñää;Ø#Ø!*ñóòð ð ô (ØØØØ";ô	ð ùs   ‚C.C0z/sso/cli/complete/{login_id}c              ƒ   ó
  K  — ddl m} ddlm} ddlm} t        ||¬«      }|j                  d«      r|j                  d«      st        dd	¬
«      ‚| j                  «       ƒ d {  –—† j                  d«      }t        |«      }|j                  d«      xs dgd   }|j                  d«      xs dgd   }	t        t        |«      «      }
t        |	«      }|j                  d«      }t        |t        «      rt!        j"                  |
|«      st        dd¬
«      ‚|j                  d«      }t        |t        «      rt!        j"                  ||«      st        dd¬
«      ‚d|d<   t%        |||¬«        |«       } ||d¬«      S 7 �Œ­w)Nr   ©ÚHTMLResponse)Úrender_cli_sso_success_page©r±  ©rú   r  rµ  rž  r'  zCLI login is not readyr  rÜ   râ   rä   r£  r´  zInvalid verification codeÚbrowser_complete_token_hashTr¶  r·  éÈ   ©Úcontentr   )Úfastapi.responsesrÂ  Ú5litellm.proxy.common_utils.html_forms.cli_sso_successrÃ  r
  r±  r4  rÒ   r   ÚbodyÚdecoder   rá   rî   r°   r•   rñ   r:  r8  )r  rú   rÂ  rÃ  r±  r3  rÌ  Úform_valuesÚsupplied_user_codeÚsupplied_browser_complete_tokenÚsupplied_user_code_hashÚ$supplied_browser_complete_token_hashÚexpected_user_code_hashÚ$expected_browser_complete_token_hashÚhtml_contents                  rŽ   Úcli_sso_completerÖ  ð  so  è ø€ å.õõ Aä,°hÐF[Ô\€DØ�8‰8�NÔ#¨4¯8©8°NÔ+CÜ¨Ð4LÔMÐMà Ÿ™›×'×/Ñ/°Ó8€DÜ! $›€KØ!,§¡°Ó!=Ò!EÀ"ÀÀqÑ IÐØ.9¯o©oÐ>VÓ.WÒ._Ð\^Ð[_ÐabÑ-cÐ#Ü%9Ô:VÐWiÓ:jÓ%kÐÜ2FÐGfÓ2gÐ(à%)§X¡XÐ.>Ó%?ÐÜÐ-¬sÔ3¼7×;QÑ;QØÐ!8ô<ô ¨Ð4OÔPÐPà26·(±(Ð;XÓ2YÐ(ÜÐ:¼CÔ@Ì×H^ÑH^Ø,Ð.RôIô ¨Ð4OÔPÐPà!%€DÐ	ÑÜ˜xÐ/DÈ4ÕPá5Ó7€LÙ ¸#Ô>Ð>ð/ (ûs   ‚A"FÁ$F Á%DFÚemailc                 óL   — | €yt        | t        «      r| j                  «       S | S )aî  
    Normalize email address to lowercase for consistent storage and comparison.

    Email addresses should be treated as case-insensitive for SSO purposes,
    even though RFC 5321 technically allows case-sensitive local parts.
    This prevents issues where SSO providers return emails with different casing
    than what's stored in the database.

    Args:
        email: Email address to normalize, can be None

    Returns:
        Lowercased email address, or None if input is None
    N)r°   r•   rN  )r×  s    rŽ   Únormalize_emailrÙ    s&   € ð €}ØÜ& u¬cÔ2ˆ5�;‰;‹=Ð=¸Ð=r�   ÚLITELLM_USER_ROLE_HIERARCHYÚuser_groupsÚrole_mappingsrl   c                 óÊ  — |j                   s|j                  S t        | t        «      rt	        | «      n	t	        «       }t
        D ]q  }||j                   v sŒ|j                   |   }t        |t        «      sŒ2|j                  t	        |«      «      sŒMt        j                  d| |j                  |«       |c S  t        j                  d| |j                  «       |j                  S )a²  
    Determine the highest privilege role for a user based on their groups.

    Role hierarchy (highest to lowest):
    - proxy_admin
    - proxy_admin_viewer
    - internal_user
    - internal_user_viewer

    Args:
        user_groups: List of group names from the SSO token
        role_mappings: RoleMappings configuration object

    Returns:
        The highest privilege role found, or default_role if no matches, or None
    z/User groups %s matched role '%s' via groups: %szFUser groups %s did not match any role mappings, using default_role: %s)
ÚrolesÚdefault_roler°   r•  ÚsetrÚ  Úintersectionr$   r€  r®   )rÛ  rÜ  Úuser_groups_setÚroleÚrole_groupss        rŽ   Údetermine_role_from_groupsrå  4  sÓ   € ð( ×Òà×)Ñ)Ð)ô 2<¸KÌÔ1NœS Ô-ÔTWÓTY€Oô ,ò ˆØ�=×&Ñ&Ò&Ø'×-Ñ-¨dÑ3ˆKÜ˜+¤tÕ,°×1MÑ1MÌcÐR]ÓN^Õ1_Ü$×*Ñ*ØEÀ{ÐTX×T^ÑT^Ð`kôð ’ðô ×ÑØPØØ×"Ñ"ôð
 ×%Ñ%Ð%r�   Úaccess_token_strÚsso_jwt_handlerc                 óè  — | �r1|�r.ddl }	  |j                  | ddi¬«      }|rlt        |t        «      r+|j                  dg «      }|sH|j                  |«      }||d<   n1|rt        |dg «      ng }|s|j                  |«      }t        |d|«       t        |t        «      r|j                  d«      nt        |dd«      }|�€rd}	|�ë|j                  rß|j                  }
t        ||
«      }g }t        |t        «      r|}|D �cg c]  }t!        |«      ‘Œ }}n\t        |t         «      r>|j#                  d	«      D �cg c]#  }|j%                  «       sŒ|j%                  «       ‘Œ% }}n|�t!        |«      g}|r$t'        ||«      }	t	        j
                  d
|	|«       n|j(                  r|j(                  }	|	€Ft+        j,                  dd«      }t        ||«      }|�"t/        |«      }	t	        j
                  d|	|«       |	�9t        |t        «      r|	|d<   nt        |d|	«       t	        j
                  d|	«       |S y# |j                  j                  $ r t	        j
                  d«       Y yw xY wc c}w c c}w )aê  
    Process SSO JWT access token and extract team IDs and user role if available.

    This function decodes the JWT access token and extracts team IDs and user
    role, then sets them on the result object. Role extraction from the access
    token is needed because some SSO providers (e.g., Keycloak) do not include
    role claims in the UserInfo endpoint response.

    Args:
        access_token_str: The JWT access token string
        sso_jwt_handler: SSO-specific JWT handler for team ID extraction
        result: The SSO result object to update with team IDs and role
        role_mappings: Optional role mappings configuration for group-based role determination

    Returns:
        The decoded access token payload dict, or None if decoding failed or
        inputs were missing. Callers can pass this to _sync_user_role_from_jwt_role_map
        so it has access to custom role claims (e.g. custom_roles) that are
        encoded inside the JWT but stripped from received_response.
    r   NÚverify_signatureF©ÚoptionszYAccess token is not a valid JWT (possibly an opaque token), skipping JWT-based extractionÚteam_idsÚ	user_roler?  zFDetermined role '%s' from access token groups '%s' using role_mappingsÚGENERIC_USER_ROLE_ATTRIBUTErã  z0Extracted role '%s' from access token field '%s'z(Set user_role='%s' from JWT access token)ÚjwtrÍ  Ú
exceptionsÚDecodeErrorr$   r€  r°   r0  rÒ   Úget_team_ids_from_jwtrk  ÚsetattrrÞ  Úgroup_claimr3   r•  r•   rA  r@  rå  rß  ÚosÚgetenvrZ   )ræ  rç  rX  rÜ  rï  Úaccess_token_payloadÚresult_team_idsrì  Úexisting_rolerí  rô  Úuser_groups_rawrÛ  Ú
raw_groupsÚgÚ generic_user_role_attribute_nameÚuser_role_from_tokens                    rŽ   Úprocess_sso_jwt_access_tokenrÿ  b  sz  € ò4 šFÛð	Ø*4¨#¯*©*Ð5EÐPbÐdiÐOjÔ*kÐ ñ Ü˜&¤$Ô'Ø4:·J±J¸zÈ2Ó4N�Ù&Ø.×DÑDÐEYÓZ�HØ)1�F˜:Ò&áEK¤'¨&°*¸bÔ"AÐQS�Ù&Ø.×DÑDÐEYÓZ�HÜ˜F J°Ô9ô 4>¸fÄdÔ3K˜Ÿ
™
 ;Ô/ÔQXÐY_ÐalÐnrÓQsˆØÑ Ø15ˆIð Ð(¨]×-@Ò-@Ø%2×%>Ñ%>�Ü1AÐBVÐXcÓ1d�à)+�Ü˜o¬tÔ4Ø:I�JØ3=Ö">¨a¤3 q¥6Ð">�KÑ">Ü ´Ô5Ø6E×6KÑ6KÈCÓ6PÖ"^°ÐTU×T[ÑT[ÕT] 1§7¡7¥9Ð"^�KÑ"^Ø$Ð0Ü#& Ó#7Ð"8�KáÜ :¸;ÈÓ V�IÜ(×.Ñ.Ø`ÐbkÐmxõð #×/Ò/Ø -× :Ñ :�Ið Ð Ü:<¿)¹)ÐDaÐciÓ:jÐ0Ü.>Ð?SÐUuÓ.vÐ$Ø'Ð3Ü 5Ð6JÓ K�IÜ(×.Ñ.ØJÈIÐWwôð Ð$Ü˜f¤dÔ+Ø*3�F˜;Ò'ä˜F K°Ô;Ü$×*Ñ*Ð+UÐW`Ôaà#Ð#àøðC �~‰~×)Ñ)ò 	Ü ×&Ñ&Økôñ ð		üò@ #?ùâ"^s#   ŒH6 ÄI*Ä9I/ÅI/È6.I'É&I'Útokenc           	      ó  — | st        i «      S 	 t        t        j                  t        j                  | ddi¬«      «      «      S # t        j
                  j                  t        f$ r# t        j                  d«       t        i «      cY S w xY w)Nré  Frê  z7SSO token is not a decodable JWT, skipping token claims)
r   r­   Úvalidate_pythonrï  rÍ  rð  ÚInvalidTokenErrorr#   r$   r€  )r   s    rŽ   Ú_decode_sso_token_claimsr  Å  s|   € ÙÜ Ó#Ð#ð$ÜÜ%×5Ñ5´c·j±jÀÐQcÐejÐPkÔ6lÓmó
ð 	
øô �N‰N×,Ñ,¬oÐ>ò $Ü×"Ñ"Ð#\Ô]Ü Ó#Ò#ð$ús   �4A ÁAB
Â	B
Úuserinforq   rr   c           
      ó¼   ‡— | t        |«      t        |«      f}t        d„ |D «       «      }t        |D �‡ci c]  Š‰t        ˆfd„|D «       d «      “Œ c}«      S c c}w )Nc              3   ó.   K  — | ]  }|D ]  }|–— Œ Œ y ­wrŠ   r‹   ©rè   r‰  rÏ   s      rŽ   rê   z*_merge_sso_token_claims.<locals>.<genexpr>×  s   è ø€ Ò"O¨6ÈÒ"OÀ¤3Ð"O 3Ñ"Oùs   ‚c              3   óL   •K  — | ]  }|j                  ‰«      €Œ|‰   –— Œ y ­wrŠ   )rÒ   r  s     €rŽ   rê   z*_merge_sso_token_claims.<locals>.<genexpr>Ù  s"   øè ø€ ÒU F¸¿¹ÀC»Ñ9T�F˜3•KÑUùs   ƒ$š
$)r  Ú	frozensetr   Únext)r  rq   rr   ÚsourcesÚclaim_namesrÏ   s        `rŽ   Ú_merge_sso_token_claimsr  Ñ  s`   ø€ ð
 Ô 8¸Ó BÔD\Ð]iÓDjÐk€GÜ"Ñ"O°WÔ"OÓO€KÜØhs×tÐadˆŒdÓU¨gÔUÐW[Ó\Ñ	\Òtóð ùÚts   µAÚpremium_userc              ƒ   óL  K  — | du ry|€Ct        t        j                  j                  t        j
                  dt        j                  ¬«      ‚t        |«      j                  «       ƒ d{  –—† }|r1|dkD  r+t        dt        j
                  dt        j                  ¬«      ‚yy7 Œ8­w)z\Free tier allows SSO for up to 5 billable users; beyond that requires an Enterprise license.TNr  ©ÚmessageÚtypeÚparamÚcodeé   aˆ  You must be a LiteLLM Enterprise user to use SSO for more than 5 users. If you have a license please set `LITELLM_LICENSE` in your env. If you want to obtain a license meet with us here: https://enterprise.litellm.ai/demo You are seeing this error message because You configured SSO (one of `MICROSOFT_CLIENT_ID`, `GOOGLE_CLIENT_ID`, `GENERIC_CLIENT_ID`, or SAML) in your env. Please unset it)
rB   r:   Údb_not_connected_errorr®   rA   Ú
auth_errorr   ÚHTTP_403_FORBIDDENrc   Úcount_billable_users)r  rŒ  Úbillable_userss      rŽ   Ú%_raise_if_sso_exceeds_free_user_limitr  Ý  sŸ   è ø€ à�tÑØØÐÜÜ%×<Ñ<×BÑBÜ ×+Ñ+Ø Ü×*Ñ*ô	
ð 	
ô #1°Ó"?×"TÑ"TÓ"V×V€NÙ˜.¨1Ò,Üð _Ü ×+Ñ+Ø Ü×*Ñ*ô	
ð 	
ð -€~ð Wús   ‚A'B$Á)B"Á*9B$z/sso/key/generater‰  rÏ   Úexisting_keyÚ	return_toc              ƒ   óà  K  — ddl m}m}m}m}	m}
m} t        j                  dd«      }t        j                  dd«      }t        j                  dd«      }t        j                  d«      }|�t        |¬«      }|r
t        «       S |€|€|€t        j                  «       rt        ||	«      ƒ d{  –—†  t        «       }|�|S t        j!                  | d	¬
«      }|t"        k(  rt%        ||¬«       t        j'                  ||t)        «       r|nd¬«      }|�!	 ddlm} |j/                  | ¬«      ƒ d{  –—† S |€M|€K|€It        j                  «       r5t5        j6                  d«       t        j8                  | |
|¬«      ƒ d{  –—† S t        j;                  |||¬«      du rIt5        j6                  d|«       t        j=                  |||||| ¬«      ƒ d{  –—† }|�t?        ||«       |S ddl m!} t        j                  dd«      jE                  «       dk(  xs |jG                  dd«      du } |tI        d|¬«      d¬«      }t?        ||«       |S 7 �ŒŸ7 �Œ # t0        $ r t3        d«      ‚w xY w7 Œë7 Œš­w)úõ
    Create Proxy API Keys using Google Workspace SSO. Requires setting PROXY_BASE_URL in .env
    PROXY_BASE_URL should be the your deployed proxy endpoint, e.g. PROXY_BASE_URL="https://litellm-production-7002.up.railway.app/"
    Example:
    r   )r±  r  r  rŒ  Úuser_api_key_cacheÚ"user_custom_ui_sso_sign_in_handlerÚMICROSOFT_CLIENT_IDNÚGOOGLE_CLIENT_IDÚGENERIC_CLIENT_IDÚDISABLE_ADMIN_UIr²   ússo/callback©r  Ússo_callback_routerÅ  r¼  )ÚEnterpriseCustomSSOHandler)r  zYEnterprise features are not available. Custom UI SSO sign-in requires LiteLLM Enterprise.zRedirecting to SAML SSO login©r  r  Úrelay_state©Úmicrosoft_client_idÚgoogle_client_idÚgeneric_client_idTzRedirecting to SSO login for %s)Úredirect_urlr.  r/  r0  Ústater  rÁ  Ú%LITELLM_HIDE_DEFAULT_CREDENTIALS_HINTÚfalseÚtrueÚhide_default_credentials_hintF)Úshow_deprecation_bannerr6  rÇ  rÈ  )%r
  r±  r  r  rŒ  r!  r"  rõ  rö  rf   rM   rT   Úis_saml_configuredr  rN   ÚSSOAuthenticationHandlerÚget_redirect_url_for_ssor+   r4  Ú_get_cli_stater  Ú0litellm_enterprise.proxy.auth.custom_sso_handlerr*  Úhandle_custom_ui_sso_sign_inÚImportErrorr/  r$   r”  Úbuild_login_redirectÚshould_use_sso_handlerÚget_sso_login_redirectÚ_persist_return_to_cookierÊ  rÂ  rN  rÒ   rP   )r  r‰  rÏ   r  r  râ   r±  r  r  rŒ  r!  r"  r.  r/  r0  Ú_disable_ui_flagÚis_disabledÚmissing_env_varsr1  Ú	cli_stater*  Ússo_redirectrÂ  r6  Úform_responses                            rŽ   Úgoogle_loginrI  ò  sÍ  è ø€ ÷÷ ô "$§¡Ð+@À$Ó!GÐÜ Ÿi™iÐ(:¸DÓAÐÜ!Ÿy™yÐ)<¸dÓCÐô !Ÿi™iÐ(:Ó;ÐØÐ#Ü(Ð/?Ô@ˆÙÜ$Ó&Ð&ð 	Ð'ØÐ'ØÐ(Ü×-Ñ-Ô/ä3°LÀ-ÓP×PÐPô 7Ó8ÐØÐ#ØÐô 3×KÑKØØ)ð Ló €Lð
 Ô.Ò.Ü"¨CÐ7LÕMô $<×#JÑ#JØØÜ JÔ L‘9ÐRVð $Kó $€Ið *Ð5ð	õð 4×PÑPØð Qó ÷ ð ð 	Ð#ØÐ$ØÐ%Ü×.Ñ.Ô0ä×!Ñ!Ð"AÔBÜ$×9Ñ9ØØ$Ø!ô
÷ 
ð 	
ô 	!×7Ñ7Ø 3Ø-Ø/ð 	8ó 	
ð
 ñ	ô 	×!Ñ!Ð"CÀ\ÔRÜ$<×$SÑ$SØ%Ø 3Ø-Ø/ØØð %Tó %
÷ 
ˆð Ð#Ü% l°IÔ>ØÐå.ô 	�	‰	Ð9¸7ÓC×IÑIÓKÈvÑUò 	PØ×ÑÐ ?ÀÓGÈ4ÐOð "ñ (Ü#Ø$(Ø*Gô
ð ô€Mô ˜m¨YÔ7ØÐðw 	Qùð<úô ò 	ÜØkóð ð	úð
øð 
ús^   ‚B+I.Â-IÂ.A%I.ÄI Ä/IÄ0I Ä3AI.Å>I*Å?AI.ÇI,ÇA;I.ÉI ÉI'É'I.É,I.Újwt_handlerÚteam_mappingsrm   c                 ó.  — t        j                  dd«      }t        j                  dd«      }t        j                  dd«      }t        j                  dd«      }t        j                  d	d
«      }	t        j                  dd«      }
t        j                  dd«      }t        j                  dd «      }t        j                  d||«       g }|�0|j	                  t        t        | «      «      }|j                  |«       |�g|j                  �[t        t        t        | «      |j                  g ¬«      }|rc|j                  |«       t        j                  d|j                  |«       n0|j	                  t        t        | «      «      }|j                  |«       d }|��|j                  j                  «       dv �r|j                  }t        | |«      }g }t        |t        «      r|}|D �cg c]  }t        |«      ‘Œ }}n\t        |t        «      r>|j!                  d«      D �cg c]#  }|j#                  «       sŒ|j#                  «       ‘Œ% }}n|�t        |«      g}|r2t%        ||«      }t        j                  d|r|j&                  nd |«       n-|j(                  }t        j                  d||j(                  «       |€>t        | |«      }|�0t+        |«      }|�#|}t        j                  d|j&                  |«       d }|r7i }|j!                  d«      D ]!  }|j#                  «       }t        | |«      ||<   Œ# t-        t        | |«      t        | |«      t/        t        | |«      «      t        | |«      t        | |	«      t        | |
«      |||¬«	      S c c}w c c}w )NÚGENERIC_USER_ID_ATTRIBUTEÚpreferred_usernameÚ#GENERIC_USER_DISPLAY_NAME_ATTRIBUTEÚsubÚGENERIC_USER_EMAIL_ATTRIBUTEr×  Ú!GENERIC_USER_FIRST_NAME_ATTRIBUTEÚ
first_nameÚ GENERIC_USER_LAST_NAME_ATTRIBUTEÚ	last_nameÚGENERIC_USER_PROVIDER_ATTRIBUTEÚproviderrî  rã  ÚGENERIC_USER_EXTRA_ATTRIBUTESzJ generic_user_id_attribute_name: %s
 generic_user_email_attribute_name: %s)r]  ro  rÕ   zALoaded team_ids from DB team_mappings.team_ids_jwt_field='%s': %s)ÚgenericÚoktar?  z9Determined role '%s' from groups '%s' using role_mappingsz/No groups found in '%s', using default_role: %sz9Found valid LitellmUserRoles '%s' from SSO attribute '%s')	ÚidÚdisplay_namer×  rS  rU  rW  rì  rí  rj  )rõ  rö  r$   r€  Úget_all_jwt_team_idsr   r0  ÚextendÚteam_ids_jwt_fieldr3   rW  rN  rô  r°   r•  r•   rA  r@  rå  r®   rß  rZ   rY   rÙ  )ÚresponserJ  rç  rÜ  rK  Úgeneric_user_id_attribute_nameÚ(generic_user_display_name_attribute_nameÚ!generic_user_email_attribute_nameÚ&generic_user_first_name_attribute_nameÚ%generic_user_last_name_attribute_nameÚgeneric_provider_attribute_namerý  Úgeneric_user_extra_attributesÚ	all_teamsrì  Úteam_ids_from_db_mappingrí  rô  rú  rÛ  rû  rü  Úuser_role_from_ssorã  rj  Ú	attr_names                             rŽ   Úgeneric_response_convertorrl  y  s  € ô -/¯I©IÐ6QÐSgÓ,hÐ"Ü68·i±iÐ@eÐglÓ6mÐ,Ü/1¯y©yÐ9WÐY`Ó/aÐ%ä46·I±IÐ>aÐcoÓ4pÐ*Ü35·9±9Ð=_ÐalÓ3mÐ)ä-/¯Y©YÐ7XÐZdÓ-eÐ#ä.0¯i©iÐ8UÐW]Ó.^Ð$ä+-¯9©9Ð5TÐVZÓ+[Ð!ä×ÑØUØ&Ø)ôð €IØÐ"Ø"×7Ñ7¼¼TÀ8Ó8LÓMˆØ×Ñ˜Ô"àÐ  ]×%EÑ%EÐ%QÜ<LÜ”d˜HÓ%Ø"×5Ñ5Øô=
Ð ñ
 $Ø×ÑÐ5Ô6Ü ×&Ñ&ØSØ×0Ñ0Ø(õð ×3Ñ3´D¼¸xÓ4HÓIˆØ×Ñ˜Ô"ð *.€IàÑ  ]×%;Ñ%;×%AÑ%AÓ%Cð Hò &ð
 +×6Ñ6ˆÜ)9¸(ÀKÓ)Pˆð "$ˆÜ�o¤tÔ,Ø2AˆJØ+5Ö6 aœ3˜q�6Ð6ˆKÑ6Ü˜¬Ô-à.=×.CÑ.CÀCÓ.HÖV¨ÈAÏGÉGÍI˜1Ÿ7™7�9ÐVˆKÑVØÐ(ä˜Ó/Ð0ˆKáÜ2°;ÀÓNˆIÜ ×&Ñ&ØKÙ#,�	—’°$Øõð &×2Ñ2ˆIÜ ×&Ñ&ØAÀ;ÐP]×PjÑPjôð
 ÐÜ$4°XÐ?_Ó$`ÐØÐ)Ü/Ð0BÓCˆDØÐØ �	Ü$×*Ñ*ØOØ—J‘JØ4ôð .2€LÙ$ØˆØ6×<Ñ<¸SÓAò 	LˆIØ!Ÿ™Ó)ˆIÜ&6°xÀÓ&KˆL˜Ò#ð	Lô Ü˜HÐ&DÓEÜ% hÐ0XÓYÜÔ.¨xÐ9ZÓ[Ó\Ü# HÐ.TÓUÜ" 8Ð-RÓSÜ! (Ð,KÓLØØØ!ô
ð 
ùòW 7ùò Ws   Ç'NÈNÈ5Nr0  r1  c                 ó   — t        j                  dd«      }t        j                  dd«      j                  d«      }t        j                  dd«      }t        j                  dd«      }t        j                  dd«      }t        j                  d	d
«      j                  «       dk(  }|€+t	        dt
        j                  dt        j                  ¬«      ‚|€+t	        dt
        j                  dt        j                  ¬«      ‚|€+t	        dt
        j                  dt        j                  ¬«      ‚|€+t	        dt
        j                  dt        j                  ¬«      ‚t        j                  d|||«       t        j                  d|| «       ||||||fS )z5Setup and validate Generic SSO environment variables.ÚGENERIC_CLIENT_SECRETNÚGENERIC_SCOPEúopenid email profileú ÚGENERIC_AUTHORIZATION_ENDPOINTÚGENERIC_TOKEN_ENDPOINTÚGENERIC_USERINFO_ENDPOINTÚGENERIC_INCLUDE_CLIENT_IDr4  r5  ú2GENERIC_CLIENT_SECRET not set. Set it in .env filer  ú;GENERIC_AUTHORIZATION_ENDPOINT not set. Set it in .env fileú3GENERIC_TOKEN_ENDPOINT not set. Set it in .env fileú6GENERIC_USERINFO_ENDPOINT not set. Set it in .env fileúCauthorization_endpoint: %s
token_endpoint: %s
userinfo_endpoint: %sú/GENERIC_REDIRECT_URI: %s
GENERIC_CLIENT_ID: %s
)rõ  rö  rA  rN  rB   rA   r  r   ÚHTTP_500_INTERNAL_SERVER_ERRORr$   r€  )r0  r1  Úgeneric_client_secretÚgeneric_scopeÚgeneric_authorization_endpointÚgeneric_token_endpointÚgeneric_userinfo_endpointÚgeneric_include_client_ids           rŽ   Ú_setup_generic_sso_env_varsrƒ  ñ  s�  € ô $&§9¡9Ð-DÀdÓ#KÐÜŸ9™9 _Ð6LÓM×SÑSÐTWÓX€MÜ,.¯I©IÐ6VÐX\Ó,]Ð"Ü$&§I¡IÐ.FÈÓ$MÐÜ')§y¡yÐ1LÈdÓ'SÐÜ')§y¡yÐ1LÈgÓ'V×'\Ñ'\Ó'^ÐbhÑ'hÐð Ð$ÜØHÜ ×+Ñ+Ø)Ü×6Ñ6ô	
ð 	
ð &Ð-ÜØQÜ ×+Ñ+Ø2Ü×6Ñ6ô	
ð 	
ð Ð%ÜØIÜ ×+Ñ+Ø*Ü×6Ñ6ô	
ð 	
ð !Ð(ÜØLÜ ×+Ñ+Ø-Ü×6Ñ6ô	
ð 	
ô ×ÑØOØ&ØØ!ô	ô ×ÑÐRÐT`ÐbsÔtð 	ØØ&ØØ!Ø!ðð r�   c               ƒ   ó  K  — ddl m}  d}	 ddlm}  |d«      }t	        t        |«      «      j                  ddi¬«      ƒ d{  –—† }|r‰|j                  r}t        |j                  «      }|j                  d	«      }|rUt        |t        «      r	 | di |¤Ž}nt        || «      r|}|r,|j                  r t        j                  d
|j                  «       |S 7 Œ‘# t        $ r!}t        j                  d|«       Y d}~|S d}~ww xY w­w)z/Setup team mappings from SSO database settings.r   )rm   N©Úget_prisma_client_or_throwú7Prisma client is None, connect a database to your proxyr[  Ú
sso_configr�  rK  z2Loaded team_mappings with team_ids_jwt_field: '%s'zZCould not load team_mappings from database: %s. Continuing with config-based team mapping.r‹   )Ú/litellm.types.proxy.management_endpoints.ui_ssorm   Úlitellm.proxy.utilsr†  r¤   ra   r’  r¡   r0  rÒ   r°   r_  r$   r€  r—  )rm   rK  r†  rŒ  Ússo_db_recordÚsso_settings_dictÚteam_mappings_datarœ  s           rŽ   Ú_setup_team_mappingsrŽ  ,  s  è ø€ åLà)-€Mð
ÝBá9Ð:sÓtˆä%3Ô4GÈÓ4VÓ%W×%cÑ%cØ˜Ð&ð &dó &
÷  
ˆñ ˜]×7Ò7Ü'+¨M×,FÑ,FÓ'GÐØ(9×(=Ñ(=¸oÓ(NÐá!ÜÐ0´$Ô7Ù$0Ñ$FÐ3EÑ$F‘MÜÐ 2°LÔAØ$6�Má  ]×%EÒ%EÜ(×.Ñ.ØLÈm×NnÑNnôð Ðð/ 
ùô$ ò 
Ü×"Ñ"ØhÐjk÷	
ð 	
ð Ðûð
üsA   ‚	DŒ7C ÁCÁBC ÃDÃC Ã	DÃ C<Ã6DÃ<DÄDc               ƒ   ó¼  K  — d} 	 ddl m}  |d«      }t        t        |«      «      j	                  ddi¬«      ƒ d{  –—† }|r„|j
                  rxt        |j
                  «      }|j                  d«      }|rPt        |t        «      rt        di |¤Ž} nt        |t        «      r|} | r t        j                  d	| j                  «       t        j                  dd«      }t        j                  dd«      }t        j                  dd«      }	|�rt        j                  d«       ddl}
	 |
j#                  |«      }t        |t        «      r4d||	|dœ}t        di |¤Ž} t        j                  d| j                  «       | S 	 | S | S 7 �ŒC# t        $ r }t        j                  d
|«       Y d}~Œßd}~ww xY w# t$        $ r!}t        j&                  d|«       Y d}~| S d}~ww xY w­w)z/Setup role mappings from SSO database settings.Nr   r…  r‡  r[  rˆ  r�  rÜ  z&Loaded role_mappings for provider '%s'zTCould not load role_mappings from database: %s. Continuing with existing role logic.ÚGENERIC_ROLE_MAPPINGS_ROLESÚ!GENERIC_ROLE_MAPPINGS_GROUP_CLAIMÚ"GENERIC_ROLE_MAPPINGS_DEFAULT_ROLEzAFound role_mappings for generic provider in environment variablesrY  )rW  rô  rß  rÞ  z9Loaded role_mappings from environments for provider '%s'.zaError decoding role mappings from environment variables: %s. Continuing with existing role logic.r‹   )rŠ  r†  r¤   ra   r’  r¡   r0  rÒ   r°   rl   r$   r€  rW  r—  rõ  rö  ÚastÚliteral_evalÚ	TypeErrorr1  )rÜ  r†  rŒ  r‹  rŒ  Úrole_mappings_datarœ  Úgeneric_role_mappingsÚ!generic_role_mappings_group_claimÚ"generic_role_mappings_default_roler“  Úgeneric_user_role_mappings_datas               rŽ   Ú_setup_role_mappingsr›  P  sñ  è ø€ à)-€Mð
ÝBá9Ð:sÓtˆä%3Ô4GÈÓ4VÓ%W×%cÑ%cØ˜Ð&ð &dó &
÷  
ˆñ ˜]×7Ò7Ü'+¨M×,FÑ,FÓ'GÐØ!2×!6Ñ!6°Ó!GÐá!ÜÐ0´$Ô7Ü$0Ñ$FÐ3EÑ$F‘MÜÐ 2´LÔAØ$6�Má Ü(×.Ñ.Ð/WÐYf×YoÑYoÔpô $&§9¡9Ð-JÈDÓ#QÐÜ/1¯y©yÐ9\Ð^bÓ/cÐ%Ü02·	±	Ð:^Ð`dÓ0eÐ&ØÐ(Ü×"Ñ"Ð#fÔgÛð	ØQT×QaÑQaÐbwÓQxÐ+ÜÐ9¼4Ô@à )Ø#DØ$FØ<ñ	&Ð"ô !-Ñ BÐ/AÑ B�Ü$×*Ñ*ØOÐQ^×QgÑQgôð %Ð$ð Að" Ðˆ=Ðð_ 
úô  ò 
Ü×"Ñ"ØbÐde÷	
ñ 	
ûð
ûô6 ò 	Ü ×(Ñ(ØsÐuv÷ð ð Ðûð		üsq   ‚G†7F ½F ¾B
F ÃAGÄ&AF/ Å:GÅ<GÆ F Æ	F,ÆF'Æ"GÆ'F,Æ,GÆ/	GÆ8GÇGÇGÇGc                  óÂ   — t        j                  dd«      } | €i S i }| j                  d«      D ].  }|j                  «       }|sŒ|j                  d«      \  }}|||<   Œ0 |S )z>Parse comma-separated GENERIC_SSO_HEADERS env var into a dict.ÚGENERIC_SSO_HEADERSNr?  ú=)rõ  rö  rA  r@  )ÚrawrX  ÚheaderrÏ   r®   s        rŽ   Ú_parse_generic_sso_headersr¡  Š  si   € ä—‘Ð0°$Ó7€CØ
€{Øˆ	Ø$&€FØ—)‘)˜C“.ò  ˆØ—‘“ˆÚØŸ™ cÓ*‰JˆC�ØˆF�3ŠKð	 ð
 €Mr�   rœ  r  r€  Úadditional_headersc                 ó  — t        | «      }t        j                  dd«      j                  «       dk(  }|sŠd|v sd|j                  «       v rt|xr d|j                  «       v xs |xr d|j                  «       v }|rdnd}d	|› d
�}|r|dz  }|d|› �z  }t	        |t
        j                  dt        j                  ¬«      ‚t        | t        «      rt        j                  d| |«       | ‚t        j                  d| |«       | ‚)zDHandle errors from generic SSO verify_and_process. Always re-raises.ÚGENERIC_CLIENT_USE_PKCEr4  r5  ÚPKCEzcode verifierrZ  ÚOktazYour OAuth providerzSSO authentication failed: zÂ requires PKCE (Proof Key for Code Exchange) but it's not enabled in your LiteLLM configuration.

SOLUTION: Add this environment variable and restart your proxy:
  GENERIC_CLIENT_USE_PKCE=true

zÓFor AWS ECS: Add the environment variable to your task definition.
For Docker: Add -e GENERIC_CLIENT_USE_PKCE=true to your docker run command.
For .env file: Add GENERIC_CLIENT_USE_PKCE=true to your .env file.

zOriginal error: r  z4SSO authentication failed: %s. Passed in headers: %szEError verifying and processing generic SSO: %s. Passed in headers: %s)r•   rõ  rö  rN  rB   rA   r  r   ÚHTTP_401_UNAUTHORIZEDr°   r$   r˜  Ú	exception)	rœ  r  r€  r¢  Úerror_messageÚpkce_configuredÚis_oktaÚprovider_nameÚdetailed_messages	            rŽ   Ú_handle_generic_sso_errorr®  ˜  s?  € ô ˜q›6€Mô
  ŸY™YÐ'@À'ÓJ×PÑPÓRÐV\Ñ\€OÙ ¨-Ñ 7¸?Èm×NaÑNaÓNcÑ;cØ8Òm¸VÐGe×GkÑGkÓGmÐ=mò 
Ø"ÒO vÐ1G×1MÑ1MÓ1OÐ'Oð 	ñ *1™vÐ6Kˆð *¨-¨ð 91ð 2ð 	ñ ØðYñÐð
 	Ð.¨}¨oÐ>Ñ>ÐäØ$Ü ×+Ñ+Ø+Ü×-Ñ-ô	
ð 	
ô �!”^Ô$Ü×"Ñ"ØBØØô	
ð €Gô 	×&Ñ&ØSØØô	
ð
 €Gr�   c              ƒ   óp  ‡‡‡‡‡‡ ‡!K  — ddl m} ddlm} d Šd }t	        ||«      \  }}	}
}}} ||
||¬«      }t        «       ƒ d {  –—† Š t        «       ƒ d {  –—† Š!t        j                  dd«      j                  «       dk(  Šdt        t        t        f   d	t        fˆˆˆˆˆ ˆˆ!fd
„} |d||¬«      } ||||d|	¬«      Št        j                  d«       t        «       }d }d }	 t         j#                  | |¬«      ƒ d {  –—† }|j%                  dd «      }|j%                  dd «      }| j&                  j)                  d«      }|�r¨| j&                  j)                  d«      }| j*                  j)                  d«      }|r|rt-        j.                  ||«      s+t1        dt2        j4                  dt6        j8                  ¬«      ‚|s+t1        dt2        j4                  dt6        j8                  ¬«      ‚|s+t1        dt2        j4                  dt6        j:                  ¬«      ‚|s+t1        dt2        j4                  dt6        j:                  ¬«      ‚t=        |t        «      s+t1        dt2        j4                  dt6        j8                  ¬«      ‚t         j?                  |||||||||¬«	      ƒ d {  –—† } ||‰«      }tA        |j)                  d«      |j)                  d«      «      }|j)                  d «      }nH‰jC                  | ||¬!«      ƒ d {  –—† }‰jD                  }tA        ‰jF                  ‰jH                  «      }tK        |‰|‰ ¬"«      }|rt         jM                  |«      ƒ d {  –—†  t        j                  d#«       |xs i ‰||fS 7 �Œ>7 �Œ/7 �Œ‹7 Œè7 Œ‰7 Œ1# tN        $ r}tQ        ||
||«       Y d }~ŒKd }~ww xY w­w)$Nr   ©ÚDiscoveryDocument©Úcreate_provider©Úauthorization_endpointÚtoken_endpointÚuserinfo_endpointÚGENERIC_INCLUDE_TOKEN_CLAIMSr4  r5  r`  Úhttpx_sessionc                 ór  •— | j                  d«      }| j                  d«      }t        |t        «      r|r|n‰
j                  }t        |t        «      r|r|n‰
j                  }‰	rt        | ||¬«      n| }|j                  «       D ��ci c]  \  }}|t        vsŒ||“Œ c}}Št        |‰‰‰‰¬«      S c c}}w )Nrq   rr   )r  rq   rr   )r`  rJ  rç  rÜ  rK  )	rÒ   r°   r•   rq   rr   r  rv  rt   rl  )r`  r¹  Úresponse_id_tokenÚresponse_access_tokenrq   rr   ÚclaimsrÏ   r®   Úgeneric_include_token_claimsÚgeneric_ssorJ  Úreceived_responserÜ  rç  rK  s            €€€€€€€rŽ   Úresponse_convertorz4get_generic_sso_response.<locals>.response_convertoró  sÖ   ø€ à#+§<¡<°
Ó#;ÐØ'/§|¡|°NÓ'CÐä!+Ð,=¼sÔ!CÑHYÑÐ_j×_sÑ_sð 	ô
 Ð/´Ô5Ñ:Oñ "à×)Ñ)ð 	ñ ,ô $Ø!Ø!Ø)õð ð 	ð *0¯©«÷
Ù%˜3 ¸3ÔFYÒ;YˆC�‰Jó
Ðô *ØØ#Ø+Ø'Ø'ô
ð 	
ùó
s   Â	B3ÂB3Úoidc)ÚnameÚdiscovery_documentrÁ  T©Ú	client_idr„   Úredirect_uriÚallow_insecure_httpÚscopez&calling generic_sso.verify_and_process)r  r‚  Úcode_verifierÚ_pkce_cache_keyr  r2  Úlitellm_oauth_stateuP   Invalid OAuth state parameter â€” does not match the browser-bound state cookie.r  z&Missing authorization code in callbackz2GENERIC_CLIENT_ID must be set when PKCE is enabledr%  z7GENERIC_TOKEN_ENDPOINT must be set when PKCE is enabledrs  )	Úauthorization_coderÊ  rÆ  r„   r¶  r·  Úinclude_client_idr1  r¢  rq   rs   rr   )ÚparamsÚheaders)rÜ  zgeneric result: %s))Úfastapi_sso.sso.baser±  Úfastapi_sso.sso.genericr³  rƒ  r›  rŽ  rõ  rö  rN  r   r•   r–   r$   r€  r¡  r9  Ú!prepare_token_exchange_parametersru  Úquery_paramsrÒ   Úcookiesrñ   r:  rB   rA   r  r   ÚHTTP_400_BAD_REQUESTr§  r°   Ú_pkce_token_exchanger8   Úverify_and_processrr   rq   rs   rÿ  Ú_delete_pkce_verifierr—  r®  )"r  rJ  rç  r0  r1  r±  r³  Ússo_assertionr}  r~  r  r€  r�  r‚  Ú	discoveryrÁ  ÚSSOProviderÚ#additional_generic_sso_headers_dictrÊ  r÷  Útoken_exchange_paramsÚpkce_cache_keyrÍ  Ú	url_stateÚcookie_stateÚcombined_responserX  ræ  rœ  r¾  r¿  rÀ  rÜ  rK  s"    ``                          @@@@@rŽ   Úget_generic_sso_responserã  Ï  só  þè ø€ õ 7Ý7à%)ÐØ15€Mô 	$Ð$5°|ÓDñØØØ&ØØ!Ø!ñ )Ø=Ø-Ø3ô€Iô "6Ó!7×7€MÜ!5Ó!7×7€MÜ*,¯)©)Ð4RÐT[Ó*\×*bÑ*bÓ*dÐhnÑ*nÐ ð
¤W¬S´&¨[Ñ%9ð 
Ì&÷ 
ó 
ñ@ )ØØ$Ø-ô€Kñ
 %Ø#Ø+Ø!Ø Øô€Kô ×ÑÐGÔHÜ1KÓ1MÐ'à $€MØ(,Ððm
Ü-E×-gÑ-gØØ&?ð .hó .
÷ (
Ðð .×1Ñ1°/À4ÓHˆØ 5× 9Ñ 9Ð:KÈTÓ Rˆð
 %,×$8Ñ$8×$<Ñ$<¸VÓ$DÐâð  '×3Ñ3×7Ñ7¸Ó@ˆIØ")§/¡/×"5Ñ"5Ð6KÓ"LˆLÙ¡L¼×8NÑ8NÈyÐZfÔ8gÜ$ØoÜ(×3Ñ3Ø!Ü×4Ñ4ô	ð ñ &Ü$ØDÜ(×3Ñ3Ø Ü×4Ñ4ô	ð ñ %Ü$ØPÜ(×3Ñ3Ø-Ü×5Ñ5ô	ð ñ *Ü$ØUÜ(×3Ñ3Ø2Ü×5Ñ5ô	ð ô Ð0´#Ô6Ü$ØDÜ(×3Ñ3Ø Ü×4Ñ4ô	ð ô .F×-ZÑ-ZØ#5Ø+Ø+Ø3Ø5Ø";Ø";Ø)Ø#Fð .[ó 
.÷ 
(Ðñ (Ð(9¸;ÓGˆFÜ4Ø!×%Ñ% jÓ1Ð3D×3HÑ3HÈÓ3YóˆMð ,=×+@Ñ+@ÀÓ+PÑà&×9Ñ9ØØ,Ø;ð :ó ÷ ˆFð
  +×7Ñ7ÐÜ4°[×5IÑ5IÈ;×KdÑKdÓeˆMä;Ø˜o¨vÀ]ô 
Ðñ Ü*×@Ñ@ÀÓP×PÐPô ×ÑÐ3°VÔ<ØŠ<�RÐ*Ð,@À-ÐOÐOðK 8ùØ7ùðl(
ùð|
(øð,øð  Qùäò 
Ü!ØØ*Ø"Ø/÷		
ñ 	
ûð
üs™   ‰<N6ÁNÁN6ÁNÁBN6Ã$N Ã>N	Ã?F$N Ê#NÊ$A N ÌNÌAN ÍNÍN Í#!N6ÎN6Î	N ÎN ÎN ÎN Î	N3ÎN.Î)N6Î.N3Î3N6c              ƒ   ó
  K  — 	 t        |j                  d¬«      }t        || ¬«      }t        |t	        t
        j                  ¬«      ¬«      ƒ d{  –—† S 7 Œ# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w­w)z,Create a task for adding a member to a team.Úuser)r�  rã  )Úmemberr¼   ©rí  ©r]  Úuser_api_key_dictNú5[Non-Blocking] Error trying to add sso user to db: %s)
r=   r�  rD   rX   rE   r<   ÚPROXY_ADMINr—  r$   r€  )r¼   Ú	user_inforæ  Úteam_member_add_requestrœ  s        rŽ   Úcreate_team_member_add_taskrî  —  s‚   è ø€ ð_Ü y×'8Ñ'8¸vÔFˆÜ)=ØØô*
Ðô %Ø(Ü,Ô7G×7SÑ7SÔTô
÷ 
ð 	
ð 
ùô ò _Ü×"Ñ"Ð#ZÐ\]×^Ñ^ûð_üsA   ‚B„AA ÁAÁA ÁBÁA Á	B Á A;Á6BÁ;B Â Brì  Ú	sso_teamsc              ƒ   óV  K  — | j                   �| j                   ng }t        |«      t        |«      z
  }t        |«      }g }|D �cg c]  }t        || «      ‘Œ }}	 t	        j
                  |Ž ƒ d{  –—†  yc c}w 7 Œ
# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w­w)zq
    - Get missing teams (diff b/w user_info.team_ids and sso_teams)
    - Add missing user to missing teams
    Nrê  )	Úteamsrà  r•  rî  ÚasyncioÚgatherr—  r$   r€  )rì  rï  Ú
user_teamsÚmissing_teamsÚmissing_teams_listÚtasksr¼   rœ  s           rŽ   Úadd_missing_team_memberrø  §  s¢   è ø€ ð ,5¯?©?Ð+F˜	ŸšÈB€JÜ˜y›>¬C°
«OÑ;€MÜ $ ]Ó 3ÐØ€EØL^Ö_ÀÔ(¨°)Õ<Ð_€EÐ_ð_Ü�n‰n˜eÐ$×$Ñ$ùò `ð 	%ùÜò _Ü×"Ñ"Ð#ZÐ\]×^Ñ^ûð_üsN   ‚AB)ÁA6ÁB)ÁA= Á0A;Á1A= Á5B)Á;A= Á=	B&ÂB!ÂB)Â!B&Â&B)c                  ó–   — t         j                  } | €y| j                  d«      xs i }|j                  d«      xs g }t        d|v «      S )NFÚpersonal_key_generationÚallowed_user_rolesÚproxy_admin)ÚlitellmÚkey_generation_settingsrÒ   r   )rþ  rú  rû  s      rŽ   Ú,get_disabled_non_admin_personal_key_creationrÿ  ¹  sX   € Ü%,×%DÑ%DÐØÐ&ØØ%<×%@Ñ%@ÐAZÓ%[Ò%aÐ_aÐØ 7× ;Ñ ;Ð<PÓ QÒ WÐUWÐÜ�Ð!3Ð3Ó4Ð4r�   Ú
user_emailr!  Úproxy_logging_objc           
   ƒ   ó¨   K  — 	 t        | |||dd || ¬«      ƒ d {  –—† }|S 7 Œ# t        $ r#}t        j                  d|«       d }Y d }~|S d }~ww xY w­w)NF)r�  r   rŒ  r!  Úuser_id_upsertÚparent_otel_spanr  Ússo_user_idzError getting user object: %s)rG   r—  r$   r€  )r�  r   rŒ  r!  r  rì  rœ  s          rŽ   Úget_existing_user_info_from_dbr  Â  sl   è ø€ ðÜ)ØØ!Ø'Ø1Ø Ø!Ø/Øô	
÷ 	
ˆ	ð Ðð	
ùô ò Ü×"Ñ"Ð#BÀAÔFØŒ	àÐûð	üs6   ‚A„# š!›# ŸA¡# £	A¬A
ÁAÁ
AÁAÚuser_defined_valuesÚalternate_user_idc              ƒ   ó  K  — 	 g }|�|j                  |«       t        | t        «      s1t        | dd «      }|�Wt        |t        «      rG|j                  |«       n5| j                  dd «      }|�!t        |t        «      r|j                  |«       t        t        | t        «      st        | dd «      n| j                  dd «      «      }d }	|D ]  }
t        |
||||¬«      ƒ d {  –—† }	|	€Œ n t        j                  d|	t        j                  «       t        j                  | |	|||¬«      ƒ d {  –—† }	t        j                  | |	¬«      ƒ d {  –—†  |	S 7 Œr7 Œ'7 Œ
# t        $ r }t        j                   d|«       Y d }~y d }~ww xY w­w)Nr[  r×  )r�  r   rŒ  r!  r  z7user_info: %s; litellm.default_internal_user_params: %s)rX  rì  r   r  rŒ  )rX  rì  rê  )rC  r°   r0  rk  r•   rÒ   rÙ  r  r$   r€  rý  Údefault_internal_user_paramsr9  Úupsert_sso_userÚ#add_user_to_teams_from_sso_responser—  r¨  )rX  rŒ  r!  r  r   r  r  Úpotential_user_idsÚ_idrì  r�  rœ  s               rŽ   Úget_user_info_from_dbr  Û  s­  è ø€ ð2cØ$&ÐØÐ(Ø×%Ñ%Ð&7Ô8Ü˜&¤$Ô'Ü˜& $¨Ó-ˆCØˆ¤:¨c´3Ô#7Ø"×)Ñ)¨#Õ.à—*‘*˜T 4Ó(ˆCØˆ¤:¨c´3Ô#7Ø"×)Ñ)¨#Ô.ä$Ü2<¸VÄTÔ2JŒG�F˜G TÔ*ÐPV×PZÑPZÐ[bÐdhÓPió
ˆ
ð AEˆ	à)ò 		ˆGÜ<ØØ%Ø+Ø#5Ø"3ô÷ ˆIð Ñ$Ùð		ô 	×"Ñ"ØEÀyÔRY×RvÑRvô	
ô
 3×BÑBØØØ!Ø 3Ø'ð Có 
÷ 
ˆ	ô '×JÑJØØð Kó 
÷ 	
ð 	
ð
 Ðð9øð
øð	
ùô ò cÜ×&Ñ&Ð'^Ð`a×bÐbàûðcüsl   ‚F„CE Ã!EÃ"E Ã)AE Ä.EÄ/E ÅEÅE ÅFÅE ÅE ÅE Å	FÅ#E>Å9FÅ>FÆFÚsso_rolec                 óN   — | €yt        | «      st        j                  d| «       yy)zLreturns true if SSO upsert should use the 'role' defined on the SSO responseFz{SSO role '%s' is not a valid LiteLLM user role. Ignoring role from SSO response. See LitellmUserRoles enum for valid roles.T)r[   r$   r€  )r  s    rŽ   Ú"_should_use_role_from_sso_responser    s2   € àÐØä% hÔ/Ü×"Ñ"ð JØô	
ð Ør�   rY   c                 óÈ   — dt        |«      i}t        | dd«      }|�Et        |t        «      r|j                  n|}t        |«      r||d<   t        j                  d||«       |S )aI  
    Build the update data dictionary for SSO user upsert.

    Args:
        result: The SSO response containing user information
        user_email: The user's email from SSO
        user_id: The user's ID for logging purposes

    Returns:
        dict: Update data containing user_email and optionally user_role if valid
    r   rí  Nz"Updating user %s role from SSO: %s)rÙ  rk  r°   r<   r®   r  r$   r”  )rX  r   r�  Úupdate_datar  Ússo_role_strs         rŽ   Ú_build_sso_user_update_datar  )  sm   € ð  .:¼?È:Ó;VÐ,W€Kô ˜f k°4Ó8€HØÐä0:¸8ÔEUÔ0V˜hŸnšnÐ\dˆô .¨lÔ;Ø'3ˆK˜Ñ$Ü ×%Ñ%Ð&JÈGÐUaÔbàÐr�   rÀ  c              ƒ   ó>  K  — | �|€y| j                   j                  sy| j                   j                  sy| j                  |«      }|€yt	        j
                  d|j                  «       |�|j                  |d<   |�›|j                  |j                  k7  r�t        t        |«      «      j                  d|j                  id|j                  i¬«      ƒ d{  –—†  |j                  |_        |j                  |j                  |t        ¬«      ƒ d{  –—†  yyy7 ŒB7 Œ	­w)aY  
    Apply jwt_litellm_role_map during SSO login.

    When jwt_litellm_role_map is configured with sync_user_role_and_teams=True,
    this ensures SSO users get the same role mapping as API/JWT users. Without
    this, the SSO path falls back to INTERNAL_USER_VIEW_ONLY for roles that
    don't directly match LitellmUserRoles enum values.
    Nz)SSO jwt_litellm_role_map matched role: %srí  r�  r‘  )rÏ   r®   Ú
model_type)Úlitellm_jwtauthÚsync_user_role_and_teamsÚjwt_litellm_role_mapÚmap_jwt_role_to_litellm_roler$   r”  r®   rí  r�   rc   Úupdater�  Úasync_set_cacher;   )rJ  rÀ  rì  rŒ  r!  r  Úmapped_roles          rŽ   Ú!_sync_user_role_from_jwt_role_mapr   I  s4  è ø€ ð  ÐÐ/Ð7ØØ×&Ñ&×?Ò?ØØ×&Ñ&×;Ò;Øà$×AÑAÐBSÓT€KØÐØä×ÑÐIÈ;×K\ÑK\Ô]ð Ð&Ø+6×+<Ñ+<Ð˜KÑ(ð Ð ×!4Ñ!4¸×8IÑ8IÒ!IÜœN¨=Ó9Ó:×AÑAØ˜i×/Ñ/Ð0Ø˜{×0Ñ0Ð1ð Bó 
÷ 	
ð 	
ð *×/Ñ/ˆ	ÔØ ×0Ñ0Ø×!Ñ!ØÜ(ð 1ó 
÷ 	
ñ 	
ð "JÐð	
øð
	
ús$   ‚CDÃDÃ:DÄDÄDÄDc                 ó   — |€y | �| j                   �| j                   |d<   |j                  d«      }| r| j                  nd }t        |«      rt	        j
                  d||«       np| �| j                  €3t        j                  j                  |d<   t	        j                  d«       n/| j                  |d<   t	        j                  d| j                  «       | �'t        | d«      r| j                  r| j                  |d<   |S )Nr�  rí  z$Using SSO role: %s (DB role was: %s)z?No SSO or DB role found, using default: INTERNAL_USER_VIEW_ONLYzUsing DB role: %sr¾   )r�  rÒ   rí  r  r$   r”  r<   ÚINTERNAL_USER_VIEW_ONLYr®   r€  rZ  r¾   )rì  r  r  Údb_roles       rŽ   Ú1apply_user_info_values_to_sso_user_defined_valuesr$  x  sý   € ð Ð"ØØÐ ×!2Ñ!2Ð!>Ø)2×):Ñ):Ð˜IÑ&ð *×-Ñ-¨kÓ:€HÙ,5�Y×(Ò(¸4€Gä)¨(Ô3ä×!Ñ!Ð"HÈ(ÐT[Õ\ð Ð 	× 3Ñ 3Ð ;Ü/?×/WÑ/W×/]Ñ/]Ð Ñ,Ü ×&Ñ&Ð'hÕià/8×/BÑ/BÐ Ñ,Ü ×&Ñ&Ð':¸I×<OÑ<OÔPð Ð¤¨°HÔ!=À)×BRÒBRØ(1×(8Ñ(8Ð˜HÑ%àÐr�   rí  c              ƒ   óV  K  — t        j                  d«      }|�‹||k(  r†| r| t        j                  j                  k(  r| S |rIt        t        |«      «      j                  d|idt        j                  j                  i¬«      ƒ d{  –—†  t        j                  j                  } | S 7 Œ ­w)z`
    - Check if user role in DB is admin
    - If not, update user role in DB to admin role
    ÚPROXY_ADMIN_IDNr�  rí  r‘  )rõ  rö  r<   rë  r®   r�   rc   r  )rí  r�  rŒ  Úproxy_admin_ids       rŽ   Ú"check_and_update_if_proxy_admin_idr(  ™  s§   è ø€ ô
 ŸI™IÐ&6Ó7€NØÐ! n¸Ò&?Ù˜Ô&6×&BÑ&B×&HÑ&HÒHØÐáÜ¤¨}Ó =Ó>×EÑEØ  'Ð*Ø!Ô#3×#?Ñ#?×#EÑ#EÐFð Fó ÷ ð ô
 %×0Ñ0×6Ñ6ˆ	àÐðús   ‚BB)ÂB'Â!B)z/sso/callbackr2  c              ƒ   ó>  K  — t        j                  d|«       | j                  j                  d«      }|rS| j                  j                  d«      }t        j                  d||«       t        dd|› �|rd|› �z   ¬	«      ‚dz   ¬	«      ‚d
dlm} d
dlm	} d
dl
m} d
dlm}m}m}	m}
m} |
€%t        dt$        j&                  j(                  ¬	«      ‚d}|j                  dd«      }|�St+        |t,        «      rC |«       }|j/                  |
| ||j                  di «      j                  dd«      ¬«      d
¬«       t1        j2                  dd«      }t1        j2                  dd«      }t1        j2                  dd«      }d}d}d}|	€+t5        dt6        j8                  dt:        j<                  ¬«      ‚t>        jA                  | d¬«      }t        j                  d|«       d}|�!tB        jE                  | ||¬«      ƒ d{  –—† }nB|�!tF        jI                  | ||¬«      ƒ d{  –—† }n|�tK        | ||||¬ «      ƒ d{  –—† \  }}}}|€t        dd!¬	«      ‚|r~|jM                  |› d"�«      rj|jO                  d"d#«      }tQ        |«      d$kD  r|d$   nd}tQ        |«      d#kD  r|d#   nd}t        j                  d%«       tS        | |||||¬&«      ƒ d{  –—† S | jT                  j                  d'«      }t>        jW                  || |||||||¬(«	      ƒ d{  –—† S 7 �Œ7 Œ÷7 ŒÞ7 ŒL7 Œ­w))zVerify loginz$Starting SSO callback with state: %sr˜  Úerror_descriptionz6SSO callback received OAuth error: %s, description: %sé‘  zOAuth error: z, error_description: rä   r  r   ©Ú LITELLM_CLI_SESSION_TOKEN_PREFIX©ÚLiteLLM_JWTAuthrJ   )r  rJ  Ú
master_keyrŒ  r!  Néô  Úui_access_modeÚsso_group_jwt_field©r_  ©rŒ  r!  r  Úleewayr#  r$  r%  zùMaster Key not set for Proxy. Please set Master Key to use Admin UI. Set `LITELLM_MASTER_KEY` in .env or set general_settings:master_key in config.yaml.  https://docs.litellm.ai/docs/proxy/virtual_keys. If set, use `--detailed_debug` to debug issue.r0  r  r'  r(  úRedirecting to %s)r  r/  r1  )r  r.  r1  ©r  rJ  r0  r1  rç  z$Result not returned by SSO provider.rü   rT  r  zCLI SSO callback detected)r  rÏ   r¤  rX  rÀ  rÚ  Úlitellm_cp_return_to)	rX  r  rÀ  r0  r2  r÷  rJ  r  rÚ  ),r$   r”  rÔ  rÒ   r1  r   Úlitellm.constantsr-  Úlitellm.proxy._typesr/  Úlitellm.proxy.auth.handle_jwtrK   r
  r  rJ  r0  rŒ  r!  r:   r  r®   r°   r0  Úupdate_environmentrõ  rö  rB   rA   r  r   r|  r9  r:  ÚGoogleSSOHandlerÚget_google_callback_responseÚMicrosoftSSOHandlerÚget_microsoft_callback_responserã  r*  rA  rU  Úcli_sso_callbackrÕ  Ú!get_redirect_response_from_openid)r  r2  Úoauth_errorÚoauth_error_descriptionr-  r/  rK   r  rJ  r0  rŒ  r!  rç  r2  r.  r/  r0  rÀ  r÷  rÚ  r1  rX  Ústate_partsÚkey_idr¤  Úcp_return_tos                             rŽ   Úauth_callbackrI  ®  s›  è ø€ ô ×ÑÐDÀeÔLà ×-Ñ-×1Ñ1°'Ó:€KÙØ)0×)=Ñ)=×)AÑ)AÐBUÓ)VÐÜ×$Ñ$ØDÀkÐSjô	
ô ØØ" ; -Ð0ÙD[Ð&Ð'>Ð&?Ð@ñeô
ð 	
ð bdñeô
ð 	
õ CÝ4Ý8÷õ ð ÐÜ¨Ô4E×4\Ñ4\×4bÑ4bÔcÐcà)-€OØ,×0Ñ0Ð1AÀ4ÓH€NØÐ!¤j°ÄÔ&FÙ$›,ˆØ×*Ñ*Ø'Ø1Ù+Ø#3×#7Ñ#7Ð8HÈ"Ó#M×#QÑ#QÐRgÐimÓ#nôð ð 	+ô 	
ô "$§¡Ð+@À$Ó!GÐÜ Ÿi™iÐ(:¸DÓAÐÜ!Ÿy™yÐ)<¸dÓCÐØ%)ÐØ(,ÐØ15€MàÐÜð PÜ ×+Ñ+ØÜ×6Ñ6ô	
ð 	
ô ,×DÑDÈWÐiwÐDÓx€Lä×ÑÐ1°<Ô@Ø€FØÐ#Ü'×DÑDØØ-Ø%ð Eó 
÷ 
‰ð
 
Ð	(Ü*×JÑJØØ 3Ø%ð Kó 
÷ 
‰ð 
Ð	&ô +ØØ#Ø/Ø%Ø+ô
÷ 
ñ	
ØØØ Øð €~ÜØØ9ô
ð 	
ñ
 �×!Ñ!Ð%EÐ$FÀaÐ"HÔIà"Ÿ[™[¨¨aÓ0ˆÜ*-¨kÓ*:¸QÒ*>˜ AšÀDˆÜ58¸Ó5EÈÒ5I ;¨q¢>ÈtÐä×!Ñ!Ð"=Ô>Ü%ØØØ/ØØ/Ø'ô
÷ 
ð 	
ð '.§o¡o×&9Ñ&9Ð:PÓ&Q€Lä)×KÑKØØØ+Ø+Ø%Ø1ØØØ#ð Ló 
÷ 
ð 
ði
ùð
øð
øð*
øð
ús\   ‚G8LÇ:LÇ;"LÈLÈLÈ8LÈ9BLËLËA LÌLÌLÌLÌLÌLÌLz/sso/saml/loginc              ƒ   ó´   K  — ddl m} t        j                  d«      }|�t	        |¬«      r
t        «       S t        j                  | ||¬«      ƒ d{  –—† S 7 Œ­w)zBSP-initiated SAML login. Redirects the user to the configured IdP.r   ©r!  r&  Nr²   r+  )r
  r!  rõ  rö  rf   rM   rT   r?  )r  r  r!  rC  s       rŽ   Ú
saml_loginrL  /  sO   è ø€ õ >ä Ÿi™iÐ(:Ó;ÐØÐ#¬Ð:JÕ(KÜ Ó"Ð"ä ×5Ñ5¸gÐM_ÐmvÔw×wÐwÐwús   ‚AAÁAÁAz/sso/saml/metadatac              ƒ   ór   K  — ddl m} t        j                  | |¬«      ƒ d{  –—† }t	        |d¬«      S 7 Œ­w)zEService Provider metadata XML, for registering this proxy at the IdP.r   rK  )r  r  Nzapplication/xml)rÉ  Ú
media_type)r
  r!  rT   Úbuild_sp_metadatar   )r  r!  r�   s      rŽ   Úsaml_metadatarP  ;  s5   è ø€ õ >ä+×=Ñ=ÀgÐUgÔh×h€HÜ˜HÐ1BÔCÐCð iús   ‚!7£5¤7z/sso/saml/callbackc           
   ƒ   óâ  K  — ddl m}m}m}m}m}m} t        j                  d«      }|�t        |¬«      r
t        «       S |€%t        dt        j                  j                  ¬«      ‚|€+t        dt         j"                  d	t$        j&                  ¬
«      ‚t)        j*                  | «      ƒ d{  –—† }d|vrt        dd¬«      ‚t)        j,                  | ||¬«      ƒ d{  –—† }	t/        ||«      ƒ d{  –—†  |j1                  dd«      }
|j1                  d«      }t3        |t4        «      rt6        j9                  |«      r|nd}t6        j;                  |	| dd|
d||¬«      ƒ d{  –—† S 7 Œº7 Œ‹7 Œy7 Œ
­w)zPAssertion Consumer Service. Validates the IdP assertion and issues a UI session.r   )r  rJ  r0  r  rŒ  r!  r&  Nr²   r1  r  zmMaster Key not set for Proxy. Set `LITELLM_MASTER_KEY` in .env or general_settings:master_key in config.yaml.r0  r  ÚSAMLResponser'  z)Missing SAMLResponse in callback request.)r  r  Ú	post_datar2  Ú
RelayState)rX  r  rÀ  r0  r2  r÷  rJ  r  )r
  r  rJ  r0  r  rŒ  r!  rõ  rö  rf   rM   r   r:   r  r®   rB   rA   r  r   r|  rT   Úread_acs_post_dataÚ
handle_acsr  rÒ   r°   r•   r9  Ú_validate_return_torC  )r  r  rJ  r0  r  rŒ  r!  rC  rS  rX  r2  r,  rH  s                rŽ   Úsaml_callbackrX  D  ss  è ø€ ÷÷ ô !Ÿi™iÐ(:Ó;ÐØÐ#¬Ð:JÕ(KÜ Ó"Ð"àÐÜ¨Ô4E×4\Ñ4\×4bÑ4bÔcÐcØÐÜð DÜ ×+Ñ+ØÜ×6Ñ6ô	
ð 	
ô -×?Ñ?ÀÓH×H€IØ˜YÑ&Ü¨Ð4_Ô`Ð`ä)×4Ñ4¸WÐL^ÐjsÔt×t€Fä
/°¸mÓ
L×LÐLà,×0Ñ0Ð1AÀ4ÓH€NØ"Ÿ™ |Ó4€Kô �k¤3Ô'Ô,D×,XÑ,XÐYdÔ,eñ 	àð ô *×KÑKØØØØØ%Ø!ØØð Ló 	÷ 	ð 	ð! Iøð uøàLøð	úsI   ‚B*E/Â,E'Â-0E/ÃE)ÃE/Ã1E+Ã2A0E/Å"E-Å#E/Å)E/Å+E/Å-E/Úparsed_openid_resultc           	   ƒ   ó@  K  — ddl m} |}|j                  d«      }|�0t        j                  |«      r || «      ƒ d {  –—† S t        d«      ‚|€y t        g ||j                  d«      t        j                  |j                  d«      t        j                  ¬«      S 7 Œ]­w)Nr   )Úuser_custom_ssor�  ú,user_custom_sso must be a coroutine functionr   rí  ©r¾   r�  r   Ú
max_budgetrí  Úbudget_duration)
r
  r[  rÒ   ÚinspectÚiscoroutinefunctionr/  rC   rý  Úmax_internal_user_budgetÚinternal_user_budget_duration)rX  rY  r[  Úcustom_sso_handlerr�  s        rŽ   Ú"_build_cli_sso_user_defined_valuesre  z  sž   è ø€ õ ;à7FÐØ)×-Ñ-¨iÓ8€GØÐ%Ü×&Ñ&Ð'9Ô:Ù+¨FÓ3×3Ð3ÜÐGÓHÐHØ€ØÜØØØ'×+Ñ+¨LÓ9Ü×3Ñ3Ø&×*Ñ*¨;Ó7Ü×=Ñ=ôð ð	 4ús   ‚<B¾B¿ABÚteam_rowc                 óÄ   — t         j                  | «      }|j                  }t        |j                  |j
                  |j                  |�|j                  ¬«      S d ¬«      S )N)r¼   r½   rÃ   rÄ   )r»   Úmodel_validater¿   rÂ   r¼   r½   r¾   r·   )rf  ÚteamÚalias_tables      rŽ   Ú_cli_sso_team_detailrk  ’  s^   € Ü ×/Ñ/°Ó9€DØ×1Ñ1€KÜØ—‘Ø—?‘?Ø—K‘KØ8CÐ8O˜;×4Ñ4ô	ð ð VZô	ð r�   rñ  c              ƒ   óø   K  — |sy	 t        t        | «      «      j                  dd|iiddi¬«      ƒ d{  –—† }t        d	„ |D «       «      S 7 Œ# t        $ r }t	        j
                  d|«       Y d}~yd}~ww xY w­w)
z[``None`` means the lookup itself failed, which is not the same as the user having no teams.r‹   r¼   Úinr¿   T)r�  ÚincludeNz3Error fetching team details for CLI SSO session: %sc              3   óN   K  — | ]  }t        |j                  «       «      –— Œ y ­wrŠ   )rk  r¨   )rè   rf  s     rŽ   rê   z-fetch_cli_sso_team_details.<locals>.<genexpr>¬  s   è ø€ ÒZÀÔ% h×&9Ñ&9Ó&;×<ÑZùrô   )r«   rb   Ú	find_manyr—  r$   r˜  rÀ   )rŒ  rñ  Úprisma_teamsrœ  s       rŽ   Úfetch_cli_sso_team_detailsrr  �  sŠ   è ø€ ñ
 ØðÜ$3´NÀ=Ó4QÓ$R×$\Ñ$\Ø˜t U˜mÐ,Ø*¨DÐ1ð %]ó %
÷ 
ˆô ÑZÈ\ÔZÓZÐZð
ùô ò Ü×"Ñ"Ð#XÐZ[Ô\Üûðüs=   ‚A:‡.A µA¶A ºA:ÁA Á	A7ÁA2Á-A:Á2A7Á7A:Úteam_detailsc                 óZ   — | D �cg c]  }|j                   €Œ|j                   ‘Œ c}S c c}w )a7  The teams a login may bind to: only those whose row still exists.

    A team deleted out from under a membership, which is what deleting an organization
    leaves behind, can never resolve its grants, so offering it would refuse every
    future login for that user with nothing they could do to recover.
    ©r¼   )rs  r!  s     rŽ   Ú_cli_sso_session_teamsrv  ¯  s%   € ð *6ÖT˜v¸¿¹Ñ9SˆF�N‹NÒTÐTùÒTs   …(—(r¼   c                 óˆ   ‡— ‰€t         S 	 t        j                  | «      }t	        ˆfd„|D «       d«      S # t        $ r Y yw xY w)z•``None`` means the team's grants are unknown. An empty grant is a real value meaning unrestricted,
    so an unknown one must not be minted as empty.Nc              3   óB   •K  — | ]  }|j                   ‰k(  sŒ|–— Œ y ­wrŠ   ru  )rè   r!  r¼   s     €rŽ   rê   z/selected_cli_sso_team_detail.<locals>.<genexpr>Â  s   øè ø€ ÒK˜F°·±À7Ó1J”ÑKùs   ƒ˜)rÇ   rÆ   r  r#   r  )rs  r¼   Údetailss    ` rŽ   Úselected_cli_sso_team_detailrz  ¹  sN   ø€ ð €Ü,Ð,ðÜ6×FÑFÀ|ÓTˆô ÓK gÔKÈTÓRÐRøô ò Ùðús   ‹5 µ	AÁ A)r¤  rÚ  r±  rÚ  c           
   ƒ   ó’  K  — ddl m} |j                  d«      }|j                  d«      }t        ||||	|||¬«      ƒ d {  –—† }|€t	        dd¬«      ‚|j
                  st	        dd¬«      ‚t        |j
                  |¬	«      ƒ d {  –—†  g }t        |d
«      r4|j                  r(t        |j                  t        «      r|j                  ng }t        ||¬«      ƒ d {  –—† }|€t	        dd¬«      ‚t        |«      }t        |¬«      }|r.t        |t        t         |j
                  «      |¬«      ƒ d {  –—†  t        t         |j
                  «      |j"                  t        |d«      r|j$                  ng |||D �cg c]  }|j'                  «       ‘Œ c}|dœ|d<   d|d<   t)        j*                  d«      }t-        |«      |d<   t/        |||¬«       t1        j2                  d|j
                  |t5        |«      «       t7        t!        | j8                  «      d|› �¬«      } |t;        |||
¬«      d¬«      S 7 �Œö7 �Œ²7 �Œ^7 �Œc c}w ­w)Nr   rÁ  r�  r   ©rX  rŒ  r!  r  r   r  r  r1  z,Failed to retrieve user information from SSOr  ©r�  Ú	assertionrñ  )rŒ  rñ  zDCould not resolve team model grants for this login. Please try again)rX  )rŒ  r�  r…  r¾   )r�  rí  r¾   r   rñ  rs  r…  rž  Trµ  r³  rÆ  r·  z=Stored CLI SSO session for user: %s, teams: %s, num_teams: %szsso/cli/complete/r¸  )r¢  r£  r¤  rÇ  rÈ  )rÊ  rÂ  rÒ   r  r   r�  r9   rZ  rñ  r°   r•  rr  rv  rƒ  r�  r   r•   rí  r¾   r¨   rñ   r½  rá   r8  r$   r”  rU  r^   r¾  r¬  )r  rÏ   r3  rX  rY  r  rŒ  r!  r±  r  r¤  rÚ  rÂ  r�  r   rì  rñ  rs  Úresolved_teamsr…  r!  r£  r¢  s                          rŽ   Ú"_complete_cli_sso_callback_sessionr€  Å  sO  è ø€ õ /à)×-Ñ-¨iÓ8€GØ,×0Ñ0°Ó>€JÜ2ØØ#Ø-Ø+ØØ/Ø!ô÷ €Ið ÐÜ¨Ð4bÔcÐcØ×ÒÜ¨Ð4bÔcÐcä
/¸	×8IÑ8IÐUbÔ
c×cÐcà€EÜˆy˜'Ô" y§¢Ü#-¨i¯o©o¼tÔ#D�	—’È"ˆä :ÈÐ^cÔ d×d€LØÐÜØØYô
ð 	
ô 3°<Ó@€NÜ"DÈFÔ"SÐÙÜ,Ø'Üœ˜i×/Ñ/Ó0Ø!5ô
÷ 	
ð 	
ô œ˜Y×.Ñ.Ó/Ø×(Ñ(Ü&-¨i¸Ô&B�)×"Ò"ÈØ ØØ;GÖH°˜×*Ñ*Õ,ÒHØ 4ñ€DˆÑð  €DˆÑÜ$+×$9Ñ$9¸"Ó$=ÐÜ*>Ð?UÓ*V€DÐ	&Ñ'Ü˜sÐ*?ÀdÕKä×ÑØGØ×ÑØÜˆNÓô	ô 'Ü˜W×-Ñ-Ó.Ø! # Ð'ô€Jñ Ü1Ø!Ø#9Ø/ô
ð
 ôð ðwùð dùð eùð	
ûò Iùs^   ‚>IÁ H6ÁAIÂH9ÂAIÃH<ÃAIÄ4H?Ä5AIÅ<IÆB$IÈ9IÈ<IÈ?IÉIc              ƒ   óÖ  K  — t        j                  d«       ddlm}m}m}m}	m}
 t        ||¬«      }|€%t        dt        j                  j                  ¬«      ‚|€t        dd¬«      ‚t        t        t        z  |«      }	 t         j#                  |t%        j&                  d	d«      ¬
«      }t        j(                  d|«       t+        ||¬«      ƒ d{  –—† }t         j-                  |||¬«       t/        | t        t0        |«      ||||||
||	||¬«      ƒ d{  –—† S 7 ŒI7 Œ# t2        $ r ‚ t        $ r ‚ t4        $ r+}t        j6                  d|«       t        dd|› �¬«      ‚d}~ww xY w­w)zDCLI SSO callback - stores session info for JWT generation on pollingzCLI SSO callbackr   )r±  r  rŒ  r  r!  rÅ  Nr1  r  z<SSO authentication failed - no result returned from providerr%  ©rX  r0  zparsed_openid_result: %s)rX  rY  ©r  rX  rÀ  )r  rÏ   r3  rX  rY  r  rŒ  r!  r±  r  r¤  rÚ  zError with CLI SSO callback: %szFailed to process CLI SSO: )r$   r”  r
  r±  r  rŒ  r  r!  r4  r   r:   r  r®   r   ro   r0  r9  Ú"_get_user_email_and_id_from_resultrõ  rö  r€  re  Ú#verify_user_in_restricted_sso_groupr€  r•   rB   r—  r˜  )r  rÏ   rX  rÀ  r¤  rÚ  r±  r  rŒ  r  r!  r3  Úresult_non_nonerY  r  rœ  s                   rŽ   rB  rB  	  sŒ  è ø€ ô ×ÑÐ0Ô1÷õ ô -°cÐAVÔW€DàÐÜ¨Ô4E×4\Ñ4\×4bÑ4bÔcÐcà€~ÜØØQô
ð 	
ô -1´¼$±ÀÓ,G€Oð%WÜ&>×&aÑ&aØ"Ü Ÿi™iÐ(;¸TÓBð 'bó '
Ðô 	×"Ñ"Ð#=Ð?SÔTÜ+MØ"Ø!5ô,
÷ &
Ðô
 	!×DÑDØ-Ø"Ø/ð 	Eô 	
ô 8ØÜ”S˜#“ØØ"Ø!5Ø 3Ø'Ø1Ø"7Ø/Ø/Ø'ô
÷ 
ð 	
ð&
øð
ùô ò ØÜò ØÜò WÜ×"Ñ"Ð#DÀaÔHÜ¨Ð6QÐRSÐQTÐ4UÔVÐVûðWüsP   ‚A>E)ÂAD  ÃDÃAD  ÄDÄD  ÄE)ÄD  ÄD  Ä E&Ä;&E!Å!E&Å&E)z/sso/cli/poll/{key_id})rÕ   rG  Úx_litellm_cli_poll_secretc           	   ƒ   óì  K  — ddl m} ddlm} 	 t	        | |¬«      }t        ||¬«      st        dd¬«      ‚|j                  d	«      r|j                  d
«      sddiS |j                  d«      }t        |t        «      �r¬|j                  dg «      }|j                  d«      }|d   }	t        j                  d|	||t        |«      «       |€lt        |«      dkD  r^t        j                  d|	|«       d}
t        |t        «      r|r|}
n|r|D �cg c]  }|ddœ‘Œ	 }
}d|	||
ddœ}t        |«      }|r||d<   |S |�||vr(t        dd|› d|› �¬«      ‚t        |«      dkD  r|d   nd}t        ||¬«      }|€t        dd|› d�¬«      ‚t!        |	|d    |j                  d!g «      ¬"«      } |j"                  |||j$                  |j&                  |j(                  d¬#«      }|j+                  t-        | «      ¬$«       t        j                  d%|	|«       d||	|||d&œ}t        |«      }|r||d<   |S ddiS c c}w # t        $ r ‚ t.        $ r+}t        j0                  d'|«       t        dd(|› �¬«      ‚d}~ww xY w­w))a“  
    CLI polling endpoint - retrieves session from cache and generates JWT.

    Flow:
    1. First poll (no team_id): Returns teams list without generating JWT
    2. Second poll (with team_id): Generates JWT with selected team and deletes session

    Args:
        key_id: The CLI login session ID
        team_id: Optional team ID to assign to the JWT. If provided, must be one of user's teams.
    r   )rF   rÄ  rÅ  )r3  r  i“  zInvalid CLI polling secretr  rµ  r¶  r   r‡  rž  rñ  rs  r�  z:CLI poll: user=%s, team_id=%s, user_teams=%s, num_teams=%sNr  z3Returning teams list for user %s to select from: %s©r¼   r½   ÚreadyT)r   r�  rñ  rs  Úrequires_team_selectionr…  zUser does not belong to team: z. Available teams: )rs  r¼   r1  z-Could not resolve the model grants for team: z. Please run `lite login` againrí  r¾   )r�  rí  r¾   )rì  r¼   r½   rÃ   rÄ   r^  r(  z(CLI JWT generated for user: %s, team: %s)r   rÏ   r�  r¼   rñ  rs  zError polling for CLI JWT: %szError checking session status: )Úlitellm.proxy.auth.auth_checksrF   r
  r±  r4  r=  r   rÒ   r°   r0  r$   r”  rU  r•  r¡  rz  r;   Úget_cli_jwt_auth_tokenr½   rÃ   rÄ   Údelete_cacherþ   r—  r˜  )rG  r¼   r‡  rF   r±  r3  rž  rô  Úuser_team_detailsr�  Úteam_details_responseÚtÚpoll_responser…  Úselected_teamrì  Ú	jwt_tokenrœ  s                     rŽ   Úcli_poll_keyr•  f	  s  è ø€ õ" FÝ@ðm[Ü0¸&ÐH]Ô^ˆÜ*°ÐB[Õ\Ü¨CÐ8TÔUÐUà�x‰x˜Ô'¨t¯x©xÐ8LÔ/MØ˜iÐ(Ð(à"Ÿh™h ~Ó6ˆä�l¤DÕ)Ø ,× 0Ñ 0°¸"Ó =ˆJØ'3×'7Ñ'7¸Ó'GÐØ)¨)Ñ4ˆGä ×%Ñ%ØLØØØÜ�J“ôð ˆ¤3 z£?°QÒ#6Ü$×)Ñ)Ð*_ÐahÐjtÔuð IMÐ%ÜÐ/´Ô6Ñ;LØ,=Ñ)ÙØYcÖ,dÐTU¸È$Ó-OÐ,dÐ)Ð,dà%Ø&Ø'Ø$9Ø/3ñ4�ô (SÐS_Ó'`Ð$Ù'Ø<P�MÐ"8Ñ9Ø$Ð$ð Ð"Ø *Ñ,Ü'Ø$'Ø!?À¸yÐH[Ð\fÐ[gÐhôð ô ,/¨z«?¸QÒ+>˜* Qš-ÀD�ä#?Ø.Øô$ˆMð Ð$Ü#Ø #ØJÈ7È)ÐSrÐsôð ô
  1ØØ& {Ñ3Ø#×'Ñ'¨°"Ó5ô ˆIð  MÐ5×LÑLØ#ØØ(×3Ñ3Ø)×5Ñ5Ø#0×#CÑ#CØô ˆIð "×.Ñ.Ô3NÈvÓ3VÐ.ÔWä ×%Ñ%Ð&PÐRYÐ[bÔcà!Ø Ø"Ø"Ø#ð !2ñ	ˆMô $OÈ|Ó#\Ð Ù#Ø8L�Ð4Ñ5Ø Ð à˜iÐ(Ð(ùòI -eøôL ò ØÜò [Ü×"Ñ"Ð#BÀAÔFÜ¨Ð6UÐVWÐUXÐ4YÔZÐZûð[üsa   ‚I4�AH4 ÁI4ÁB0H4 ÄH/ÄH4 Ä6I4Ä7C3H4 È*I4È+H4 È.I4È/H4 È4I1É&I,É,I1É1I4Úresult_openidc           	   ƒ   óÆ  K  — t        j                  d|«       | €t        d«      ‚t        | t        «      rt        di | ¤Ž} |€t        d«      ‚t        j                  rx|j                  d«      }t        |«      r=|}|j                  t        j                  «       ||d<   t        j                  d|«       n|j                  t        j                  «       |j                  d«      t        j                  j                  k(  rH|j                  d«      €t        j                  |d<   |j                  d«      €t        j                  |d<   |d   €t        j                   |d<   t#        |d	   t%        |d
   «      |d   |d   |d   |d	   d¬«      }| rt'        | d«      rdt)        | d«      i|_        t-        |t/        t        j0                  ¬«      ¬«      ƒ d{  –—† }|S 7 Œ­w)ar  
    Helper function to create a New User in LiteLLM DB after a successful SSO login

    Args:
        result_openid (OpenID): User information in OpenID format if the login was successful.
        user_defined_values (Optional[SSOUserDefinedValues], optional): LiteLLM SSOValues / fields that were read

    Returns:
        Tuple[str, str]: User ID and User Role
    z+Inserting SSO user into DB. User values: %sNzresult_openid is Nonezuser_defined_values is Nonerí  z!Preserved SSO-extracted role '%s'r^  r_  r�  r   F)r�  r   rí  r^  r_  r  Úauto_create_keyrW  Úauth_providerrç  rè  r‹   )r$   r€  r/  r°   r0  ro   rý  r
  rÒ   r  r  r<   ÚINTERNAL_USERr®   rb  rc  r"  r?   rÙ  rZ  rk  r�   rR   rE   rë  )r–  r  r  Úpreserved_roleÚnew_user_requestr`  s         rŽ   Úinsert_sso_userr�  ê	  sÞ  è ø€ ô ×ÑÐLÐNaÔbØÐÜÐ0Ó1Ð1Ü�-¤Ô&ÜÑ/ Ñ/ˆàÐ"ÜÐ6Ó7Ð7ô ×+Ò+ð .×1Ñ1°+Ó>ˆÜ-¨hÔ7à$,ˆNØ×&Ñ&¤w×'KÑ'KÔLØ/=Ð Ñ,Ü ×&Ñ&Ð'JÈNÕ[ð  ×&Ñ&¤w×'KÑ'KÔLð ×Ñ˜{Ó+Ô/?×/MÑ/M×/SÑ/SÒSØ×"Ñ" <Ó0Ð8Ü07×0PÑ0PÐ Ñ-Ø×"Ñ"Ð#4Ó5Ð=Ü5<×5ZÑ5ZÐÐ 1Ñ2à˜;Ñ'Ð/Ü+;×+SÑ+SÐ˜KÑ(ä,Ø# IÑ.Ü"Ð#6°|Ñ#DÓEØ% kÑ2Ø& |Ñ4Ø+Ð,=Ñ>Ø'¨	Ñ2ØôÐñ œ °
Ô;Ø%4´g¸mÈZÓ6XÐ$YÐÔ!ä$ØÜ(Ô3C×3OÑ3OÔPô÷ €Hð
 €Oðús   ‚GG!ÇGÇG!z/sso/get/ui_settings)r®  r¯  Údependenciesc              ƒ   ó¨  K  — ddl m}m} t        j                  dd «      }t        j                  dd «      }t        j                  dd «      }t        «       }|j                  d«      t        kD  }|j                  dd«      }d	t        j                  v r&t        j                  d	   j                  «       d
k(  rd}||||||j                  d«      |dœS ­w)Nr   )r  Úproxy_stateÚPROXY_BASE_URLÚPROXY_LOGOUT_URLÚLITELLM_UI_API_DOC_BASE_URLÚspend_logs_row_countÚdefault_team_disabledFÚPROXY_DEFAULT_TEAM_DISABLEDr5  T)r¡  r¢  r£  ÚDEFAULT_TEAM_DISABLEDÚSSO_ENABLEDÚNUM_SPEND_LOGS_ROWSÚDISABLE_EXPENSIVE_DB_QUERIES)r
  r  r   rõ  rö  rI   Úget_proxy_state_variabler-   rÒ   ÚenvironrN  )	r  r  r   Ú_proxy_base_urlÚ_logout_urlÚ_api_doc_base_urlÚ_is_sso_enabledÚdisable_expensive_db_queriesr¥  s	            rŽ   Úget_ui_settingsr²  0
  sÒ   è ø€ ÷ IäŸY™YÐ'7¸Ó>€OÜŸ™Ð#5°tÓ<€KÜ!Ÿy™yÐ)FÈÓMÐÜ0Ó2€Oà×,Ñ,Ð-CÓDÔGaÑað !ð -×0Ñ0Ð1HÈ%ÓPÐØ$¬¯
©
Ñ2Ü�:‰:Ð3Ñ4×:Ñ:Ó<ÀÒFØ$(Ð!ð *Ø'Ø'8Ø!6Ø&Ø*×CÑCÐDZÓ[Ø(Dñð ùs   ‚CCz/sso/readiness)r®  rž  c               ƒ   óÜ  K  — t        j                  dd«      } t        j                  dd«      }t        j                  dd«      }d}|�d}n	| �d}n|�d}|€dd	d
dœS g }|dk(  r,t        j                  dd«      }|�€|j                  d«       �n|dk(  rSt        j                  dd«      }t        j                  dd«      }|€|j                  d«       |€»|j                  d«       n©|dk(  r¤t        j                  dd«      }t        j                  dd«      }	t        j                  dd«      }
t        j                  dd«      }|€|j                  d«       |	€|j                  d«       |
€|j                  d«       |€|j                  d«       t        |«      dk(  rdd||j	                  «       › d�dœS t        ddd|||j	                  «       › ddj                  |«      › �dœ¬«      ‚­w)z•
    Health endpoint for checking SSO readiness.
    Checks if the configured SSO provider has all required environment variables set in memory.
    r#  Nr$  r%  ÚgoogleÚ	microsoftrY  ÚhealthyFzNo SSO provider configured)r   Ússo_configuredr  ÚGOOGLE_CLIENT_SECRETÚMICROSOFT_CLIENT_SECRETÚMICROSOFT_TENANTrn  rr  rs  rt  r   Tz SSO is properly configured)r   r·  rW  r  i÷  Ú	unhealthyz? SSO is configured but missing required environment variables: z, )r   r·  rW  Úmissing_environment_variablesr  r  )rõ  rö  rC  rU  Ú
capitalizer   rë   )r.  r/  r0  Úconfigured_providerÚmissing_varsÚgoogle_client_secretÚmicrosoft_client_secretÚmicrosoft_tenantr}  r  r€  r�  s               rŽ   Ússo_readinessrÃ  P
  sO  è ø€ ô "$§¡Ð+@À$Ó!GÐÜ Ÿi™iÐ(:¸DÓAÐÜ!Ÿy™yÐ)<¸dÓCÐð ÐØÐ#Ø&ÑØ	Ð	(Ø)ÑØ	Ð	&Ø'Ðð Ð"àØ#Ø3ñ
ð 	
ð €Là˜hÒ&Ü&(§i¡iÐ0FÈÓ&MÐØÑ'Ø×ÑÐ 6Ö7à	 Ò	+Ü)+¯©Ð3LÈdÓ)SÐÜ"$§)¡)Ð,>ÀÓ"EÐØ"Ð*Ø×ÑÐ 9Ô:ØÐ#Ø×ÑÐ 2Õ3à	 	Ò	)Ü')§y¡yÐ1HÈ$Ó'OÐÜ02·	±	Ð:ZÐ\`Ó0aÐ&Ü(*¯	©	Ð2JÈDÓ(QÐÜ+-¯9©9Ð5PÐRVÓ+WÐ!Ø Ð(Ø×ÑÐ 7Ô8Ø)Ð1Ø×ÑÐ @ÔAØ!Ð)Ø×ÑÐ 8Ô9Ø$Ð,Ø×ÑÐ ;Ô<ô ˆ<Ó˜AÒàØ"Ø+Ø-×8Ñ8Ó:Ð;Ð;VÐWñ	
ð 	
ô Øà!Ø"Ø+Ø-9Ø-×8Ñ8Ó:Ð;Ð;zÐ{÷  |Eñ  |Eð  FRó  |Sð  {Tð  Uñ
ô	ð 	ùs   ‚G*G,c                 óv   — | j                  d«      r| j                  d«      sd| v ryt        d„ | D «       «       S )aÕ  True for a strictly relative return path that stays on the gateway's own origin by
    construction, and is therefore safe to honor without a configured ``control_plane_url``.
    Used by the MCP gateway DCR authorize round-trip so a browser sent through login lands
    back on the authorize request.

    Requires a single leading ``/`` (not protocol-relative ``//``), no backslash (browsers
    fold ``\`` to ``/``, so ``/\evil.com`` would escape the origin), and no control or
    whitespace characters. Rejecting control chars keeps a ``\r\n``/tab-bearing value out
    of the redirect ``Location`` and the ``litellm_cp_return_to`` cookie entirely, rather
    than relying on downstream header encoding to neutralize it.ú/z//ú\Fc              3   óD   K  — | ]  }t        |«      d k  xs |dv –— Œ y­w)r³  )rq  úN)Úordrç   s     rŽ   rê   z._is_same_origin_return_path.<locals>.<genexpr>°
  s%   è ø€ ÒM¸R”3�r“7˜T‘>Ò8 R¨=Ð%8Ó8ÑMùs   ‚ )r*  rO  )r  s    rŽ   Ú_is_same_origin_return_pathrÊ  £
  s=   € ð ×Ñ Ô$¨	×(<Ñ(<¸TÔ(BÀdÈiÑFWØÜÑMÀ9ÔMÓMÐMÐMr�   r”  c              ƒ   ó  K  — | €yt        | «      r3t        | d¬«      }|j                  d|¬«       |j                  d«       |S t        j                  | «      r«t        j                  d«      }d|› �}|| d	œ}|�|j                  ||d
¬«      ƒ d{  –—†  n|j                  ||d
¬«      ƒ d{  –—†  d| v rdnd}| |z   t        d|dœ«      z   }	t        j                  d«       t        |	d¬«      }|j                  d«       |S y7 Œs7 ŒX­w)aa  Resolve the post-SSO redirect for a ``return_to``, or None to fall through to the dashboard.

    Two arms, both clearing the one-shot ``litellm_cp_return_to`` cookie:
    - **Same-origin relative path** (the MCP gateway DCR authorize round-trip): set the session cookie
      exactly like the dashboard path, then send the browser back where it came from.
    - **Control-plane cross-origin** (``control_plane_url``): stash the JWT behind a single-use opaque
      code (60s TTL) so the token never lands in browser history/logs; the control plane redeems it via
      ``POST /v3/login/exchange``.

    Extracted from ``get_redirect_response_from_openid`` to keep that method inside the complexity
    budget; behavior is identical to the inline arms it replaces (including letting
    ``_validate_return_to`` raise for a mismatched absolute return_to, as before).Né/  ©Úurlr   r   ©rÏ   r®   r9  r³  zlogin_code:)r   r1  rw   r  r»  ú&Úsuccess)Úloginr  z>Cross-origin SSO: redirecting to control plane with login code)rÊ  r   Ú
set_cookieÚdelete_cookier9  rW  rñ   r½  r  r   r$   r”  )
r  r”  Úredis_usage_cacher!  Úredirect_responser  r2  Úcache_valueÚ	separatorr1  s
             rŽ   Ú_sso_return_to_redirectrÙ  ³
  s&  è ø€ ð$ ÐØä" 9Ô-Ü,°ÈÔLÐØ×$Ñ$¨¸	Ð$ÔBØ×'Ñ'Ð(>Ô?Ø Ð ä×3Ñ3°IÔ>Ü×+Ñ+¨BÓ/ˆØ(¨¨Ð/ˆ	Ø'0À)ÑLˆØÐ(Ø#×3Ñ3¸	ÈÐZ\Ð3Ó]×]Ñ]à$×4Ñ4¸È+Ð[]Ð4Ó^×^Ð^à"%¨Ñ"2™3¸ˆ	Ø'¨)Ñ3´iÈ)Ð]aÑ@bÓ6cÑcˆÜ×!Ñ!Ð"bÔcÜ,°È3ÔOÐØ×'Ñ'Ð(>Ô?Ø Ð àð ^øà^ús%   ‚BD	ÂDÂD	Â.DÂ/AD	ÄD	r`  c                 ó    — |€y	 t        |«      xs t        j                  |«      }|r| j	                  d|ddd¬«       yy# t        $ r Y yw xY w)u¤  Best-effort: persist a SAFE ``return_to`` on ``response`` as the one-shot ``litellm_cp_return_to``
    cookie so ANY sign-in path â€” SSO / Okta / generic OR the username/password form â€” can resume there
    afterwards. THIS is the single source of truth, called by every sign-in branch so they cannot
    diverge (a per-branch reimplementation is exactly how the two drifted before). Honors a strictly
    relative same-origin path, and (when ``control_plane_url`` is configured) a return_to matching that
    origin. It NEVER raises: a mismatched or invalid ``return_to`` is simply not stored, so it can never
    block sign-in â€” the login entrypoint must always render.Nr9  éX  TÚlax)rÏ   r®   Úmax_ageÚhttponlyÚsamesite)rÊ  r9  rW  r   rÓ  )r`  r  Úsafes      rŽ   rB  rB  á
  sn   € ð ÐØðÜ1°)Ó<ÒwÔ@X×@lÑ@lÐmvÓ@wˆñ Ø×ÑØ&ØØØØð 	õ 	
ð øô ò Ùðús   …"A Á	AÁAc                   óØ  — e Zd ZdZededefd„«       Ze	 	 	 	 	 dIdededz  dedz  d	edz  d
edz  dedz  de	dz  fd„«       Z
e	 	 	 dJded
edz  dedz  dedz  de	dz  f
d„«       Ze	 	 dKd
edz  dedz  deeeef   edz  f   fd„«       Ze	 	 	 dJdedz  dedz  d	edz  defd„«       Ze	 dLdedededz  defd„«       Zedeez  ez  dz  deez  dz  dedz  dedz  def
d„«       Zedeez  ez  dz  deez  dz  fd„«       Zededeez  ez  dz  dedz  ded   fd„«       Ze	 dLd ed!edz  fd"„«       Ze	 dLd#eez  d$ed ed!edz  def
d%„«       Ze	 	 dKd&edz  d'edz  dedz  d(edz  dedz  f
d)„«       Z e	 dLdeez  dz  d	edz  de!fd*„«       Z"e	 	 	 	 	 	 	 dMdeez  ez  dededz  d	edz  d+edz  d,edz  d-e#dz  dedz  d.e$dz  de	fd/„«       Z%eded0edefd1„«       Z&ed
edz  d2ed3e'd4ed5e'd6e'ddfd7„«       Z(ed2eddfd8„«       Z)edeeef   fd9„«       Z*ed:d;defd<„«       Z+ed=ed>ed?ed@edz  dAedBedz  dCededz  dDeeef   defdE„«       Z,edFedGedz  dBedz  dDeeef   def
dH„«       Z-y)Nr9  zA
    Handler for SSO Authentication across all SSO providers
    r  rˆ   c                 ó”   — ddl m} |j                  d«      }|€ydt        dt        fd„} || «       ||«      k7  rt        dd	¬
«      ‚y)aN  
        Validate that return_to matches the configured control_plane_url origin.

        Returns True if return_to is valid and should be used.
        Returns False if control_plane_url is not configured (return_to is ignored).
        Raises HTTPException(400) if return_to origin does not match control_plane_url origin.
        r   r  Úcontrol_plane_urlFrÎ  rˆ   c                 óà   — t        | «      }|j                  xs dj                  «       }|j                  xs dj                  «       }|dk(  rdnd}|j                  �|j                  n|}|||fS )Nrä   Úhttpsi»  éP   )r   ÚschemerN  ÚhostnameÚport)rÎ  rE  rç  rè  Údefault_portré  s         rŽ   Ú_originz=SSOAuthenticationHandler._validate_return_to.<locals>._origin  sh   € Ü$ S›MˆFØ#Ÿ]™]Ò0¨b×7Ñ7Ó9ˆFØ%Ÿ™Ò4°"×;Ñ;Ó=ˆHØ)/°7Ò):¡#ÀˆLØ)/¯©Ð)@˜&Ÿ+š+ÀlˆDØ˜H dÐ+Ð+r�   r'  z9return_to does not match the configured control_plane_urlr  T)r
  r  rÒ   r•   rÀ   r   )r  r  rã  rë  s       rŽ   rW  z,SSOAuthenticationHandler._validate_return_toþ
  sc   € õ 	@à#3×#7Ñ#7Ð8KÓ#LÐØÐ$Øð	,œð 	,¤ó 	,ñ �9Ó¡Ð):Ó!;Ò;ÜØØRôð ð
 r�   Nr1  r/  r.  r0  r2  r  c              ƒ   ó4  K  — |�‘ddl m} t        j                  dd«      }|€+t	        dt
        j                  dt        j                  ¬«      ‚ |||| ¬«      }t        j                  d| |«       |5  |j                  |¬	«      ƒ d{  –—† cddd«       S |��t        j                  d
d«      }	t        j                  dd«      }
|	€+t	        dt
        j                  d
t        j                  ¬«      ‚t        ||	|
| d¬«      }|5  |j                  |¬	«      ƒ d{  –—† cddd«       S |��¯ddlm} ddlm} t        j                  dd«      }t        j                  dd«      j#                  d«      }t        j                  dd«      }t        j                  dd«      }t        j                  dd«      }|€+t	        dt
        j                  dt        j                  ¬«      ‚|€+t	        dt
        j                  dt        j                  ¬«      ‚|€+t	        dt
        j                  dt        j                  ¬«      ‚|€+t	        dt
        j                  dt        j                  ¬«      ‚t        j$                  d|||«       t        j$                  d| |«        ||||¬«      } |d|¬ «      } |||| d|¬!«      }t&        j)                  ||||¬"«      ƒ d{  –—† S t+        d#«      ‚7 �Œ\# 1 sw Y   t+        d#«      ‚xY w7 �Œä# 1 sw Y   t+        d#«      ‚xY w7 ŒA­w)$aæ  
        Step 1. Call Get Login Redirect for the SSO provider. Send the redirect response to `redirect_url`

        Args:
            redirect_url (str): The URL to redirect the user to after login
            google_client_id (Optional[str], optional): The Google Client ID. Defaults to None.
            microsoft_client_id (Optional[str], optional): The Microsoft Client ID. Defaults to None.
            generic_client_id (Optional[str], optional): The Generic Client ID. Defaults to None.
            request: Optional FastAPI request, used to drive the ``Secure``
                attribute on the ``litellm_oauth_state`` CSRF cookie.

        Returns:
            RedirectResponse: The redirect response from the SSO provider.
        Nr   ©Ú	GoogleSSOr¸  ú1GOOGLE_CLIENT_SECRET not set. Set it in .env filer  )rÆ  r„   rÇ  zLIn /google-login/key/generate, 
GOOGLE_REDIRECT_URI: %s
GOOGLE_CLIENT_ID: %s)r2  r¹  rº  ú4MICROSOFT_CLIENT_SECRET not set. Set it in .env fileT©rÆ  r„   ÚtenantrÇ  rÈ  r°  r²  rn  ro  rp  rq  rr  rs  rt  rv  rw  rx  ry  rz  r{  r´  rÂ  )rÃ  rÄ  rÅ  )r¿  r2  r  r  zfUnknown SSO provider. Please setup SSO with client IDs https://docs.litellm.ai/docs/proxy/admin_ui_sso)Úfastapi_sso.sso.googlerî  rõ  rö  rB   rA   r  r   r|  r$   r”  Úget_login_redirectrS   rÑ  r±  rÒ  r³  rA  r€  r9  Ú!get_generic_sso_redirect_responser/  )r1  r/  r.  r0  r2  r  rî  rÀ  Ú
google_ssorÁ  rÂ  Úmicrosoft_ssor±  r³  r}  r~  r  r€  r�  rÛ  rÜ  r¿  s                         rŽ   rA  z/SSOAuthenticationHandler.get_sso_login_redirect  sc  è ø€ ð0 Ð'Ý8ä*,¯)©)Ð4JÈDÓ*QÐ Ø#Ð+Ü$ØOÜ(×3Ñ3Ø0Ü×>Ñ>ô	ð ñ !*Ø*Ø2Ø)ô!ˆJô
 !×%Ñ%Ø`ØØ ôð
 ñ HØ'×:Ñ:ÀÐ:ÓG×G÷Hñ Hð !Ð,Ü-/¯Y©YÐ7PÐRVÓ-WÐ#Ü&(§i¡iÐ0BÀDÓ&IÐØ&Ð.Ü$ØRÜ(×3Ñ3Ø3Ü×>Ñ>ô	ð ô $6Ø-Ø5Ø'Ø)Ø$(ô$ˆMð ñ KØ*×=Ñ=ÀEÐ=ÓJ×J÷Kñ KàÑ*Ý>Ý?ä+-¯9©9Ð5LÈdÓ+SÐ!Ü#%§9¡9¨_Ð>TÓ#U×#[Ñ#[Ð\_Ó#`ˆMÜ46·I±IÐ>^Ð`dÓ4eÐ*Ü,.¯I©IÐ6NÐPTÓ,UÐ"Ü/1¯y©yÐ9TÐVZÓ/[Ð%Ø$Ð,Ü$ØPÜ(×3Ñ3Ø1Ü×>Ñ>ô	ð ð .Ð5Ü$ØYÜ(×3Ñ3Ø:Ü×>Ñ>ô	ð ð &Ð-Ü$ØQÜ(×3Ñ3Ø2Ü×>Ñ>ô	ð ð )Ð0Ü$ØTÜ(×3Ñ3Ø5Ü×>Ñ>ô	ð ô !×&Ñ&ØWØ.Ø&Ø)ô	ô !×&Ñ&ØCÀ\ÐSdôñ  1Ø'EØ5Ø";ô ˆIñ
 "1°fÐQZÔ![ˆKÙ!,Ø+Ø3Ø)Ø$(Ø#ô"ˆKô 2×SÑSØ'ØØ/MØð	 Tó ÷ ð ô Øtó
ð 	
ðm Hù÷Hôn Øtó
ð 	
úðE Kù÷KôF Øtó
ð 	
úðúsh   ‚A0LÁ2K'ÂK$Â	K'ÂA7LÄL ÄK=ÄL ÄF7LËLËLË$K'Ë'K:Ë,LË=L Ì LÌLr¿  r  c           	   ƒ   óæ  K  — ddl m}m}m}m} ddlm}m}	 | 5  t        j                  ||¬«      \  }
}i }i }|
j                  «       D ]  \  }}|dv r|||<   Œ|||<   Œ  | j                  di |¤Žƒ d{  –—† }|�rUd|
v �rPd|
d   › �}|�|j                  |d	|id
¬«      ƒ d{  –—†  n|	j                  |d	|id
¬«      ƒ d{  –—†  t        j                  d«       |r§ |t        |j                   d   «      «      } ||j"                  «      }|j                  «       D ]  \  }}|g||<   Œ  ||d¬«      } ||j$                  |j&                  |j(                  |j*                  ||j,                  f«      }||j                   d<   |
j/                  d«      }|r8|�6|du xs |j0                  j$                  dk(  }|j3                  d|d
dd|¬«       |cddd«       S 7 �Œh7 �Œ;7 �Œ# 1 sw Y   yxY w­w)z;
        Get the redirect response for Generic SSO
        r   )r   r   r   Ú
urlunparse©rÕ  r!  )r2  r  )Úcode_challengeÚcode_challenge_methodNr2  úpkce_verifier:rÊ  rÛ  r  z.PKCE code_verifier stored in cache (TTL: 600s)ÚlocationT)Údoseqrå  rÌ  rÜ  )rÏ   r®   rÝ  rÞ  rß  Úsecurer‹   )Úurllib.parser   r   r   rù  r
  rÕ  r!  r9  Ú _get_generic_sso_redirect_paramsrv  rô  r  r$   r€  r•   rÐ  Úqueryrç  ÚnetlocÚpathrÏ  rL  rÒ   rÎ  rÓ  )r¿  r2  r  r  r   r   r   rù  rÕ  r!  Úredirect_paramsrÊ  Úpkce_paramsÚstate_only_paramsrÏ   r®   rÖ  r2  Ú
parsed_urlrÔ  Ú	new_queryÚnew_urlÚstate_valueÚsecure_flags                           rŽ   rõ  z:SSOAuthenticationHandler.get_generic_sso_redirect_response¥  s€  è ø€ ÷ 	KÓJçTàñ a	%ô )×IÑIØØ/Mð Jó ñØØð "$ˆKØ')ÐØ-×3Ñ3Ó5ò 3‘
��UØÐEÑEØ',�K Ò$à-2Ð% cÒ*ð	3ð .L¨[×-KÑ-KÑ-`ÐN_Ñ-`×'`Ðò  ¨OÒ!;ð &4°OÀGÑ4LÐ3MÐ#N�	Ø$Ð0Ø+×;Ñ;Ø%Ø.°Ð>Øð <ó ÷ ñ ð -×<Ñ<Ø%Ø.°Ð>Øð =ó ÷ ð ô
 %×*Ñ*Ð+[Ô\ñ Ù(0´Ð5F×5NÑ5NÈzÑ5ZÓ1[Ó(\�JÙ*2°:×3CÑ3CÓ*D�Lð '2×&7Ñ&7Ó&9ò 4™
˜˜UØ-2¨G˜ SÒ)ð4ñ (1°ÀTÔ'J�IÙ%/à&×-Ñ-Ø&×-Ñ-Ø&ŸO™OØ&×-Ñ-Ø%Ø&×/Ñ/ðó	&�Gð =DÐ%×-Ñ-¨jÑ9ð &5×%8Ñ%8¸Ó%A�ÙÐ#4Ð#@ð *1°D¨Ò)Y¸G¿K¹K×<NÑ<NÐRYÑ<Y�KØ%×0Ñ0Ø1Ø)Ø #Ø!%Ø!&Ø*ð 1ô ð %÷Ca	%ñ a	%ð4 (aùðùðù÷Sa	%ð a	%üsT   ‚G1™AG%Á4GÁ5/G%Â$GÂ%G%ÃG"ÃDG%Ç
G1ÇG%ÇG%Ç"G%Ç%G.Ç*G1c                 ó^  — i }d}| r| |d<   n?t        j                  dd«      }|r||d<   n!t        j                  «       j                  |d<   t        j                  dd«      j                  «       dk(  }|r6t        j                  «       \  }}||d<   d|d	<   t        j                  d
«       ||fS )aË  
        Get redirect parameters for Generic SSO with proper state priority handling.
        Optionally generates PKCE parameters if GENERIC_CLIENT_USE_PKCE is enabled.

        Priority order:
        1. CLI state (if provided)
        2. GENERIC_CLIENT_STATE environment variable
        3. Generated UUID (required by Okta and most OAuth providers)


        Args:
            state: Optional state parameter (e.g., CLI state)
            generic_authorization_endpoint: Authorization endpoint URL

        Returns:
            Tuple[dict, Optional[str]]:
                - Redirect parameters for SSO login (may include PKCE params)
                - code_verifier (if PKCE is enabled, None otherwise)
        Nr2  ÚGENERIC_CLIENT_STATEr¤  r4  r5  rû  ÚS256rü  z&PKCE enabled for authorization request)
rõ  rö  r%   Úuuid4ÚhexrN  r9  Úgenerate_pkce_paramsr$   r€  )r2  r  r  rÊ  Úgeneric_client_stateÚuse_pkcerû  s          rŽ   r  z9SSOAuthenticationHandler._get_generic_sso_redirect_params  sÀ   € ð0 "$ˆØ$(ˆáð (-ˆO˜GÒ$ä*,¯)©)Ð4JÈDÓ*QÐ Ù#Ø+?� Ò(ä+/¯:©:«<×+;Ñ+;� Ñ(ô Ÿ)™)Ð$=¸wÓG×MÑMÓOÐSYÑYˆáô )×=Ñ=Ó?ñØØà0>ˆOÐ,Ñ-Ø7=ˆOÐ3Ñ4Ü ×&Ñ&Ð'OÔPà Ð-Ð-r�   c                 ó   — | €|€|�yy)NTFr‹   )r/  r.  r0  s      rŽ   r@  z/SSOAuthenticationHandler.should_use_sso_handlerK  s   € ð Ð'Ð+>Ð+JÐN_ÐNkØØr�   r)  r  c                 óŠ   — ddl m}  |t        | j                  «      ¬«      }|j	                  d«      r||z  }|S |d|z   z  }|S )zÃ
        Get the redirect URL for SSO

        Note: existing_key is not added to the URL to avoid changing the callback URL.
        It should be passed via the state parameter instead.
        r   )r^   )r¹  rÅ  )rŠ  r^   r•   r¾  Úendswith)r  r)  r  r^   r1  s        rŽ   r:  z1SSOAuthenticationHandler.get_redirect_url_for_ssoU  sU   € õ 	7á%´s¸7×;KÑ;KÓ7LÔMˆØ× Ñ  Ô%ØÐ.Ñ.ˆLð Ðð ˜CÐ"4Ñ4Ñ4ˆLàÐr�   rX  rì  r   r  rŒ  c              ƒ   ób  K  — 	 |�K|j                   }t        | ||¬«      }t        t        |«      «      j	                  d|i|¬«      ƒ d{  –—†  |S t        j                  d«       t        | |¬«      ƒ d{  –—† }|S 7 Œ27 Œ# t        $ r"}t        j                  d|«       |cY d}~S d}~ww xY w­w)a  
        Connects the SSO Users to the User Table in LiteLLM DB

        - If user on LiteLLM DB, update the user_email and user_role (if SSO provides valid role) with the SSO values
        - If user not on LiteLLM DB, insert the user into LiteLLM DB
        N)rX  r   r�  r�  r‘  z.user not in DB, inserting user into LiteLLM DB)r–  r  z,Error upserting SSO user into LiteLLM DB: %s)
r�  r  r�   rc   r“  r$   r”  r�  r—  r¨  )rX  rì  r   r  rŒ  r�  r  rœ  s           rŽ   r  z(SSOAuthenticationHandler.upsert_sso_userk  sÍ   è ø€ ð	ØÐ$Ø!*×!2Ñ!2�Ü%@Ø!Ø)Ø#ô&�ô $¤N°=Ó$AÓB×NÑNØ$ gÐ.°[ð Oó ÷ ð ð Ðô %×)Ñ)Ð*ZÔ[ä"1Ø"(Ø(;ô#÷ �	ð Ððøðùô
 ò 	Ü ×*Ñ*Ð+YÐ[\Ô]ØÕûð	üse   ‚B/„AB Á
A=ÁB ÁB/Á%B Á6A?Á7B Á<B/Á=B Á?B Â	B,Â
B'Â!B,Â"B/Â'B,Â,B/c              ƒ   ó„   K  — |€t        j                  d«       yt        | dg «      }t        ||¬«      ƒ d{  –—†  y7 Œ­w)zÆ
        Adds the user as a team member to the teams specified in the SSO responses `team_ids` field


        The `team_ids` field is populated by litellm after processing the SSO response
        Nz;User not found in LiteLLM DB, skipping team member additionrì  )rì  rï  )r$   r€  rk  rø  )rX  rì  rï  s      rŽ   r  z<SSOAuthenticationHandler.add_user_to_teams_from_sso_response‘  s>   è ø€ ð ÐÜ ×&Ñ&Ð'dÔeØÜ" 6¨:°rÓ:ˆ	Ü%°	ÀYÔO×OÒOús   ‚6A ¸>¹A r  rÀ  Tc                 óR  — t        t        t        z  dz  | j                  d«      «      }|€yt	        |t        «      ryt        |dg «      }|j                  d«      dk(  rI|j                  d«      }||vr4t        d|› d|› d	|› �t        j                  dt        j                  ¬
«      ‚y)a´  
        when ui_access_mode.type == "restricted_sso_group":

        - result.team_ids should contain the restricted_sso_group
        - if not, raise a ProxyException
        - if so, return True
        - if result.team_ids is None, return False
        - if result.team_ids is an empty list, return False
        - if result.team_ids is a list, return True if the restricted_sso_group is in the list, otherwise return False
        Nr2  Trì  r  Úrestricted_sso_groupz)User is not in the restricted SSO group: z. User groups: z. Received SSO response: r  )r   r0  r•   rÒ   r°   rk  rB   rA   r  r   r  )r  rX  rÀ  r2  rì  r  s         rŽ   r…  z<SSOAuthenticationHandler.verify_user_in_restricted_sso_group¢  sÌ   € ô" !%¤T¬C¡Z°$Ñ%6Ð8H×8LÑ8LÐM]Ó8^Ó _ˆàÐ!ØÜ�n¤cÔ*ØÜ! &¨*°bÓ9ˆà×Ñ˜fÓ%Ð)?Ò?Ø*8×*<Ñ*<Ð=SÓ*TÐ Ø#¨8Ñ3Ü$ØGÐH\ÐG]Ð]lÐmuÐlvð  wPð  Qbð  Pcð  dÜ(×3Ñ3Ø0Ü×2Ñ2ô	ð ð r�   Úlitellm_team_idÚlitellm_team_namec           	   ƒ   ó–  K  — ddl m} |€+t        dt        j                  dt
        j                  ¬«      ‚	 t        t        |«      «      j                  d| i¬«      ƒ d{  –—† }t        j                  d	|«       |rt        j                  d
| |«       yt        | |¬«      }t        j                  r't        j!                  t        j                  | ||¬«      }t#        |t%        dddœ¬«      t'        ddt(        j*                  › �¬«      ¬«      ƒ d{  –—†  y7 Œ¸7 Œ# t,        $ r }t        j.                  d|«       Y d}~yd}~ww xY w­w)aj  
        Creates a Litellm Team from a SSO Group ID

        Your SSO provider might have groups that should be created on LiteLLM

        Use this helper to create a Litellm Team from a SSO Group ID

        Args:
            litellm_team_id (str): The ID of the Litellm Team
            litellm_team_name (Optional[str]): The name of the Litellm Team
        r   )rŒ  Nz;Prisma client not found. Set it in the proxy_server.py filerŒ  r  r¼   r�  zTeam object: %szTeam already exists: %s - %sr‰  )Údefault_team_paramsr  r  Úteam_requestÚhttpÚPOST)r  Úmethod)rÉ  rä   zlitellm.)r   Ú	key_alias)r]  Úhttp_requestré  zError creating Litellm Team: %s)r
  rŒ  rB   rA   r  r   r|  r«   rb   Ú
find_firstr$   r€  r>   rý  r   r9  Ú._cast_and_deepcopy_litellm_default_team_paramsrW   r   rE   r@  r‘   r—  r¨  )r  r  rŒ  Úteam_objr!  rœ  s         rŽ   Ú"create_litellm_team_from_sso_groupz;SSOAuthenticationHandler.create_litellm_team_from_sso_groupÆ  sN  è ø€ õ  	=àÐ Ü ØUÜ$×/Ñ/Ø%Ü×:Ñ:ô	ð ð!	QÜ$3´NÀ=Ó4QÓ$R×$]Ñ$]Ø  /Ð2ð %^ó %÷ ˆHô !×&Ñ&Ð'8¸(ÔCñ Ü$×*Ñ*Ð+IÈ?Ð\mÔnØä+9Ø'Ø,ô,ˆLô ×*Ò*Ü7×fÑfÜ(/×(CÑ(CØ$3Ø&7Ø!-ð	  gó  �ô Ø!ä$°FÀfÑ+MÔNÜ"0ØØ (Ô)<×)EÑ)EÐ(FÐGô#ô	÷ ñ ð-øð,ùô ò 	QÜ ×*Ñ*Ð+LÈa×PÑPûð	Qüs_   ‚4E	·)D Á DÁ!3D ÂE	ÂA>D ÄDÄD ÄE	ÄD ÄD Ä	EÄ&EÄ<E	ÅEÅE	r   r!  c                 óD  — t        | t        «      r"t        | «      }||d<   ||d<   t        di |¤Ž}|S t        t        j
                  t        «      rOt        t        j
                  «      }|j                  «       }|j                  |«       t        j                  |«      }|S )ac  
        Casts and deepcopies the litellm.default_team_params to a NewTeamRequest object

        - Ensures we create a new DefaultTeamSSOParams object
        - Handle the case where litellm.default_team_params is a dict or a DefaultTeamSSOParams object
        - Adds the litellm_team_id and litellm_team_name to the DefaultTeamSSOParams object
        r¼   r½   r‹   )
r°   r0  r   r>   rý  r   rh   r¨   r  rh  )r   r!  r  r  Ú_team_requestÚ_default_team_paramsÚ_new_team_requests          rŽ   r(  zGSSOAuthenticationHandler._cast_and_deepcopy_litellm_default_team_params  sœ   € ô Ð)¬4Ô0Ü#+Ð,?Ó#@ˆMØ'6ˆM˜)Ñ$Ø*;ˆM˜,Ñ'Ü)Ñ:¨MÑ:ˆLð Ðô œ×3Ñ3Ô5IÔJÜ*2´7×3NÑ3NÓ*OÐ Ø'3×'>Ñ'>Ó'@ÐØ×$Ñ$Ð%9Ô:Ü)×8Ñ8Ð9JÓKˆLØÐr�   r‰  rÏ   râ   c                 ó^   — ddl m} | t        k(  r|rt        |«      r
|› d|› d|› �S |› d|› �S y)a¾  
        Checks the request 'source' if a cli state token was passed in

        This is used to authenticate through the CLI login flow.

        The state parameter format is: {PREFIX}:{login_id}[:{user_code}]
        - The state parameter is used to pass data through the OAuth flow without changing the callback URL
        - user_code is appended only for the opt-in verification_uri_complete flow so the verify page can pre-fill it
        r   r,  rü   N)r:  r-  r+   r  )r‰  rÏ   r  râ   r-  s        rŽ   r;  z'SSOAuthenticationHandler._get_cli_state  sI   € õ 	
ð Ô2Ò2±sÜ*¨9Ô5Ø:Ð;¸1¸S¸EÀÀ9À+ÐNÐNØ6Ð7°q¸¸Ð>Ð>àr�   c           	      ó"  — t        t        | dd«      «      }| �t        | dd«      nd}d}|�gt        j                  d«      �R|j	                  d«      d   }t        j                  d«      j	                  d«      }||vrt        dd	d
|› d|› d�i¬«      ‚| �Ct        | dd«      }|�4t        |t        «      r|j                  n|}t        j                  d|«       |�j| �ht        j                  dd«      }t        | dd«      }t        t        | dd«      «      }|€-t        | |d«      }	|	�t        |	t        «      r|	j                  n|	}|€)| �'t        | dd«      xs d}
t        | dd«      xs d}|
|z   }|�|�t        |«      dk(  r|}t        |||¬«      S )ze
        Gets the user email and id from the OpenID result after validating the email domain
        r×  Nr[  ÚALLOWED_EMAIL_DOMAINSú@r  r?  r+  r  zThe email domain=z!, is not an allowed email domain=z$. Contact your admin to change this.r  rí  z'Extracted user_role from SSO result: %srî  rã  rS  rä   rU  r   )r   r�  rí  )rÙ  rk  rõ  rö  rA  r   r°   r<   r®   r$   r€  rU  rn   )rX  r0  r   r�  rí  Úemail_domainÚallowed_domainsÚ
_user_rolerý  Ú_role_from_attrÚ_first_nameÚ
_last_names               rŽ   r„  z;SSOAuthenticationHandler._get_user_email_and_id_from_result7  sß  € ô "1´¸ÀÈ$Ó1OÓ!Pˆ
Ø=CÐ=Oœg f¨d°DÔ9ÐUYˆØ $ˆ	àÐ!¤b§i¡iÐ0GÓ&HÐ&TØ",×"2Ñ"2°3Ó"7¸Ñ":ˆLÜ%'§Y¡YÐ/FÓ%G×%MÑ%MÈcÓ%RˆOØ ?Ñ2Ü#Ø #à!Ð%6°|°nÐDeÐfuÐevð  w[ð  $\ðôð ð ÐÜ '¨°¸TÓ BˆJØÐ%ä0:¸:ÔGWÔ0X˜J×,Ò,Ð^h�	Ü$×*Ñ*Ð+TÐV_Ô`ð Ð(¨VÐ-?Ü68·i±iÐ@]Ð_eÓ6fÐ,Ü˜f d¨DÓ1ˆGÜ(¬°¸À$Ó)GÓHˆJØÐ Ü)0°Ð9YÐ[_Ó)`�Ø"Ð.ô 2<¸OÔM]Ô1^˜×-Ò-Ðdsð ð ˆ?˜vÐ1Ü!(¨°¸rÓ!BÒ!HÀbˆKÜ '¨°¸RÓ @Ò FÀBˆJØ! JÑ.ˆGàÐ! w ¼#¸g»,È!Ò:KØ ˆGä!Ø!ØØô
ð 	
r�   r2  r÷  rJ  rÚ  c	              ƒ   óæ  K  — ddl m}	m}
m}m}m}m}m}m} ddl	m
} ddlm}  |d«      }t        j                  | |¬«      }|j                  d«      }|j                  d«      }|j                  d	«      }t!        j"                  d
| «       d }g }t$        j&                  }t$        j(                  }d }|}|�1t+        j,                  |«      r || «      ƒ d {  –—† }nt/        d«      ‚|�t1        ||||||¬«      }t        j3                  |	| |¬«       t5        | ||||||¬«      ƒ d {  –—† }t7        ||xs |||||¬«      ƒ d {  –—†  t9        ||¬«      }|€t;        d«      ‚t!        j"                  d|«        |
dt<        t$        j>                  i i dd|d   |d   |d   |d	   |d   |d   d¬«      ƒ d {  –—† }|d   }|d   }|d	   xs t@        jB                  jD                  }|r&tG        |tH        «      rtK        |||¬«      ƒ d {  –—† }t!        jL                  d||«       tO        |xs i «      } | r&tQ        |xs d«      }!|!stS        ddd|› d |› �i¬!«      ‚tG        |tH        «      r|rtU        ||¬"«      ƒ d {  –—†  tW        «       }"tY        tI        |jZ                  «      d#¬$«      }#t]        d%«      rVd }$|�,|d   �'t_        |d   |d	   xs |g t$        j>                  ¬&«      }$|$€tS        ddd'i¬!«      ‚ta        jb                  |$«      } |te        tH        |«      |||xs t@        jB                  jD                  d(||	j                  d)d*«      |"tg        «       ¬+«	      }%dd,l4m5}&  |&|%|xs d«      }'tm        ||'||¬-«      ƒ d {  –—† }(|(�|(S |�tG        |tH        «      r|#d.z  }#t!        j"                  d/|#«       to        |#d0¬1«      })|)jq                  d|'¬2«       |)S 7 �Œ7 �Œº7 �Œ 7 �Œ17 �Œá7 �Œo7 Œi­w)3Nr   )r  Úgenerate_key_helper_fnr0  r  r  rÕ  r!  r[  r…  )ÚReturnedUITokenObjectr‡  r‚  r   r�  rí  zSSO callback result: %sr\  r]  rƒ  r|  )rJ  rÀ  rì  rŒ  r!  r  )rì  r  z…Unable to map user identity to known values. 'user_defined_values' is None. File an issue - https://github.com/BerriAI/litellm/issuesz+user_defined_values for creating ui key: %srÏ   zlitellm-dashboardr¾   r^  r_  )Úrequest_typeÚdurationÚkey_max_budgetÚaliasesÚconfigÚspendr¼   r¾   r�  r   rí  r^  r_  Ú
table_namer   )rí  r�  rŒ  z!user_role: %s; ui_access_mode: %srä   r+  r˜  z,User not allowed to access proxy. User role=z, proxy mode=r  r}  zui/r¸  ÚEXPERIMENTAL_UI_LOGIN)r�  rí  r¾   r^  z6User Information is required for experimental UI loginÚssoÚlitellm_key_header_nameÚAuthorization)	r�  rÏ   r   rí  Úlogin_methodr  Úauth_header_nameÚ(disabled_non_admin_personal_key_creationÚserver_root_path)Úencode_ui_session_jwt)r  r”  rÕ  r!  z?login=successr7  rÌ  rÍ  rÏ  )9r
  r  r:  r0  r  r  rÕ  r!  r[  rŠ  r†  Úlitellm.types.proxy.ui_ssor;  r9  r„  rÒ   r$   r”  rý  rb  rc  r`  ra  r/  rC   r…  r  r   r$  r—  r,   Úmax_ui_session_budgetr<   r"  r®   r°   r•   r(  r€  rU   rV   r   r9   rÿ  r^   r¾  rd   r;   rF   Ú(get_experimental_ui_login_jwt_auth_tokenr   r_   Úlitellm.proxy.auth.login_utilsrK  rÙ  r   rÓ  )*rX  r  rÀ  r0  r2  r÷  rJ  r  rÚ  r  r:  r0  r  r  rÕ  r!  r[  r†  r;  rŒ  rY  r   r�  rí  rì  Úuser_id_modelsrb  rc  r  rd  r`  rÏ   Úis_admin_only_accessÚ
has_accessrI  Úlitellm_dashboard_uiÚ
_user_infoÚreturned_ui_token_objectrK  r”  Úreturn_to_redirectrÖ  s*                                             rŽ   rC  z:SSOAuthenticationHandler.get_redirect_response_from_openidq  s²  è ø€ ÷		
÷ 		
ó 		
õ 	CÝDá9Ð:sÓtˆô '?×&aÑ&aØÐ->ð 'bó '
Ðð 1×4Ñ4°\ÓBˆ
Ø&×*Ñ*¨9Ó5ˆØ(×,Ñ,¨[Ó9ˆ	Ü×!Ñ!Ð";¸VÔDàˆ	Ø&(ˆÜ*1×*JÑ*JÐ Ü/6×/TÑ/TÐ%ð <@Ðà;JÐØÐ)Ü×*Ñ*Ð+=Ô>Ù,>¸vÓ,F×&FÑ#ä Ð!OÓPÐPØÐ Ü"6Ø%ØØ%Ø3Ø#Ø =ô#Ðô 	!×DÑDØ-ØØ/ð 	Eô 	
ô 0ØØ'Ø1Ø/Ø!Ø 3Ø%ô
÷ 
ˆ	ô 0Ø#Ø2ÒGÐ6GØØ'Ø1Ø 3ô
÷ 	
ð 	
ô PØÐ5Hô
Ðð Ð&Üð Xóð ô 	×!Ñ!Ð"OÐQdÔeá 6ØÜ0Ü"×8Ñ8ØØØØ'Ø& xÑ0Ø'¨	Ñ2Ø*¨<Ñ8Ø)¨+Ñ6Ø*¨<Ñ8Ø/Ð0AÑBØô!
÷ 
ˆð" �wÑˆØ˜9Ñ%ˆà'¨Ñ4ÒfÔ8H×8`Ñ8`×8fÑ8fˆ	Ù”z '¬3Ô/Ü@Ø#¨WÀMô÷ ˆIô 	×"Ñ"Ð#FÈ	ÐSaÔbä&@ÀÒAUÐSUÓ&VÐÙÜ 3°I²OÀÓ DˆJÙÜ#Ø #àÐ#OÐPYÈ{ÐZgÐhvÐgwÐ!xðôð ô �gœsÔ#©Ü7ÀÐS`Ôa×aÐaä:fÓ:hÐ0Ü-¼sÀ7×CSÑCSÓ?TÐ\aÔbÐäÐ2Ô3Ø37ˆJØ"Ð.Ð3FÀyÑ3QÐ3]Ü.Ø/°	Ñ:Ø1°+Ñ>ÒKÀ)ØÜ&×<Ñ<ô	�
ð Ð!Ü#Ø #Ø#Ð%]Ð^ôð ô
 )×QÑQÐR\Ó]ˆCá*?Üœ˜gÓ&ØØ!ØÒQÔ#3×#KÑ#K×#QÑ#QØØ%Ø-×1Ñ1Ð2KÈ_Ó]Ø5]Ü1Ó3ô
+
Ð õ 	Iá0Ð1IÈ:ÒK[ÐY[Ó\ˆ	ô
 +BØØØ/Ø1ô	+
÷ %
Ðð Ð)Ø%Ð%àÐ¤:¨g´sÔ#;Ø Ð$4Ñ4Ð Ü×!Ñ!Ð"5Ð7KÔLÜ#3Ð8LÐZ]Ô#^ÐØ×$Ñ$¨¸	Ð$ÔBØ Ð ðm 'Gùð(
ùð	
ùð(
ùð,ùð$ bùðR%
ús„   ‚CO1ÃOÃAO1Ä&O Ä'O1ÅO#ÅA1O1Æ5O&Æ6AO1ÈO)È	A4O1É=O,É>DO1ÎO/ÎAO1Ï O1Ï#O1Ï&O1Ï)O1Ï,O1Ï/O1r‚  c              ƒ   ó&  K  — d|i}t        | j                  «      }|j                  d«      }t        j                  dd«      j                  «       dk(  }|r|st        j                  d«       |�r|�rddlm	}m
} d	|› �}|�|j                  |¬«      ƒ d
{  –—† }	n|j                  |¬«      ƒ d
{  –—† }	d
}
d}|	r›t        |	t         «      r:d|	v r6|	d   }
|
sd}t        j                  d|«       ngt        j                  d«       nQt        |	t        «      r|	}
t        j                  d«       n)t        j                  dt        |	«      j                   «       |
r|
|d<   ||d<   |S t"        j%                  |||	|||¬«      ƒ d
{  –—†  |S 7 Œó7 ŒÚ7 Œ
­w)zô
        Prepare token exchange parameters for Generic SSO.

        Args:
            request: Request object
            generic_include_client_id: Generic OAuth Client ID

        Returns:
            dict: Token exchange parameters
        rÎ  r2  r¤  r4  r5  u=  PKCE is enabled (GENERIC_CLIENT_USE_PKCE=true) but no 'state' parameter was found in the callback. The PKCE verifier cannot be retrieved without a state value â€” the token exchange will proceed without code_verifier, which the provider may reject. Ensure your OAuth provider returns 'state' in the callback redirect.r   rú  rý  Nr(  FrÊ  Tu�   PKCE verifier dict for state '%s' has an empty/null code_verifier value â€” may indicate a storage bug. Treating as a cache miss.z'PKCE code_verifier retrieved from cachez[Retrieved code_verifier in legacy plain-string format. Future storage will use dict format.z:Unexpected PKCE verifier cache format (type=%s); skipping.rË  )r2  r2  Úcached_dataÚempty_value_in_dictrÕ  r!  )r0  rÔ  rÒ   rõ  rö  rN  r$   r1  r
  rÕ  r!  Úasync_get_cacher°   r€  r•   r  r‘   r9  Ú_handle_missing_pkce_verifier)r  r‚  Útoken_paramsrÔ  r2  r  rÕ  r!  r2  rX  rÊ  Ú_empty_value_in_dicts               rŽ   rÓ  z:SSOAuthenticationHandler.prepare_token_exchange_parameters:  sÃ  è ø€ ð  3FÐG`Ð1aˆô
 # 7×#7Ñ#7Ó8ˆØ#×'Ñ'¨Ó0ˆäŸ)™)Ð$=¸wÓG×MÑMÓOÐSYÑYˆá™EÜ ×(Ñ(ð,ôò ’XßXà!/°¨wÐ7ˆIØ Ð,Ø$5×$EÑ$EÈ)Ð$EÓ$T×T‘à$6×$FÑ$FÈ9Ð$FÓ$U×U�à ˆMà#(Ð áä˜k¬4Ô0°_ÈÑ5SØ$/°Ñ$@�MÙ(ð 04Ð,Ü,×4Ñ4ð^à!õô -×2Ñ2Ð3\Õ]Ü ¬SÔ1à$/�MÜ(×0Ñ0Øuõô )×.Ñ.ØTÜ˜[Ó)×2Ñ2ôñ
 à0=�˜_Ñ-ð 3<�Ð.Ñ/ð Ðô /×LÑLØØ'Ø +Ø(<Ø&7Ø'9ð Mó ÷ ð ð Ððo UøàUøðZús7   ‚BFÂFÂFÂ2FÂ3CFÆFÆFÆFÆFr2  rX  rY  rÕ  r!  c              ƒ   ó’  K  — |�|n|}t        j                  dd«      j                  «       dk(  }|�r?|rLt        j	                  |«      ƒ d{  –—†  t        d| › d�t        j                  dt        j                  ¬«      ‚|�Œt        j	                  |«      ƒ d{  –—†  t        j                  d	| t        |«      j                  «       t        d| › d
t        |«      j                  › d�t        j                  dt        j                  ¬«      ‚|�d}nd}t        j                  d| |t        |«      j                  «       t        d| › d|› �t        j                  dt        j                  ¬«      ‚|�t        j	                  |«      ƒ d{  –—†  t        j                  d| t        |«      j                  |du«       y7 �Œr7 �Œ'7 Œ8­w)zõHandle the case where PKCE verifier could not be extracted from cache.

        In strict mode (PKCE_STRICT_CACHE_MISS=true) raises ProxyException.
        Otherwise logs a warning and returns (token exchange proceeds without verifier).
        NÚPKCE_STRICT_CACHE_MISSr4  r5  zPKCE verifier for state 'u[   ' was found in cache but has an empty or null code_verifier value â€” possible storage bug.ÚPKCE_CACHE_MISSr  u¡   PKCE verifier for state '%s' has an unrecognized format (type=%s); treating as a cache miss. Investigate the cached value â€” it may be a corrupt or stale entry.z#' has an unrecognized format (type=z#). The cached entry may be corrupt.uŠ   The authorization and callback were likely handled by different instances â€” the verifier was stored on one pod but not found on another.z´The verifier may have expired (TTL), been lost on a pod restart, or the PKCE authorization step was never completed. Configure Redis so all proxy instances share the PKCE verifier.zQPKCE is enabled but no verifier found in cache for state '%s'. %s Cache type: %s.z,PKCE verifier not found in cache for state 'z'. uÁ   PKCE is enabled but verifier not found in cache for state '%s' (cache type: %s, raw data present: %s). Continuing without code_verifier â€” set PKCE_STRICT_CACHE_MISS=true to fail fast instead.)rõ  rö  rN  r9  rÙ  rB   rA   r  r   r§  r$   r˜  r  r‘   r1  )	r2  r2  rX  rY  rÕ  r!  Úactive_cacheÚstrict_cache_missÚcauses	            rŽ   r[  z6SSOAuthenticationHandler._handle_missing_pkce_verifier›  sô  è ø€ ð 4EÐ3PÑ/ÐVhˆÜ#%§9¡9Ð-EÀwÓ#O×#UÑ#UÓ#WÐ[aÑ#aÐÚÙ"Ü.×DÑDÀYÓO×OÐOÜ$à3°E°7ð ;]ð ^ô )×3Ñ3Ø+Ü×5Ñ5ôð ð Ð(Ü.×DÑDÀYÓO×OÐOÜ$×*Ñ*ð0ð Ü˜Ó%×.Ñ.ôô %à3°E°7ð ;!Ü!% kÓ!2×!;Ñ!;Ð <Ð<_ðaô )×3Ñ3Ø+Ü×5Ñ5ôð ð %Ð0ðeñ ðZð ô
 %×*Ñ*ØgØØÜ˜Ó&×/Ñ/ô	ô %ØJÈ5È'ÐQTÐUZÐT[Ð\Ü(×3Ñ3Ø+Ü×5Ñ5ô	ð ð Ð&Ü.×DÑDÀYÓO×OÐOÜ ×(Ñ(ðmð Ü�\Ó"×+Ñ+Ø 4Ð'õðo Pùð PùðV Pús8   ‚AGÁF?ÁAGÂGÂC0GÆGÆ3GÇGÇGc              ƒ   óî   K  — ddl m}m} 	 |�|j                  | ¬«      ƒ d{  –—†  y|j                  | ¬«      ƒ d{  –—†  y7 Œ 7 Œ# t        $ r!}t        j                  d| |«       Y d}~yd}~ww xY w­w)zõDelete a single-use PKCE verifier from cache after a successful exchange.

        Failure is non-fatal: a leftover verifier is a minor security concern
        (unused key in cache) but not worth aborting an otherwise-successful login.
        r   rú  Nr(  zHPKCE: failed to delete verifier cache key '%s' (best-effort cleanup): %s)r
  rÕ  r!  Úasync_delete_cacher—  r$   r1  )r2  rÕ  r!  Úexcs       rŽ   rÙ  z.SSOAuthenticationHandler._delete_pkce_verifierí  sz   è ø€ ÷ 	Uð
	Ø Ð,Ø'×:Ñ:¸yÐ:ÓI×IÑIà(×;Ñ;À	Ð;ÓJ×JÑJð JøàJùÜò 	Ü ×(Ñ(ØZØØ÷ñ ûð	üsX   ‚	A5ŒA £A¤A ¨A5©A ¾A¿A ÁA5ÁA ÁA Á	A2ÁA-Á(A5Á-A2Á2A5c                  ó`  — t        j                  t        j                  d«      «      j	                  d«      j                  d«      } t        j                  | j                  d«      «      j                  «       }t        j                  |«      j	                  d«      j                  d«      }| |fS )a‘  
        Generate PKCE (Proof Key for Code Exchange) parameters for OAuth 2.0.

        Returns:
            Tuple[str, str]: (code_verifier, code_challenge)
            - code_verifier: Random 43-128 character string (we use 43 for efficiency)
            - code_challenge: Base64-URL-encoded SHA256 hash of the code_verifier

        Reference: https://datatracker.ietf.org/doc/html/rfc7636
        r³  rÜ   rž  )
Úbase64Úurlsafe_b64encoderñ   Útoken_bytesrÍ  ÚrstriprÝ   rÞ   rß   Údigest)rÊ  Úcode_challenge_bytesrû  s      rŽ   r  z-SSOAuthenticationHandler.generate_pkce_params  s�   € ô  &×7Ñ7¼×8KÑ8KÈBÓ8OÓP×WÑWÐX_Ó`×gÑgÐhkÓlˆô '.§n¡n°]×5IÑ5IÈ'Ó5RÓ&S×&ZÑ&ZÓ&\ÐÜ &× 8Ñ 8Ð9MÓ N× UÑ UÐV]Ó ^× eÑ eÐfiÓ jˆà˜nÐ,Ð,r�   r`  zhttpx.Responsec                 ó€  — 	 t        | j                  «       «      }t        |t        «      syt        j                  dt        |«      j                  | j
                  dd «       t        dt        |«      j                  › d	�t        j                  dt        j                  ¬«      ‚|}|j                  d
«      }t        |t         «      r|s’|j                  d«      }|j                  dd«      }|r|r|› d|› �n|}ndt#        |j%                  «       «      › d	�}t        j                  d|«       t        d|› �t        j                  dt        j                  ¬«      ‚|S # t        $ rW}t        j                  d|| j
                  dd «       t        d|› �t        j                  dt        j                  ¬«      ‚d}~ww xY w)zÜ
        Parse and validate the token endpoint response.

        Ensures the response is valid JSON, a dict, and contains a non-null
        access_token string. Raises ProxyException on any validation failure.
        z4Failed to parse token response as JSON: %s. Body: %sNr1  z&Token endpoint returned invalid JSON: Útoken_exchanger  z9Token endpoint returned non-dict JSON (type=%s). Body: %szNToken endpoint returned unexpected response format (expected JSON object, got ú)rr   r˜  r*  rä   ú - zEtoken endpoint returned HTTP 200 but no access_token (response keys: z6Token response missing or null access_token. detail=%súToken exchange failed: )rÚ   r-  r—  r$   r˜  ÚtextrB   rA   r  r   r§  r°   r0  r  r‘   rÒ   r•   Úsortedr–  )r`  Útoken_response_rawÚjson_errÚtoken_responseÚaccess_token_valr˜  Ú
error_descr!  s           rŽ   Ú_validate_token_responsez1SSOAuthenticationHandler._validate_token_response  sÊ  € ð	Ü0:¸8¿=¹=»?Ó0KÐô Ð,¬dÔ3Ü ×&Ñ&ØKÜÐ'Ó(×1Ñ1Ø—‘˜d˜sÐ#ôô
 !ð2Ü26Ð7IÓ2J×2SÑ2SÐ1TÐTUðWô %×/Ñ/Ø&Ü×1Ñ1ôð ð '9ˆà"0×"4Ñ"4°^Ó"DÐÜÐ*¬CÔ0Ñ8HØ)×-Ñ-¨gÓ6ˆEØ .× 2Ñ 2Ð3FÈÓ KˆJÙÙ6@˜E˜7 # j \Ñ2Àe‘ð'Ü'-¨n×.AÑ.AÓ.CÓ'DÐ&EÀQðHð ô !×&Ñ&Ð'_ÐagÔhÜ Ø1°&°Ð:Ü$×/Ñ/Ø&Ü×1Ñ1ô	ð ð Ðøôc ò 	Ü ×&Ñ&ØFØØ—‘˜d˜sÐ#ôô
 !Ø@ÀÀ
ÐKÜ$×/Ñ/Ø&Ü×1Ñ1ô	ð ûð	ús   ‚E Å	F=Å&AF8Æ8F=rÍ  rÊ  rÆ  r„   r¶  r·  rÎ  r¢  c	              ƒ   óÂ  K  — t        j                  dt        |«      «       d| |dœ}	|r||	d<   i |¥dddœ¥}
|sG|r?t        j                  |› d|› �j                  «       «      j                  «       }d	|› �|
d
<   n||	d<   n||	d<   |r||	d<   t        t        j                  ¬«      }	 |j                  ||	|
d¬«      ƒ d{  –—† }|j$                  dk7  rvt        j                  d|j$                  |j&                  dd «       t        d|j$                  › d|j&                  dd › �t        j                  dt         j"                  ¬«      ‚t(        j+                  |«      }t        j                  dt-        |j/                  d«      «      «       t(        j1                  |d   |j/                  d«      ||¬«      ƒ d{  –—† }i |¥|¥}t2        D ]3  }|j/                  |«      �	||   ||<   Œ||v sŒ"|j5                  |d«       Œ5 |S 7 �ŒD# t        $ rJ}t        j                  d|«       t        d|› �t        j                  dt         j"                  ¬«      |‚d}~ww xY w7 Œ¡­w)au  
        Performs a direct OAuth token exchange including the PKCE code_verifier.

        fastapi-sso does not forward code_verifier, so when PKCE is enabled we
        bypass it and call the token endpoint ourselves, then fetch user info.

        Returns a combined dict of the token response and user info, suitable
        for passing to a response_convertor.
        z@PKCE: performing direct token exchange (code_verifier length=%d)rÍ  )Ú
grant_typer  rÊ  rÇ  z!application/x-www-form-urlencodedúapplication/json)úContent-TypeÚAcceptrü   zBasic rF  rÆ  r„   ©Úllm_providerg      >@)rÎ  r]  rÐ  ÚtimeoutNz#PKCE token endpoint unreachable: %szToken endpoint request failed: ro  r  rÇ  z-PKCE token exchange failed. status=%s body=%sr1  rr  rq  z3PKCE token exchange successful. id_token_present=%srq   rr   )rr   rq   r·  r¢  )r$   r€  rU  rh  Ú	b64encoderß   rÍ  r5   r6   ÚSSO_HANDLERÚpostr—  r˜  rB   rA   r  r   r§  r   rs  r9  rz  r   rÒ   Ú_get_pkce_userinfort   ru  )rÍ  rÊ  rÆ  r„   r¶  r·  rÎ  r1  r¢  Ú
token_dataÚrequest_headersÚcredentialsÚhttp_clientr`  rf  rw  r  ÚmergedÚfields                      rŽ   r×  z-SSOAuthenticationHandler._pkce_token_exchangeU  s®  è ø€ ô* 	×"Ñ"ØNÜ�Óô	
ð /Ø&Ø*ñ-
ˆ
ñ Ø)5ˆJ�~Ñ&ð"
Ø ð"
à?Ø(ò"
ˆñ !áÜ%+×%5Ñ%5¸¸À1À]ÀOÐ6T×6[Ñ6[Ó6]Ó%^×%eÑ%eÓ%g�Ø5;¸K¸=Ð3I� Ò0à*3�
˜;Ò'à&/ˆJ�{Ñ#ÙØ.;�
˜?Ñ+ä3ÔAU×AaÑAaÔbˆð	Ø$/×$4Ñ$4Ø"ØØ'Øð	 %5ó %÷ ˆHð" ×Ñ 3Ò&Ü ×&Ñ&Ø?Ø×$Ñ$Ø—‘˜d˜sÐ#ôô
 !Ø1°(×2FÑ2FÐ1GÀsÈ8Ï=É=ÐY]ÐZ]ÐK^ÐJ_Ð`Ü$×/Ñ/Ø&Ü×1Ñ1ô	ð ô !9× QÑ QÐRZÓ [ˆä×"Ñ"ØAÜ�×#Ñ# JÓ/Ó0ô	
ô !9× KÑ KØ'¨Ñ7Ø#×'Ñ'¨
Ó3Ø/Ø1ð	 !Ló !
÷ 
ˆð, 7˜>Ð6¨XÐ6ˆÜ(ò 	(ˆEØ×!Ñ! %Ó(Ð4à .¨uÑ 5��u’Ø˜.Ò(à—
‘
˜5 $Õ'ð	(ð ˆðKúô ò 
	ô !×&Ñ&Ð'LÈcÔRÜ Ø9¸#¸Ð?Ü$×/Ñ/Ø&Ü×1Ñ1ô	ð
 ðûð
	úð@
úsP   ‚B%IÂ(H Ã HÃH ÃC6IÆ;IÆ<1IÇ.IÈH È	IÈAIÉIÉIrr   rq   c              ƒ   ó>  K  — d}|r¾	 t        t        j                  ¬«      }|j                  |i |¥dd| › �i¥¬«      ƒ d{  –—† }|j                  dk(  rB	 |j                  «       }|s,t        j                  dt        |«      j                  «       d}n|}n.t        j                  d	|j                  |j                  dd
 «       |€Et        |t        «      r5|r3	 t        j                  |ddi¬«      }|st        j                  d«       d}|€]t        |t        «      xr t-        |«      }|r|rd}n
d}n|rd}nd}t#        d|› d�t$        j&                  dt(        j*                  ¬«      ‚|S 7 �Œ,# t        $ r }t        j                  d|«       Y d}~ŒÏd}~ww xY w# t        $ r }	t        j                  d|	«       Y d}	~	Œûd}	~	ww xY w# t        $ rI}
t        j                   d|
«       t#        d|
› �t$        j&                  dt(        j*                  ¬«      ‚d}
~
ww xY w­w)z‹
        Fetches user info from the userinfo endpoint.
        Falls back to decoding the id_token if the endpoint is unavailable.
        Nr€  rF  úBearer )rÎ  rÐ  rÇ  z¬Userinfo endpoint returned an empty or null response (type=%s); treating as failure and attempting id_token fallback. Check your provider's userinfo endpoint configuration.z=Userinfo endpoint returned non-JSON response (status 200): %szBUserinfo endpoint returned %s (body: %s), falling back to id_tokenr1  z5Userinfo endpoint error: %s, falling back to id_tokenré  Frê  u=   id_token decoded to an empty payload â€” treating as failure.zFailed to decode id_token: %szFailed to decode id_token JWT: r  r  ur   userinfo endpoint failed and id_token was present but decoded to an empty payload â€” no identity claims availablezJuserinfo endpoint failed and no id_token was present in the token responseuˆ   no userinfo endpoint is configured (GENERIC_USERINFO_ENDPOINT) and id_token decoded to an empty payload â€” no identity claims availablezZno userinfo endpoint is configured (GENERIC_USERINFO_ENDPOINT) and no id_token was presentzSSO user info unavailable: rS  )r5   r6   r„  rÒ   r   r-  r$   r1  r  r‘   r—  rs  r°   r•   rï  rÍ  r˜  rB   rA   r  r   r§  r   )rr   rq   r·  r¢  r  ÚclientÚrespÚuserinfo_rawrv  rœ  Ú
decode_errÚid_token_attemptedr!  s                rŽ   r†  z+SSOAuthenticationHandler._get_pkce_userinfoÔ  sS  è ø€ ð !%ˆáð$iÜ 6ÔDX×DdÑDdÔ e�Ø$*§J¡JØ)ðØ,ðà'¨7°<°.Ð)Añð %/ó %÷ �ð ×#Ñ# sÒ*ðØ.2¯i©i«k˜Ù+ô 1×8Ñ8ð!Yô !% \Ó 2× ;Ñ ;ô	ð (,™Hà'3˜Høô )×0Ñ0Ø\Ø×(Ñ(ØŸ	™	 $ 3˜ôð Ð¤
¨8´SÔ 9¹hðÜŸ:™: hÐ9KÈUÐ8SÔT�Ùô )×0Ñ0Ð1pÔqØ#�Hð ÐÜ(2°8¼SÓ(AÒ(TÄdÈ8ÃnÐÙ Ù%ðWñ ð
 j‘Fá%ðdñ ð uð ô !Ø5°f°X¸QÐ?Ü$×/Ñ/Ø Ü×1Ñ1ô	ð ð ˆðmúô, %ò Ü,×4Ñ4Ø[Ø$÷ñ ûðûô ò iÜ$×,Ñ,Ð-dÐfg×hÑhûðiûô" ò Ü$×*Ñ*Ð+JÈJÔWÜ$Ø=¸j¸\ÐJÜ(×3Ñ3Ø$Ü×5Ñ5ô	ð ûðüs‘   ‚Hˆ9F ÁE-ÁF ÁA E0 Â/F ÃHÃ2G ÄA!HÅ-F Å0	FÅ9FÆF ÆFÆF Æ	GÆ%G Æ;HÇ GÇHÇ	HÇAHÈHÈH©NNNNN©NNN)NNrŠ   )NNNNNNN).r‘   r’   r“   rÅ   Ústaticmethodr•   r   rW  r   r   rA  r   rõ  rÀ   r0  r  r@  r:  rY   ro   r@   r;   rC   r\   r  r  r   r…  r*  rh   r>   r(  r;  rn   r„  rK   r7   rC  rÓ  r–   r[  rÙ  r  rz  r×  r†  r‹   r�   rŽ   r9  r9  ù
  sÁ  „ ñð ð sð ¨tò ó ðð< ð (,Ø*.Ø(,Ø Ø"&ñE
ØðE
à ™*ðE
ð ! 4™ZðE
ð  ™:ð	E
ð
 �T‰zðE
ð ˜4‘ðE
ð 
˜DÑ	 òE
ó ðE
ðN ð !Ø59Ø"&ñ	n%Øðn%à�T‰zðn%ð ),¨d©
ðn%ð ˜4‘ð	n%ð
 
˜DÑ	 òn%ó ðn%ð` à Ø59ñ2.Ø�T‰zð2.à(+¨d©
ð2.ð 
ˆt�C˜�H‰~˜s T™zÐ)Ñ	*ò2.ó ð2.ðh à'+Ø*.Ø(,ñØ ™*ðà  4™Zðð  ™:ðð 
ò	ó ðð ð $(ñØðàðð ˜D‘jðð 
ò	ó ðð* ð#Ø˜vÑ%¨Ñ,¨tÑ3ð#à"Ð%6Ñ6¸Ñ=ð#ð ˜$‘Jð#ð 2°DÑ8ð	#ð
 $ò#ó ð#ðJ ðPØ˜vÑ%¨Ñ,¨tÑ3ðPà"Ð%6Ñ6¸Ñ=òPó ðPð  ð!Øð!à˜vÑ%¨Ñ,¨tÑ3ð!ð   $™;ð!ð 
�‰ò	!ó ð!ðF ð )-ñ9QØð9Qà ™:ò9Qó ð9Qðv ð
 )-ñ	Ø1°DÑ8ðà$ðð ðð  ™:ð	ð
 
òó ðð2 ð $(Ø $ñ	Ø�d‘
ðà�4‰Zðð ˜D‘jðð ˜‘:ð	ð
 
ˆt‰òó ðð4 ð )-ñ7
Ø˜‘ Ñ$ð7
à ™:ð7
ð 
ò7
ó ð7
ðr ð *.Ø(,Ø&*Ø,0Ø)-Ø $Ø59ñF!Ø˜‘ Ñ,ðF!àðF!ð   $™;ðF!ð  ™:ð	F!ð
 ˜t™ðF!ð # T™kðF!ð   $Ñ&ðF!ð ˜‘:ðF!ð ,¨dÑ2ðF!ð 
òF!ó ðF!ðP ð^Øð^à#'ð^ð 
ò^ó ð^ð@ ðOØ�T‰zðOàðOð ðOð "ð	Oð
 "ðOð #ðOð 
òOó ðOðb ð¨sð °tò ó ðð( ð- %¨¨S¨¡/ò -ó ð-ð* ð:Ð+;ð :Àò :ó ð:ðx ð|Øð|àð|ð ð|ð ˜T‘zð	|ð
 ð|ð  ™:ð|ð  ð|ð ˜D‘jð|ð !  c ™Nð|ð 
ò|ó ð|ð| ðgØðgà˜‘*ðgð  ™:ðgð !  c ™Nð	gð
 
ògó ñgr�   r9  c                   ó   — e Zd ZdZdZ	 dZdZedefd„«       Z	edefd„«       Z
e	 d"ded	ed
ededeez  ez  f
d„«       Zededz  dee   dedz  defd„«       Zedee   dz  dedz  fd„«       Zededz  dee   fd„«       Ze	 d#dedz  dee   fd„«       Zededededeee   edz  f   fd„«       Zededee   fd„«       Zededefd„«       Ze	 d#dedededz  deee   ee   f   fd„«       Zed ee   fd!„«       Z y)$r@  zS
    Handles Microsoft SSO callback response and returns a CustomOpenID object
    z https://graph.microsoft.com/v1.0rÇ  Úgraph_api_user_groupsrˆ   c                  ó<   — t        d«      xs t        j                  S )zì
        Returns the Microsoft Graph API base URL, configurable via the
        `MICROSOFT_GRAPH_ENDPOINT` env var so non-default clouds such as Azure
        Government (GCC High) can point at `https://graph.microsoft.us/v1.0`
        ÚMICROSOFT_GRAPH_ENDPOINT)re   r@  ÚDEFAULT_GRAPH_API_BASE_URLr‹   r�   rŽ   Úget_graph_api_base_urlz*MicrosoftSSOHandler.get_graph_api_base_urlN  s   € ô Ð8Ó9ÒkÔ=P×=kÑ=kÐkr�   c                  ó0   — t         j                  «       › d�S )Nz/me/memberOf)r@  rœ  r‹   r�   rŽ   Ú"get_graph_api_user_groups_endpointz6MicrosoftSSOHandler.get_graph_api_user_groups_endpointW  s   € ä%×<Ñ<Ó>Ð?¸|ÐLÐLr�   r  r.  r1  Úreturn_raw_sso_responsec              ƒ   ó  K  — t        j                  dd«      }t        j                  dd«      }|€+t        dt        j                  dt
        j                  ¬«      ‚|€+t        dt        j                  dt
        j                  ¬«      ‚t        ||||d¬«      }|j                  | d	¬
«      ƒ d{  –—† xs i }t        j                  |j                  ¬«      ƒ d{  –—† }t        j                  |j                  ¬«      }	t        j                  d|	«       t        j!                  |	«      }
t        j                  d|«       |r||t        j"                  <   |	|d<   |xs i S t        j%                  |||
¬«      }|S 7 ŒË7 Œ¡­w)z’
        Get the Microsoft SSO callback response

        Args:
            return_raw_sso_response: If True, return the raw SSO response
        r¹  Nrº  rð  r  z-MICROSOFT_TENANT not set. Set it in .env fileTrñ  F©r  Úconvert_response)rr   )rq   z%Extracted app roles from id_token: %sz*Combined team_ids (groups + app roles): %sÚ	app_roles)r`  rì  rí  )rõ  rö  rB   rA   r  r   r|  rS   rØ  r@  Úget_user_groups_from_graph_apirr   Úget_app_roles_from_id_tokenrq   r$   r€  Úget_user_role_from_app_rolesÚGRAPH_API_RESPONSE_KEYÚopenid_from_response)r  r.  r1  rŸ  rÁ  rÂ  r÷  Úoriginal_msft_resultÚuser_team_idsr£  rí  rX  s               rŽ   rA  z3MicrosoftSSOHandler.get_microsoft_callback_response[  s£  è ø€ ô *,¯©Ð3LÈdÓ)SÐÜ"$§)¡)Ð,>ÀÓ"EÐØ"Ð*Ü ØNÜ$×/Ñ/Ø/Ü×:Ñ:ô	ð ð Ð#Ü ØGÜ$×/Ñ/Ø(Ü×:Ñ:ô	ð ô  2Ø)Ø1Ø#Ø%Ø $ô 
ˆð  ×2Ñ2ØØ!&ð 3ó ÷ ò ð ð 	ô &9×%WÑ%WØ&×3Ñ3ð &Xó &
÷  
ˆô
 /×JÑJÐTa×TjÑTjÐJÓkˆ	Ü×"Ñ"Ð#JÈIÔVô /×KÑKÈIÓVˆ	ä×"Ñ"Ð#OÐQ^Ô_ñ #ØO\Ð Ô!4×!KÑ!KÑLØ09Ð  Ñ-Ø'Ò-¨2Ð-ä+×@Ñ@Ø)Ø"Øð Aó 
ˆð
 ˆð?øð 
ús%   ‚B-E?Â/E;Â0+E?ÃE=ÃB E?Å=E?r`  Nrì  rí  c           
      ó†  — | xs i } t        j                  d| «       t        t        | j	                  t
        «      xs | j	                  d«      «      | j	                  t        «      d| j	                  t        «      | j	                  t        «      | j	                  t        «      ||¬«      }t        j                  d|«       |S )Nz#Microsoft SSO Callback Response: %sÚmailrµ  )r×  r\  rW  r[  rS  rU  rì  rí  z!Microsoft SSO OpenID Response: %s)
r$   r€  rY   rÙ  rÒ   r/   r.   r1   r0   r2   )r`  rì  rí  Úopenid_responses       rŽ   r¨  z(MicrosoftSSOHandler.openid_from_response¡  s¢   € ð ’>˜rˆÜ×"Ñ"Ð#HÈ(ÔSÜ!-Ü! (§,¡,Ô/MÓ"NÒ"fÐRZ×R^ÑR^Ð_eÓRfÓgØ!Ÿ™Ô&KÓLØ Ø�|‰|Ô7Ó8Ø—|‘|Ô$GÓHØ—l‘lÔ#EÓFØØô	"
ˆô 	×"Ñ"Ð#FÈÔXØÐr�   r£  c                 óš   ‡— t        d„ d„ | xs dD «       D «       «      Š‰syt        ˆfd„t        D «       d«      }|�|S t        ‰d„ ¬«      S )aŠ  
        Resolve the one role LiteLLM stores for a user from their Entra app roles.

        Entra does not guarantee `roles` claim ordering, so a user holding several app
        roles resolves to the highest privilege one rather than whichever the claim
        listed first. Roles the hierarchy does not rank (org_admin, team, customer)
        resolve by name to stay deterministic
        c              3   ó&   K  — | ]	  }|€Œ|–— Œ y ­wrŠ   r‹   )rè   rã  s     rŽ   rê   zCMicrosoftSSOHandler.get_user_role_from_app_roles.<locals>.<genexpr>Â  s   è ø€ ò $
ØÐbfÑbrŒDñ$
ùs   ‚Šc              3   ó2   K  — | ]  }t        |«      –— Œ y ­wrŠ   )rZ   )rè   Úrole_strs     rŽ   rê   zCMicrosoftSSOHandler.get_user_role_from_app_roles.<locals>.<genexpr>Ã  s   è ø€ Ò^À(Ô3°H×=Ñ^ùs   ‚r‹   Nc              3   ó,   •K  — | ]  }|‰v sŒ|–— Œ y ­wrŠ   r‹   )rè   rã  Úresolveds     €rŽ   rê   zCMicrosoftSSOHandler.get_user_role_from_app_roles.<locals>.<genexpr>È  s   øè ø€ Ò_ tÈdÐV^ÒN^œdÑ_ùs   ƒ	�c                 ó   — | j                   S rŠ   r²   )rã  s    rŽ   ú<lambda>zBMicrosoftSSOHandler.get_user_role_from_app_roles.<locals>.<lambda>É  s   € ÐPT×PZÑPZ€ r�   r(  )r
  r  rÚ  Úmin)r£  Úrankedr³  s     @rŽ   r¦  z0MicrosoftSSOHandler.get_user_role_from_app_roles¶  sZ   ø€ ô $ñ $
Ù^ÈiÊoÐ[]Ô^ô$
ó 
ˆñ ØäÓ_Ô/JÔ_ÐaeÓfˆØÐ+ˆvÐ[´°XÑCZÔ1[Ð[r�   rq   c                 ó¨  — | st        j                  d«       g S 	 ddl} |j                  | ddi¬«      }|j	                  dg «      xs |j	                  dg «      }|r2t        |t        «      r"t        j                  d	t        |«      |«       |S t        j                  d
«       g S # t        $ r"}t        j                  d|«       g cY d}~S d}~ww xY w)aŠ  
        Extract app roles from the Microsoft Entra ID (Azure AD) id_token JWT.

        App roles are assigned in the Azure AD Enterprise Application and appear
        in the 'app_roles' claim of the id_token.

        Args:
            id_token (Optional[str]): The JWT id_token from Microsoft SSO

        Returns:
            List[str]: List of app role names assigned to the user
        z,No id_token provided for app role extractionr   Nré  Frê  r£  rÞ  z$Found %s app role(s) in id_token: %sz;No app roles found in id_token or roles claim is not a listz,Error extracting app roles from id_token: %s)
r$   r€  rï  rÍ  rÒ   r°   r•  rU  r—  r˜  )rq   rï  Údecoded_tokenrÞ  rœ  s        rŽ   r¥  z/MicrosoftSSOHandler.get_app_roles_from_id_tokenË  sÍ   € ñ Ü ×&Ñ&Ð'UÔVØˆIð	Ûð $. 3§:¡:¨hÐASÐUZÐ@[Ô#\ˆMð )×,Ñ,¨[¸"Ó=Ò_À×ARÑARÐSZÐ\^ÓA_ˆEáœ E¬4Ô0Ü$×*Ñ*Ð+QÔSVÐW\ÓS]Ð_dÔeØ�ä$×*Ñ*Ð+hÔiØ�	øäò 	Ü ×&Ñ&Ð'UÐWXÔYØ�Iûð	ús$   ›A3B& ÂB& Â&	CÂ/CÃCÃCrr   c              ƒ   óz  K  — 	 t        t        j                  ¬«      }t        j                  dd«      }g }g }|ret
        j                  ||| ¬«      ƒ d{  –—† \  }}t        j                  d|«       t        |«      dkD  rt
        j                  |¬«      ƒ d{  –—†  g }t
        j                  «       }dd	| › �i}d}|�b|t
        j                  k  rOt
        j                  |||¬
«      ƒ d{  –—† \  }	}|j                  |	«       |dz  }|�|t
        j                  k  rŒO|�7|t
        j                  k\  r$t        j                  dt
        j                  «       |r"t        |«      dkD  r|D �
cg c]	  }
|
|v sŒ|
‘Œ }}
|S 7 �Œ,7 Œé7 Œ—c c}
w # t         $ r"}t        j"                  d|«       g cY d}~S d}~ww xY w­w)a  
        Returns a list of `team_ids` the user belongs to from the Microsoft Graph API

        Args:
            access_token (Optional[str]): Microsoft Graph API access token

        Returns:
            List[str]: List of group IDs the user belongs to
        r€  ÚMICROSOFT_SERVICE_PRINCIPAL_IDN)Úservice_principal_idÚasync_clientrr   zService principal group IDs: %sr   )Úservice_principal_teamsrF  rŽ  )rÎ  rÐ  r½  r  zBReached maximum page limit of %s. Some groups may not be included.z6Error getting user groups from Microsoft Graph API: %s)r5   r6   r„  rõ  rö  r@  Ú$get_group_ids_from_service_principalr$   r€  rU  Ú4create_litellm_teams_from_service_principal_team_idsrž  ÚMAX_GRAPH_API_PAGESÚfetch_and_parse_groupsr^  r1  r—  r˜  )rr   r½  r¼  Úservice_principal_group_idsr¾  Úall_group_idsÚ	next_linkÚauth_headersÚ
page_countÚ	group_idsÚgroup_idrœ  s               rŽ   r¤  z2MicrosoftSSOHandler.get_user_groups_from_graph_apió  së  è ø€ ð1	Ü"8ÔFZ×FfÑFfÔ"gˆLô +-¯)©)Ð4TÐVZÓ*[Ð Ø<>Ð'ØRTÐ#Ù#ô .×RÑRØ)=Ø!-Ø!-ð Só ÷ ñØ/Ø+ô %×*Ñ*Ð+LÐNiÔjÜÐ2Ó3°aÒ7Ü-×bÑbØ0Gð có ÷ ð ð
 ˆMÜ$7×$ZÑ$ZÓ$\ˆIØ#2°g¸l¸^Ð4LÐ"MˆLØˆJàÐ'¨JÔ9L×9`Ñ9`Ò,`Ü-@×-WÑ-WØ!¨<Àlð .Xó .÷ (Ñ$�	˜9ð ×$Ñ$ YÔ/Ø˜a‘�
ð Ð'¨JÔ9L×9`Ñ9`Ó,`ð Ð$¨Ô7J×7^Ñ7^Ò)^Ü$×,Ñ,ØXÜ'×;Ñ;ôñ +¬sÐ3NÓ/OÐRSÒ/SØ:GÖ s¨hÈ8ÐWrÒKr¢Ð s�Ð sà Ð ðEùðøð(úò !tøô ò 	Ü ×&Ñ&Ð'_ÐabÔcØ�Iûð	üsŒ   ‚F;„AF ÁFÁAF ÂFÂAF Ã.FÃ/2F Ä"AF Å/	FÅ9FÅ=F Æ F;ÆF ÆF ÆF ÆF Æ	F8ÆF3Æ-F8Æ.F;Æ3F8Æ8F;rÎ  rÐ  r½  c              ƒ   óö   K  — |j                  | |¬«      ƒ d{  –—† }|j                  «       }t        j                  |¬«      ƒ d{  –—† }t        j	                  |¬«      }||j                  d«      fS 7 Œ[7 Œ/­w)z8Helper function to fetch and parse group data from a URL©rÐ  N)r`  Úodata_nextLink)rÒ   r-  r@  Ú_cast_graph_api_response_dictÚ&_get_group_ids_from_graph_api_response)rÎ  rÐ  r½  r`  Úresponse_jsonÚresponse_typedrÈ  s          rŽ   rÂ  z*MicrosoftSSOHandler.fetch_and_parse_groups3  sw   è ø€ ð
 !-× 0Ñ 0°¸gÐ 0Ó F×FˆØ'Ÿ}™}›ˆÜ&9×&WÑ&WÐanÐ&WÓ&o× oˆÜ.×UÑUÐ_mÐUÓnˆ	Ø˜.×,Ñ,Ð-=Ó>Ð>Ð>ð	 Gøà oús!   ‚A9™A5š-A9ÁA7Á.A9Á7A9c                 óŠ   — g }| j                  dg «      xs g D ]'  }|j                  d«      }|€Œ|j                  |«       Œ) |S )Nr®   r[  )rÒ   rC  )r`  rÈ  Ú_objectÚ	_group_ids       rŽ   rÎ  z:MicrosoftSSOHandler._get_group_ids_from_graph_api_response>  sR   € ð ˆ	Ø—|‘| G¨RÓ0Ò6°Bò 	,ˆGØŸ™ DÓ)ˆIØÑ$Ø× Ñ  Õ+ð	,ð Ðr�   c              ƒ   óˆ  K  — g }| j                  dg «      D ]|  }|j                  t        |j                  d«      |j                  d«      |j                  d«      |j                  d«      |j                  d«      |j                  d«      ¬«      «       Œ~ t        | j                  d	«      | j                  d
«      |¬«      S ­w)Nr®   z@odata.typer[  ÚdeletedDateTimeÚdescriptionÚdisplayNameÚroleTemplateId)Ú
odata_typer[  rÕ  rÖ  r×  rØ  z@odata.contextr×   )Úodata_contextrÌ  r®   )rÒ   rC  ri   rj   )r`  Údirectory_objectsrÒ  s      rŽ   rÍ  z1MicrosoftSSOHandler._cast_graph_api_response_dictI  s¶   è ø€ ð UWÐØ—|‘| G¨RÓ0ò 
	ˆGØ×$Ñ$Ü9Ø&Ÿ{™{¨=Ó9Ø—{‘{ 4Ó(Ø$+§K¡KÐ0AÓ$BØ '§¡¨MÓ :Ø '§¡¨MÓ :Ø#*§;¡;Ð/?Ó#@ôõ	ð
	ô 2Ø"Ÿ,™,Ð'7Ó8Ø#Ÿ<™<Ð(9Ó:Ø#ô
ð 	
ùs   ‚C Cr¼  c           	   ƒ   óö  K  — t         j                  «       }d| › d�}||z   }d|› �ddœ}g }g }d}	|��|	t         j                  k  ró|j                  ||¬«      ƒ d{  –—† }
|
j	                  «       }t        j                  d	|«       |j                  d
g «      D ]q  }|j                  d«      dk(  sŒ|j                  |j                  d«      «       |j                  t        |j                  d«      |j                  d«      ¬«      «       Œs |j                  d«      }|	dz  }	|�|	t         j                  k  rŒó|�7|	t         j                  k\  r$t        j                  dt         j                  «       ||fS 7 �Œ­w)zõ
        Gets the groups belonging to the Service Principal Application

        Service Principal Id is an `Enterprise Application` in Azure AD

        Users use Enterprise Applications to manage Groups and Users on Microsoft Entra ID
        z/servicePrincipals/z/appRoleAssignedTorŽ  r}  )rF  r~  r   NrË  z8Response from service principal app role assigned to: %sr®   ÚprincipalTypeÚGroupÚprincipalIdÚprincipalDisplayName)rà  rß  r×   r  z_Reached maximum page limit of %s. Some service principal group assignments may not be included.)
r@  rœ  rÁ  rÒ   r-  r$   r€  rC  rk   r1  )r¼  r½  rr   r¾  ÚendpointrÅ  rÐ  rÈ  r¾  rÇ  r`  rÏ  rÒ  s                rŽ   r¿  z8MicrosoftSSOHandler.get_group_ids_from_service_principal_  s‹  è ø€ ô .×DÑDÓFˆà/Ð0DÐ/EÐEWÐXˆØ (¨8Ñ 3ˆ	ð  ' | nÐ5Ø.ñ
ˆð
 ')ˆ	ØNPÐØˆ
àÑ#¨
Ô5H×5\Ñ5\Ò(\Ø)×-Ñ-¨iÀÐ-ÓI×IˆHØ3;·=±=³?ˆMÜ ×&Ñ&Ð'aÐcpÔqà(×,Ñ,¨W°bÓ9ò 
�Ø—;‘;˜Ó/°7Ó:à×$Ñ$ W§[¡[°Ó%?Ô@à+×2Ñ2Ü5Ø18·±Ð=SÓ1TØ(/¯©°MÓ(Bôõð
ð &×)Ñ)Ð*;Ó<ˆIØ˜!‰OˆJð% Ð#¨
Ô5H×5\Ñ5\Ó(\ð( Ð  ZÔ3F×3ZÑ3ZÒ%ZÜ ×(Ñ(ØqÜ#×7Ñ7ôð
 Ð1Ð1Ð1ð3 Jûs    ‚AE9ÁE6ÁAE9Â1BE9Ä9>E9r¾  c              ƒ   óþ   K  — t        j                  d| «       | D ]\  }|j                  d«      }|j                  d«      }|st        j                  d|«       Œ>t        j	                  ||¬«      ƒ d{  –—†  Œ^ y7 Œ­w)zå
        Creates Litellm Teams from the Service Principal Group IDs

        When a user sets a `SERVICE_PRINCIPAL_ID` in the env, litellm will fetch groups under that service principal and create Litellm Teams from them
        z7Creating Litellm Teams from Service Principal Teams: %srß  rà  z;Skipping team creation for %s because it has no principalId)r  r  N)r$   r€  rÒ   r9  r*  )r¾  Úservice_principal_teamr  r  s       rŽ   rÀ  zHMicrosoftSSOHandler.create_litellm_teams_from_service_principal_team_ids–  s‘   è ø€ ô 	×"Ñ"Ð#\Ð^uÔvØ&=ò 	Ð"Ø*@×*DÑ*DÀ]Ó*SˆOØ,B×,FÑ,FÐG]Ó,^ÐÙ"Ü$×*Ñ*ØQÐSdôð ä*×MÑMØ /Ø"3ð Nó ÷ ñ ñ	ðús   ‚A1A=Á3A;Á4A=©FrŠ   )!r‘   r’   r“   rÅ   r›  rÁ  r§  r–  r•   rœ  rž  r   r   rY   ro   r0  rA  r•  r<   r¨  r   r¦  r¥  r¤  r4   rÀ   rÂ  rj   rÎ  rÍ  rk   r¿  rÀ  r‹   r�   rŽ   r@  r@  ?  s˜  „ ñð "DÐðð Ðð 5Ðàðl Cò ló ðlð ðM°ò Mó ðMð ð
 ).ñ	CØðCà ðCð ðCð "&ð	Cð
 
˜Ñ	 Ñ	%òCó ðCðJ ðØ˜‘+ðà�s‘)ðð $ dÑ*ðð 
ò	ó ðð( ð\Ø˜C‘= 4Ñ'ð\à	˜DÑ	 ò\ó ð\ð( ð%¨c°D©jð %¸TÀ#¹Yò %ó ð%ðN à#'ñ=Ø˜D‘jð=à	ˆc‰ò=ó ð=ð~ ð?Øð?Øð?Ø/?ð?à	ˆt�C‰y˜# ™*Ð$Ñ	%ò?ó ð?ð ðØ4ðà	ˆc‰òó ðð ð
Øð
à	+ò
ó ð
ð* ð $(ñ42Ø!ð42à&ð42ð ˜D‘jð42ð 
ˆt�C‰y˜$Ð<Ñ=Ð=Ñ	>ò	42ó ð42ðl ðØ!%Ð&CÑ!Dòó ñr�   r@  c                   ó@   — e Zd ZdZe	 d	dededededee	z  f
d„«       Z
y)
r>  zP
    Handles Google SSO callback response and returns a CustomOpenID object
    r  r/  r1  rŸ  rˆ   c              ƒ   ó:  K  — ddl m} t        j                  dd«      }|€+t	        dt
        j                  dt        j                  ¬«      ‚ ||||¬«      }|r|j                  | d¬	«      ƒ d{  –—† xs i S |j                  | «      ƒ d{  –—† }|xs i S 7 Œ'7 Œ­w)
z�
        Get the Google SSO callback response

        Args:
            return_raw_sso_response: If True, return the raw SSO response
        r   rí  r¸  Nrï  r  )rÆ  rÇ  r„   Fr¡  )
ró  rî  rõ  rö  rB   rA   r  r   r|  rØ  )r  r/  r1  rŸ  rî  rÀ  rö  rX  s           rŽ   r?  z-GoogleSSOHandler.get_google_callback_response´  sº   è ø€ õ 	5ä&(§i¡iÐ0FÈÓ&MÐØÐ'Ü ØKÜ$×/Ñ/Ø,Ü×:Ñ:ô	ð ñ &Ø&Ø%Ø.ô
ˆ
ñ #à ×3Ñ3Ø#Ø%*ð 4ó ÷ ò ð ðð )×;Ñ;¸GÓD×DˆØŠ|˜Ððøð Eús$   ‚A-BÁ/BÁ0BÂBÂBÂBNrä  )r‘   r’   r“   rÅ   r–  r   r•   r   ro   r0  r?  r‹   r�   rŽ   r>  r>  ¯  sR   „ ñð ð
 ).ñ	'Øð'àð'ð ð'ð "&ð	'ð
 
�$‰ò'ó ñ'r�   r>  z/sso/debug/loginc              ƒ   ó°  K  — ddl m} t        j                  dd«      }t        j                  dd«      }t        j                  dd«      }|€|€|�/|dur+t	        dt
        j                  d	t        j                  ¬
«      ‚t        j                  | d¬«      }t        j                  |||¬«      du r"t        j                  ||||| ¬«      ƒ d{  –—† S y7 Œ­w)r   r   )r  r#  Nr$  r%  Taa  You must be a LiteLLM Enterprise user to use SSO. If you have a license please set `LITELLM_LICENSE` in your env. If you want to obtain a license meet with us here: https://enterprise.litellm.ai/demo You are seeing this error message because You set one of `MICROSOFT_CLIENT_ID`, `GOOGLE_CLIENT_ID`, or `GENERIC_CLIENT_ID` in your env. Please unset thisr  r  ússo/debug/callbackr(  r-  )r1  r.  r/  r0  r  )r
  r  rõ  rö  rB   rA   r  r   r  r9  r:  r@  rA  )r  r  r.  r/  r0  r1  s         rŽ   Údebug_sso_loginré  ß  s  è ø€ õ 8ä!#§¡Ð+@À$Ó!GÐÜ Ÿi™iÐ(:¸DÓAÐÜ!Ÿy™yÐ)<¸dÓCÐð Ð&Ð*:Ð*FÐJ[ÐJgØ˜tÑ#Ü ð |Ü$×/Ñ/Ø$Ü×.Ñ.ô	ð ô 3×KÑKØØ/ð Ló €Lô 	!×7Ñ7Ø 3Ø-Ø/ð 	8ó 	
ð
 ñ	ô .×DÑDØ%Ø 3Ø-Ø/Øð Eó 
÷ 
ð 	
ð	ð
ús   ‚CCÃCÃCú/sso/debug/callbackc           
   ƒ   ó   K  — ddl }ddlm} ddlm} ddlm} ddlm}m	}m
}m} d}	|j                  dd«      }
|
�St        |
t        «      rC |«       }	|	j                  || ||j                  di «      j                  dd«      ¬	«      d¬
«       t!        j"                  dd«      }t!        j"                  dd«      }t!        j"                  dd«      }t!        j"                  dt%        | j&                  «      «      }|j)                  d«      r|dz  }n|dz  }d}d}d}|�"t*        j-                  | ||d¬«      ƒ d{  –—† }nC|�"t.        j1                  | ||d¬«      ƒ d{  –—† }n|�t3        | ||||	¬«      ƒ d{  –—† \  }}}}|€
 |dd¬«      S t5        |d«      r|j6                  }nt        |«      }i }|j9                  «       D ]Q  \  }}|€Œ	|j;                  d«      rŒt        |t$        t<        t>        t@        f«      s|€|||<   ŒC	 t%        |«      ||<   ŒS |xs i j9                  «       D ��ci c]  \  }}|tD        vsŒ||“Œ }}}|xs i j9                  «       D ��ci c]  \  }}|tD        vsŒ||“Œ }}}|||dœ} |jF                  |dt$        ¬«      jI                  dd «      }tK        jH                  d!d"|› d#�«      } ||¬$«      S 7 �Œ‘7 �Œp7 �ŒX# tB        $ r}d|› �||<   Y d}~�Œ&d}~ww xY wc c}}w c c}}w ­w)%z@
    Returns the OpenID object returned by the SSO provider
    r   NrÁ  r.  rJ   )r  rJ  rŒ  r!  r2  r3  r4  r5  r#  r$  r%  r¡  rÅ  rè  rê  T)r  r/  r1  rŸ  )r  r.  r1  rŸ  r8  zT<h1>SSO Authentication Failed</h1><p>No data was returned from the SSO provider.</p>r'  rÈ  Ú__dict__ró   z!Complex value (not displayable): )Úparsed_by_proxyÚ
raw_claimsÚaccess_token_claimsrT  )ÚindentrÕ   z</z<\/zconst ssoData = SSO_DATA;zconst ssoData = ú;)rÉ  )&r-  rÊ  rÂ  r;  r/  r<  rK   r
  r  rJ  rŒ  r!  rÒ   r°   r0  r=  rõ  rö  r•   r¾  r  r>  r?  r@  rA  rã  rZ  rì  rv  r*  rw  rx  r   r—  rt   r7  rb  rO   )r  r-  rÂ  r/  rK   r  rJ  rŒ  r!  rç  r2  r.  r/  r0  r1  rX  rÀ  r÷  Ú_sso_assertionrm  Úfiltered_resultrÏ   r®   rœ  ÚkÚvÚsafe_raw_claimsÚsafe_access_token_claimsÚsso_payloadÚsso_payload_jsonrÕ  s                                  rŽ   Údebug_sso_callbackrú    s`  è ø€ ó
 å.å4Ý8÷ó ð *.€OØ,×0Ñ0Ð1AÀ4ÓH€NØÐ!¤j°ÄÔ&FÙ$›,ˆØ×*Ñ*Ø'Ø1Ù+Ø#3×#7Ñ#7Ð8HÈ"Ó#M×#QÑ#QÐRgÐimÓ#nôð ð 	+ô 	
ô "$§¡Ð+@À$Ó!GÐÜ Ÿi™iÐ(:¸DÓAÐÜ!Ÿy™yÐ)<¸dÓCÐä—9‘9Ð-¬s°7×3CÑ3CÓ/DÓE€LØ×Ñ˜SÔ!ØÐ,Ñ,‰àÐ-Ñ-ˆà€FØ%)ÐØ(,ÐØÐ#Ü'×DÑDØØ-Ø%Ø$(ð	 Eó 
÷ 
‰ð 
Ð	(Ü*×JÑJØØ 3Ø%Ø$(ð	 Kó 
÷ 
‰ð 
Ð	&ô +ØØ#Ø/Ø%Ø+ô
÷ 
ñ	
ØØØ Øð €~ÙØjØô
ð 	
ô ˆv�zÔ"Ø—o‘o‰ä˜6“lˆð  €OØ!×'Ñ'Ó)ò 	S‰
ˆˆUØÑ S§^¡^°CÕ%8Ü˜%¤#¤s¬E´4Ð!8Ô9¸U¸]Ø',� Ò$ðSä+.¨u«:�O CÒ(ð	Sð 1BÒ0GÀR×/NÑ/NÓ/P×q¡t q¨!ÐTUÔ]pÒTp˜a ™dÐq€OÑqØ2FÒ2LÈ"×1SÑ1SÓ1U×v©¨¨AÐYZÔbuÒYu  1¡ÐvÐÑvð +Ø%Ø7ñ€Kð )˜dŸj™j¨¸QÌÔL×TÑTÐUYÐ[aÓbÐÜ.×6Ñ6Ø#Ø
Ð+Ð,¨AÐ.ó€Lñ
  Ô-Ð-ðQ
ùð
ùð
úô> !ò SØ-NÈqÈcÐ+R�O C×(ûðSüó
 rùÛvùs’   ‚D7K>Ä9K
Ä:#K>ÅKÅK>Å8KÅ9AK>ÇK>Ç(K>ÈKÈK>È/K2É K2ÉK>ÉK8É0K8É5AK>ËK>ËK>Ë	K/ËK*Ë$K>Ë*K/Ë/K>rä  rŠ   r”  r•  (  rÅ   rò  rh  rÝ   r`  r-  rõ  Úrerñ   Úcollections.abcr   r   Úcopyr   Úhtmlr   Útypesr   Útypingr	   r
   r   r   r   r   r   r   r   r   r   r  r   r   r   Úhttpxrï  Úfastapir   r   r   r   r   r   r   rÊ  r   Úpydanticr   r    r!   r"   r#   rý  Úlitellm._loggingr$   Úlitellm._uuidr%   Úlitellm.caching.dual_cacher&   r:  r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   Ú0litellm.litellm_core_utils.dot_notation_indexingr3   Ú&litellm.llms.custom_httpx.http_handlerr4   r5   r6   ÚOlitellm.proxy._experimental.mcp_server.outbound_credentials.sso_assertion_storer7   r8   r9   r;  r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rŒ  rF   rG   Úlitellm.proxy.auth.auth_utilsrH   rI   r<  rK   Ú$litellm.proxy.auth.user_api_key_authrL   Ú)litellm.proxy.common_utils.admin_ui_utilsrM   rN   Ú:litellm.proxy.common_utils.html_forms.jwt_display_templaterO   Ú.litellm.proxy.common_utils.html_forms.ui_loginrP   Ú-litellm.proxy.common_utils.user_api_key_cacherQ   Ú:litellm.proxy.management_endpoints.internal_user_endpointsrR   Ú&litellm.proxy.management_endpoints.ssorS   Ú/litellm.proxy.management_endpoints.sso.saml_ssorT   Ú3litellm.proxy.management_endpoints.sso_helper_utilsrU   rV   Ú1litellm.proxy.management_endpoints.team_endpointsrW   rX   Ú(litellm.proxy.management_endpoints.typesrY   rZ   r[   rŠ  r\   r]   r^   r_   Ú%litellm.repositories.prisma_protocolsr`   Ú'litellm.repositories.table_repositoriesra   Ú$litellm.repositories.team_repositoryrb   Ú$litellm.repositories.user_repositoryrc   Úlitellm.secret_managers.mainrd   re   rf   r‰  rh   ri   rj   rk   rl   rm   rL  rn   rÑ  ro   rp   r¹   r
  rt   ru   rv   rx   rz   r|   Úcompiler}   r  r•   rw  rx  r   r~   r   r…   r‡   r�   rŸ   r¤   r¦   r«   r0  r¬   r–   r­   r³   rµ   r»   rÂ   rÀ   rÆ   rÇ   rÉ   rÎ   rÔ   rÚ   rá   rî   rù   rþ   r  r  r  r  r  r%  r4  r8  r=  r•  rI  rP  rW  r\  rh  rn  rs  r~  rƒ  r‹  r�  r¡  r¬  r…  r¿  rÖ  rÙ  rë  ÚPROXY_ADMIN_VIEW_ONLYrš  r"  rÚ  rå  rÿ  r  r  r  rÒ   rI  rl  rƒ  rŽ  r›  r¡  r—  r®  rã  rî  rø  rÿ  r  r  r  r  r   r$  r(  rI  rL  rP  rX  re  rk  rr  rv  rz  r€  rB  r•  r�  r²  rÃ  rÊ  rÙ  rB  r9  r@  r>  ré  rú  r‹   r�   rŽ   ú<module>r     s�  ðòó Û Û Û Û Û 	Û 	Û ß -Ý Ý Ý "÷÷ ÷ ñ ÷ 7Ñ 6áÛã 
ß X× XÑ XÝ .ß YÕ Yã Ý 1Ý Ý 0÷÷ ÷ ó õ N÷ñ ÷
ñ ÷
÷ ÷ ó ÷ S÷õ 5Ý B÷õõ OÝ IÝ OÝ EÝ K÷÷ X÷ñ ÷
ó õ ?Ý GÝ ?Ý ?ß UÑ UÜ =÷÷ õ :áÞ+å$á“€ˆÓ ñ 'Ò'TÓUÐ �UÓ UØ+KÐ*LÈEÐ(RÐ  Ó RØ7UÐ6VÐVgÐ4hÐ *¨EÓ hØ24Ð (¨%Ó 4Ø02Ð &¨Ó 2Ø%GÐ ˜UÓ GØ(˜bŸjšjÐ)GÓHÐ �eÓ HØ"˜Ÿ
š
 bÐ)DÐ(EÀXÐNiÐMjÐjqÐ#rÓsÐ Ø # S¨%°Ð6Ð �uÓ 6Ø(˜bŸjšjÐ)=Ó>Ð �eÓ >Ù'0ò	ó(Ð ˜uó ô;�xô ;ð
˜ð Ð+Kó ô?�Hô ?ð
Ð,ð Ð1Nó ô6�Xô 6ð˜.ð Ð-Kó ñ !,¨D°°c°©NÓ ;Ð ˜Ó ;Ù#.¨w°s¸F°{Ñ/CÓ#DÐ ˜5Ó Dð ð ¨Fó ôf˜9ô fô<�Yô <ô8�yô 8ñ (3°5Ð9IÈ3Ð9NÑ3OÓ'PÐ ˜uÓ PÙ'7ÀBÔ'GÐ ˜uÓ GôW�Xô Wô( (ô (ô	F˜Hô 	Fð�fð  ó ð> ð >¨ó >ðC¨Cð C°Có Cð. Só .ð
:¨#ð :°#ó :ðX¨¨t©ð X¸ó Xð[¨3°©:ð [¸$ó [ðX°Dó Xðàðð ðð ð	ð
  # T™zðð 
ˆ#ˆs�S‰yˆ.Ñóò.L°Wð LÐSWÐZ^ÑS^ð LÐknó Lð (-ò
Øð
àð
ð  ™ð
ð 
ó	
ð(&¨¨t©ð &¸Ið &È$ó &ðRT ð T¨Ið T¸Tð TÀdó TðX dð X¸¸t¹ð XÈó Xð $ u¨S°#¨X¡Ñ"7ó ð6V°ð V¸ó Vð¨vð ¸$ó ð ¨vÑ 5¸¸SÀ&¸[Ñ8IÑ Ið ÈdÐSVÐX^ÐS^ÑN_ó ð '¨#¨v¨+Ñ"6ð ÀCð ÈFó ð.< \°FÑ%:¸TÀ#ÀvÀ+Ñ=NÑ%Nð <Ð\_ð <Ðdjó <ð ¨¨c°6¨kÑ):ð Àcð ÐRXð Ð]aó ðØ�c˜6�kÑ"ðà	ˆ#ˆs�S‰y˜5Ñ  4Ñ'Ð
'Ñ(óð$Ø˜6Ñ! D¨¨f¨Ñ$5Ñ5ðà	ˆ#ˆvˆ+Ñóð8Ø˜C ˜KÑ(ðØ@DÀSÈ&À[Ñ@Qðà	ˆ#ˆvˆ+Ñóð0qØðqàðqð ˜s F˜{Ñ+ðqð 
ó	qðBØ˜#˜v˜+Ñ&ðà	ˆ#ˆs�S‰y˜5Ñ  4Ñ'Ð
'Ñ(óð %)òLØðLàðLð ˜T‘zðLð 	ó	Lð^ ‡‚Ð ^Ð$4È€ÓNð* ò *ó Oð*ðZ ‡‚Ð+°>Ð2BÐV[€Ó\ð#? Gð #?°sò #?ó ]ð#?ðL>˜3 ™:ð >¨#°©*ó >ð, × Ò Ø×*Ò*Ø×"Ò"Ø×,Ò,ð	&Ð ˜Uó ð+&Ø�c‘ð+&à!ð+&ð ˜Ñó+&ðd /3ò	`Ø˜D‘jð`à $Ñ&ð`ð �T‰M˜DÑ ð`ð ˜NÑ+ð	`ð
 
ˆD�[ó`ðF	$ C¨$¡Jð 	$°7¸3À¸;Ñ3Gó 	$ð	Ø�c˜6�kÑ"ð	à�D‰jð	ð ˜‘*ð	ð ˆS�&ˆ[Ñó		ð
¸dð 
ÐS_ÐbfÑSfð 
Ðkoó 
ð* ‡‚Ð ~Ð&6È%€ÓPð ØØ#Ø Ø òCØðCà�$‰JðCð 
ˆt‰ðCð ˜‘*ð	Cð
 �T‰zðCð �T‰zòCó QðCðR *.Ø.2Ø.2òuàðuð   $Ñ&ðuð ˜NÑ+ð	uð
 ˜NÑ+ðuð óuðp8Øð8Ø*-ð8à
ˆ3��S‘	˜3  S¨$Ð.Ñ/ó8ðv! H¨^Ñ$<ó !ðH7 H¨^Ñ$<ó 7ðt D¨¨c¨¡Nó ð4Øð4à$'¨$¡Jð4ð   $™Jð4ð ð	4ð
 ó4ðnEPØðEPàðEPð   $Ñ&ðEPð ð	EPð
 ðEPð Ø
ˆT�M�4˜$‘;  t¡Ð-AÀDÑ-HÐHñóEPòP_ð _¨_Ð?PÑ-Pð _Ð]aÐbeÑ]fó _ò$5ðØ�4‰Zðà�d‘
ðð  ðð (ð	ð
 $ðð ˜Ñóð@ %)ò=Ø˜6Ñ! DÑ(ð=àð=ð (ð=ð $ð	=ð
 �d‘
ð=ð .°Ñ4ð=ð ˜T‘zð=ð ˜Ñ(¨4Ñ/ó=ð@°°t±ð Àó ðØ�. &¨$Ð.Ñ/°$Ñ6ðà�d‘
ðð �4‰Zðð 
ˆ#ˆvˆ+Ñó	ð@,
Ø˜dÑ"ð,
à˜d‘{ð,
ð ! ?Ñ2°TÑ9ð,
ð  ð	,
ð
 (ð,
ð .°Ñ4ð,
ð 
ô,
ð^Ø  ?Ñ2°TÑ9ðà-°Ñ4ðð ˜DÑ ôðB¸ð Àcð ÐZfÐimÑZmô ð* ‡‚ˆO >Ð"2Àe€ÓLò} ð }°°t±ò }ó Mñ}ð@ ‡‚Ð ^Ð$4È€ÓNòx˜gð x°#¸±*ò xó Oñxð ‡‚Ð ¨Ð'7È5€ÓQðD ò Dó RñDð ‡‚Ð!¨Ð(8ÈE€ÓRð2 ò 2ó Sñ2ðjØ�T‰Mðà,ðð ˜DÑ ôð0 7¨3°¨;Ñ#7ð Ð<Lô ð[Øð[à�C‰=ð[ð Ð˜SÐ Ñ! DÑ(ô[ð$U¨Ð2BÑ)Cð UÈÈSÉ	ô Uð	S¨vð 	SÀÀdÁ
ð 	SÐO_ÐbfÑOfô 	Sð0 %)Ø15òUàðUð 
ðUð ð	Uð
 �T‰MðUð -ðUð .°Ñ4ðUð  ðUð (ðUð %ðUð $ðUð ˜T‘zðUð (¨$Ñ.ôUðt Ø#'Ø%)Ø$(Ø15òFWØðFWà	ˆt‰ðFWð �T‰M˜DÑ ðFWð ˜d‘{ð	FWð
 ˜T‘zðFWð (¨$Ñ.ôFWðR ‡‚Ð$¨NÐ+;Èu€ÓUð Ù,2¸4Ô,@ñ@[Øð@[à�4‰Zð@[ð  # T™zò@[ó Vñ@[ðJ 8<òCØ˜D‘= 4Ñ'ðCà-°Ñ4ðCð ôCðL ‡‚ØØ
Ð	ØÙÐ+Ó,Ð-ð	 ó ð 7ò óñð4 ‡‚ØØ
Ð	ÙÐ+Ó,Ð-ñ ó ò
Kóñ
Kð\N¨3ð N°4õ Nð +Ø�T‰zñ+àð+ð
 ˜Ñõ+ñ\
¨ð 
¸SÀ4¹Zð 
ÈDõ 
÷0Cô C÷L*mô m÷`-ô -ð` ‡‚Ñ nÐ%5È€ÓOð+
 7ó +
ó Pñ+
ð\ ‡‚Ñ!¨Ð(8ÈE€ÓRðt. gó t.ó Sòt.r�   