diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2992b06 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,24 @@ +# Config taken from https://stackoverflow.com/a/77257732 +# +# This docker-compose is for development and test purposes. Tests are recorded with +# VCR against this instance. +# +# Log in to http://localhost:8080/admin/master/console/ with `admin`/`admin` +# credentials. +# +# DO NOT USE THIS IN PRODUCTION. +# + +version: '3.8' + +services: + keycloak: + image: quay.io/keycloak/keycloak:23.0.6 + command: start-dev --import-realm + environment: + - KEYCLOAK_ADMIN=admin + - KEYCLOAK_ADMIN_PASSWORD=admin + volumes: + - ./docker/import:/opt/keycloak/data/import + ports: + - 8080:8080 diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..ca24494 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,33 @@ +# Keycloak Realm export and import + +The `import/realm.json` is loaded when the Keycloak service is spun up through +docker-compose. In the top-level directory: + +```bash +docker-compose up -d +``` + +You can now log in via `http://localhost:8080` with the `admin`/`admin` credentials. + +## Exporting the Realm + +In short - exporting through the admin UI (rightfully) obfuscates client secrets and +user credentials. However, for reproducible builds/environments, we want to include +this data in the Realm export. + +Ensure the service is up and running through docker-compose. + +Ensure that UID `1000` can write to `./docker/import/`: + +```bash +chmod o+rwx ./docker/import/ +``` + +Then open another terminal and run: + + ```bash + docker-compose exec keycloak ./bin/kc.sh \ + export \ + --file /opt/keycloak/data/import/test-realm.json \ + --realm test + ``` diff --git a/docker/import/test-realm.json b/docker/import/test-realm.json new file mode 100644 index 0000000..6271fa5 --- /dev/null +++ b/docker/import/test-realm.json @@ -0,0 +1,1932 @@ +{ + "id" : "f74c917b-fd69-4c6d-9afa-d9f6774e9d7d", + "realm" : "test", + "notBefore" : 0, + "defaultSignatureAlgorithm" : "RS256", + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 300, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 1800, + "ssoSessionMaxLifespan" : 36000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "clientSessionIdleTimeout" : 0, + "clientSessionMaxLifespan" : 0, + "clientOfflineSessionIdleTimeout" : 0, + "clientOfflineSessionMaxLifespan" : 0, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "oauth2DeviceCodeLifespan" : 600, + "oauth2DevicePollingInterval" : 5, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "28c07910-21e3-460d-98f3-18bdb430ffe1", + "name" : "default-roles-test", + "description" : "${role_default-roles}", + "composite" : true, + "composites" : { + "realm" : [ "offline_access", "uma_authorization" ], + "client" : { + "account" : [ "view-profile", "manage-account" ] + } + }, + "clientRole" : false, + "containerId" : "f74c917b-fd69-4c6d-9afa-d9f6774e9d7d", + "attributes" : { } + }, { + "id" : "a3d84717-84c9-4d08-a90c-01b4d913b919", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "f74c917b-fd69-4c6d-9afa-d9f6774e9d7d", + "attributes" : { } + }, { + "id" : "50173816-9726-4655-8a65-13b0d0c23729", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "f74c917b-fd69-4c6d-9afa-d9f6774e9d7d", + "attributes" : { } + } ], + "client" : { + "realm-management" : [ { + "id" : "0c16a480-bbf3-49ad-8843-d4055cc83100", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "e2fa2cdd-feb7-42b1-a0f9-c6653e62d578", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "6d0c5def-b4d0-43b6-87c6-9cf6d6f9f2fb", + "name" : "realm-admin", + "description" : "${role_realm-admin}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-groups", "manage-clients", "view-identity-providers", "query-clients", "view-authorization", "view-clients", "manage-events", "manage-users", "manage-identity-providers", "query-users", "create-client", "impersonation", "query-realms", "manage-authorization", "view-events", "manage-realm", "view-realm", "view-users" ] + } + }, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "7d602068-73ae-4d83-bd9a-994a8dbf24b6", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "670970ae-e6b0-44f8-bd0e-c6945d41cacf", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "931ad9f0-c8ad-456a-a69d-d6c08abbe42a", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "3015f5e3-f9b4-4938-bae2-c2e1415b01c3", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "9648682e-3b89-4fa7-83e0-bd673d4d3119", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "baa8f313-386c-4ade-832f-0d2a7da6a2bc", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "f59ed8c2-772a-4faf-87a8-04e9e1f0a032", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "3a950e7f-4762-4306-8d42-63fdd90aa212", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "ab1e85d0-4e35-42ac-acc3-4fde650a1b9f", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "f517cd55-5d1e-4baa-bedb-35fbb7135b24", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "7c437eed-ebd0-41fe-a5f2-c569724b71e9", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "8ec7b657-c507-4548-9a88-0c018350bdb9", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "bfec4ce4-563a-4f9c-a678-f5cda9f554c4", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "08ab5b1c-0d0c-4789-a595-81dcac9d4b5a", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "fbfe356d-f049-475c-a7f3-35276f12173b", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + }, { + "id" : "42c2f2c5-eb42-49e3-93a0-a6c352af85c5", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-users", "query-groups" ] + } + }, + "clientRole" : true, + "containerId" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "attributes" : { } + } ], + "security-admin-console" : [ ], + "admin-cli" : [ ], + "testid" : [ ], + "account-console" : [ ], + "broker" : [ { + "id" : "b740a3c9-82ad-4b74-8a83-46c7d1d69441", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "0263ec51-8f33-4f73-952b-8cdb1712028c", + "attributes" : { } + } ], + "account" : [ { + "id" : "70072e4f-0600-42d1-b490-92de314f63bb", + "name" : "view-groups", + "description" : "${role_view-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "89fbc9e2-7a6c-4600-8ee8-f028644297fa", + "attributes" : { } + }, { + "id" : "87ffa29a-0a89-443b-bcf9-d26350bf74f8", + "name" : "view-applications", + "description" : "${role_view-applications}", + "composite" : false, + "clientRole" : true, + "containerId" : "89fbc9e2-7a6c-4600-8ee8-f028644297fa", + "attributes" : { } + }, { + "id" : "f6d0fe38-c146-4aab-924e-24b2d63ed95f", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "89fbc9e2-7a6c-4600-8ee8-f028644297fa", + "attributes" : { } + }, { + "id" : "0a6283c0-8c43-41e6-b6be-de81d6927b35", + "name" : "delete-account", + "description" : "${role_delete-account}", + "composite" : false, + "clientRole" : true, + "containerId" : "89fbc9e2-7a6c-4600-8ee8-f028644297fa", + "attributes" : { } + }, { + "id" : "f45f95f0-6a9e-4e98-ae9b-75e9b41023a6", + "name" : "view-consent", + "description" : "${role_view-consent}", + "composite" : false, + "clientRole" : true, + "containerId" : "89fbc9e2-7a6c-4600-8ee8-f028644297fa", + "attributes" : { } + }, { + "id" : "c21366ff-5003-4a3d-936d-925de4c347ae", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "89fbc9e2-7a6c-4600-8ee8-f028644297fa", + "attributes" : { } + }, { + "id" : "79e03b78-c3b2-4bcc-a04f-a58bba9a67a7", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } + }, + "clientRole" : true, + "containerId" : "89fbc9e2-7a6c-4600-8ee8-f028644297fa", + "attributes" : { } + }, { + "id" : "9fd80770-e9cc-4393-aded-ce9969067b35", + "name" : "manage-consent", + "description" : "${role_manage-consent}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "view-consent" ] + } + }, + "clientRole" : true, + "containerId" : "89fbc9e2-7a6c-4600-8ee8-f028644297fa", + "attributes" : { } + } ] + } + }, + "groups" : [ ], + "defaultRole" : { + "id" : "28c07910-21e3-460d-98f3-18bdb430ffe1", + "name" : "default-roles-test", + "description" : "${role_default-roles}", + "composite" : true, + "clientRole" : false, + "containerId" : "f74c917b-fd69-4c6d-9afa-d9f6774e9d7d" + }, + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpPolicyCodeReusable" : false, + "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], + "localizationTexts" : { }, + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyExtraOrigins" : [ ], + "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessRpId" : "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessCreateTimeout" : 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessExtraOrigins" : [ ], + "users" : [ { + "id" : "a28aac19-6ac5-4ce5-bbe3-b6c24051914a", + "createdTimestamp" : 1707141299906, + "username" : "service-account-testid", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "serviceAccountClientId" : "testid", + "credentials" : [ ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-test" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "aa10cfc7-2c4d-41f6-8fac-7bf405c572c4", + "createdTimestamp" : 1707141446005, + "username" : "testuser", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "attributes" : { + "bsn" : [ "000000000" ], + "kvk" : [ "012345678" ] + }, + "credentials" : [ { + "id" : "7592b843-a7ab-4372-a133-d4d984ae687c", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1707141485838, + "secretData" : "{\"value\":\"s9LcIc++9CRM7/wgifxyz0jUFYfmn2VuNpLP3NwUcDw=\",\"salt\":\"JReLfJs5YgTCeB+7u0tgfA==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-test" ], + "notBefore" : 0, + "groups" : [ ] + } ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + } ], + "clientScopeMappings" : { + "account" : [ { + "client" : "account-console", + "roles" : [ "manage-account", "view-groups" ] + } ] + }, + "clients" : [ { + "id" : "89fbc9e2-7a6c-4600-8ee8-f028644297fa", + "clientId" : "account", + "name" : "${client_account}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/test/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/test/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "6030fa07-5521-4c89-ad5f-0055bac6a47f", + "clientId" : "account-console", + "name" : "${client_account-console}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/test/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/test/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "675a1d8e-030c-4be6-bc22-bbcff46771b4", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "0ba5f086-39ea-4545-a237-639bcfbb6d20", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "0263ec51-8f33-4f73-952b-8cdb1712028c", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "b61c6592-3036-4e48-8c90-b0818f63576c", + "clientId" : "realm-management", + "name" : "${client_realm-management}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "d20d5fd5-e7aa-4641-8c83-c6a2fa0acfe2", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "rootUrl" : "${authAdminUrl}", + "baseUrl" : "/admin/test/console/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/admin/test/console/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "2c68a174-10c2-464e-bbc4-d8d414053fd6", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "adf4ad83-4550-4619-9231-73bd8d700f45", + "clientId" : "testid", + "name" : "", + "description" : "", + "rootUrl" : "", + "adminUrl" : "", + "baseUrl" : "", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "7DB3KUAAizYCcmZufpHRVOcD0TOkNO3I", + "redirectUris" : [ "http://testserver/*", "http://127.0.0.1:8000/*", "http://localhost:8000/*" ], + "webOrigins" : [ "http://127.0.0.1:8000" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : true, + "publicClient" : false, + "frontchannelLogout" : true, + "protocol" : "openid-connect", + "attributes" : { + "oidc.ciba.grant.enabled" : "false", + "client.secret.creation.time" : "1707141299", + "backchannel.logout.session.required" : "true", + "oauth2.device.authorization.grant.enabled" : "false", + "display.on.consent.screen" : "false", + "backchannel.logout.revoke.offline.tokens" : "false" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "protocolMappers" : [ { + "id" : "e62c9c9b-3a85-41a3-8529-42483cc285f1", + "name" : "Client ID", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "client_id", + "introspection.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "client_id", + "jsonType.label" : "String" + } + }, { + "id" : "c283ef6b-0be7-4ce0-a5dc-622b6ca88dc9", + "name" : "Client IP Address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientAddress", + "introspection.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientAddress", + "jsonType.label" : "String" + } + }, { + "id" : "68d1ac80-7066-45c3-af1b-48fd1bb52f25", + "name" : "Client Host", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientHost", + "introspection.token.claim" : "true", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientHost", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "kvk", "acr", "roles", "profile", "bsn", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + } ], + "clientScopes" : [ { + "id" : "f32301bc-3922-491a-89c3-9764356d9d17", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${emailScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "7d845a9b-b76e-4b9f-890b-ef313f9c2e5d", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + }, { + "id" : "e939e96f-9eec-4cc3-9a8e-137760c65b7a", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "cbee953a-f6cc-47d0-9417-bde0ade67c28", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${rolesScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "895028b7-75e6-4d1e-ab98-74e8fd83688c", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String" + } + }, { + "id" : "7a9b8a8d-b221-4748-941a-5b465036b01e", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String" + } + }, { + "id" : "0066ba3c-8feb-40ae-a8c4-f82e556b7001", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "626b8bbf-e0f7-4b59-93c7-80e875d48f75", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${phoneScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "f153d49f-b2eb-4631-b5d4-d994b1a5c1b1", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + }, { + "id" : "d225930c-582f-456e-b286-b95d8c4dd916", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "593033e2-5011-46b1-be8f-df036dee32b2", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${profileScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "ab90bd48-a6c3-4b47-bab6-1d993c010404", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + }, { + "id" : "33f67e40-80d4-4e10-951c-0c08d1051969", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "56f353fd-546e-48e4-8344-73332df31d3a", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "f78c250d-df76-4e1e-904f-c8d2d60aeb04", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "ab97273d-18bd-426f-a3f7-61e45309500d", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + }, { + "id" : "82effad5-1147-4b1d-bcc7-bda7e9c61760", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + }, { + "id" : "40d6f0ed-f41e-4a3c-acce-5f536fe91fcd", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + }, { + "id" : "07c6a4b7-4a27-4d1b-872d-4a726169c641", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + }, { + "id" : "df1e7c2d-e8e8-4176-8da9-628985e9cb51", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "20e3fa91-8afc-4735-977c-5de3d486a50d", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "long" + } + }, { + "id" : "3e525255-568d-40df-9c46-a4f25823ff7e", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + }, { + "id" : "b7cc3936-ca28-4aa5-9eed-7811ed2d6215", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "4ef08463-2a21-44bf-8e5e-6f4783aacf95", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + }, { + "id" : "15a35ab1-e602-445d-81bb-5a5a997a83dc", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "68c885a8-6cc4-4e18-8213-d69e80f9deef", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${addressScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "f328d8ca-8da7-4d0c-a8d4-35a8e0912649", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "introspection.token.claim" : "true", + "user.attribute.postal_code" : "postal_code", + "userinfo.token.claim" : "true", + "user.attribute.street" : "street", + "id.token.claim" : "true", + "user.attribute.region" : "region", + "access.token.claim" : "true", + "user.attribute.locality" : "locality" + } + } ] + }, { + "id" : "2a595631-0f05-4e03-9bf7-d0a86743f246", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "7e2ae83b-388d-4f10-ab1f-37b84ebde9d6", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "036a72a9-c46f-40e8-8324-c30ba3ea671c", + "name" : "kvk", + "description" : "", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "gui.order" : "", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "8cbdcd7a-239f-4f8c-ae19-6896a04bb680", + "name" : "kvk", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "kvk", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "kvk", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "b906f0fd-71de-43e6-959d-201c9a0d8cef", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "11c0d4eb-482e-4b8a-946d-63b268bf7fc9", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "0a26b3ef-c0eb-418c-85ca-6030c13e4182", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "13f9f62d-8be7-40bb-9507-f4fd9dd4168f", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + }, { + "id" : "51caccb7-1d50-4347-94d4-41ae1af2cea6", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "cdf790bc-c9d4-450c-9088-ef0435d0c7fb", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "3d18951b-0124-4daf-aad5-c8f6bebbb54b", + "name" : "acr loa level", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-acr-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "a1de3cd0-4499-4b82-86da-45c2f1c2eb5e", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + }, { + "id" : "9071e077-8fe3-4ea4-a2a8-51d8c8929329", + "name" : "bsn", + "description" : "", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "gui.order" : "", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "e9a645fb-f731-43a0-bcca-c0a40070727a", + "name" : "bsn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "bsn", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "bsn", + "jsonType.label" : "String" + } + } ] + } ], + "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins", "acr" ], + "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "referrerPolicy" : "no-referrer", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection" : "1; mode=block", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { }, + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "identityProviders" : [ ], + "identityProviderMappers" : [ ], + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "c47d8d87-0dda-4a91-a778-1ff4953d0c72", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] + } + }, { + "id" : "2e42c404-90e4-4d4f-aae9-5de838dcf012", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "9545949f-87fd-4416-8f3b-a2be3203b43b", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "d7ed32b7-9bc0-4c22-af63-95e605fa571c", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "saml-role-list-mapper", "saml-user-property-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "oidc-full-name-mapper", "oidc-usermodel-property-mapper", "oidc-usermodel-attribute-mapper" ] + } + }, { + "id" : "c6b13ddf-1676-4e33-85d7-c778891156b3", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "28c52629-450d-4e79-a7ba-c4a28d1f9e7c", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "1e4a85fd-6412-470d-9edf-562a8b8021b2", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-address-mapper", "saml-role-list-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper" ] + } + }, { + "id" : "9557d357-cc12-443e-bba6-a89e89b22c2e", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + } ], + "org.keycloak.keys.KeyProvider" : [ { + "id" : "8b83b45b-d80d-49c7-ae04-c3f4618c7514", + "name" : "aes-generated", + "providerId" : "aes-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "d993f461-f278-47ef-8c93-70488711ebfd" ], + "secret" : [ "o3i6s9I3iiVzLyDPxclUkg" ], + "priority" : [ "100" ] + } + }, { + "id" : "4a08d0a0-4d74-4b42-b18a-e06e27fc062b", + "name" : "hmac-generated", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "e715e051-6cdb-48cc-b4f4-f0722c81f9d3" ], + "secret" : [ "sR5n-Ep98RcqFydPbvUYTqdnwIB7742D09yUYMiB-OTsqTzoH5op0_KkVqNy9EYg-ibOR3QkvtcauTyjhaK7uw" ], + "priority" : [ "100" ], + "algorithm" : [ "HS256" ] + } + }, { + "id" : "4d6e8de3-aecf-4209-9922-a890eafa9691", + "name" : "rsa-generated", + "providerId" : "rsa-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEpAIBAAKCAQEA2DOZ0qHie73SuFVR7civrl6r82YUiAghfzaMowjCg0o06AF++2lIS7vNV/PbsVVznPAAMqVrNG+8CcevEzvVZMQD9nH4DI7xlOxK0lrYu8rmMeSfOvXVbBVsWBZe0jnGNukZqjwmRE5//ttJdxPfIBT5+2L6mguQbDfhSUEEdIW7y7UfOXvqLqEcBtoIEB+ORKDTUIQwGZM5mSCy+cY3cHvvZfZVgaUUy5NvujPRXTMje4n/hG0KfEV+40G9qC2/Xvx4EooJzBZ6FSThiWhCpwhIvzcQqB6M9lHW7nU6wADhYPNCa2OKWvphwZ/zbrF4B9dmS6Zli5rBvbox9Hh45wIDAQABAoIBAGshgp7zVbFgWdq6eGr9z0P1qHnnAtR3RvXs91pQHGaHLlkqaJw2yrqwWCu1bA7e23eQG2D9Q/aLSV+FQZUjyHVyhc4oIjRC3qWfQuIiXxQLEe72LQq/xx4ULYgmqZy9QSFzdyK6RHIDffww+CHXyG/yxP5SyP/tLAbb17f/TjBYLMoVcdDmn/wl4UWZMR7ZqFeGOGJWmFpHmeB3HBPU2TyzsTLF9ECgCw298qIKwH0kD3rvGZ+fXPRCX8bLqDkVNL/jDLT5Z/ITGmIUWaBAT/MFoMeuKvOG8NC82edNb7RukoHoXxVgVywbd9Cdlrzu5S0TAgg8qhTlAAx7PuLqyNECgYEA9zqS5smIu1iDwczqYbGxXab3wEVhfAZ/rHa2zB0/tMyZBWJjWlw3jrcNouWnRlxWXoUrcVe/NavKkRBMjlhITZ+nPA7kOQaZIpujulN6euKVgf57zcfhxc4SUeyxYwnOGQFErorP8UnuDYC8rK8tloPVyp3B+sXyZpHOjTtH0RcCgYEA39850L18FfqSN1oDRe01BCJNF0/OM++CFka+OyPkTI7GpmeeEobhY2VsTJuPGMw07uB9OWHOrfsxNbd3R5QO4Rd0svlfBpz8XtUCgWaHV3pNm+zprAf3Fq06Gk3KfO9QMO116fd7RS/RmsFhGIqFGRZ+IP0Tl02mA+ri7wQ3WLECgYAp8Ofm+x2VGskPYaIJfMmoJ6E0HxEQp1GVgnY0XmnmVCdJgI12UNqj/W30ypz8FMIaOuFJ0yb/BevRfEBgjZ2GfaUzTRtuiS4Fbv3xqCPJIRNYAEIkgNpOYk09VLgrIwixuUNbkPUB7BbUd5iKexVyyV7FhsnXrykWOXoe/4WJdQKBgQC03JDG1O50izSpRy0xxwt3xYZmePDsAGkmOgzhloOQXiCau0d3TES2mm++DEa1D/ULr407WIsy/6an8QqKZ1EGBH8hQFnG6/jvXENj60MYJxSgDexSMTUrutMgAQy/lk9A1/bVCD0sjg9WaThaLT6OIB/R4uN67x5aN98SnmNgYQKBgQClIzFFq6Ks2sqxn4PguvL1B4vnqetR4WJc9RvoKp+WAHcJD372B3N4i25n0kv7xyWgYUp25qj1SJL11NTsbiPdFzc4IYBEOwf7/y4l+ZRg2PSF96wZmuQdK3mwzUj9OiYkPUeYd6mtNVbgsCZLrr3Tvgd6NZMSeigFMfESiIpo6w==" ], + "keyUse" : [ "SIG" ], + "certificate" : [ "MIIClzCCAX8CBgGNeYaMLTANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0MB4XDTI0MDIwNTEzNDYxN1oXDTM0MDIwNTEzNDc1N1owDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANgzmdKh4nu90rhVUe3Ir65eq/NmFIgIIX82jKMIwoNKNOgBfvtpSEu7zVfz27FVc5zwADKlazRvvAnHrxM71WTEA/Zx+AyO8ZTsStJa2LvK5jHknzr11WwVbFgWXtI5xjbpGao8JkROf/7bSXcT3yAU+fti+poLkGw34UlBBHSFu8u1Hzl76i6hHAbaCBAfjkSg01CEMBmTOZkgsvnGN3B772X2VYGlFMuTb7oz0V0zI3uJ/4RtCnxFfuNBvagtv178eBKKCcwWehUk4YloQqcISL83EKgejPZR1u51OsAA4WDzQmtjilr6YcGf826xeAfXZkumZYuawb26MfR4eOcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAsnQG/Yi2g1XTCJn74hWv9MjxVAaZb4gBAc2AWm5VgAjhFEM9h6x6m1mQkq7JM4rIdAj8jw55Ok9CBVBIqq4G4cME3eUvVytkj2lC9zcRoAivjjZF2HPg7zNPa2TTR50asmHPRokppV6gewO/C+o5as+4P2zqDXBh61aRd/9kdQfkg14LBbH5/dYccAuvUqlTYC4IEPCvVmBNC1xsMjf0vohvoSjm9vL2bfqG/RJH0ScdCjOd5d2zju4/e2oVdluWm+vzKBQplc7tVMuKpn6LcLmVHiGNAl+EBIZH+WVLlTx0D1+kbHZsfLYG53lQg2LsvurRbWyF/a5fVM/oLTn5ag==" ], + "priority" : [ "100" ] + } + }, { + "id" : "d50865f3-256c-4fe2-b426-f8fe01b21381", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEpAIBAAKCAQEApNvU3ecpVHbJT4bCOEpw6cnV1yi65tB3I0bRF2ilLVOY944QRAGnjBBECPIzNbgqavghYp1j75F2nq6/ny1CYfoaxTV2iDpRUw8/f7sliYbl8FrLLat0S25ItlZrg5TEJHObvOqlG2/nXoeH36MRWwNhms2uCqfhn5VgtenIzpQIBolnM7zzGp21NvdJ1C/ZAUzkXC+l3oQ+BXTtpEVM4h2KpYh4gfZJWCbYij5d1e1YApKD6V61/Cs3Oa2OY7CAUyq5kgAWJZFDB6CpzIr226u3bV7F9RbrQu3Ybc/Lv33EwykscLznKWZY2Mbs3Iz/rFNv3sVX/vHpH4DHWlKu7QIDAQABAoIBAAn84YwiHaBm4/Jj/S9Q3z9iwYhcCNrEBXvHJhLPfbZdyrYwzq54FTEIqT6Lgeu+wR8i8k7ZrzzL6M5bUvOvV8a80tNg1lIRimzITzYLXg5TdGnX7lhRe2W4hEI7wR7DLBDzShurcZ5UbMWO234CkKIdddPdoy41FpfHAoly5P4S48ZYqoEcx3V2g3S7XJ4pz2JE9bCF6c9PAiYWimIW6yJgopqjslMrkFxbyWhQir7tuulGSsLaHvX2wuHlKJ0GqNUQiVAd1xapmTleJstJ0OHFnfxn+2gHqiBc08c1IjNDpDmH/54nA8MQhMR8qMRIBO1OMzu7do5HKiSf25FfRacCgYEA6HUpKuo2k/2SjxSnYaHAozGiXdmCFf6mNuT0sCQdDu5ZxMmS2QLTLeH0BbFIXf98EXfFeqwBcA00PXpfc5Fo7fudxnMl/lVyqN+gGO/Sfo7sM+Ds/iXDvucE+vGpgcLEpMvvnFphs0ScPyE0mbbAbYVukKz5YrUgeL+d+I+Z938CgYEAtY4PKsvgRy1sD5WCZqoCRpoY2H3/MuLxDQUu8EAlU4ALyxBkEmaMAcXx+fIDT0X8ldCEoLcyy7800UdgxRbdKflT/lRTEW4CC/1slYpg1jPkkhYaCpsQG9G92dcAUaJWtCbLG0/9I3KFUOAhozKkvmz4gIyARw9bW28BY5Ym75MCgYEApHkRMb4Z88f8hKQWcivigxVBTqnxMuLEdB63SlGjBcd7WJNPBaDMDrDK2aRAEdIM1McrwMonEkMlbUJCeyCtX4UicyFSBowq3nWrbzlwc/9n/KTuyjuqLk6C5ZNLXfaS8A8jcDs62X54FurFruTxbgx02ISqxz5kxUq+2Pmx9L0CgYEArQtu92qFJTJs+dmWBcZrDuIXZlmJYPYfrTpQh9uL+C9mjjDcQRGOxq3lukbq0qcxXZX2o7yZZMulSweOe6wUNsqXPSUgW8+PkeAFm+7d56xkYr1AKvWq/+kE3FnpyuVBYMpM8oZmD2A7I1/Nj+BYV8xDezrvlUtU1yxRlZrrF5MCgYBUMysubXkyp2nqor+x8VExN0BIlDG+0I4XwcGrI47Sb8bNaVd39XuF4GSnLGxxJ7phSOzmlNGq20ssL6h9b8czq6l5l04q0g6w0IQiWvXiFT5fQ5B2NL3jiC1feqBhXppP6Ew60a0eK7LA+/QqQLvZHkbKW72L//8B/kFACcx69Q==" ], + "keyUse" : [ "ENC" ], + "certificate" : [ "MIIClzCCAX8CBgGNeYaMlzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0MB4XDTI0MDIwNTEzNDYxN1oXDTM0MDIwNTEzNDc1N1owDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKTb1N3nKVR2yU+GwjhKcOnJ1dcouubQdyNG0RdopS1TmPeOEEQBp4wQRAjyMzW4Kmr4IWKdY++Rdp6uv58tQmH6GsU1dog6UVMPP3+7JYmG5fBayy2rdEtuSLZWa4OUxCRzm7zqpRtv516Hh9+jEVsDYZrNrgqn4Z+VYLXpyM6UCAaJZzO88xqdtTb3SdQv2QFM5Fwvpd6EPgV07aRFTOIdiqWIeIH2SVgm2Io+XdXtWAKSg+letfwrNzmtjmOwgFMquZIAFiWRQwegqcyK9turt21exfUW60Lt2G3Py799xMMpLHC85ylmWNjG7NyM/6xTb97FV/7x6R+Ax1pSru0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAQGJHeTYSMvp0yndbIn7DLohO9lom5nRrx/bLyb7TiRfogyJEF6rQZ66CAkQFk5eMF878fsHTuMVjtmXVBnhojhVmK91HwjsNQu/8xR6QMXNKJQMvHR245vwUGxlWRw/36ObM1D7QjCd/q+FonpBEY4m5Y6Uz1U0HR2Cbh0E2afVlPLeV+F0LKrlyVMdIaWBGWftCGIKDAHaG/PD66zbAKtxerv2fBIDq100WHPhd57BZxX+2aGJp1IaRDgkxV0E/CjEy3+Knd8xbAgUSW0Tl6OTC75exIvlbzeluEBe0wlapAb7WvBKYsipSW8G8Ey7tjoolDT4AU82EaKUPstiMnA==" ], + "priority" : [ "100" ], + "algorithm" : [ "RSA-OAEP" ] + } + } ] + }, + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "authenticationFlows" : [ { + "id" : "eade39e3-8a2f-4e07-a459-24085849cc7b", + "alias" : "Account verification options", + "description" : "Method with which to verity the existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-email-verification", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false + } ] + }, { + "id" : "4ba9c174-71c9-4c41-9c4f-c0c0961c2e60", + "alias" : "Browser - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "3c863e05-422e-4048-b5df-8db9f407265c", + "alias" : "Direct Grant - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "195520f1-5683-4d15-8512-722882436cb6", + "alias" : "First broker login - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "ffb0fb4e-a5b3-47d2-a695-b458f0ae98e6", + "alias" : "Handle Existing Account", + "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Account verification options", + "userSetupAllowed" : false + } ] + }, { + "id" : "13083de7-5ca7-4090-a325-fac79ad8974a", + "alias" : "Reset - Conditional OTP", + "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "2c726272-8443-4bb3-aede-e853348de93d", + "alias" : "User creation or linking", + "description" : "Flow for the existing/non-existing user alternatives", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false + } ] + }, { + "id" : "8c368b22-beaf-460f-852c-ed22a9f634e0", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "First broker login - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "a513e259-143c-4ca5-8453-7b40b3adaca2", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "identity-provider-redirector", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 25, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "forms", + "userSetupAllowed" : false + } ] + }, { + "id" : "567fabf9-3a81-4994-82f2-32265b469f0a", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-secret-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-x509", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "9138d835-7470-40b8-bd87-9dea7dddf38b", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "Direct Grant - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "27ebb1ca-e8b7-44ac-b012-8d580a323249", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "1dfada24-8a57-4790-8e9b-537d5325f304", + "alias" : "first broker login", + "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "User creation or linking", + "userSetupAllowed" : false + } ] + }, { + "id" : "abdd8910-0519-418d-9bf6-d74350116737", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "1d657342-0a34-43b2-88a9-de018c0f2f3e", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "registration form", + "userSetupAllowed" : false + } ] + }, { + "id" : "e26131b1-5820-405b-98b5-5dd1ff5d146e", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-password-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-recaptcha-action", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 60, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "d7de4f38-5c54-434b-b429-109bc617d88e", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-credential-email", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 40, + "autheticatorFlow" : true, + "flowAlias" : "Reset - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "8a5af7f0-4be1-4a71-82e6-53b998ab9996", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "ad975f49-59a4-4091-9591-a533e4a9b162", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "id" : "f0a940bd-6086-461e-89c2-18dcebdc8f57", + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + } ], + "requiredActions" : [ { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 10, + "config" : { } + }, { + "alias" : "TERMS_AND_CONDITIONS", + "name" : "Terms and Conditions", + "providerId" : "TERMS_AND_CONDITIONS", + "enabled" : false, + "defaultAction" : false, + "priority" : 20, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : true, + "defaultAction" : false, + "priority" : 30, + "config" : { } + }, { + "alias" : "UPDATE_PROFILE", + "name" : "Update Profile", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 50, + "config" : { } + }, { + "alias" : "delete_account", + "name" : "Delete Account", + "providerId" : "delete_account", + "enabled" : false, + "defaultAction" : false, + "priority" : 60, + "config" : { } + }, { + "alias" : "webauthn-register", + "name" : "Webauthn Register", + "providerId" : "webauthn-register", + "enabled" : true, + "defaultAction" : false, + "priority" : 70, + "config" : { } + }, { + "alias" : "webauthn-register-passwordless", + "name" : "Webauthn Register Passwordless", + "providerId" : "webauthn-register-passwordless", + "enabled" : true, + "defaultAction" : false, + "priority" : 80, + "config" : { } + }, { + "alias" : "update_user_locale", + "name" : "Update User Locale", + "providerId" : "update_user_locale", + "enabled" : true, + "defaultAction" : false, + "priority" : 1000, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "attributes" : { + "cibaBackchannelTokenDeliveryMode" : "poll", + "cibaExpiresIn" : "120", + "cibaAuthRequestedUserHint" : "login_hint", + "oauth2DeviceCodeLifespan" : "600", + "oauth2DevicePollingInterval" : "5", + "parRequestUriLifespan" : "60", + "cibaInterval" : "5", + "realmReusableOtpCode" : "false" + }, + "keycloakVersion" : "23.0.6", + "userManagedAccessAllowed" : false, + "clientProfiles" : { + "profiles" : [ ] + }, + "clientPolicies" : { + "policies" : [ ] + } +} \ No newline at end of file diff --git a/mozilla_django_oidc_db/forms.py b/mozilla_django_oidc_db/forms.py index 0ac041c..f1e8ef0 100644 --- a/mozilla_django_oidc_db/forms.py +++ b/mozilla_django_oidc_db/forms.py @@ -31,6 +31,18 @@ def __init__(self, *args, **kwargs): for endpoint in self.required_endpoints: self.fields[endpoint].required = False + @classmethod + def get_endpoints_from_discovery(cls, base_url: str): + response = requests.get(f"{base_url}{OPEN_ID_CONFIG_PATH}", timeout=10) + response.raise_for_status() + configuration = response.json() + + endpoints = { + model_attr: configuration.get(oidc_attr) + for model_attr, oidc_attr in cls.oidc_mapping.items() + } + return endpoints + def clean(self): cleaned_data = super().clean() @@ -39,13 +51,8 @@ def clean(self): # Derive the endpoints from the discovery endpoint if discovery_endpoint: try: - response = requests.get( - f"{discovery_endpoint}{OPEN_ID_CONFIG_PATH}", timeout=10 - ) - configuration = response.json() - - for model_attr, oidc_attr in self.oidc_mapping.items(): - cleaned_data[model_attr] = configuration.get(oidc_attr) + endpoints = self.get_endpoints_from_discovery(discovery_endpoint) + cleaned_data.update(**endpoints) except ( requests.exceptions.RequestException, json.decoder.JSONDecodeError, diff --git a/setup.cfg b/setup.cfg index 9e5b75e..ad974f0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,7 +40,11 @@ tests_require = psycopg2 pytest pytest-django - requests_mock + pytest-mock + pytest-recording + requests-mock + factory-boy + pyquery tox isort black @@ -50,8 +54,11 @@ tests = psycopg2 pytest pytest-django - requests_mock + pytest-mock + pytest-recording + requests-mock factory-boy + pyquery tox isort black diff --git a/testapp/settings.py b/testapp/settings.py index 03c1323..0c3ed2b 100644 --- a/testapp/settings.py +++ b/testapp/settings.py @@ -8,6 +8,8 @@ SECRET_KEY = "so-secret-i-cant-believe-you-are-looking-at-this" +USE_TZ = True + DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", diff --git a/testapp/urls.py b/testapp/urls.py index d123745..cd5a605 100644 --- a/testapp/urls.py +++ b/testapp/urls.py @@ -2,10 +2,14 @@ from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.urls import include, path -from mozilla_django_oidc_db.views import AdminLoginFailure +from mozilla_django_oidc_db.views import ( + AdminLoginFailure, + OIDCAuthenticationRequestView, +) urlpatterns = [ path("admin/login/failure/", AdminLoginFailure.as_view(), name="admin-oidc-error"), path("admin/", admin.site.urls), + path("login", OIDCAuthenticationRequestView.as_view(), name="login"), path("oidc/", include("mozilla_django_oidc.urls")), ] + staticfiles_urlpatterns() diff --git a/tests/cassettes/test_integration_oidc_flow_variants/test_client_id_secret_full_flow.yaml b/tests/cassettes/test_integration_oidc_flow_variants/test_client_id_secret_full_flow.yaml new file mode 100644 index 0000000..66ab3c6 --- /dev/null +++ b/tests/cassettes/test_integration_oidc_flow_variants/test_client_id_secret_full_flow.yaml @@ -0,0 +1,317 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.31.0 + 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 +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.31.0 + method: GET + uri: http://localhost:8080/realms/test/protocol/openid-connect/auth?response_type=code&scope=openid+email+profile+bsn+kvk&client_id=testid&redirect_uri=http%3A%2F%2Ftestserver%2Foidc%2Fcallback%2F&state=not-a-random-string&nonce=not-a-random-string + response: + body: + string: "\n\n\n\n \n + \ \n \n\n \n Sign + in to test\n \n \n \n \n \n \n \n\n\n\n
\n + \
\n
test
\n
\n
\n + \
\n

