From 637151cd03862da68bcc6939d3577c21797f133e Mon Sep 17 00:00:00 2001 From: Paul Schilling Date: Wed, 16 Oct 2024 14:19:44 +0200 Subject: [PATCH] [#2618] Update settings + docs for django-setup-configuration --- docs/configuration/admin_oidc.rst | 13 +-- docs/configuration/digid_oidc.rst | 32 +++----- docs/configuration/eherkenning_oidc.rst | 30 ++----- docs/configuration/eherkenning_saml.rst | 4 +- .../configurations/bootstrap/auth.py | 72 +++++++++-------- .../tests/bootstrap/test_setup_auth_config.py | 81 +++++++------------ 6 files changed, 89 insertions(+), 143 deletions(-) diff --git a/docs/configuration/admin_oidc.rst b/docs/configuration/admin_oidc.rst index 366c3ca0b5..5221f51c69 100644 --- a/docs/configuration/admin_oidc.rst +++ b/docs/configuration/admin_oidc.rst @@ -36,7 +36,6 @@ All settings: ADMIN_OIDC_DEFAULT_GROUPS ADMIN_OIDC_GROUPS_CLAIM ADMIN_OIDC_MAKE_USERS_STAFF - ADMIN_OIDC_OIDC_EXEMPT_URLS ADMIN_OIDC_OIDC_NONCE_SIZE ADMIN_OIDC_OIDC_OP_AUTHORIZATION_ENDPOINT ADMIN_OIDC_OIDC_OP_DISCOVERY_ENDPOINT @@ -65,12 +64,12 @@ Detailed Information Setting claim mapping Description Mapping from user-model fields to OIDC claims Possible values Mapping: {'some_key': 'Some value'} - Default value {'email': 'email', 'first_name': 'given_name', 'last_name': 'family_name'} + Default value {'email': ['email'], 'first_name': ['given_name'], 'last_name': ['family_name']} Variable ADMIN_OIDC_GROUPS_CLAIM Setting groups claim Description The name of the OIDC claim that holds the values to map to local user groups. - Possible values string + Possible values No information available Default value roles Variable ADMIN_OIDC_MAKE_USERS_STAFF @@ -79,12 +78,6 @@ Detailed Information Possible values True, False Default value False - Variable ADMIN_OIDC_OIDC_EXEMPT_URLS - Setting URLs exempt from session renewal - Description This is a list of absolute url paths, regular expressions for url paths, or Django view names. This plus the mozilla-django-oidc urls are exempted from the session renewal by the SessionRefresh middleware. - Possible values string, comma-delimited ('foo,bar,baz') - Default value - Variable ADMIN_OIDC_OIDC_NONCE_SIZE Setting Nonce size Description Sets the length of the random string used for OpenID Connect nonce verification @@ -190,5 +183,5 @@ Detailed Information Variable ADMIN_OIDC_USERNAME_CLAIM Setting username claim Description The name of the OIDC claim that is used as the username - Possible values string + Possible values No information available Default value sub diff --git a/docs/configuration/digid_oidc.rst b/docs/configuration/digid_oidc.rst index 9e726395da..7215d1b8d7 100644 --- a/docs/configuration/digid_oidc.rst +++ b/docs/configuration/digid_oidc.rst @@ -31,10 +31,8 @@ All settings: :: + DIGID_OIDC_BSN_CLAIM DIGID_OIDC_ENABLED - DIGID_OIDC_ERROR_MESSAGE_MAPPING - DIGID_OIDC_IDENTIFIER_CLAIM_NAME - DIGID_OIDC_OIDC_EXEMPT_URLS DIGID_OIDC_OIDC_KEYCLOAK_IDP_HINT DIGID_OIDC_OIDC_NONCE_SIZE DIGID_OIDC_OIDC_OP_AUTHORIZATION_ENDPOINT @@ -57,30 +55,18 @@ Detailed Information :: + Variable DIGID_OIDC_BSN_CLAIM + Setting BSN-claim + Description Naam van de claim die het BSN bevat van de ingelogde gebruiker. + Possible values No information available + Default value bsn + Variable DIGID_OIDC_ENABLED Setting inschakelen - Description Geeft aan of OpenID Connect voor authenticatie/autorisatie is ingeschakeld. Deze overschrijft het gebruik van SAML voor DigiD-authenticatie. + Description Indicates whether OpenID Connect for authentication/authorization is enabled Possible values True, False Default value False - Variable DIGID_OIDC_ERROR_MESSAGE_MAPPING - Setting Foutmelding mapping - Description Mapping die de door de identiteitsprovider geretourneerde foutmeldingen, omzet in leesbare meldingen die aan de gebruiker worden getoond - Possible values Mapping: {'some_key': 'Some value'} - Default value {} - - Variable DIGID_OIDC_IDENTIFIER_CLAIM_NAME - Setting BSN claim naam - Description De naam van de claim waarin het BSN nummer van de gebruiker is opgeslagen - Possible values string - Default value bsn - - Variable DIGID_OIDC_OIDC_EXEMPT_URLS - Setting URLs exempt from session renewal - Description This is a list of absolute url paths, regular expressions for url paths, or Django view names. This plus the mozilla-django-oidc urls are exempted from the session renewal by the SessionRefresh middleware. - Possible values No information available - Default value - Variable DIGID_OIDC_OIDC_KEYCLOAK_IDP_HINT Setting Keycloak-identiteitsprovider hint Description Specifiek voor Keycloak: parameter die aangeeft welke identiteitsprovider gebruikt moet worden (inlogscherm van Keycloak overslaan). @@ -149,7 +135,7 @@ Detailed Information Variable DIGID_OIDC_OIDC_RP_SCOPES_LIST Setting OpenID Connect scopes - Description OpenID Connect-scopes die worden bevraagd tijdens het inloggen. Deze zijn hardcoded en moeten worden ondersteund door de identiteitsprovider. + Description OpenID Connect scopes that are requested during login. These scopes are hardcoded and must be supported by the identity provider. Possible values No information available Default value openid, bsn diff --git a/docs/configuration/eherkenning_oidc.rst b/docs/configuration/eherkenning_oidc.rst index 933c2a63e4..ed312af924 100644 --- a/docs/configuration/eherkenning_oidc.rst +++ b/docs/configuration/eherkenning_oidc.rst @@ -32,9 +32,7 @@ All settings: :: EHERKENNING_OIDC_ENABLED - EHERKENNING_OIDC_ERROR_MESSAGE_MAPPING - EHERKENNING_OIDC_IDENTIFIER_CLAIM_NAME - EHERKENNING_OIDC_OIDC_EXEMPT_URLS + EHERKENNING_OIDC_LEGAL_SUBJECT_CLAIM EHERKENNING_OIDC_OIDC_KEYCLOAK_IDP_HINT EHERKENNING_OIDC_OIDC_NONCE_SIZE EHERKENNING_OIDC_OIDC_OP_AUTHORIZATION_ENDPOINT @@ -59,27 +57,15 @@ Detailed Information Variable EHERKENNING_OIDC_ENABLED Setting inschakelen - Description Geeft aan of OpenID Connect voor authenticatie/autorisatie is ingeschakeld. Deze heeft voorrang op het gebruik van SAML voor eHerkenning-authenticatie. + Description Indicates whether OpenID Connect for authentication/authorization is enabled Possible values True, False Default value False - Variable EHERKENNING_OIDC_ERROR_MESSAGE_MAPPING - Setting Foutmelding mapping - Description Mapping die de door de identiteitsprovider geretourneerde foutmeldingen, omzet in leesbare meldingen die aan de gebruiker worden getoond - Possible values Mapping: {'some_key': 'Some value'} - Default value {} - - Variable EHERKENNING_OIDC_IDENTIFIER_CLAIM_NAME - Setting KVK claim naam - Description De naam van de claim waarin het KVK nummer van de gebruiker is opgeslagen - Possible values string - Default value kvk - - Variable EHERKENNING_OIDC_OIDC_EXEMPT_URLS - Setting URLs exempt from session renewal - Description This is a list of absolute url paths, regular expressions for url paths, or Django view names. This plus the mozilla-django-oidc urls are exempted from the session renewal by the SessionRefresh middleware. - Possible values string, comma-delimited ('foo,bar,baz') - Default value + Variable EHERKENNING_OIDC_LEGAL_SUBJECT_CLAIM + Setting bedrijfsidenticatie-claim + Description Naam van de claim die de identificatie van het ingelogde/vertegenwoordigde bedrijf bevat. + Possible values No information available + Default value urn:etoegang:core:LegalSubjectID Variable EHERKENNING_OIDC_OIDC_KEYCLOAK_IDP_HINT Setting Keycloak-identiteitsprovider hint @@ -149,7 +135,7 @@ Detailed Information Variable EHERKENNING_OIDC_OIDC_RP_SCOPES_LIST Setting OpenID Connect scopes - Description OpenID Connect-scopes die worden bevraagd tijdens het inloggen. Deze zijn hardcoded en moeten worden ondersteund door de identiteitsprovider. + Description OpenID Connect scopes that are requested during login. These scopes are hardcoded and must be supported by the identity provider. Possible values string, comma-delimited ('foo,bar,baz') Default value openid, kvk diff --git a/docs/configuration/eherkenning_saml.rst b/docs/configuration/eherkenning_saml.rst index 41f9f6e68f..80ed4d896f 100644 --- a/docs/configuration/eherkenning_saml.rst +++ b/docs/configuration/eherkenning_saml.rst @@ -134,7 +134,7 @@ Detailed Information Variable EHERKENNING_SAML_EH_LOA Setting eHerkenning LoA - Description Level of Assurance (LoA) to use for the eHerkenning service. + Description Betrouwbaarheidsniveau (LoA) voor de eHerkenningservice. Possible values urn:etoegang:core:assurance-class:loa1, urn:etoegang:core:assurance-class:loa2, urn:etoegang:core:assurance-class:loa2plus, urn:etoegang:core:assurance-class:loa3, urn:etoegang:core:assurance-class:loa4 Default value urn:etoegang:core:assurance-class:loa3 @@ -164,7 +164,7 @@ Detailed Information Variable EHERKENNING_SAML_EIDAS_LOA Setting eIDAS LoA - Description Level of Assurance (LoA) to use for the eIDAS service. + Description Betrouwbaarheidsniveau (LoA) voor de eIDAS-service. Possible values urn:etoegang:core:assurance-class:loa1, urn:etoegang:core:assurance-class:loa2, urn:etoegang:core:assurance-class:loa2plus, urn:etoegang:core:assurance-class:loa3, urn:etoegang:core:assurance-class:loa4 Default value urn:etoegang:core:assurance-class:loa3 diff --git a/src/open_inwoner/configurations/bootstrap/auth.py b/src/open_inwoner/configurations/bootstrap/auth.py index e2fd44bef7..954390cffa 100644 --- a/src/open_inwoner/configurations/bootstrap/auth.py +++ b/src/open_inwoner/configurations/bootstrap/auth.py @@ -9,6 +9,8 @@ EherkenningConfigurationAdmin, ) from digid_eherkenning.models import DigidConfiguration, EherkenningConfiguration +from digid_eherkenning.oidc.admin import admin_modelform_factory +from django_jsonform.forms.fields import JSONFormField from django_setup_configuration.config_settings import ConfigSettings from django_setup_configuration.configuration import BaseConfigurationStep from django_setup_configuration.exceptions import ConfigurationRunFailed @@ -16,19 +18,36 @@ from mozilla_django_oidc_db.models import OpenIDConnectConfig from simple_certmanager.models import Certificate -from digid_eherkenning_oidc_generics.admin import ( - OpenIDConnectDigiDConfigForm, - OpenIDConnectEHerkenningConfigForm, -) -from digid_eherkenning_oidc_generics.models import ( - OpenIDConnectDigiDConfig, - OpenIDConnectEHerkenningConfig, -) +from open_inwoner.accounts.models import OpenIDDigiDConfig, OpenIDEHerkenningConfig from open_inwoner.configurations.models import SiteConfiguration from .utils import convert_setting_to_model_field_name, log_form_errors +class LOAValueMappingField(JSONFormField): + def to_python(self, value): + value = super().to_python(value) + # super class treats [] as empty (not wrong), but converts it to None, which + # doesn't pass the schema validation + if value is None: + value = [] + return value + + +def formfield_callback(model_field, **kwargs): + if model_field.name == "loa_value_mapping": + kwargs["form_class"] = LOAValueMappingField + return model_field.formfield(**kwargs) + + +OpenIDDigiDConfigForm = admin_modelform_factory( + OpenIDDigiDConfig, formfield_callback=formfield_callback +) +OpenIDEHerkenningConfigForm = admin_modelform_factory( + OpenIDEHerkenningConfig, formfield_callback=formfield_callback +) + + # # DigiD OIDC # @@ -41,16 +60,14 @@ class DigiDOIDCConfigurationStep(BaseConfigurationStep): config_settings = ConfigSettings( enable_setting="DIGID_OIDC_CONFIG_ENABLE", namespace="DIGID_OIDC", - models=[OpenIDConnectDigiDConfig], + models=[OpenIDDigiDConfig], required_settings=[ "DIGID_OIDC_OIDC_RP_CLIENT_ID", "DIGID_OIDC_OIDC_RP_CLIENT_SECRET", ], optional_settings=[ "DIGID_OIDC_ENABLED", - "DIGID_OIDC_ERROR_MESSAGE_MAPPING", - "DIGID_OIDC_IDENTIFIER_CLAIM_NAME", - "DIGID_OIDC_OIDC_EXEMPT_URLS", + "DIGID_OIDC_BSN_CLAIM", "DIGID_OIDC_OIDC_KEYCLOAK_IDP_HINT", "DIGID_OIDC_OIDC_NONCE_SIZE", "DIGID_OIDC_OIDC_OP_AUTHORIZATION_ENDPOINT", @@ -72,18 +89,18 @@ def is_enabled(self): return getattr(settings, self.config_settings.enable_setting, False) def is_configured(self) -> bool: - return OpenIDConnectDigiDConfig.get_solo().enabled + return OpenIDDigiDConfig.get_solo().enabled def configure(self): if not self.is_enabled(): return - config = OpenIDConnectDigiDConfig.get_solo() + config = OpenIDDigiDConfig.get_solo() # Use the model defaults form_data = { field.name: getattr(config, field.name) - for field in OpenIDConnectDigiDConfig._meta.fields + for field in OpenIDDigiDConfig._meta.fields } # Only override field values with settings if they are defined @@ -101,12 +118,8 @@ def configure(self): form_data["enabled"] = True - # Saving the form with the default error_message_mapping `{}` causes the save to fail - if not form_data["error_message_mapping"]: - del form_data["error_message_mapping"] - # Use the admin form to apply validation and fetch URLs from the discovery endpoint - form = OpenIDConnectDigiDConfigForm(data=form_data) + form = OpenIDDigiDConfigForm(data=form_data) if not form.is_valid(): raise ConfigurationRunFailed( f"Something went wrong while saving configuration: {form.errors}" @@ -133,7 +146,7 @@ class eHerkenningOIDCConfigurationStep(BaseConfigurationStep): config_settings = ConfigSettings( enable_setting="EHERKENNING_OIDC_CONFIG_ENABLE", namespace="EHERKENNING_OIDC", - models=[OpenIDConnectEHerkenningConfig], + models=[OpenIDEHerkenningConfig], update_fields=True, required_settings=[ "EHERKENNING_OIDC_OIDC_RP_CLIENT_ID", @@ -141,7 +154,7 @@ class eHerkenningOIDCConfigurationStep(BaseConfigurationStep): ], optional_settings=[ "EHERKENNING_OIDC_ENABLED", - "EHERKENNING_OIDC_IDENTIFIER_CLAIM_NAME", + "EHERKENNING_OIDC_LEGAL_SUBJECT_CLAIM", "EHERKENNING_OIDC_OIDC_RP_SCOPES_LIST", "EHERKENNING_OIDC_OIDC_RP_SIGN_ALGO", "EHERKENNING_OIDC_OIDC_RP_IDP_SIGN_KEY", @@ -152,28 +165,26 @@ class eHerkenningOIDCConfigurationStep(BaseConfigurationStep): "EHERKENNING_OIDC_OIDC_OP_USER_ENDPOINT", "EHERKENNING_OIDC_OIDC_OP_LOGOUT_ENDPOINT", "EHERKENNING_OIDC_USERINFO_CLAIMS_SOURCE", - "EHERKENNING_OIDC_ERROR_MESSAGE_MAPPING", "EHERKENNING_OIDC_OIDC_KEYCLOAK_IDP_HINT", "EHERKENNING_OIDC_OIDC_USE_NONCE", "EHERKENNING_OIDC_OIDC_NONCE_SIZE", "EHERKENNING_OIDC_OIDC_STATE_SIZE", - "EHERKENNING_OIDC_OIDC_EXEMPT_URLS", ], ) def is_configured(self) -> bool: - return OpenIDConnectEHerkenningConfig.get_solo().enabled + return OpenIDEHerkenningConfig.get_solo().enabled def configure(self): if not getattr(settings, self.config_settings.enable_setting, None): return - config = OpenIDConnectEHerkenningConfig.get_solo() + config = OpenIDEHerkenningConfig.get_solo() # Use the model defaults form_data = { field.name: getattr(config, field.name) - for field in OpenIDConnectEHerkenningConfig._meta.fields + for field in OpenIDEHerkenningConfig._meta.fields } # Only override field values with settings if they are defined @@ -191,12 +202,8 @@ def configure(self): form_data["enabled"] = True - # Saving the form with the default error_message_mapping `{}` causes the save to fail - if not form_data["error_message_mapping"]: - del form_data["error_message_mapping"] - # Use the admin form to apply validation and fetch URLs from the discovery endpoint - form = OpenIDConnectEHerkenningConfigForm(data=form_data) + form = OpenIDEHerkenningConfigForm(data=form_data) if not form.is_valid(): raise ConfigurationRunFailed( f"Something went wrong while saving configuration: {form.errors}" @@ -235,7 +242,6 @@ class AdminOIDCConfigurationStep(BaseConfigurationStep): "ADMIN_OIDC_CLAIM_MAPPING", "ADMIN_OIDC_GROUPS_CLAIM", "ADMIN_OIDC_MAKE_USERS_STAFF", - "ADMIN_OIDC_OIDC_EXEMPT_URLS", "ADMIN_OIDC_OIDC_NONCE_SIZE", "ADMIN_OIDC_OIDC_OP_AUTHORIZATION_ENDPOINT", "ADMIN_OIDC_OIDC_OP_DISCOVERY_ENDPOINT", diff --git a/src/open_inwoner/configurations/tests/bootstrap/test_setup_auth_config.py b/src/open_inwoner/configurations/tests/bootstrap/test_setup_auth_config.py index 025390d9db..6e501a8599 100644 --- a/src/open_inwoner/configurations/tests/bootstrap/test_setup_auth_config.py +++ b/src/open_inwoner/configurations/tests/bootstrap/test_setup_auth_config.py @@ -23,10 +23,7 @@ from privates.test import temp_private_root from simple_certmanager.constants import CertificateTypes -from digid_eherkenning_oidc_generics.models import ( - OpenIDConnectDigiDConfig, - OpenIDConnectEHerkenningConfig, -) +from open_inwoner.accounts.models import OpenIDDigiDConfig, OpenIDEHerkenningConfig from open_inwoner.utils.test import ClearCachesMixin from ...bootstrap.auth import ( @@ -67,7 +64,7 @@ DIGID_OIDC_CONFIG_ENABLE=True, DIGID_OIDC_OIDC_RP_CLIENT_ID="client-id", DIGID_OIDC_OIDC_RP_CLIENT_SECRET="secret", - DIGID_OIDC_IDENTIFIER_CLAIM_NAME="claim_name", + DIGID_OIDC_BSN_CLAIM=["claim_name"], DIGID_OIDC_OIDC_RP_SCOPES_LIST=["openid", "bsn", "extra_scope"], DIGID_OIDC_OIDC_RP_SIGN_ALGO="RS256", DIGID_OIDC_OIDC_RP_IDP_SIGN_KEY="key", @@ -78,23 +75,21 @@ DIGID_OIDC_OIDC_OP_USER_ENDPOINT=f"{IDENTITY_PROVIDER}protocol/openid-connect/userinfo", DIGID_OIDC_OIDC_OP_LOGOUT_ENDPOINT=f"{IDENTITY_PROVIDER}protocol/openid-connect/logout", DIGID_OIDC_USERINFO_CLAIMS_SOURCE=UserInformationClaimsSources.id_token, - DIGID_OIDC_ERROR_MESSAGE_MAPPING={"some_error": "Some readable error"}, DIGID_OIDC_OIDC_KEYCLOAK_IDP_HINT="parameter", DIGID_OIDC_OIDC_USE_NONCE=False, DIGID_OIDC_OIDC_NONCE_SIZE=64, DIGID_OIDC_OIDC_STATE_SIZE=64, - DIGID_OIDC_OIDC_EXEMPT_URLS=["/foo"], ) class DigiDOIDCConfigurationTest(ClearCachesMixin, TestCase): def test_configure(self): DigiDOIDCConfigurationStep().configure() - config = OpenIDConnectDigiDConfig.get_solo() + config = OpenIDDigiDConfig.get_solo() self.assertTrue(config.enabled) self.assertEqual(config.oidc_rp_client_id, "client-id") self.assertEqual(config.oidc_rp_client_secret, "secret") - self.assertEqual(config.identifier_claim_name, "claim_name") + self.assertEqual(config.bsn_claim, ["claim_name"]) self.assertEqual(config.oidc_rp_scopes_list, ["openid", "bsn", "extra_scope"]) self.assertEqual(config.oidc_rp_sign_algo, "RS256") self.assertEqual(config.oidc_rp_idp_sign_key, "key") @@ -122,37 +117,31 @@ def test_configure(self): self.assertEqual( config.userinfo_claims_source, UserInformationClaimsSources.id_token ) - self.assertEqual( - config.error_message_mapping, {"some_error": "Some readable error"} - ) self.assertEqual(config.oidc_keycloak_idp_hint, "parameter") self.assertEqual(config.oidc_use_nonce, False) self.assertEqual(config.oidc_nonce_size, 64) self.assertEqual(config.oidc_state_size, 64) - self.assertEqual(config.oidc_exempt_urls, ["/foo"]) @override_settings( - DIGID_OIDC_IDENTIFIER_CLAIM_NAME=None, + DIGID_OIDC_BSN_CLAIM=None, DIGID_OIDC_OIDC_RP_SCOPES_LIST=None, DIGID_OIDC_OIDC_RP_SIGN_ALGO=None, DIGID_OIDC_OIDC_RP_IDP_SIGN_KEY=None, DIGID_OIDC_USERINFO_CLAIMS_SOURCE=None, - DIGID_OIDC_ERROR_MESSAGE_MAPPING=None, DIGID_OIDC_OIDC_KEYCLOAK_IDP_HINT=None, DIGID_OIDC_OIDC_USE_NONCE=None, DIGID_OIDC_OIDC_NONCE_SIZE=None, DIGID_OIDC_OIDC_STATE_SIZE=None, - DIGID_OIDC_OIDC_EXEMPT_URLS=None, ) def test_configure_use_defaults(self): DigiDOIDCConfigurationStep().configure() - config = OpenIDConnectDigiDConfig.get_solo() + config = OpenIDDigiDConfig.get_solo() self.assertTrue(config.enabled) self.assertEqual(config.oidc_rp_client_id, "client-id") self.assertEqual(config.oidc_rp_client_secret, "secret") - self.assertEqual(config.identifier_claim_name, "bsn") + self.assertEqual(config.bsn_claim, ["bsn"]) self.assertEqual(config.oidc_rp_scopes_list, ["openid", "bsn"]) self.assertEqual(config.oidc_rp_sign_algo, "HS256") self.assertEqual(config.oidc_rp_idp_sign_key, "") @@ -181,12 +170,10 @@ def test_configure_use_defaults(self): config.userinfo_claims_source, UserInformationClaimsSources.userinfo_endpoint, ) - self.assertEqual(config.error_message_mapping, {}) self.assertEqual(config.oidc_keycloak_idp_hint, "") self.assertEqual(config.oidc_use_nonce, True) self.assertEqual(config.oidc_nonce_size, 32) self.assertEqual(config.oidc_state_size, 32) - self.assertEqual(config.oidc_exempt_urls, []) @override_settings( DIGID_OIDC_OIDC_OP_DISCOVERY_ENDPOINT=IDENTITY_PROVIDER, @@ -205,7 +192,7 @@ def test_configure_use_discovery_endpoint(self, m): DigiDOIDCConfigurationStep().configure() - config = OpenIDConnectDigiDConfig.get_solo() + config = OpenIDDigiDConfig.get_solo() self.assertTrue(config.enabled) self.assertEqual(config.oidc_op_discovery_endpoint, IDENTITY_PROVIDER) @@ -257,7 +244,7 @@ def test_configure_failure(self, m): with self.assertRaises(ConfigurationRunFailed): DigiDOIDCConfigurationStep().configure() - self.assertFalse(OpenIDConnectDigiDConfig.get_solo().enabled) + self.assertFalse(OpenIDDigiDConfig.get_solo().enabled) @skip("Testing config for DigiD OIDC is not implemented yet") @requests_mock.Mocker() @@ -291,7 +278,7 @@ def test_disable_digid_oidc_config(self): EHERKENNING_OIDC_CONFIG_ENABLE=True, EHERKENNING_OIDC_OIDC_RP_CLIENT_ID="client-id", EHERKENNING_OIDC_OIDC_RP_CLIENT_SECRET="secret", - EHERKENNING_OIDC_IDENTIFIER_CLAIM_NAME="claim_name", + EHERKENNING_OIDC_LEGAL_SUBJECT_CLAIM=["claim_name"], EHERKENNING_OIDC_OIDC_RP_SCOPES_LIST=["openid", "kvk", "extra_scope"], EHERKENNING_OIDC_OIDC_RP_SIGN_ALGO="RS256", EHERKENNING_OIDC_OIDC_RP_IDP_SIGN_KEY="key", @@ -302,23 +289,21 @@ def test_disable_digid_oidc_config(self): EHERKENNING_OIDC_OIDC_OP_USER_ENDPOINT=f"{IDENTITY_PROVIDER}protocol/openid-connect/userinfo", EHERKENNING_OIDC_OIDC_OP_LOGOUT_ENDPOINT=f"{IDENTITY_PROVIDER}protocol/openid-connect/logout", EHERKENNING_OIDC_USERINFO_CLAIMS_SOURCE=UserInformationClaimsSources.id_token, - EHERKENNING_OIDC_ERROR_MESSAGE_MAPPING={"some_error": "Some readable error"}, EHERKENNING_OIDC_OIDC_KEYCLOAK_IDP_HINT="parameter", EHERKENNING_OIDC_OIDC_USE_NONCE=False, EHERKENNING_OIDC_OIDC_NONCE_SIZE=64, EHERKENNING_OIDC_OIDC_STATE_SIZE=64, - EHERKENNING_OIDC_OIDC_EXEMPT_URLS=["/foo"], ) class eHerkenningOIDCConfigurationTest(ClearCachesMixin, TestCase): def test_configure(self): eHerkenningOIDCConfigurationStep().configure() - config = OpenIDConnectEHerkenningConfig.get_solo() + config = OpenIDEHerkenningConfig.get_solo() self.assertTrue(config.enabled) self.assertEqual(config.oidc_rp_client_id, "client-id") self.assertEqual(config.oidc_rp_client_secret, "secret") - self.assertEqual(config.identifier_claim_name, "claim_name") + self.assertEqual(config.legal_subject_claim, ["claim_name"]) self.assertEqual(config.oidc_rp_scopes_list, ["openid", "kvk", "extra_scope"]) self.assertEqual(config.oidc_rp_sign_algo, "RS256") self.assertEqual(config.oidc_rp_idp_sign_key, "key") @@ -346,37 +331,33 @@ def test_configure(self): self.assertEqual( config.userinfo_claims_source, UserInformationClaimsSources.id_token ) - self.assertEqual( - config.error_message_mapping, {"some_error": "Some readable error"} - ) self.assertEqual(config.oidc_keycloak_idp_hint, "parameter") self.assertEqual(config.oidc_use_nonce, False) self.assertEqual(config.oidc_nonce_size, 64) self.assertEqual(config.oidc_state_size, 64) - self.assertEqual(config.oidc_exempt_urls, ["/foo"]) @override_settings( - EHERKENNING_OIDC_IDENTIFIER_CLAIM_NAME=None, + EHERKENNING_OIDC_LEGAL_SUBJECT_CLAIM=None, EHERKENNING_OIDC_OIDC_RP_SCOPES_LIST=None, EHERKENNING_OIDC_OIDC_RP_SIGN_ALGO=None, EHERKENNING_OIDC_OIDC_RP_IDP_SIGN_KEY=None, EHERKENNING_OIDC_USERINFO_CLAIMS_SOURCE=None, - EHERKENNING_OIDC_ERROR_MESSAGE_MAPPING=None, EHERKENNING_OIDC_OIDC_KEYCLOAK_IDP_HINT=None, EHERKENNING_OIDC_OIDC_USE_NONCE=None, EHERKENNING_OIDC_OIDC_NONCE_SIZE=None, EHERKENNING_OIDC_OIDC_STATE_SIZE=None, - EHERKENNING_OIDC_OIDC_EXEMPT_URLS=None, ) def test_configure_use_defaults(self): eHerkenningOIDCConfigurationStep().configure() - config = OpenIDConnectEHerkenningConfig.get_solo() + config = OpenIDEHerkenningConfig.get_solo() self.assertTrue(config.enabled) self.assertEqual(config.oidc_rp_client_id, "client-id") self.assertEqual(config.oidc_rp_client_secret, "secret") - self.assertEqual(config.identifier_claim_name, "kvk") + self.assertEqual( + config.legal_subject_claim, ["urn:etoegang:core:LegalSubjectID"] + ) self.assertEqual(config.oidc_rp_scopes_list, ["openid", "kvk"]) self.assertEqual(config.oidc_rp_sign_algo, "HS256") self.assertEqual(config.oidc_rp_idp_sign_key, "") @@ -405,12 +386,10 @@ def test_configure_use_defaults(self): config.userinfo_claims_source, UserInformationClaimsSources.userinfo_endpoint, ) - self.assertEqual(config.error_message_mapping, {}) self.assertEqual(config.oidc_keycloak_idp_hint, "") self.assertEqual(config.oidc_use_nonce, True) self.assertEqual(config.oidc_nonce_size, 32) self.assertEqual(config.oidc_state_size, 32) - self.assertEqual(config.oidc_exempt_urls, []) @override_settings( EHERKENNING_OIDC_OIDC_OP_DISCOVERY_ENDPOINT=IDENTITY_PROVIDER, @@ -429,7 +408,7 @@ def test_configure_use_discovery_endpoint(self, m): eHerkenningOIDCConfigurationStep().configure() - config = OpenIDConnectEHerkenningConfig.get_solo() + config = OpenIDEHerkenningConfig.get_solo() self.assertTrue(config.enabled) self.assertEqual(config.oidc_op_discovery_endpoint, IDENTITY_PROVIDER) @@ -481,7 +460,7 @@ def test_configure_failure(self, m): with self.assertRaises(ConfigurationRunFailed): eHerkenningOIDCConfigurationStep().configure() - self.assertFalse(OpenIDConnectEHerkenningConfig.get_solo().enabled) + self.assertFalse(OpenIDEHerkenningConfig.get_solo().enabled) @skip("Testing config for DigiD OIDC is not implemented yet") @requests_mock.Mocker() @@ -523,9 +502,9 @@ def test_disable_eherkenning_oidc_config(self): ADMIN_OIDC_OIDC_OP_AUTHORIZATION_ENDPOINT=f"{IDENTITY_PROVIDER}protocol/openid-connect/auth", ADMIN_OIDC_OIDC_OP_TOKEN_ENDPOINT=f"{IDENTITY_PROVIDER}protocol/openid-connect/token", ADMIN_OIDC_OIDC_OP_USER_ENDPOINT=f"{IDENTITY_PROVIDER}protocol/openid-connect/userinfo", - ADMIN_OIDC_USERNAME_CLAIM="claim_name", - ADMIN_OIDC_GROUPS_CLAIM="groups_claim_name", - ADMIN_OIDC_CLAIM_MAPPING={"first_name": "given_name"}, + ADMIN_OIDC_USERNAME_CLAIM=["claim_name"], + ADMIN_OIDC_GROUPS_CLAIM=["groups_claim_name"], + ADMIN_OIDC_CLAIM_MAPPING={"first_name": ["given_name"]}, ADMIN_OIDC_SYNC_GROUPS=False, ADMIN_OIDC_SYNC_GROUPS_GLOB_PATTERN="local.groups.*", ADMIN_OIDC_DEFAULT_GROUPS=["Admins", "Read-only"], @@ -534,7 +513,6 @@ def test_disable_eherkenning_oidc_config(self): ADMIN_OIDC_OIDC_USE_NONCE=False, ADMIN_OIDC_OIDC_NONCE_SIZE=48, ADMIN_OIDC_OIDC_STATE_SIZE=48, - ADMIN_OIDC_OIDC_EXEMPT_URLS=["http://testserver/some-endpoint"], ADMIN_OIDC_USERINFO_CLAIMS_SOURCE=UserInformationClaimsSources.id_token, ) class AdminOIDCConfigurationTest(ClearCachesMixin, TestCase): @@ -568,9 +546,9 @@ def test_configure(self): config.oidc_op_user_endpoint, f"{IDENTITY_PROVIDER}protocol/openid-connect/userinfo", ) - self.assertEqual(config.username_claim, "claim_name") - self.assertEqual(config.groups_claim, "groups_claim_name") - self.assertEqual(config.claim_mapping, {"first_name": "given_name"}) + self.assertEqual(config.username_claim, ["claim_name"]) + self.assertEqual(config.groups_claim, ["groups_claim_name"]) + self.assertEqual(config.claim_mapping, {"first_name": ["given_name"]}) self.assertEqual(config.sync_groups, False) self.assertEqual(config.sync_groups_glob_pattern, "local.groups.*") self.assertEqual( @@ -582,7 +560,6 @@ def test_configure(self): self.assertEqual(config.oidc_use_nonce, False) self.assertEqual(config.oidc_nonce_size, 48) self.assertEqual(config.oidc_state_size, 48) - self.assertEqual(config.oidc_exempt_urls, ["http://testserver/some-endpoint"]) self.assertEqual( config.userinfo_claims_source, UserInformationClaimsSources.id_token ) @@ -599,7 +576,6 @@ def test_configure(self): ADMIN_OIDC_OIDC_USE_NONCE=None, ADMIN_OIDC_OIDC_NONCE_SIZE=None, ADMIN_OIDC_OIDC_STATE_SIZE=None, - ADMIN_OIDC_OIDC_EXEMPT_URLS=None, ADMIN_OIDC_USERINFO_CLAIMS_SOURCE=None, ) def test_configure_use_defaults(self): @@ -630,11 +606,11 @@ def test_configure_use_defaults(self): config.oidc_op_user_endpoint, f"{IDENTITY_PROVIDER}protocol/openid-connect/userinfo", ) - self.assertEqual(config.username_claim, "sub") - self.assertEqual(config.groups_claim, "groups_claim_name") + self.assertEqual(config.username_claim, ["sub"]) + self.assertEqual(config.groups_claim, ["groups_claim_name"]) self.assertEqual( config.claim_mapping, - {"last_name": "family_name", "first_name": "given_name"}, + {"last_name": ["family_name"], "first_name": ["given_name"]}, ) self.assertEqual(config.sync_groups, True) self.assertEqual(config.sync_groups_glob_pattern, "*") @@ -647,7 +623,6 @@ def test_configure_use_defaults(self): self.assertEqual(config.oidc_use_nonce, True) self.assertEqual(config.oidc_nonce_size, 32) self.assertEqual(config.oidc_state_size, 32) - self.assertEqual(config.oidc_exempt_urls, []) self.assertEqual( config.userinfo_claims_source, UserInformationClaimsSources.userinfo_endpoint,