Skip to content

Commit

Permalink
✨[#114] combine settings into single setting
Browse files Browse the repository at this point in the history
  • Loading branch information
Coperh committed Aug 13, 2024
1 parent aca9492 commit 76ccc85
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 154 deletions.
70 changes: 24 additions & 46 deletions mozilla_django_oidc_db/setupconfig/boostrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,66 +14,44 @@ class AdminOIDCConfigurationStep(BaseConfigurationStep):
"""

verbose_name = "Configuration for admin login via OpenID Connect"
required_settings = [
"ADMIN_OIDC_OIDC_RP_CLIENT_ID",
"ADMIN_OIDC_OIDC_RP_CLIENT_SECRET",
"ADMIN_OIDC_OIDC_OP_AUTHORIZATION_ENDPOINT",
"ADMIN_OIDC_OIDC_OP_TOKEN_ENDPOINT",
"ADMIN_OIDC_OIDC_OP_USER_ENDPOINT",
]
all_settings = required_settings + [
"ADMIN_OIDC_OIDC_RP_SCOPES_LIST",
"ADMIN_OIDC_OIDC_RP_SIGN_ALGO",
"ADMIN_OIDC_OIDC_RP_IDP_SIGN_KEY",
"ADMIN_OIDC_OIDC_OP_DISCOVERY_ENDPOINT",
"ADMIN_OIDC_OIDC_OP_JWKS_ENDPOINT",
"ADMIN_OIDC_USERNAME_CLAIM",
"ADMIN_OIDC_GROUPS_CLAIM",
"ADMIN_OIDC_CLAIM_MAPPING",
"ADMIN_OIDC_SYNC_GROUPS",
"ADMIN_OIDC_SYNC_GROUPS_GLOB_PATTERN",
"ADMIN_OIDC_DEFAULT_GROUPS",
"ADMIN_OIDC_MAKE_USERS_STAFF",
"ADMIN_OIDC_SUPERUSER_GROUP_NAMES",
"ADMIN_OIDC_OIDC_USE_NONCE",
"ADMIN_OIDC_OIDC_NONCE_SIZE",
"ADMIN_OIDC_OIDC_STATE_SIZE",
"ADMIN_OIDC_USERINFO_CLAIMS_SOURCE",
]
enable_setting = "ADMIN_OIDC_CONFIG_ENABLE"
required_fields = {
"OIDC_DB_SETUP_CONFIG_ADMIN_AUTH": [
"oidc_rp_client_id",
"oidc_rp_client_secret",
"oidc_op_authorization_endpoint",
"oidc_op_token_endpoint",
"oidc_op_user_endpoint",
]
}
required_settings = ["OIDC_DB_SETUP_CONFIG_ADMIN_AUTH"]
enable_setting = "OIDC_DB_CONFIG_ENABLE"

def is_configured(self) -> bool:
return OpenIDConnectConfig.get_solo().enabled

def configure(self):
config = OpenIDConnectConfig.get_solo()

# Use the model defaults
form_data = {
all_settings = {
field.name: getattr(config, field.name)
for field in OpenIDConnectConfig._meta.fields
}

# `email` is in the claim_mapping by default, but email is used as the username field
# by OIP, and you cannot map the username field when using OIDC
if "email" in form_data["claim_mapping"]:
del form_data["claim_mapping"]["email"]
all_settings.update(settings.OIDC_DB_SETUP_CONFIG_ADMIN_AUTH)

# Only override field values with settings if they are defined
for setting in self.all_settings:
value = getattr(settings, setting, None)
if value is not None:
model_field_name = setting.split("ADMIN_OIDC_")[1].lower()
if model_field_name == "default_groups":
for group_name in value:
Group.objects.get_or_create(name=group_name)
value = Group.objects.filter(name__in=value)
if "default_groups" in all_settings:
groups = all_settings["default_groups"]
for group_name in groups:
Group.objects.get_or_create(name=group_name)
all_settings["default_groups"] = Group.objects.filter(name__in=groups)

form_data[model_field_name] = value
form_data["enabled"] = True
all_settings["enabled"] = True

# Use the admin form to apply validation and fetch URLs from the discovery endpoint
form = OpenIDConnectConfigForm(data=form_data)
form = OpenIDConnectConfigForm(
instance=config,
data=all_settings,
empty_permitted=False,
)
if not form.is_valid():
raise ConfigurationRunFailed(
f"Something went wrong while saving configuration: {form.errors.as_json()}"
Expand Down
32 changes: 0 additions & 32 deletions testapp/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,35 +80,3 @@
LOGIN_REDIRECT_URL = reverse_lazy("admin:index")

STATIC_URL = "/static/"


# Setup Configuration Settings

IDENTITY_PROVIDER = "https://keycloak.local/realms/digid/"

ADMIN_OIDC_OIDC_RP_CLIENT_ID = "client-id"
ADMIN_OIDC_OIDC_RP_CLIENT_SECRET = "secret"
ADMIN_OIDC_OIDC_RP_SCOPES_LIST = ["open_id", "email", "profile", "extra_scope"]
ADMIN_OIDC_OIDC_RP_SIGN_ALGO = "RS256"
ADMIN_OIDC_OIDC_RP_IDP_SIGN_KEY = "key"
ADMIN_OIDC_OIDC_OP_DISCOVERY_ENDPOINT = None
ADMIN_OIDC_OIDC_OP_JWKS_ENDPOINT = f"{IDENTITY_PROVIDER}protocol/openid-connect/certs"
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_SYNC_GROUPS = False
ADMIN_OIDC_SYNC_GROUPS_GLOB_PATTERN = "local.groups.*"
ADMIN_OIDC_DEFAULT_GROUPS = ["Admins", "Read-only"]
ADMIN_OIDC_MAKE_USERS_STAFF = True
ADMIN_OIDC_SUPERUSER_GROUP_NAMES = ["superuser"]
ADMIN_OIDC_OIDC_USE_NONCE = False
ADMIN_OIDC_OIDC_NONCE_SIZE = 48
ADMIN_OIDC_OIDC_STATE_SIZE = 48
ADMIN_OIDC_USERINFO_CLAIMS_SOURCE = "id_token"
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.32.3
method: GET
uri: http://localhost:8080/realms/test/.well-known/openid-configuration
response:
body:
string: '{"issuer":"http://localhost:8080/realms/test","authorization_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/auth","token_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/token","introspection_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/token/introspect","userinfo_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/userinfo","end_session_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/logout","frontchannel_logout_session_supported":true,"frontchannel_logout_supported":true,"jwks_uri":"http://localhost:8080/realms/test/protocol/openid-connect/certs","check_session_iframe":"http://localhost:8080/realms/test/protocol/openid-connect/login-status-iframe.html","grant_types_supported":["authorization_code","implicit","refresh_token","password","client_credentials","urn:openid:params:grant-type:ciba","urn:ietf:params:oauth:grant-type:device_code"],"acr_values_supported":["0","1"],"response_types_supported":["code","none","id_token","token","id_token
token","code id_token","code token","code id_token token"],"subject_types_supported":["public","pairwise"],"id_token_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"id_token_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"id_token_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"userinfo_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512","none"],"userinfo_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"userinfo_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"request_object_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512","none"],"request_object_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"request_object_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"response_modes_supported":["query","fragment","form_post","query.jwt","fragment.jwt","form_post.jwt","jwt"],"registration_endpoint":"http://localhost:8080/realms/test/clients-registrations/openid-connect","token_endpoint_auth_methods_supported":["private_key_jwt","client_secret_basic","client_secret_post","tls_client_auth","client_secret_jwt"],"token_endpoint_auth_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"introspection_endpoint_auth_methods_supported":["private_key_jwt","client_secret_basic","client_secret_post","tls_client_auth","client_secret_jwt"],"introspection_endpoint_auth_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"authorization_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"authorization_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"authorization_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"claims_supported":["aud","sub","iss","auth_time","name","given_name","family_name","preferred_username","email","acr"],"claim_types_supported":["normal"],"claims_parameter_supported":true,"scopes_supported":["openid","email","roles","phone","profile","address","kvk","web-origins","microprofile-jwt","acr","offline_access","bsn"],"request_parameter_supported":true,"request_uri_parameter_supported":true,"require_request_uri_registration":true,"code_challenge_methods_supported":["plain","S256"],"tls_client_certificate_bound_access_tokens":true,"revocation_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/revoke","revocation_endpoint_auth_methods_supported":["private_key_jwt","client_secret_basic","client_secret_post","tls_client_auth","client_secret_jwt"],"revocation_endpoint_auth_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"backchannel_logout_supported":true,"backchannel_logout_session_supported":true,"device_authorization_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/auth/device","backchannel_token_delivery_modes_supported":["poll","ping"],"backchannel_authentication_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/ext/ciba/auth","backchannel_authentication_request_signing_alg_values_supported":["PS384","ES384","RS384","ES256","RS256","ES512","PS256","PS512","RS512"],"require_pushed_authorization_requests":false,"pushed_authorization_request_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/ext/par/request","mtls_endpoint_aliases":{"token_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/token","revocation_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/revoke","introspection_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/token/introspect","device_authorization_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/auth/device","registration_endpoint":"http://localhost:8080/realms/test/clients-registrations/openid-connect","userinfo_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/userinfo","pushed_authorization_request_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/ext/par/request","backchannel_authentication_endpoint":"http://localhost:8080/realms/test/protocol/openid-connect/ext/ciba/auth"},"authorization_response_iss_parameter_supported":true}'
headers:
Cache-Control:
- no-cache, must-revalidate, no-transform, no-store
Content-Type:
- application/json;charset=UTF-8
Referrer-Policy:
- no-referrer
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-XSS-Protection:
- 1; mode=block
content-length:
- '5847'
status:
code: 200
message: OK
version: 1
54 changes: 54 additions & 0 deletions tests/setupconfig/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import pytest

from ..conftest import KEYCLOAK_BASE_URL


@pytest.fixture
def setup_config_discovery(settings):
settings.OIDC_DB_SETUP_CONFIG_ADMIN_AUTH = {
"oidc_rp_client_id": "testid",
"oidc_rp_client_secret": "7DB3KUAAizYCcmZufpHRVOcD0TOkNO3I",
"oidc_op_discovery_endpoint": KEYCLOAK_BASE_URL,
}


@pytest.fixture
def setup_config_defaults(settings):
settings.OIDC_DB_SETUP_CONFIG_ADMIN_AUTH = {
"oidc_rp_client_id": "client-id",
"oidc_rp_client_secret": "secret",
"oidc_op_authorization_endpoint": f"{KEYCLOAK_BASE_URL}protocol/openid-connect/auth",
"oidc_op_token_endpoint": f"{KEYCLOAK_BASE_URL}protocol/openid-connect/token",
"oidc_op_user_endpoint": f"{KEYCLOAK_BASE_URL}protocol/openid-connect/userinfo",
}


@pytest.fixture
def setup_config_full(settings):

settings.OIDC_DB_SETUP_CONFIG_ADMIN_AUTH = {
"oidc_rp_client_id": "client-id",
"oidc_rp_client_secret": "secret",
"oidc_rp_scopes_list": ["open_id", "email", "profile", "extra_scope"],
"oidc_rp_sign_algo": "RS256",
"oidc_rp_idp_sign_key": "key",
"oidc_op_discovery_endpoint": None,
"oidc_op_jwks_endpoint": f"{KEYCLOAK_BASE_URL}protocol/openid-connect/certs",
"oidc_op_authorization_endpoint": (
f"{KEYCLOAK_BASE_URL}protocol/openid-connect/auth"
),
"oidc_op_token_endpoint": f"{KEYCLOAK_BASE_URL}protocol/openid-connect/token",
"oidc_op_user_endpoint": f"{KEYCLOAK_BASE_URL}protocol/openid-connect/userinfo",
"username_claim": ["claim_name"],
"groups_claim": ["groups_claim_name"],
"claim_mapping": {"first_name": "given_name"},
"sync_groups": False,
"sync_groups_glob_pattern": "local.groups.*",
"default_groups": ["Admins", "Read-only"],
"make_users_staff": True,
"superuser_group_names": ["superuser"],
"oidc_use_nonce": False,
"oidc_nonce_size": 48,
"oidc_state_size": 48,
"userinfo_claims_source": "id_token",
}
Loading

0 comments on commit 76ccc85

Please sign in to comment.