mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-23 00:41:40 +00:00
fix: address SSO/JWT bugfix findings
- ui_sso: thread env_prefix through get_redirect_response_from_openid and _get_user_email_and_id_from_result so OKTA_USER_ROLE_ATTRIBUTE is honored on the Okta callback path (falls back to GENERIC_USER_ROLE_ATTRIBUTE then 'role'). - handle_jwt: use 'is None' rather than 'or' when falling back from litellm_jwtauth.audience/issuer to JWT_AUDIENCE/JWT_ISSUER env vars, so explicit empty values are not silently overridden. - proxy_setting_endpoints: use _decrypt_db_variables instead of _decrypt_and_set_db_env_variables when restoring redacted SSO secrets, to avoid polluting os.environ with lowercase model-field names. Co-authored-by: Yassin Kortam <yassin@berri.ai>
This commit is contained in:
parent
bffcc0ee0b
commit
b7eb716f2f
3 changed files with 20 additions and 10 deletions
|
|
@ -762,12 +762,12 @@ class JWTHandler:
|
|||
When both are unset PyJWT only checks the signature and expiry, which
|
||||
is preserved for backward compatibility but logged once as a warning.
|
||||
"""
|
||||
audience = (
|
||||
litellm_jwtauth.audience if litellm_jwtauth is not None else None
|
||||
) or os.getenv("JWT_AUDIENCE")
|
||||
issuer = (
|
||||
litellm_jwtauth.issuer if litellm_jwtauth is not None else None
|
||||
) or os.getenv("JWT_ISSUER")
|
||||
audience = litellm_jwtauth.audience if litellm_jwtauth is not None else None
|
||||
if audience is None:
|
||||
audience = os.getenv("JWT_AUDIENCE")
|
||||
issuer = litellm_jwtauth.issuer if litellm_jwtauth is not None else None
|
||||
if issuer is None:
|
||||
issuer = os.getenv("JWT_ISSUER")
|
||||
|
||||
if (
|
||||
audience is None
|
||||
|
|
|
|||
|
|
@ -1796,6 +1796,11 @@ async def auth_callback(request: Request, state: Optional[str] = None): # noqa:
|
|||
access_token_payload=access_token_payload,
|
||||
jwt_handler=jwt_handler,
|
||||
return_to=cp_return_to,
|
||||
env_prefix=_get_oidc_env_prefix(
|
||||
_OIDC_PROVIDER_OKTA
|
||||
if okta_client_id is not None and generic_client_id is None
|
||||
else _OIDC_PROVIDER_GENERIC
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -2830,6 +2835,7 @@ class SSOAuthenticationHandler:
|
|||
def _get_user_email_and_id_from_result(
|
||||
result: Optional[Union[OpenID, dict]],
|
||||
generic_client_id: Optional[str] = None,
|
||||
env_prefix: str = "GENERIC",
|
||||
) -> ParsedOpenIDResult:
|
||||
"""
|
||||
Gets the user email and id from the OpenID result after validating the email domain
|
||||
|
|
@ -2870,7 +2876,8 @@ class SSOAuthenticationHandler:
|
|||
# generic client id - override with custom attribute name if specified
|
||||
if generic_client_id is not None and result is not None:
|
||||
generic_user_role_attribute_name = os.getenv(
|
||||
"GENERIC_USER_ROLE_ATTRIBUTE", "role"
|
||||
f"{env_prefix}_USER_ROLE_ATTRIBUTE",
|
||||
os.getenv("GENERIC_USER_ROLE_ATTRIBUTE", "role"),
|
||||
)
|
||||
user_id = getattr(result, "id", None)
|
||||
user_email = normalize_email(getattr(result, "email", None))
|
||||
|
|
@ -2908,6 +2915,7 @@ class SSOAuthenticationHandler:
|
|||
access_token_payload: Optional[dict] = None,
|
||||
jwt_handler: Optional[JWTHandler] = None,
|
||||
return_to: Optional[str] = None,
|
||||
env_prefix: str = "GENERIC",
|
||||
) -> RedirectResponse:
|
||||
import jwt
|
||||
|
||||
|
|
@ -2931,7 +2939,9 @@ class SSOAuthenticationHandler:
|
|||
# User is Authe'd in - generate key for the UI to access Proxy
|
||||
parsed_openid_result = (
|
||||
SSOAuthenticationHandler._get_user_email_and_id_from_result(
|
||||
result=result, generic_client_id=generic_client_id
|
||||
result=result,
|
||||
generic_client_id=generic_client_id,
|
||||
env_prefix=env_prefix,
|
||||
)
|
||||
)
|
||||
user_email = parsed_openid_result.get("user_email")
|
||||
|
|
|
|||
|
|
@ -854,8 +854,8 @@ async def update_sso_settings(sso_config: SSOConfig):
|
|||
)
|
||||
existing_plain: dict = {}
|
||||
if existing_sso_record and existing_sso_record.sso_settings:
|
||||
existing_plain = proxy_config._decrypt_and_set_db_env_variables(
|
||||
environment_variables=dict(existing_sso_record.sso_settings)
|
||||
existing_plain = proxy_config._decrypt_db_variables(
|
||||
variables_dict=dict(existing_sso_record.sso_settings)
|
||||
)
|
||||
|
||||
# Update environment variables in config and in memory
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue