+
    jHàjûB  ã                  óV  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt	^ RI
HtHtHt ^ RIt^ RIHtHtHt ^ RIHtHtHtHtHtHtHtHtHtHtHtH t H!t!H"t"H#t#H$t$ ]PJ                  ! ]&4      t'Rt(Rt)Rt*Rt+R	t,R
s-R].R&   R R lt/R R lt0 ! R R]4      t1R R lt2R R lt3R R lt4R# )u  SelfHostedOIDCProvider â€” generic self-hosted OpenID Connect dashboard auth.

A plain OIDC Relying Party (Authentik, Keycloak, Zitadel, Authelia, Auth0, Okta, â€¦): discovers
endpoints from ``{issuer}/.well-known/openid-configuration``, builds the PKCE (S256) authorize
URL, exchanges the code, and verifies the **ID token** (the access token is opaque per spec)
against the discovered ``jwks_uri`` with ``iss``/``aud`` pinned. Public and confidential
(``client_secret`` layered on top of PKCE, never replacing it) clients both work. Config:
``dashboard.oauth.self_hosted.{issuer,client_id,scopes,client_secret,id_token_leeway}`` or
``HERMES_DASHBOARD_OIDC_*`` (leeway is config.yaml-only; default 60s of clock-skew tolerance
for the ID token's time claims, ``0`` restores strict verification).
)ÚannotationsN)ÚAnyÚDictÚOptional)Ú
LoginStartÚProviderErrorÚSession)ÚDEFAULT_TOKEN_LEEWAY_SECONDSÚJSON_HEADERSÚTOKEN_ENDPOINT_TIMEOUT_SECÚJwtOAuthProviderÚSkipRegistrationÚexchange_tokenÚload_config_sectionÚparse_json_bodyÚparse_leewayÚpkce_login_startÚrefresh_token_fromÚregister_providerÚresolve_env_or_cfgÚsession_from_claimsÚvalidate_redirect_uriÚ
verify_jwtzdashboard-auth-self-hostedzopenid profile emailg      $@i  Ú ÚstrÚLAST_SKIP_REASONc               ó$   € V ^8„  d   QhRRRRRR/# )é   Úurlr   ÚfieldÚreturn© )Úformats   "ÚP/home/ubuntu/.hermes/hermes-agent/plugins/dashboard_auth/self_hosted/__init__.pyÚ__annotate__r$   >   s&   € ÷ ^ñ ^ Cð ^°3ð ^¸3ñ ^ó    c               óâ   € \         P                  P                  V 4      pVP                  R8X  g-   VP                  R8X  d   VP                  ;'       g    RR9   d   V # \        RV RV : 24      h)z…Reject non-HTTPS endpoint URLs (loopback http allowed) so a misconfigured
issuer can't ship auth codes / refresh tokens in cleartext.ÚhttpsÚhttpr   zOIDC z. must be https:// (or http on localhost), got )Ú	localhostz	127.0.0.1z::1)ÚurllibÚparseÚurlparseÚschemeÚhostnamer   )r   r   Úparseds   &$ r#   Ú_require_https_or_loopbackr0   >   sd   € ô �\‰\×"Ñ" 3Ó'€FØ‡}�}˜Ô F§M¡M°VÔ$;ÀÇÁ×AVÐAVÐTVÐ[|Ô@|Øˆ
Ü
˜% ˜wÐ&TÐUXÑT[Ð\Ó
]Ð]r%   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r    Útupler!   )r"   s   "r#   r$   r$   G   s   € ÷ Bñ B�ð B˜ñ Br%   c                ó  € \         P                  P                  V 4      pVP                  P	                  4       pY!P
                  ;'       g    RP	                  4       VP                  ;'       g    RRR^P/P                  V4      3# )z�``(scheme, hostname, port)`` for an origin compare, with default ports