+ \ Sign in to your account\n\n

\n
\n
\n + \
\n\n\n
\n + \
\n
\n
\n \n\n \n\n\n
\n\n
\n \n\n
\n + \ \n \n + \
\n\n\n
\n\n
\n
\n + \
\n
\n + \
\n\n
\n\n
\n \n \n
\n + \
\n
\n
\n \n\n\n\n\n\n + \
\n
\n\n
\n
\n\n\n" + headers: + Cache-Control: + - no-store, must-revalidate, max-age=0 + Content-Language: + - en + Content-Security-Policy: + - frame-src 'self'; frame-ancestors 'self'; object-src 'none'; + Content-Type: + - text/html;charset=utf-8 + Referrer-Policy: + - no-referrer + Set-Cookie: + - AUTH_SESSION_ID=674dd4fc-0059-4ba7-89e2-8ff217ea7b0c; Version=1; Path=/realms/test/; + SameSite=None; Secure; HttpOnly + - AUTH_SESSION_ID_LEGACY=674dd4fc-0059-4ba7-89e2-8ff217ea7b0c; Version=1; Path=/realms/test/; + HttpOnly + - KC_RESTART=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlNzE1ZTA1MS02Y2RiLTQ4Y2MtYjRmNC1mMDcyMmM4MWY5ZDMifQ.eyJjaWQiOiJ0ZXN0aWQiLCJwdHkiOiJvcGVuaWQtY29ubmVjdCIsInJ1cmkiOiJodHRwOi8vdGVzdHNlcnZlci9vaWRjL2NhbGxiYWNrLyIsImFjdCI6IkFVVEhFTlRJQ0FURSIsIm5vdGVzIjp7InNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUgYnNuIGt2ayIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9yZWFsbXMvdGVzdCIsInJlc3BvbnNlX3R5cGUiOiJjb2RlIiwicmVkaXJlY3RfdXJpIjoiaHR0cDovL3Rlc3RzZXJ2ZXIvb2lkYy9jYWxsYmFjay8iLCJzdGF0ZSI6Im5vdC1hLXJhbmRvbS1zdHJpbmciLCJub25jZSI6Im5vdC1hLXJhbmRvbS1zdHJpbmcifX0.i8j5h2oK7wCQJD0j4WgiObNnD6QLrcy1MjXZSIiFrD0; + Version=1; Path=/realms/test/; HttpOnly + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Robots-Tag: + - none + X-XSS-Protection: + - 1; mode=block + content-length: + - '4474' + status: + code: 200 + message: OK +- request: + body: username=testuser&password=testuser&credentialId=&login=Sign+In + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '63' + Content-Type: + - application/x-www-form-urlencoded + Cookie: + - AUTH_SESSION_ID_LEGACY=674dd4fc-0059-4ba7-89e2-8ff217ea7b0c; KC_RESTART=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlNzE1ZTA1MS02Y2RiLTQ4Y2MtYjRmNC1mMDcyMmM4MWY5ZDMifQ.eyJjaWQiOiJ0ZXN0aWQiLCJwdHkiOiJvcGVuaWQtY29ubmVjdCIsInJ1cmkiOiJodHRwOi8vdGVzdHNlcnZlci9vaWRjL2NhbGxiYWNrLyIsImFjdCI6IkFVVEhFTlRJQ0FURSIsIm5vdGVzIjp7InNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUgYnNuIGt2ayIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9yZWFsbXMvdGVzdCIsInJlc3BvbnNlX3R5cGUiOiJjb2RlIiwicmVkaXJlY3RfdXJpIjoiaHR0cDovL3Rlc3RzZXJ2ZXIvb2lkYy9jYWxsYmFjay8iLCJzdGF0ZSI6Im5vdC1hLXJhbmRvbS1zdHJpbmciLCJub25jZSI6Im5vdC1hLXJhbmRvbS1zdHJpbmcifX0.i8j5h2oK7wCQJD0j4WgiObNnD6QLrcy1MjXZSIiFrD0 + User-Agent: + - python-requests/2.31.0 + method: POST + uri: http://localhost:8080/realms/test/login-actions/authenticate?session_code=rLH2AG65j0c8gpd50AInl2Uz7UMzjSWCnVSDgEy8rF4&execution=5d476fe6-1c62-4f0a-9d3e-9e1f49df4766&client_id=testid&tab_id=j3RLW9MsPMI + response: + body: + string: '' + headers: + Cache-Control: + - no-store, must-revalidate, max-age=0 + Content-Security-Policy: + - frame-src 'self'; frame-ancestors 'self'; object-src 'none'; + Location: + - http://testserver/oidc/callback/?state=not-a-random-string&session_state=674dd4fc-0059-4ba7-89e2-8ff217ea7b0c&iss=http%3A%2F%2Flocalhost%3A8080%2Frealms%2Ftest&code=02e0de98-7c71-4a23-9ee6-0698e9de4967.674dd4fc-0059-4ba7-89e2-8ff217ea7b0c.adf4ad83-4550-4619-9231-73bd8d700f45 + Referrer-Policy: + - no-referrer + Set-Cookie: + - KEYCLOAK_LOCALE=; Version=1; Comment=Expiring cookie; Expires=Thu, 01-Jan-1970 + 00:00:10 GMT; Max-Age=0; Path=/realms/test/; HttpOnly + - KC_RESTART=; Version=1; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; + Path=/realms/test/; HttpOnly + - KC_AUTH_STATE=; Version=1; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; + Path=/realms/test/ + - KEYCLOAK_IDENTITY=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlNzE1ZTA1MS02Y2RiLTQ4Y2MtYjRmNC1mMDcyMmM4MWY5ZDMifQ.eyJleHAiOjE3MDcxODUxMjUsImlhdCI6MTcwNzE0OTEyNSwianRpIjoiZjQxZjllYmItZjNkNy00ODNkLWFlMmUtODg3N2ZmOTQ3NTliIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0Iiwic3ViIjoiYWExMGNmYzctMmM0ZC00MWY2LThmYWMtN2JmNDA1YzU3MmM0IiwidHlwIjoiU2VyaWFsaXplZC1JRCIsInNlc3Npb25fc3RhdGUiOiI2NzRkZDRmYy0wMDU5LTRiYTctODllMi04ZmYyMTdlYTdiMGMiLCJzaWQiOiI2NzRkZDRmYy0wMDU5LTRiYTctODllMi04ZmYyMTdlYTdiMGMiLCJzdGF0ZV9jaGVja2VyIjoiLXUwT213YkVpUkRFZVZwMnc4ZDAzLTVCSTdneEg2ZGxIbHB6dkN3ZWJHWSJ9.mlG_mCkuaukXT7g_oPhlb-niwWjyCaBSyR8wngLruDA; + Version=1; Path=/realms/test/; SameSite=None; Secure; HttpOnly + - KEYCLOAK_IDENTITY_LEGACY=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlNzE1ZTA1MS02Y2RiLTQ4Y2MtYjRmNC1mMDcyMmM4MWY5ZDMifQ.eyJleHAiOjE3MDcxODUxMjUsImlhdCI6MTcwNzE0OTEyNSwianRpIjoiZjQxZjllYmItZjNkNy00ODNkLWFlMmUtODg3N2ZmOTQ3NTliIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0Iiwic3ViIjoiYWExMGNmYzctMmM0ZC00MWY2LThmYWMtN2JmNDA1YzU3MmM0IiwidHlwIjoiU2VyaWFsaXplZC1JRCIsInNlc3Npb25fc3RhdGUiOiI2NzRkZDRmYy0wMDU5LTRiYTctODllMi04ZmYyMTdlYTdiMGMiLCJzaWQiOiI2NzRkZDRmYy0wMDU5LTRiYTctODllMi04ZmYyMTdlYTdiMGMiLCJzdGF0ZV9jaGVja2VyIjoiLXUwT213YkVpUkRFZVZwMnc4ZDAzLTVCSTdneEg2ZGxIbHB6dkN3ZWJHWSJ9.mlG_mCkuaukXT7g_oPhlb-niwWjyCaBSyR8wngLruDA; + Version=1; Path=/realms/test/; HttpOnly + - KEYCLOAK_SESSION=test/aa10cfc7-2c4d-41f6-8fac-7bf405c572c4/674dd4fc-0059-4ba7-89e2-8ff217ea7b0c; + Version=1; Expires=Tue, 06-Feb-2024 02:05:25 GMT; Max-Age=36000; Path=/realms/test/; + SameSite=None; Secure + - KEYCLOAK_SESSION_LEGACY=test/aa10cfc7-2c4d-41f6-8fac-7bf405c572c4/674dd4fc-0059-4ba7-89e2-8ff217ea7b0c; + Version=1; Expires=Tue, 06-Feb-2024 02:05:25 GMT; Max-Age=36000; Path=/realms/test/ + - KEYCLOAK_REMEMBER_ME=; Version=1; Comment=Expiring cookie; Expires=Thu, 01-Jan-1970 + 00:00:10 GMT; Max-Age=0; Path=/realms/test/; HttpOnly + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Robots-Tag: + - none + X-XSS-Protection: + - 1; mode=block + content-length: + - '0' + status: + code: 302 + message: Found +- request: + body: client_id=testid&client_secret=7DB3KUAAizYCcmZufpHRVOcD0TOkNO3I&grant_type=authorization_code&code=02e0de98-7c71-4a23-9ee6-0698e9de4967.674dd4fc-0059-4ba7-89e2-8ff217ea7b0c.adf4ad83-4550-4619-9231-73bd8d700f45&redirect_uri=http%3A%2F%2Ftestserver%2Foidc%2Fcallback%2F + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '267' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - python-requests/2.31.0 + method: POST + uri: http://localhost:8080/realms/test/protocol/openid-connect/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0VU5RQWN2VWN2LURGVU94XzRPMWd0MTNPZEpTb3RxRUtQWnVyczJ2UVc4In0.eyJleHAiOjE3MDcxNDk0MjUsImlhdCI6MTcwNzE0OTEyNSwiYXV0aF90aW1lIjoxNzA3MTQ5MTI1LCJqdGkiOiIwMjE4ZjZjZS04YjhjLTRmZGQtYTU4NC0yMGFlMzc1ZDM5OTciLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiYWExMGNmYzctMmM0ZC00MWY2LThmYWMtN2JmNDA1YzU3MmM0IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGVzdGlkIiwibm9uY2UiOiJub3QtYS1yYW5kb20tc3RyaW5nIiwic2Vzc2lvbl9zdGF0ZSI6IjY3NGRkNGZjLTAwNTktNGJhNy04OWUyLThmZjIxN2VhN2IwYyIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovLzEyNy4wLjAuMTo4MDAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLXRlc3QiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSBrdmsgYnNuIiwic2lkIjoiNjc0ZGQ0ZmMtMDA1OS00YmE3LTg5ZTItOGZmMjE3ZWE3YjBjIiwia3ZrIjoiMDEyMzQ1Njc4IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0dXNlciIsImJzbiI6IjAwMDAwMDAwMCJ9.yEGjsexg2SkTqSEwl3YFjJJqURAy68xyIKD9WUji8p8GwxBiNyE1hM9ADJPx--VJyeMdFv26Q67tY8J6jrGKtBZpKneooUrAWGUuoxcfY3PoyJDtndOUfQmWsiiVfSFPNpz7kvGraXxYfY0C3St-XGCJPgaue3EgFMC7Fg1jru3BN2_H0TvdccymRX9rD-eUZUBWCAqcuZHoxjMFovDy1t25hxQPQ89GbJ-MUtDamAQVJKkX1v9wx_J2igK6TffKUrS2QjttqvTzcaHC_Mbr2TUfZyLmCTFxLZo_Ag_9KihZCWp6gk-wrAtEjpeC9xFu-Wfo29IlbV0bkX7kB3uVpQ","expires_in":300,"refresh_expires_in":1800,"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlNzE1ZTA1MS02Y2RiLTQ4Y2MtYjRmNC1mMDcyMmM4MWY5ZDMifQ.eyJleHAiOjE3MDcxNTA5MjUsImlhdCI6MTcwNzE0OTEyNSwianRpIjoiMGNkMjgxZjAtMTE2NS00NmFhLTkzZGMtM2ZmMDRlOGQ0ZDM0IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0IiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0Iiwic3ViIjoiYWExMGNmYzctMmM0ZC00MWY2LThmYWMtN2JmNDA1YzU3MmM0IiwidHlwIjoiUmVmcmVzaCIsImF6cCI6InRlc3RpZCIsIm5vbmNlIjoibm90LWEtcmFuZG9tLXN0cmluZyIsInNlc3Npb25fc3RhdGUiOiI2NzRkZDRmYy0wMDU5LTRiYTctODllMi04ZmYyMTdlYTdiMGMiLCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIGt2ayBic24iLCJzaWQiOiI2NzRkZDRmYy0wMDU5LTRiYTctODllMi04ZmYyMTdlYTdiMGMifQ.aQKED3CEH9budF7ASiCrsEsIfHxnmZHyZgrsBCPO3o8","token_type":"Bearer","id_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0VU5RQWN2VWN2LURGVU94XzRPMWd0MTNPZEpTb3RxRUtQWnVyczJ2UVc4In0.eyJleHAiOjE3MDcxNDk0MjUsImlhdCI6MTcwNzE0OTEyNSwiYXV0aF90aW1lIjoxNzA3MTQ5MTI1LCJqdGkiOiJkMzkyMDliOC03ZjM2LTQyNTYtYTQwNS1lZGI1M2ZjZDc4MGEiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QiLCJhdWQiOiJ0ZXN0aWQiLCJzdWIiOiJhYTEwY2ZjNy0yYzRkLTQxZjYtOGZhYy03YmY0MDVjNTcyYzQiLCJ0eXAiOiJJRCIsImF6cCI6InRlc3RpZCIsIm5vbmNlIjoibm90LWEtcmFuZG9tLXN0cmluZyIsInNlc3Npb25fc3RhdGUiOiI2NzRkZDRmYy0wMDU5LTRiYTctODllMi04ZmYyMTdlYTdiMGMiLCJhdF9oYXNoIjoiUXoxS2ZzbmdOOGJpR3ptTjhOSjNOQSIsImFjciI6IjEiLCJzaWQiOiI2NzRkZDRmYy0wMDU5LTRiYTctODllMi04ZmYyMTdlYTdiMGMiLCJrdmsiOiIwMTIzNDU2NzgiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InRlc3R1c2VyIiwiYnNuIjoiMDAwMDAwMDAwIn0.dwBzOCXUMKuEpcD38anNEbkkgtfHum3mvfcwKGMEUiH_4sArV6tyXGu0QWBeKhZwiWjLjBomMZcDGAtSS98FvVvEtOUcekfKlNH0hVHhQJxquVa3EiQka6JtoBYdkwFN7Yzxmen9gA8RKAC0hhb0S_Z6I-Ws_ckPuy6-dOYUg5aPNBZ-y4SuNJM0scwGQ0Sa8XmWPK08bpXjkwrFebRtizEVS9y6I4USiTElBdQkS0o8fPValakUsGflEY0OpNJ7omzmo6XxgCk7XxYCPAih3d8xk5XF10JmHlT6LMsxygy1OK5qbOodH7kANOy16tdciNMvkpC111YHtbqizuXdrA","not-before-policy":0,"session_state":"674dd4fc-0059-4ba7-89e2-8ff217ea7b0c","scope":"openid + email profile kvk bsn"}' + headers: + Cache-Control: + - no-store + Content-Type: + - application/json + Pragma: + - no-cache + 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: + - '3475' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.31.0 + method: GET + uri: http://localhost:8080/realms/test/protocol/openid-connect/certs + response: + body: + string: '{"keys":[{"kid":"4UNQAcvUcv-DFUOx_4O1gt13OdJSotqEKPZurs2vQW8","kty":"RSA","alg":"RS256","use":"sig","n":"2DOZ0qHie73SuFVR7civrl6r82YUiAghfzaMowjCg0o06AF--2lIS7vNV_PbsVVznPAAMqVrNG-8CcevEzvVZMQD9nH4DI7xlOxK0lrYu8rmMeSfOvXVbBVsWBZe0jnGNukZqjwmRE5__ttJdxPfIBT5-2L6mguQbDfhSUEEdIW7y7UfOXvqLqEcBtoIEB-ORKDTUIQwGZM5mSCy-cY3cHvvZfZVgaUUy5NvujPRXTMje4n_hG0KfEV-40G9qC2_Xvx4EooJzBZ6FSThiWhCpwhIvzcQqB6M9lHW7nU6wADhYPNCa2OKWvphwZ_zbrF4B9dmS6Zli5rBvbox9Hh45w","e":"AQAB","x5c":["MIIClzCCAX8CBgGNeYaMLTANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0MB4XDTI0MDIwNTEzNDYxN1oXDTM0MDIwNTEzNDc1N1owDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANgzmdKh4nu90rhVUe3Ir65eq/NmFIgIIX82jKMIwoNKNOgBfvtpSEu7zVfz27FVc5zwADKlazRvvAnHrxM71WTEA/Zx+AyO8ZTsStJa2LvK5jHknzr11WwVbFgWXtI5xjbpGao8JkROf/7bSXcT3yAU+fti+poLkGw34UlBBHSFu8u1Hzl76i6hHAbaCBAfjkSg01CEMBmTOZkgsvnGN3B772X2VYGlFMuTb7oz0V0zI3uJ/4RtCnxFfuNBvagtv178eBKKCcwWehUk4YloQqcISL83EKgejPZR1u51OsAA4WDzQmtjilr6YcGf826xeAfXZkumZYuawb26MfR4eOcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAsnQG/Yi2g1XTCJn74hWv9MjxVAaZb4gBAc2AWm5VgAjhFEM9h6x6m1mQkq7JM4rIdAj8jw55Ok9CBVBIqq4G4cME3eUvVytkj2lC9zcRoAivjjZF2HPg7zNPa2TTR50asmHPRokppV6gewO/C+o5as+4P2zqDXBh61aRd/9kdQfkg14LBbH5/dYccAuvUqlTYC4IEPCvVmBNC1xsMjf0vohvoSjm9vL2bfqG/RJH0ScdCjOd5d2zju4/e2oVdluWm+vzKBQplc7tVMuKpn6LcLmVHiGNAl+EBIZH+WVLlTx0D1+kbHZsfLYG53lQg2LsvurRbWyF/a5fVM/oLTn5ag=="],"x5t":"H5xfs1pRtvX0HyVTskx7eTXx88U","x5t#S256":"XurVtKAIEyc4w9HCGOhnjoRHnYu4d9HCn_5YHmkScJg"},{"kid":"TV3Tl5jIY1nrJLSb53UKEubLR5gYiq9slq1SsDDg1HU","kty":"RSA","alg":"RSA-OAEP","use":"enc","n":"pNvU3ecpVHbJT4bCOEpw6cnV1yi65tB3I0bRF2ilLVOY944QRAGnjBBECPIzNbgqavghYp1j75F2nq6_ny1CYfoaxTV2iDpRUw8_f7sliYbl8FrLLat0S25ItlZrg5TEJHObvOqlG2_nXoeH36MRWwNhms2uCqfhn5VgtenIzpQIBolnM7zzGp21NvdJ1C_ZAUzkXC-l3oQ-BXTtpEVM4h2KpYh4gfZJWCbYij5d1e1YApKD6V61_Cs3Oa2OY7CAUyq5kgAWJZFDB6CpzIr226u3bV7F9RbrQu3Ybc_Lv33EwykscLznKWZY2Mbs3Iz_rFNv3sVX_vHpH4DHWlKu7Q","e":"AQAB","x5c":["MIIClzCCAX8CBgGNeYaMlzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0MB4XDTI0MDIwNTEzNDYxN1oXDTM0MDIwNTEzNDc1N1owDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKTb1N3nKVR2yU+GwjhKcOnJ1dcouubQdyNG0RdopS1TmPeOEEQBp4wQRAjyMzW4Kmr4IWKdY++Rdp6uv58tQmH6GsU1dog6UVMPP3+7JYmG5fBayy2rdEtuSLZWa4OUxCRzm7zqpRtv516Hh9+jEVsDYZrNrgqn4Z+VYLXpyM6UCAaJZzO88xqdtTb3SdQv2QFM5Fwvpd6EPgV07aRFTOIdiqWIeIH2SVgm2Io+XdXtWAKSg+letfwrNzmtjmOwgFMquZIAFiWRQwegqcyK9turt21exfUW60Lt2G3Py799xMMpLHC85ylmWNjG7NyM/6xTb97FV/7x6R+Ax1pSru0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAQGJHeTYSMvp0yndbIn7DLohO9lom5nRrx/bLyb7TiRfogyJEF6rQZ66CAkQFk5eMF878fsHTuMVjtmXVBnhojhVmK91HwjsNQu/8xR6QMXNKJQMvHR245vwUGxlWRw/36ObM1D7QjCd/q+FonpBEY4m5Y6Uz1U0HR2Cbh0E2afVlPLeV+F0LKrlyVMdIaWBGWftCGIKDAHaG/PD66zbAKtxerv2fBIDq100WHPhd57BZxX+2aGJp1IaRDgkxV0E/CjEy3+Knd8xbAgUSW0Tl6OTC75exIvlbzeluEBe0wlapAb7WvBKYsipSW8G8Ey7tjoolDT4AU82EaKUPstiMnA=="],"x5t":"AlfHDI0FOPQpt3RBAILt0dtW1yw","x5t#S256":"a7bhm8-JsnfY7bL_m8Yl72hgmp5516VZlFcVloKzk08"}]}' + headers: + Cache-Control: + - no-cache + 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: + - '2909' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Authorization: + - Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0VU5RQWN2VWN2LURGVU94XzRPMWd0MTNPZEpTb3RxRUtQWnVyczJ2UVc4In0.eyJleHAiOjE3MDcxNDk0MjUsImlhdCI6MTcwNzE0OTEyNSwiYXV0aF90aW1lIjoxNzA3MTQ5MTI1LCJqdGkiOiIwMjE4ZjZjZS04YjhjLTRmZGQtYTU4NC0yMGFlMzc1ZDM5OTciLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiYWExMGNmYzctMmM0ZC00MWY2LThmYWMtN2JmNDA1YzU3MmM0IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGVzdGlkIiwibm9uY2UiOiJub3QtYS1yYW5kb20tc3RyaW5nIiwic2Vzc2lvbl9zdGF0ZSI6IjY3NGRkNGZjLTAwNTktNGJhNy04OWUyLThmZjIxN2VhN2IwYyIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovLzEyNy4wLjAuMTo4MDAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLXRlc3QiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSBrdmsgYnNuIiwic2lkIjoiNjc0ZGQ0ZmMtMDA1OS00YmE3LTg5ZTItOGZmMjE3ZWE3YjBjIiwia3ZrIjoiMDEyMzQ1Njc4IiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0dXNlciIsImJzbiI6IjAwMDAwMDAwMCJ9.yEGjsexg2SkTqSEwl3YFjJJqURAy68xyIKD9WUji8p8GwxBiNyE1hM9ADJPx--VJyeMdFv26Q67tY8J6jrGKtBZpKneooUrAWGUuoxcfY3PoyJDtndOUfQmWsiiVfSFPNpz7kvGraXxYfY0C3St-XGCJPgaue3EgFMC7Fg1jru3BN2_H0TvdccymRX9rD-eUZUBWCAqcuZHoxjMFovDy1t25hxQPQ89GbJ-MUtDamAQVJKkX1v9wx_J2igK6TffKUrS2QjttqvTzcaHC_Mbr2TUfZyLmCTFxLZo_Ag_9KihZCWp6gk-wrAtEjpeC9xFu-Wfo29IlbV0bkX7kB3uVpQ + Connection: + - keep-alive + User-Agent: + - python-requests/2.31.0 + method: GET + uri: http://localhost:8080/realms/test/protocol/openid-connect/userinfo + response: + body: + string: '{"sub":"aa10cfc7-2c4d-41f6-8fac-7bf405c572c4","kvk":"012345678","email_verified":false,"preferred_username":"testuser","bsn":"000000000"}' + headers: + Cache-Control: + - no-cache + Content-Type: + - application/json + 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: + - '137' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/conftest.py b/tests/conftest.py index 3e3adab..f2f4161 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,51 @@ -# import pytest +import pytest +from mozilla_django_oidc_db.forms import OpenIDConnectConfigForm +from mozilla_django_oidc_db.models import OpenIDConnectConfig, get_default_scopes -# @pytest.fixture -# def some_fixture(request): -# return "foo" +KEYCLOAK_BASE_URL = "http://localhost:8080/realms/test/" + + +@pytest.fixture +def mock_state_and_nonce(mocker): + mocker.patch( + "mozilla_django_oidc.views.get_random_string", + return_value="not-a-random-string", + ) + + +@pytest.fixture +def keycloak_config(db): + """ + Keycloak configuration for the provided docker-compose.yml setup. + + This install a configuration (solo model) configured with the appropriate + credentials. + + When not using VCR cassettes, make sure the service is up and running: + + .. code-block:: console + + docker-compose up -d + + """ + endpoints = OpenIDConnectConfigForm.get_endpoints_from_discovery(KEYCLOAK_BASE_URL) + + config, _ = OpenIDConnectConfig.objects.update_or_create( + pk=OpenIDConnectConfig.singleton_instance_id, + defaults={ + "enabled": True, + "oidc_rp_client_id": "testid", + "oidc_rp_client_secret": "7DB3KUAAizYCcmZufpHRVOcD0TOkNO3I", + "oidc_rp_sign_algo": "RS256", + **endpoints, + "oidc_rp_scopes_list": get_default_scopes() + ["bsn", "kvk"], + "sync_groups": False, + }, + ) + # in case caching is setup, ensure that it is invalidated + config.save() + + yield + + OpenIDConnectConfig.clear_cache() diff --git a/tests/test_admin_form.py b/tests/test_admin_form.py index fb15766..f44310d 100644 --- a/tests/test_admin_form.py +++ b/tests/test_admin_form.py @@ -5,12 +5,10 @@ import pytest import requests_mock -from requests import Response from requests.exceptions import RequestException from mozilla_django_oidc_db.forms import OpenIDConnectConfigForm from mozilla_django_oidc_db.models import ( - OpenIDConnectConfig, UserInformationClaimsSources, get_claim_mapping, ) diff --git a/tests/test_integration_oidc_flow_variants.py b/tests/test_integration_oidc_flow_variants.py new file mode 100644 index 0000000..7c074e4 --- /dev/null +++ b/tests/test_integration_oidc_flow_variants.py @@ -0,0 +1,40 @@ +from django.urls import reverse + +import pytest + +from .utils import keycloak_login + +KEYCLOAK_BASE_URL = "http://localhost:8080/realms/test/" + + +@pytest.mark.vcr +def test_client_id_secret_full_flow( + keycloak_config, mock_state_and_nonce, client, django_user_model, vcr +): + login_url = reverse("login") + django_login_response = client.get(login_url) + assert django_login_response.status_code, 302 + + # simulate login to Keycloak + redirect_uri = keycloak_login(django_login_response["Location"]) + + # complete the login flow on our end + callback_response = client.get(redirect_uri) + + assert callback_response.status_code == 302 + assert callback_response["Location"] == "/admin/" + + # a user was created + assert django_user_model.objects.count() == 1 + + # check that the token request was performed as expected + token_request = next( + req + for req in vcr.requests + if req.uri == f"{KEYCLOAK_BASE_URL}protocol/openid-connect/token" + and req.method == "POST" + ) + assert token_request is not None + assert b"client_id=testid" in token_request.body + assert b"secret=7DB3KUAAizYCcmZufpHRVOcD0TOkNO3I" in token_request.body + assert "Authorization" not in token_request.headers diff --git a/tests/test_views.py b/tests/test_views.py index 62d493f..c0e3f0c 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,7 +1,6 @@ from unittest.mock import patch from django.contrib.auth import get_user_model -from django.core.exceptions import ValidationError from django.db import IntegrityError from django.test import TestCase from django.urls import reverse diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..dc1d30f --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,45 @@ +from pyquery import PyQuery as pq +from requests import Session + + +def keycloak_login( + login_url: str, + username: str = "testuser", + password: str = "testuser", +) -> str: + """ + Test helper to perform a keycloak login. + + :param login_url: A login URL for keycloak with all query string parameters. E.g. + `client.get(reverse("login"))["Location"]`. + :returns: The redirect URI to consume in the django application, with the ``code`` + ``state`` query parameters. Consume this with ``response = client.get(url)``. + """ + + with Session() as session: + login_page = session.get(login_url) + assert login_page.status_code == 200 + + # process keycloak's login form and submit the username + password to + # authenticate + document = pq(login_page.text) + login_form = document("form#kc-form-login") + submit_url = login_form.attr("action") + assert isinstance(submit_url, str) + login_response = session.post( + submit_url, + data={ + "username": username, + "password": password, + "credentialId": "", + "login": "Sign In", + }, + allow_redirects=False, + ) + + assert login_response.status_code == 302 + assert (redirect_uri := login_response.headers["Location"]).startswith( + "http://testserver/" + ) + + return redirect_uri