From eebdce80cdda2c7e9399f6673489bf43655f4124 Mon Sep 17 00:00:00 2001 From: Martin Gross Date: Wed, 11 Sep 2024 16:40:42 +0200 Subject: [PATCH] OIDC: Respect token_endpoint_auth_methods_supported (Z#2164777) (#4459) --- src/pretix/base/customersso/oidc.py | 34 ++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/pretix/base/customersso/oidc.py b/src/pretix/base/customersso/oidc.py index cf733de90..cb3a6d20d 100644 --- a/src/pretix/base/customersso/oidc.py +++ b/src/pretix/base/customersso/oidc.py @@ -46,6 +46,8 @@ This module contains utilities for implementing OpenID Connect for customer auth as well as an OpenID Provider (OP). """ +pretix_token_endpoint_auth_methods = ['client_secret_basic', 'client_secret_post'] + def _urljoin(base, path): if not base.endswith("/"): @@ -127,6 +129,16 @@ def oidc_validate_and_complete_config(config): fields=", ".join(provider_config.get("claims_supported", [])) )) + if "token_endpoint_auth_methods_supported" in provider_config: + token_endpoint_auth_methods_supported = provider_config.get("token_endpoint_auth_methods_supported", + ["client_secret_basic"]) + if not any(x in pretix_token_endpoint_auth_methods for x in token_endpoint_auth_methods_supported): + raise ValidationError( + _(f'No supported Token Endpoint Auth Methods supported: {token_endpoint_auth_methods_supported}').format( + token_endpoint_auth_methods_supported=", ".join(token_endpoint_auth_methods_supported) + ) + ) + config['provider_config'] = provider_config return config @@ -147,6 +159,18 @@ def oidc_authorize_url(provider, state, redirect_uri): def oidc_validate_authorization(provider, code, redirect_uri): endpoint = provider.configuration['provider_config']['token_endpoint'] + + # Wall of shame and RFC ignorant IDPs + if endpoint == 'https://www.linkedin.com/oauth/v2/accessToken': + token_endpoint_auth_method = 'client_secret_post' + else: + token_endpoint_auth_methods = provider.configuration['provider_config'].get( + 'token_endpoint_auth_methods_supported', ['client_secret_basic'] + ) + token_endpoint_auth_method = [ + x for x in pretix_token_endpoint_auth_methods if x in token_endpoint_auth_methods + ][0] + params = { # https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3 # https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint @@ -154,6 +178,11 @@ def oidc_validate_authorization(provider, code, redirect_uri): 'code': code, 'redirect_uri': redirect_uri, } + + if token_endpoint_auth_method == 'client_secret_post': + params['client_id'] = provider.configuration['client_id'] + params['client_secret'] = provider.configuration['client_secret'] + try: resp = requests.post( endpoint, @@ -161,7 +190,10 @@ def oidc_validate_authorization(provider, code, redirect_uri): headers={ 'Accept': 'application/json', }, - auth=(provider.configuration['client_id'], provider.configuration['client_secret']), + auth=( + provider.configuration['client_id'], + provider.configuration['client_secret'] + ) if token_endpoint_auth_method == 'client_secret_basic' else None, ) resp.raise_for_status() data = resp.json()