normalised so ``https://h`` and ``https://h:443`` are the same origin.r   r'   i»  r(   )r*   r+   r,   r-   Úlowerr.   ÚportÚget)r   Úpartsr-   s   &  r#   Ú_originr8   G   sq   € ô �L‰L×!Ñ! #Ó&€EØ�\‰\×ÑÓ!€FØ—^‘^×)Ð) r×0Ñ0Ó2Ø�J‰J×@Ð@˜7 C¨°Ð4×8Ñ8¸Ó@ðBð Br%   c                  óâ   € ] tR t^Pt$ RtRtRt]tR]	R&   R]
RRR	]/R
 R lltR R ltR R ltR R ltR R ltRRRR/R R lltR R ltR R ltR R ltR R  ltR! R" lt]tR# R$ ltR%tR# )&ÚSelfHostedOIDCProviderzHGeneric self-hosted OpenID Connect provider (authorization-code + PKCE).zself-hostedzSelf-Hosted OIDCÚfloatÚ_id_token_leewayÚscopesÚclient_secretr   Úid_token_leewayc               ó0   € V ^8„  d   QhRRRRRRRRRRRR	/# )
r   Úissuerr   Ú	client_idr=   r>   r?   r;   r    ÚNoner!   )r"   s   "r#   r$   Ú#SelfHostedOIDCProvider.__annotate__Z   s>   € ÷ &ñ &Øð&Ø),ð&Ø69ð&Ø\_ð&àð&ð 
ñ&r%   c               	óº  € V'       g   \        R 4      hV'       g   \        R4      hVP                  R4      V n        \        V P                  RR7       W n        VP                  4       ;'       g    \        V n        \        V4      V n	        T;'       g    RP                  4       V n
        RV n        RV n        \        P                  ! 4       V n        RV n        R# )zissuer is requiredzclient_id is requiredÚ/rA   ©r   r   Ng        )Ú
ValueErrorÚrstripÚ_issuerr0   Ú
_client_idÚstripÚ_DEFAULT_SCOPESÚ_scopesr   r<   Ú_client_secretÚ
_discoveryÚ_discovery_fetched_atÚ	threadingÚLockÚ_discovery_lockÚ_jwks_client)ÚselfrA   rB   r=   r>   r?   s   &$$$$$r#   Ú__init__ÚSelfHostedOIDCProvider.__init__Z   s®   € ÷ ÜÐ1Ó2Ð2ßÜÐ4Ó5Ð5ð —}‘} SÓ)ˆŒÜ" 4§<¡<°xÕ@Ø#ŒØ—|‘|“~×8Ð8¬ˆŒô !-¨_Ó =ˆÔð  -×2Ð2°×9Ñ9Ó;ˆÔð 26ˆŒØ,/ˆÔ"Ü(Ÿ~š~Ó/ˆÔØ!%ˆÖr%   c               ó    € V ^8„  d   QhRRRR/# )r   Úredirect_urir   r    r   r!   )r"   s   "r#   r$   rD   u   s   € ÷ wñ w¨3ð w°:ñ wr%   c               	óŒ   € \        V4       V P                  4       p\        VR ,          V P                  V P                  VR7      # )Úauthorization_endpoint)rB   ÚscoperZ   )r   Ú_get_discoveryr   rK   rN   )rV   rZ   Údiscos   &$ r#   Ústart_loginÚ"SelfHostedOIDCProvider.start_loginu   s?   € ä˜lÔ+Ø×#Ñ#Ó%ˆÜØÐ*Õ+°t·±ÈdÏlÉlÐiuôwð 	wr%   c               ó    € V ^8„  d   QhRRRR/# )r   Úrefresh_tokenr   r    rC   r!   )r"   s   "r#   r$   rD   |   s   € ÷ ñ ¨sð °tñ r%   c               	óÐ  € V'       g   R #  V P                  4       p\        TP                  R4      ;'       g    R4      P	                  4       pT'       g   R # T P                  T4      w  rERTRRRT P                  /TCp \        P                  ! Y6/ \        CTC\        R7       R #   \         d     R # i ; i  \         d"   p\        P                  RT4        R p?R # R p?ii ; i)	NÚrevocation_endpointr   ÚtokenÚtoken_type_hintrc   rB   )ÚdataÚheadersÚtimeoutz-self-hosted OIDC: revoke failed (ignored): %s)r^   r   r   r6   rL   Ú_token_endpoint_authrK   ÚhttpxÚpostr
   Ú_TOKEN_ENDPOINT_TIMEOUT_SECÚ	ExceptionÚloggerÚdebug)rV   rc   r_   ÚendpointÚ
extra_dataÚextra_headersrh   Úexcs   &$      r#   Úrevoke_sessionÚ%SelfHostedOIDCProvider.revoke_session|   sà   € ÷ Ùð	Ø×'Ñ'Ó)ˆEô �u—y‘yÐ!6Ó7×=Ð=¸2Ó>×DÑDÓFˆßÙà$(×$=Ñ$=¸eÓ$DÑ!ˆ
Ø˜Ð(9¸?ÈKÐY]×YhÑYhÐwÐlvÐwˆð	OÜ�JŠJ�xÐ4U´|Ð4UÀ}Ð4UÔ_zÕ{ñ 	øô ô 	Úð	ûô ô 	OÜ�L‰LÐHÈ#×NÐNÙûð	Oús)   ŒB' Â %B9 Â'B6Â5B6Â9C%ÃC Ã C%c               ó    € V ^8„  d   QhRRRR/# )r   r_   údict[str, Any]r    z%tuple[dict[str, str], dict[str, str]]r!   )r"   s   "r#   r$   rD   “   s   € ÷ lñ l¨.ð lÐ=bñ lr%   c                óÈ  € V P                   '       g   / / 3# VP                  R4      ;'       g    . pRV9   d   RV9  d   RV P                   // 3# \        P                  P	                  V P
                  RR7       R\        P                  P	                  V P                   RR7       2p/ RR	\        P                  ! VP                  R
4      4      P                  R4       2/3# )u;  ``(extra_data, extra_headers)`` for token-endpoint client auth. Public client â†’
``({}, {})`` (PKCE alone). Confidential client â†’ ``client_secret_post`` when the IDP
advertises it *without* ``client_secret_basic``, else HTTP Basic (the OIDC default
and the fallback when nothing is advertised). RFC 6749 Â§2.3.1.Ú%token_endpoint_auth_methods_supportedÚclient_secret_postÚclient_secret_basicr>   r   )ÚsafeÚ:ÚAuthorizationzBasic zutf-8Úascii)
rO   r6   r*   r+   ÚquoterK   Úbase64Ú	b64encodeÚencodeÚdecode)rV   r_   ÚmethodsÚuserpasss   &&  r#   rk   Ú+SelfHostedOIDCProvider._token_endpoint_auth“   sÖ   € ð
 ×"×"Ð"Ø�r�6ˆMØ—)‘)ÐCÓD×JÐJÈˆØ 7Ô*Ð/DÈGÔ/SØ# T×%8Ñ%8Ð9¸2Ð=Ð=ô —l‘l×(Ñ(¨¯©¸rÐ(ÓBÐCÀ1ÄVÇ\Á\×EWÑEWÐX\×XkÑXkÐrtÐEWÓEuÐDvÐwˆØ�O v¬f×.>Ò.>¸x¿¹ÈwÓ?WÓ.X×._Ñ._Ð`gÓ.hÐ-iÐ%jÐkÐkÐkr%   c               ó    € V ^8„  d   QhRRRR/# )r   rc   r   r    z/tuple[dict[str, str], Optional[dict[str, str]]]r!   )r"   s   "r#   r$   rD   ¢   s   € ÷ ñ ¨cð Ð6eñ r%   c                	óB   € R RRV P                   RVRV P                  /R3# )Ú
grant_typerc   rB   r]   N)rK   rN   )rV   rc   s   &&r#   Ú_refresh_requestÚ'SelfHostedOIDCProvider._refresh_request¢   s1   € ð ˜?¨K¸¿¹È/Ð[hØ�d—l‘lð$àðð 	r%   ri   NÚprevious_refresh_tokenc          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r   rh   zdict[str, str]Úbad_request_excztype[Exception]ri   zOptional[dict[str, str]]r�   r   r    r   r!   )r"   s   "r#   r$   rD   ª   s=   € ÷ dñ dØ"ðdØ8GðdØRjðdà #ðdð 
ñdr%   c               óà   € V P                  4       pV P                  V4      w  rg\        VR,          / VCVCWrRRRRR7      w  r‰V P                  V4      p
V P	                  V\        W”4      V
4      # )uß   POST the discovered token endpoint and turn the response into a Session.
Confidential-client auth (body field or Basic header) is added for both grants â€”
the IDP rejects an unauthenticated refresh with ``invalid_client``.Útoken_endpointÚIDPzOIDC token endpointÚid_tokenu‚   OIDC token response missing id_token â€” ensure the 'openid' scope is configured and the client is allowed to receive an ID token.)ri   r‘   Úidprr   Ú	token_keyÚmissing_msg)r^   rk   r   Ú_verify_id_tokenÚ_sessionr   )rV   rh   r‘   ri   r�   r_   rs   rt   r•   ÚpayloadÚclaimss   &&$$$      r#   Ú_grantÚSelfHostedOIDCProvider._grantª   sƒ   € ð ×#Ñ#Ó%ˆØ$(×$=Ñ$=¸eÓ$DÑ!ˆ
Ü*ØÐ"Õ#Ð%;¨Ð%;°
Ð%;À]ØÐ 5Àðô	Ñˆð ×&Ñ& xÓ0ˆà�}‰}˜XÔ'9¸'Ó'ZÐ\bÓcÐcr%   c               ó   € V ^8„  d   QhRR/# )r   r    zdict[str, Any] | Noner!   )r"   s   "r#   r$   rD   À   s   € ÷ ñ Ð"7ñ r%   c                	ó˜   € V P                   e<   \        P                  ! 4       V P                  ,
          \        8  d   V P                   # R # ©N)rP   ÚtimerQ   Ú_DISCOVERY_CACHE_TTL_SEC©rV   s   &r#   Ú_fresh_discoveryÚ'SelfHostedOIDCProvider._fresh_discoveryÀ   s2   € Ø�?‰?Ò&¬4¯9ª9«;¸×9SÑ9SÕ+SÔVnÔ+nØ—?‘?Ð"Ùr%   c               ó   € V ^8„  d   QhRR/# ©r   r    ry   r!   )r"   s   "r#   r$   rD   Å   s   € ÷ 
ñ 
 ñ 
r%   c                ó*  € V P                  4       pVfk   V P                  ;_uu_ 4        V P                  4       pVf8   V P                  4       ;qn        \        P                  ! 4       V n        RV n        RRR4       V# V#   + '       g   i     T# ; i)zSReturn the cached OIDC discovery document, fetching if stale (double-checked lock).N)r¥   rT   Ú_fetch_discoveryrP   r¢   rQ   rU   )rV   r_   s   & r#   r^   Ú%SelfHostedOIDCProvider._get_discoveryÅ   s}   € à×%Ñ%Ó'ˆØŠ=Ø×%×%Ó%Ø×-Ñ-Ó/�Ø’=Ø.2×.CÑ.CÓ.EÐE�EœOÜ15·²³�DÔ.Ø(,�DÔ%÷ &ð ˆˆuˆ÷ &Ö%ð ˆús   ©ABÂB	c               ó   € V ^8„  d   QhRR/# r¨   r!   )r"   s   "r#   r$   rD   Ñ   s   € ÷ 0cñ 0c .ñ 0cr%   c           
     	óp  a€ V P                    R 2p \        P                  ! V\        \        RR7      pTP                  ^È8w  d   \        RTP                   RT: 24      h\        \        TP                  4      4      \        T P                   4      8w  d(   \        RTP                   RT P                   : R	24      h\        T4      oS'       g   \        R
4      hR T3R llpR Uu/ uF  qUT! T4      bK  	  pp\        TP                  4       4      '       g   \        R4      hT! R4      pT'       d>   TP                  R4      T P                   8w  d   \        RT: RT P                   : 24      hTP                  4        F  w  r�\!        YR7       K  	  SP                  R4      p	RT;'       g    T P                   /TCRT! R4      R\#        T	\$        4      '       d   T	 U
u. uF  p
\        T
4      NK  	  up
/C# . /C#   \        P
                   d   p\        RT 24      ThRp?ii ; iu upi u up
i )z!/.well-known/openid-configurationT)ri   rj   Úfollow_redirectszOIDC discovery unreachable: NzOIDC discovery returned z for zOIDC discovery resolved to z*, outside the configured issuer's origin (Ú)z'OIDC discovery returned a non-JSON bodyc               ó    € V ^8„  d   QhRRRR/# )r   Úkeyr   r    r!   )r"   s   "r#   r$   Ú=SelfHostedOIDCProvider._fetch_discovery.<locals>.__annotate__ë   s   € ÷ 	;ñ 	;�sð 	;˜sñ 	;r%   c                ój   <€ \        SP                  V R 4      ;'       g    R 4      P                  4       # )r   )r   r6   rL   )r±   r›   s   &€r#   r   Ú6SelfHostedOIDCProvider._fetch_discovery.<locals>.fieldë   s*   ø€ Ü�w—{‘{ 3¨Ó+×1Ð1¨rÓ2×8Ñ8Ó:Ð:r%   zPOIDC discovery missing one of authorization_endpoint / token_endpoint / jwks_urirA   rF   z4OIDC discovery issuer mismatch: document advertises z but configured issuer is rG   r{   re   )r\   r“   Újwks_uri)rJ   rl   r6   r
   Ú_DISCOVERY_TIMEOUT_SECÚRequestErrorr   Ústatus_coder8   r   r   r   ÚallÚvaluesrI   Úitemsr0   Ú
isinstanceÚlist)rV   r   Úresponseru   r   ÚkÚ	endpointsÚadvertised_issuerr±   Úauth_methods_rawÚmr›   s   &          @r#   rª   Ú'SelfHostedOIDCProvider._fetch_discoveryÑ   sI  ø€ Ø—‘�Ð?Ð@ˆð	Oô
 —y’y ¬lÔDZÐmqÔrˆHð ×Ñ 3Ô&ÜÐ":¸8×;OÑ;OÐ:PÐPUÐVYÑU\Ð ]Ó^Ð^ô ”3�x—|‘|Ó$Ó%¬°·±Ó)>Ô>ÜØ-¨h¯l©l¨^ð <$Ø$(§L¡LÑ#3°1ð6ó7ð 7ô " (Ó+ˆßÜÐ IÓJÐJ÷	;ð 	;ñ +cÓcÑ*b Q™˜a›’[Ñ*bˆ	ÐcÜ�9×#Ñ#Ó%×&Ò&ÜÐ rÓsÐsñ " (›OÐßÐ!2×!9Ñ!9¸#Ó!>À$Ç,Á,Ô!NÜØFÐGXÑF[ð \,Ø,0¯L©LÑ+;ð=ó>ð >ð "Ÿ™Ö)‰HˆCÜ& s×6ñ *ð #Ÿ;™;Ð'NÓOÐàÐ'×7Ð7¨4¯<©<ðcàðcð "¡5Ð)>Ó#?Ø3Ü6@ÐAQÔSW×6XÒ6XÑ!1Ó2Ñ!1˜A”�Q–Ñ!1Ñ2ñcð 	cð
 _añcð 	cøôG ×!Ñ!ô 	OÜÐ">¸s¸eÐ DÓEÈ3ÐNûð	Oüò* dùò& 3s#   ’"H Ã)H.Ç%H3ÈH+ÈH&È&H+c               ó   € V ^8„  d   QhRR/# )r   r    r   r!   )r"   s   "r#   r$   rD     s   € ÷ 1ñ 1˜3ñ 1r%   c                	ó0   € V P                  4       R ,          # )rµ   )r^   r¤   s   &r#   Ú	_jwks_uriÚ SelfHostedOIDCProvider._jwks_uri  s   € Ø×"Ñ"Ó$ ZÕ0Ð0r%   c               ó    € V ^8„  d   QhRRRR/# )r   r•   r   r    ry   r!   )r"   s   "r#   r$   rD     s   € ÷ eñ e¨ð e°ñ er%   c           
     	ó°   € V P                  4       R ,          p\        WP                  4       \        \        4      V P
                  VRV P                  R7      # )rA   úID token)Ú
algorithmsÚaudiencerA   ÚlabelÚleeway)r^   r   Ú_get_jwks_clientr½   Ú_ALLOWED_ID_TOKEN_ALGSrK   r<   )rV   r•   rA   s   && r#   r™   Ú'SelfHostedOIDCProvider._verify_id_token  sK   € Ø×$Ñ$Ó& xÕ0ˆÜØ×+Ñ+Ó-¼$Ô?UÓ:VØ—_‘_¨V¸:Èd×NcÑNcôeð 	er%   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r•   r   rc   rœ   ry   r    r   r!   )r"   s   "r#   r$   rD     s)   € ÷ &ñ & ð &°Sð &À.ð &ÐU\ñ &r%   c                ól  € \        VP                  RR4      ;'       g    R4      pVP                  R4      ;'       g    VP                  R4      ;'       g    RpVP                  R4      pV'       g7   \        V\        4      '       d!   V'       d   RP	                  R V 4       4      p\        V P                  Y1TRT\        VP                  R	4      ;'       g?    VP                  R
4      ;'       g&    VP                  R4      ;'       g    T;'       g    R4      \        T;'       g    R4      R7      # )uó   Map verified OIDC claims onto a Session. The verified ID token is stored in
``Session.access_token`` so the per-request ``verify_session`` re-verifies a real
JWT; the opaque OAuth access token is not kept â€” the dashboard only needs identity.Úemailr   Úorg_idÚorganizationÚgroupsÚ,c              3  ó8   "  € T F  p\        V4      x € K  	  R # 5ir¡   )r   )Ú.0Úgs   & r#   Ú	<genexpr>Ú2SelfHostedOIDCProvider._session.<locals>.<genexpr>  s   é € Ð5©f¨œc !Ÿf˜f«fùs   ‚rË   ÚnameÚpreferred_usernameÚnickname)Úaccess_tokenrc   rÎ   rÕ   Údisplay_namerÖ   )r   r6   r¼   r½   Újoinr   rß   )rV   r•   rc   rœ   rÕ   rÖ   rØ   s   &&&&   r#   rš   ÚSelfHostedOIDCProvider._session  só   € ô �F—J‘J˜w¨Ó+×1Ð1¨rÓ2ˆð —‘˜HÓ%×IÐI¨¯©°NÓ)C×IÐIÀrˆØ—‘˜HÓ%ˆßœ* V¬T×2Ò2·vØ—X‘XÑ5©fÓ5Ó5ˆFÜ"Ø�I‰I�vÀMÐYcÐkpÜ˜VŸZ™Z¨Ó/×|Ð|°6·:±:Ð>RÓ3S×|Ð|ÐW]×WaÑWaÐblÓWm×|Ð|Ðqv×|Ð|Ðz|Ó}Ü�v—|�| Ó$ô&ð 	&r%   )	rK   rO   rP   rQ   rT   r<   rJ   rU   rN   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rß   rã   r	   r<   Ú__annotations__rM   rW   r`   rv   rk   r�   r�   r¥   r^   rª   rÇ   r™   Ú_claims_forrš   Ú__static_attributes__r!   r%   r#   r:   r:   P   s”   ‡ ÙRà€DØ%€Lð ;Ð�eÓ:ð&Ø<Kð&Øbdð&à!=÷&õ6wõõ.lõðdØmqðdà&(÷dõ,õ

õ0cõh1õeð #€K÷&ñ &r%   r:   c               ó   € V ^8„  d   QhRR/# ©r   r    Údictr!   )r"   s   "r#   r$   r$   #  s   € ÷ Rñ R Dñ Rr%   c                 ó0   € \        \        \        R RR4      # )Ú	dashboardÚoauthÚself_hosted)r   rp   Ú_TAGr!   r%   r#   Ú_load_config_oauth_sectionrö   #  s   € Üœv¤t¨[¸'À=ÓQÐQr%   c               ó   € V ^8„  d   QhRR/# rï   r!   )r"   s   "r#   r$   r$   '  s   € ÷ Jñ J�4ñ Jr%   c                 ó6  a€ \        4       oR V3R llp V ! RR4      pV ! RR4      pV'       d	   V'       g%   \        R\        V4       R\        V4       R	24      hRTRTR
V ! RR
4      ;'       g    \        RV ! RR4      R\	        SP                  R4      4      /# )zYResolve SelfHostedOIDCProvider kwargs; the skip reason names BOTH configuration surfaces.c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úenv_namer   Úcfg_keyr    r!   )r"   s   "r#   r$   Ú_settings.<locals>.__annotate__+  s&   € ÷ Cñ C˜#ð C¨ð C°ñ Cr%   c                ó:   <€ \        V SP                  V4      4      # r¡   )r   r6   )rú   rû   Úoidc_cfgs   &&€r#   ÚsettingÚ_settings.<locals>.setting+  s   ø€ Ü! (¨H¯L©L¸Ó,AÓBÐBr%   ÚHERMES_DASHBOARD_OIDC_ISSUERrA   ÚHERMES_DASHBOARD_OIDC_CLIENT_IDrB   u:  Self-hosted OIDC dashboard auth is not configured. Set both an issuer and a client_id â€” either as env vars (HERMES_DASHBOARD_OIDC_ISSUER + HERMES_DASHBOARD_OIDC_CLIENT_ID) or under dashboard.oauth.self_hosted.{issuer,client_id} in config.yaml â€” or pass --insecure to skip the OAuth gate entirely. (issuer set: z; client_id set: r¯   r=   ÚHERMES_DASHBOARD_OIDC_SCOPESr>   Ú#HERMES_DASHBOARD_OIDC_CLIENT_SECRETr?   )rö   r   ÚboolrM   r   r6   )rÿ   rA   rB   rþ   s      @r#   Ú	_settingsr  '  s¿   ø€ ä)Ó+€H÷Cð Cñ Ð3°XÓ>€FÙÐ9¸;ÓG€IßŸÜðHô IMÈVËÀ~ÐUfÔgkÐluÓgvÐfwÐwxð	zó{ð 	{ð 	�&˜+ yØ‘'Ð8¸(ÓC×VÐVÄà™Ð!FÈÓXàœ<¨¯©Ð5FÓ(GÓHðJð Jr%   c               ó   € V ^8„  d   QhRR/# )r   r    rC   r!   )r"   s   "r#   r$   r$   @  s   € ÷ 	kñ 	k�Tñ 	kr%   c           
     óæ   € Rs \        V \        \        \        \
        4      w  ps VeI   \        P                  RVR,          VR,          VR,          \        VR,          4      VR,          4       R# R# )	zIRegister :class:`SelfHostedOIDCProvider` when issuer + client_id are set.r   Nzzdashboard-auth-self-hosted: registered provider (issuer=%s, client_id=%s, scopes=%r, confidential=%s, id_token_leeway=%ss)rA   rB   r=   r>   r?   )r   r   rp   rõ   r:   r  Úinfor  )ÚctxÚkws   & r#   Úregisterr  @  si   € ð ÐÜ,¨S´&¼$Ô@VÔXaÓbÑ€BÐØ	‚~Ü�‰ðYàˆx�L˜"˜[�/¨2¨h­<¼¸bÀÕ>QÓ9RÐTVÐWhÕTiö	kñ r%   )ÚRS256ÚES256ÚRS384ÚRS512ÚES384ÚES512)5Ú__conditional_annotations__rê   Ú
__future__r   rƒ   ÚloggingrR   r¢   Úurllib.parser*   Útypingr   r   r   rl   Úhermes_cli.dashboard_authr   r   r   Úplugins.dashboard_auth._sharedr	   r
   r   rn   r   r   r   r   r   r   r   r   r   r   r   r   r   Ú	getLoggerræ   rp   rõ   rM   rÑ   r¶   r£   r   rë   r0   r8   r:   rö   r  r  )r  s   @r#   Ú<module>r     sµ   øðô
õ #ã Û Û Û Û ß &Ñ &ã ç HÑ H÷÷ ÷ ÷ ó ð$ 
×	Ò	˜8Ó	$€Ø#€ð )€ð
 PÐ àÐ ð  Ð àÐ �#Ó õ^õBôN&Ð-ô N&õfRõJ÷2	kr%   