[
  {
    "path": ".gitignore",
    "content": "target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\nnbproject/private/\nbuild/\nnbbuild/\ndist/\nnbdist/\n.nb-gradle/"
  },
  {
    "path": ".mvn/wrapper/maven-wrapper.properties",
    "content": "distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip\n"
  },
  {
    "path": "demo-realm.json",
    "content": "{\n  \"id\" : \"demo\",\n  \"realm\" : \"demo\",\n  \"notBefore\" : 0,\n  \"revokeRefreshToken\" : false,\n  \"refreshTokenMaxReuse\" : 0,\n  \"accessTokenLifespan\" : 300,\n  \"accessTokenLifespanForImplicitFlow\" : 900,\n  \"ssoSessionIdleTimeout\" : 1800,\n  \"ssoSessionMaxLifespan\" : 36000,\n  \"offlineSessionIdleTimeout\" : 2592000,\n  \"accessCodeLifespan\" : 60,\n  \"accessCodeLifespanUserAction\" : 300,\n  \"accessCodeLifespanLogin\" : 1800,\n  \"actionTokenGeneratedByAdminLifespan\" : 43200,\n  \"actionTokenGeneratedByUserLifespan\" : 300,\n  \"enabled\" : true,\n  \"sslRequired\" : \"external\",\n  \"registrationAllowed\" : false,\n  \"registrationEmailAsUsername\" : false,\n  \"rememberMe\" : false,\n  \"verifyEmail\" : false,\n  \"loginWithEmailAllowed\" : true,\n  \"duplicateEmailsAllowed\" : false,\n  \"resetPasswordAllowed\" : false,\n  \"editUsernameAllowed\" : false,\n  \"bruteForceProtected\" : false,\n  \"permanentLockout\" : false,\n  \"maxFailureWaitSeconds\" : 900,\n  \"minimumQuickLoginWaitSeconds\" : 60,\n  \"waitIncrementSeconds\" : 60,\n  \"quickLoginCheckMilliSeconds\" : 1000,\n  \"maxDeltaTimeSeconds\" : 43200,\n  \"failureFactor\" : 30,\n  \"roles\" : {\n    \"realm\" : [ {\n      \"id\" : \"9cec708f-b60c-4e72-87bd-bd6cc270804f\",\n      \"name\" : \"offline_access\",\n      \"description\" : \"${role_offline-access}\",\n      \"scopeParamRequired\" : true,\n      \"composite\" : false,\n      \"clientRole\" : false,\n      \"containerId\" : \"demo\"\n    }, {\n      \"id\" : \"b377ec00-d24e-481c-88d1-fc236fcbb4f8\",\n      \"name\" : \"uma_authorization\",\n      \"description\" : \"${role_uma_authorization}\",\n      \"scopeParamRequired\" : false,\n      \"composite\" : false,\n      \"clientRole\" : false,\n      \"containerId\" : \"demo\"\n    } ],\n    \"client\" : {\n      \"realm-management\" : [ {\n        \"id\" : \"e20d8308-6e6e-4814-8b6c-f31e429d83d8\",\n        \"name\" : \"query-clients\",\n        \"description\" : \"${role_query-clients}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"b64456f6-a12d-455d-8f91-5b2a508d1326\",\n        \"name\" : \"view-identity-providers\",\n        \"description\" : \"${role_view-identity-providers}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"968aa5a6-220f-4c73-a1d9-d1eb4b3f7f20\",\n        \"name\" : \"query-groups\",\n        \"description\" : \"${role_query-groups}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"54db3285-f76c-462f-9dea-3f0da29a8277\",\n        \"name\" : \"view-events\",\n        \"description\" : \"${role_view-events}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"f63004bf-394b-426f-b609-19ca807f3a57\",\n        \"name\" : \"manage-users\",\n        \"description\" : \"${role_manage-users}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"273b678a-2018-4480-9007-b0b5d318019e\",\n        \"name\" : \"query-users\",\n        \"description\" : \"${role_query-users}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"b0bcfe2c-e426-4cc8-8161-f6608203409b\",\n        \"name\" : \"view-users\",\n        \"description\" : \"${role_view-users}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : true,\n        \"composites\" : {\n          \"client\" : {\n            \"realm-management\" : [ \"query-groups\", \"query-users\" ]\n          }\n        },\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"4f2d2465-9e75-4975-8748-ec2bbb2f1b96\",\n        \"name\" : \"query-realms\",\n        \"description\" : \"${role_query-realms}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"65c72650-d874-4a6b-a065-4558a3e2fc6a\",\n        \"name\" : \"create-client\",\n        \"description\" : \"${role_create-client}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"a56996bc-9589-476b-9e54-88b5e6355fca\",\n        \"name\" : \"manage-clients\",\n        \"description\" : \"${role_manage-clients}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"6e8e2d8d-1632-4893-8428-3ec4c438bead\",\n        \"name\" : \"view-clients\",\n        \"description\" : \"${role_view-clients}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : true,\n        \"composites\" : {\n          \"client\" : {\n            \"realm-management\" : [ \"query-clients\" ]\n          }\n        },\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"25c953c3-a411-4237-8501-7b8ebef5988f\",\n        \"name\" : \"manage-realm\",\n        \"description\" : \"${role_manage-realm}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"dc1a53ec-d0e1-441f-8e72-8ca411ab21a0\",\n        \"name\" : \"view-authorization\",\n        \"description\" : \"${role_view-authorization}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"30bbf430-98a6-46d5-a25c-48992aebd848\",\n        \"name\" : \"realm-admin\",\n        \"description\" : \"${role_realm-admin}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : true,\n        \"composites\" : {\n          \"client\" : {\n            \"realm-management\" : [ \"query-clients\", \"query-groups\", \"view-identity-providers\", \"view-events\", \"manage-users\", \"query-users\", \"query-realms\", \"view-users\", \"create-client\", \"manage-clients\", \"view-clients\", \"manage-realm\", \"view-authorization\", \"manage-events\", \"impersonation\", \"manage-authorization\", \"view-realm\", \"manage-identity-providers\" ]\n          }\n        },\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"2f93f784-ece8-4205-a9c2-b933b6beee09\",\n        \"name\" : \"manage-events\",\n        \"description\" : \"${role_manage-events}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"eb6ab687-958a-4c24-a97d-569e31101c41\",\n        \"name\" : \"manage-authorization\",\n        \"description\" : \"${role_manage-authorization}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"e4d149d9-5c8e-4f1c-9a40-ac371aaf3794\",\n        \"name\" : \"impersonation\",\n        \"description\" : \"${role_impersonation}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"3f9d491f-7df0-4f91-ab0d-5f5531b41f9d\",\n        \"name\" : \"view-realm\",\n        \"description\" : \"${role_view-realm}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      }, {\n        \"id\" : \"11ba2522-4090-431b-9842-0e9f31884d0a\",\n        \"name\" : \"manage-identity-providers\",\n        \"description\" : \"${role_manage-identity-providers}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\"\n      } ],\n      \"security-admin-console\" : [ ],\n      \"admin-cli\" : [ ],\n      \"app-demo\" : [ {\n        \"id\" : \"57b84603-ceef-4a48-bd08-f46467eb7bd9\",\n        \"name\" : \"admin\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"ec2975dc-bde7-4012-89c4-06a499c00235\"\n      }, {\n        \"id\" : \"754c1364-9444-4477-bcc1-b07794bee2fc\",\n        \"name\" : \"user\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"ec2975dc-bde7-4012-89c4-06a499c00235\"\n      } ],\n      \"broker\" : [ {\n        \"id\" : \"f08f6cf6-09ed-41f6-9c05-164dc8f8ab5e\",\n        \"name\" : \"read-token\",\n        \"description\" : \"${role_read-token}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"0536d12c-2c36-444a-898b-ed7b527aac76\"\n      } ],\n      \"account\" : [ {\n        \"id\" : \"c4cf29c5-3375-45d1-acd2-5962af1c733a\",\n        \"name\" : \"manage-account\",\n        \"description\" : \"${role_manage-account}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : true,\n        \"composites\" : {\n          \"client\" : {\n            \"account\" : [ \"manage-account-links\" ]\n          }\n        },\n        \"clientRole\" : true,\n        \"containerId\" : \"2e441b12-8370-49b8-b8aa-2c7546144b4e\"\n      }, {\n        \"id\" : \"5d703753-792e-4167-ad2b-c5b7f6a959d7\",\n        \"name\" : \"view-profile\",\n        \"description\" : \"${role_view-profile}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"2e441b12-8370-49b8-b8aa-2c7546144b4e\"\n      }, {\n        \"id\" : \"8eb0ae88-2819-47ab-9a93-6ff34b43ae88\",\n        \"name\" : \"manage-account-links\",\n        \"description\" : \"${role_manage-account-links}\",\n        \"scopeParamRequired\" : false,\n        \"composite\" : false,\n        \"clientRole\" : true,\n        \"containerId\" : \"2e441b12-8370-49b8-b8aa-2c7546144b4e\"\n      } ]\n    }\n  },\n  \"groups\" : [ ],\n  \"defaultRoles\" : [ \"offline_access\", \"uma_authorization\" ],\n  \"requiredCredentials\" : [ \"password\" ],\n  \"otpPolicyType\" : \"totp\",\n  \"otpPolicyAlgorithm\" : \"HmacSHA1\",\n  \"otpPolicyInitialCounter\" : 0,\n  \"otpPolicyDigits\" : 6,\n  \"otpPolicyLookAheadWindow\" : 1,\n  \"otpPolicyPeriod\" : 30,\n  \"otpSupportedApplications\" : [ \"FreeOTP\", \"Google Authenticator\" ],\n  \"users\" : [ {\n    \"id\" : \"8d7a7207-94c0-4ba7-ac3a-efb79412dd44\",\n    \"createdTimestamp\" : 1523988975613,\n    \"username\" : \"admin\",\n    \"enabled\" : true,\n    \"totp\" : false,\n    \"emailVerified\" : false,\n    \"firstName\" : \"Arno\",\n    \"lastName\" : \"Admin\",\n    \"email\" : \"tom+admin@localhost\",\n    \"credentials\" : [ {\n      \"type\" : \"password\",\n      \"hashedSaltedValue\" : \"ZcC45qA9JiFQYuJau1w/pxfBmZusDDoCO0Sx4z+uFWdE4CA1FUibOqpqHh21GwRKcdRSseqrBBaaPbBznIWYRQ==\",\n      \"salt\" : \"sTMbn/fDpC/KX549o9XoHg==\",\n      \"hashIterations\" : 27500,\n      \"counter\" : 0,\n      \"algorithm\" : \"pbkdf2-sha256\",\n      \"digits\" : 0,\n      \"period\" : 0,\n      \"createdDate\" : 1523988982527,\n      \"config\" : { }\n    } ],\n    \"disableableCredentialTypes\" : [ \"password\" ],\n    \"requiredActions\" : [ ],\n    \"realmRoles\" : [ \"offline_access\", \"uma_authorization\" ],\n    \"clientRoles\" : {\n      \"app-demo\" : [ \"admin\", \"user\" ],\n      \"account\" : [ \"manage-account\", \"view-profile\" ]\n    },\n    \"notBefore\" : 0,\n    \"groups\" : [ ]\n  }, {\n    \"id\" : \"91591318-6c82-4250-b6fb-9a5e257959a5\",\n    \"createdTimestamp\" : 1523983635756,\n    \"username\" : \"tester\",\n    \"enabled\" : true,\n    \"totp\" : false,\n    \"emailVerified\" : false,\n    \"firstName\" : \"Theo\",\n    \"lastName\" : \"Tester\",\n    \"email\" : \"tom+test@localhost\",\n    \"credentials\" : [ {\n      \"type\" : \"password\",\n      \"hashedSaltedValue\" : \"h/aCiQS3fdB/euTSwOz/ww/+L0b6c9WGsRsMMSPr899rQIFLlIhjWjAgA9BbRAKsSLfo+nsNUKaXGfhwgi2r7g==\",\n      \"salt\" : \"W3mOjqoG8mctglGSgbYSKQ==\",\n      \"hashIterations\" : 27500,\n      \"counter\" : 0,\n      \"algorithm\" : \"pbkdf2-sha256\",\n      \"digits\" : 0,\n      \"period\" : 0,\n      \"createdDate\" : 1523983645059,\n      \"config\" : { }\n    } ],\n    \"disableableCredentialTypes\" : [ \"password\" ],\n    \"requiredActions\" : [ ],\n    \"realmRoles\" : [ \"offline_access\", \"uma_authorization\" ],\n    \"clientRoles\" : {\n      \"app-demo\" : [ \"user\" ],\n      \"account\" : [ \"manage-account\", \"view-profile\" ]\n    },\n    \"notBefore\" : 0,\n    \"groups\" : [ ]\n  } ],\n  \"clients\" : [ {\n    \"id\" : \"2e441b12-8370-49b8-b8aa-2c7546144b4e\",\n    \"clientId\" : \"account\",\n    \"name\" : \"${client_account}\",\n    \"baseUrl\" : \"/auth/realms/demo/account\",\n    \"surrogateAuthRequired\" : false,\n    \"enabled\" : true,\n    \"clientAuthenticatorType\" : \"client-secret\",\n    \"secret\" : \"85e4ed69-3da1-4d34-ba4e-31980b4b386d\",\n    \"defaultRoles\" : [ \"view-profile\", \"manage-account\" ],\n    \"redirectUris\" : [ \"/auth/realms/demo/account/*\" ],\n    \"webOrigins\" : [ ],\n    \"notBefore\" : 0,\n    \"bearerOnly\" : false,\n    \"consentRequired\" : false,\n    \"standardFlowEnabled\" : true,\n    \"implicitFlowEnabled\" : false,\n    \"directAccessGrantsEnabled\" : false,\n    \"serviceAccountsEnabled\" : false,\n    \"publicClient\" : false,\n    \"frontchannelLogout\" : false,\n    \"protocol\" : \"openid-connect\",\n    \"attributes\" : { },\n    \"fullScopeAllowed\" : false,\n    \"nodeReRegistrationTimeout\" : 0,\n    \"protocolMappers\" : [ {\n      \"id\" : \"61173bf1-f182-4c08-81f1-45ded5285a96\",\n      \"name\" : \"given name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${givenName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"firstName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"given_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"3fc7edb3-23e1-4211-9a71-61700c849841\",\n      \"name\" : \"family name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${familyName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"lastName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"family_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"33bcaadd-4cae-44fd-8f53-cfbb9b1804a3\",\n      \"name\" : \"email\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${email}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"email\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"email\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"b7ea4f28-5d0c-4ec3-b03f-bef776943c65\",\n      \"name\" : \"username\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${username}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"username\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"preferred_username\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"493cb2a0-3b7d-46de-9aa4-e9b36e9b75c5\",\n      \"name\" : \"role list\",\n      \"protocol\" : \"saml\",\n      \"protocolMapper\" : \"saml-role-list-mapper\",\n      \"consentRequired\" : false,\n      \"config\" : {\n        \"single\" : \"false\",\n        \"attribute.nameformat\" : \"Basic\",\n        \"attribute.name\" : \"Role\"\n      }\n    }, {\n      \"id\" : \"f2e9d26c-4703-4fac-b5d5-cbbb8cbf9fbc\",\n      \"name\" : \"full name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-full-name-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${fullName}\",\n      \"config\" : {\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\"\n      }\n    } ],\n    \"useTemplateConfig\" : false,\n    \"useTemplateScope\" : false,\n    \"useTemplateMappers\" : false\n  }, {\n    \"id\" : \"c0d68b59-146c-462e-910d-eae82c190c61\",\n    \"clientId\" : \"admin-cli\",\n    \"name\" : \"${client_admin-cli}\",\n    \"surrogateAuthRequired\" : false,\n    \"enabled\" : true,\n    \"clientAuthenticatorType\" : \"client-secret\",\n    \"secret\" : \"e4491867-8a42-4ca4-93ee-34a898ea6775\",\n    \"redirectUris\" : [ ],\n    \"webOrigins\" : [ ],\n    \"notBefore\" : 0,\n    \"bearerOnly\" : false,\n    \"consentRequired\" : false,\n    \"standardFlowEnabled\" : false,\n    \"implicitFlowEnabled\" : false,\n    \"directAccessGrantsEnabled\" : true,\n    \"serviceAccountsEnabled\" : false,\n    \"publicClient\" : true,\n    \"frontchannelLogout\" : false,\n    \"protocol\" : \"openid-connect\",\n    \"attributes\" : { },\n    \"fullScopeAllowed\" : false,\n    \"nodeReRegistrationTimeout\" : 0,\n    \"protocolMappers\" : [ {\n      \"id\" : \"e005a327-9dcb-447d-80c2-f7c668d0afaa\",\n      \"name\" : \"full name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-full-name-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${fullName}\",\n      \"config\" : {\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\"\n      }\n    }, {\n      \"id\" : \"a4cab9da-4684-4bdb-8351-abf2d9428845\",\n      \"name\" : \"given name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${givenName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"firstName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"given_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"b2fc3109-62de-4b87-8c31-29e895329f93\",\n      \"name\" : \"family name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${familyName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"lastName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"family_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"90622937-00bc-4e2e-a5d6-3f573712b2d2\",\n      \"name\" : \"username\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${username}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"username\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"preferred_username\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"4960d696-da1f-4fd2-8e15-49cdad809b03\",\n      \"name\" : \"email\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${email}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"email\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"email\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"c175c2f3-d399-4171-a46a-ac74a5b835f0\",\n      \"name\" : \"role list\",\n      \"protocol\" : \"saml\",\n      \"protocolMapper\" : \"saml-role-list-mapper\",\n      \"consentRequired\" : false,\n      \"config\" : {\n        \"single\" : \"false\",\n        \"attribute.nameformat\" : \"Basic\",\n        \"attribute.name\" : \"Role\"\n      }\n    } ],\n    \"useTemplateConfig\" : false,\n    \"useTemplateScope\" : false,\n    \"useTemplateMappers\" : false\n  }, {\n    \"id\" : \"ec2975dc-bde7-4012-89c4-06a499c00235\",\n    \"clientId\" : \"app-demo\",\n    \"baseUrl\" : \"http://localhost:8082/\",\n    \"surrogateAuthRequired\" : false,\n    \"enabled\" : true,\n    \"clientAuthenticatorType\" : \"client-secret\",\n    \"secret\" : \"e3f519b4-0272-4261-9912-8b7453ac4ecd\",\n    \"redirectUris\" : [ \"http://localhost:8082/*\" ],\n    \"webOrigins\" : [ \"http://localhost:8082\" ],\n    \"notBefore\" : 0,\n    \"bearerOnly\" : false,\n    \"consentRequired\" : false,\n    \"standardFlowEnabled\" : true,\n    \"implicitFlowEnabled\" : false,\n    \"directAccessGrantsEnabled\" : true,\n    \"serviceAccountsEnabled\" : false,\n    \"publicClient\" : false,\n    \"frontchannelLogout\" : false,\n    \"protocol\" : \"openid-connect\",\n    \"attributes\" : {\n      \"saml.assertion.signature\" : \"false\",\n      \"saml.force.post.binding\" : \"false\",\n      \"saml.multivalued.roles\" : \"false\",\n      \"saml.encrypt\" : \"false\",\n      \"saml_force_name_id_format\" : \"false\",\n      \"saml.client.signature\" : \"false\",\n      \"saml.authnstatement\" : \"false\",\n      \"saml.server.signature\" : \"false\",\n      \"saml.server.signature.keyinfo.ext\" : \"false\",\n      \"saml.onetimeuse.condition\" : \"false\"\n    },\n    \"fullScopeAllowed\" : true,\n    \"nodeReRegistrationTimeout\" : -1,\n    \"protocolMappers\" : [ {\n      \"id\" : \"f632a9a7-5cff-4254-9941-82fabfdb3216\",\n      \"name\" : \"role list\",\n      \"protocol\" : \"saml\",\n      \"protocolMapper\" : \"saml-role-list-mapper\",\n      \"consentRequired\" : false,\n      \"config\" : {\n        \"single\" : \"false\",\n        \"attribute.nameformat\" : \"Basic\",\n        \"attribute.name\" : \"Role\"\n      }\n    }, {\n      \"id\" : \"488d9ab7-7585-41dc-9d09-dd6d639b7a24\",\n      \"name\" : \"username\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${username}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"username\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"preferred_username\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"de28c7ae-a613-4f9d-8edb-1b9aa507efb9\",\n      \"name\" : \"email\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${email}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"email\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"email\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"6611aecf-daad-4ad2-aa74-c33de47037b0\",\n      \"name\" : \"full name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-full-name-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${fullName}\",\n      \"config\" : {\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\"\n      }\n    }, {\n      \"id\" : \"cb5a11ce-3311-4a78-9061-e6221184b6f5\",\n      \"name\" : \"given name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${givenName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"firstName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"given_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"4ec046bf-9c35-44ac-9395-fcda434fc061\",\n      \"name\" : \"family name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${familyName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"lastName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"family_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    } ],\n    \"useTemplateConfig\" : false,\n    \"useTemplateScope\" : false,\n    \"useTemplateMappers\" : false\n  }, {\n    \"id\" : \"0536d12c-2c36-444a-898b-ed7b527aac76\",\n    \"clientId\" : \"broker\",\n    \"name\" : \"${client_broker}\",\n    \"surrogateAuthRequired\" : false,\n    \"enabled\" : true,\n    \"clientAuthenticatorType\" : \"client-secret\",\n    \"secret\" : \"577625be-1736-4bee-9bb2-608aff465c64\",\n    \"redirectUris\" : [ ],\n    \"webOrigins\" : [ ],\n    \"notBefore\" : 0,\n    \"bearerOnly\" : false,\n    \"consentRequired\" : false,\n    \"standardFlowEnabled\" : true,\n    \"implicitFlowEnabled\" : false,\n    \"directAccessGrantsEnabled\" : false,\n    \"serviceAccountsEnabled\" : false,\n    \"publicClient\" : false,\n    \"frontchannelLogout\" : false,\n    \"protocol\" : \"openid-connect\",\n    \"attributes\" : { },\n    \"fullScopeAllowed\" : false,\n    \"nodeReRegistrationTimeout\" : 0,\n    \"protocolMappers\" : [ {\n      \"id\" : \"5f5e550c-ff29-482d-bb1f-0215d6bf081d\",\n      \"name\" : \"family name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${familyName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"lastName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"family_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"9239d7be-795f-4307-b0fe-ae0635fc367f\",\n      \"name\" : \"full name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-full-name-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${fullName}\",\n      \"config\" : {\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\"\n      }\n    }, {\n      \"id\" : \"c7be1c7e-a0d2-4fe3-869c-de00d694f067\",\n      \"name\" : \"email\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${email}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"email\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"email\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"e0c76ba5-d83d-4366-9b16-7b334fa587d4\",\n      \"name\" : \"role list\",\n      \"protocol\" : \"saml\",\n      \"protocolMapper\" : \"saml-role-list-mapper\",\n      \"consentRequired\" : false,\n      \"config\" : {\n        \"single\" : \"false\",\n        \"attribute.nameformat\" : \"Basic\",\n        \"attribute.name\" : \"Role\"\n      }\n    }, {\n      \"id\" : \"d97fa215-8d04-466b-8c19-a7c5f14ed1fa\",\n      \"name\" : \"username\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${username}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"username\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"preferred_username\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"b5359a60-d80b-4c5d-aa7c-ff3d1959aa9b\",\n      \"name\" : \"given name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${givenName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"firstName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"given_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    } ],\n    \"useTemplateConfig\" : false,\n    \"useTemplateScope\" : false,\n    \"useTemplateMappers\" : false\n  }, {\n    \"id\" : \"4e57a54d-42c8-400e-9cc1-95a36fbe02fd\",\n    \"clientId\" : \"realm-management\",\n    \"name\" : \"${client_realm-management}\",\n    \"surrogateAuthRequired\" : false,\n    \"enabled\" : true,\n    \"clientAuthenticatorType\" : \"client-secret\",\n    \"secret\" : \"05f5e2a2-83c9-45be-bc8b-7d9c2a924ed4\",\n    \"redirectUris\" : [ ],\n    \"webOrigins\" : [ ],\n    \"notBefore\" : 0,\n    \"bearerOnly\" : true,\n    \"consentRequired\" : false,\n    \"standardFlowEnabled\" : true,\n    \"implicitFlowEnabled\" : false,\n    \"directAccessGrantsEnabled\" : false,\n    \"serviceAccountsEnabled\" : false,\n    \"publicClient\" : false,\n    \"frontchannelLogout\" : false,\n    \"protocol\" : \"openid-connect\",\n    \"attributes\" : { },\n    \"fullScopeAllowed\" : false,\n    \"nodeReRegistrationTimeout\" : 0,\n    \"protocolMappers\" : [ {\n      \"id\" : \"b699f558-b852-4013-a8c2-177abf9a8353\",\n      \"name\" : \"full name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-full-name-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${fullName}\",\n      \"config\" : {\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\"\n      }\n    }, {\n      \"id\" : \"1377d3f0-8587-4458-8252-1f740f00dbe1\",\n      \"name\" : \"email\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${email}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"email\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"email\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"ca0e2b5c-6580-4949-80bd-fb3b87a0c7b5\",\n      \"name\" : \"role list\",\n      \"protocol\" : \"saml\",\n      \"protocolMapper\" : \"saml-role-list-mapper\",\n      \"consentRequired\" : false,\n      \"config\" : {\n        \"single\" : \"false\",\n        \"attribute.nameformat\" : \"Basic\",\n        \"attribute.name\" : \"Role\"\n      }\n    }, {\n      \"id\" : \"101f9558-3e9c-4f34-b11b-b7e9f6ee7645\",\n      \"name\" : \"family name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${familyName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"lastName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"family_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"be6fa79f-ade5-44c9-afa0-93b8170c47b9\",\n      \"name\" : \"username\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${username}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"username\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"preferred_username\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"b5d07f15-6a26-4350-9bf9-54d5359c0706\",\n      \"name\" : \"given name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${givenName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"firstName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"given_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    } ],\n    \"useTemplateConfig\" : false,\n    \"useTemplateScope\" : false,\n    \"useTemplateMappers\" : false\n  }, {\n    \"id\" : \"8878b917-5b73-4950-b014-8100b0c405ed\",\n    \"clientId\" : \"security-admin-console\",\n    \"name\" : \"${client_security-admin-console}\",\n    \"baseUrl\" : \"/auth/admin/demo/console/index.html\",\n    \"surrogateAuthRequired\" : false,\n    \"enabled\" : true,\n    \"clientAuthenticatorType\" : \"client-secret\",\n    \"secret\" : \"351b34ac-3a0f-4f09-af5a-6b9278c09b85\",\n    \"redirectUris\" : [ \"/auth/admin/demo/console/*\" ],\n    \"webOrigins\" : [ ],\n    \"notBefore\" : 0,\n    \"bearerOnly\" : false,\n    \"consentRequired\" : false,\n    \"standardFlowEnabled\" : true,\n    \"implicitFlowEnabled\" : false,\n    \"directAccessGrantsEnabled\" : false,\n    \"serviceAccountsEnabled\" : false,\n    \"publicClient\" : true,\n    \"frontchannelLogout\" : false,\n    \"protocol\" : \"openid-connect\",\n    \"attributes\" : { },\n    \"fullScopeAllowed\" : false,\n    \"nodeReRegistrationTimeout\" : 0,\n    \"protocolMappers\" : [ {\n      \"id\" : \"9a97567c-d9d6-4f5c-8d0f-ed1e060e598a\",\n      \"name\" : \"role list\",\n      \"protocol\" : \"saml\",\n      \"protocolMapper\" : \"saml-role-list-mapper\",\n      \"consentRequired\" : false,\n      \"config\" : {\n        \"single\" : \"false\",\n        \"attribute.nameformat\" : \"Basic\",\n        \"attribute.name\" : \"Role\"\n      }\n    }, {\n      \"id\" : \"6dae9b5b-0948-4591-a69f-51a1590e892f\",\n      \"name\" : \"username\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${username}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"username\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"preferred_username\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"085240de-a1c4-4735-af6a-2c565e9612cf\",\n      \"name\" : \"email\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${email}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"email\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"email\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"594a456d-2cdb-49a3-8c40-05145a406f92\",\n      \"name\" : \"family name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${familyName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"lastName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"family_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"00f77d41-e3d3-443d-9e0f-098379d88ca7\",\n      \"name\" : \"given name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-property-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${givenName}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"firstName\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"given_name\",\n        \"jsonType.label\" : \"String\"\n      }\n    }, {\n      \"id\" : \"b12cbc25-fe43-4597-84e5-77b506712186\",\n      \"name\" : \"full name\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-full-name-mapper\",\n      \"consentRequired\" : true,\n      \"consentText\" : \"${fullName}\",\n      \"config\" : {\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\"\n      }\n    }, {\n      \"id\" : \"08f6ee38-4048-407a-8baa-a2e770ae5123\",\n      \"name\" : \"locale\",\n      \"protocol\" : \"openid-connect\",\n      \"protocolMapper\" : \"oidc-usermodel-attribute-mapper\",\n      \"consentRequired\" : false,\n      \"consentText\" : \"${locale}\",\n      \"config\" : {\n        \"userinfo.token.claim\" : \"true\",\n        \"user.attribute\" : \"locale\",\n        \"id.token.claim\" : \"true\",\n        \"access.token.claim\" : \"true\",\n        \"claim.name\" : \"locale\",\n        \"jsonType.label\" : \"String\"\n      }\n    } ],\n    \"useTemplateConfig\" : false,\n    \"useTemplateScope\" : false,\n    \"useTemplateMappers\" : false\n  } ],\n  \"clientTemplates\" : [ ],\n  \"browserSecurityHeaders\" : {\n    \"xContentTypeOptions\" : \"nosniff\",\n    \"xRobotsTag\" : \"none\",\n    \"xFrameOptions\" : \"SAMEORIGIN\",\n    \"xXSSProtection\" : \"1; mode=block\",\n    \"contentSecurityPolicy\" : \"frame-src 'self'; frame-ancestors 'self'; object-src 'none';\",\n    \"strictTransportSecurity\" : \"max-age=31536000; includeSubDomains\"\n  },\n  \"smtpServer\" : { },\n  \"eventsEnabled\" : false,\n  \"eventsListeners\" : [ \"jboss-logging\" ],\n  \"enabledEventTypes\" : [ ],\n  \"adminEventsEnabled\" : false,\n  \"adminEventsDetailsEnabled\" : false,\n  \"components\" : {\n    \"org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy\" : [ {\n      \"id\" : \"6908d5c3-07a7-4c00-91d7-462affb7425a\",\n      \"name\" : \"Consent Required\",\n      \"providerId\" : \"consent-required\",\n      \"subType\" : \"anonymous\",\n      \"subComponents\" : { },\n      \"config\" : { }\n    }, {\n      \"id\" : \"f2fbbda7-bc89-474c-80cd-c7817d27e852\",\n      \"name\" : \"Allowed Client Templates\",\n      \"providerId\" : \"allowed-client-templates\",\n      \"subType\" : \"anonymous\",\n      \"subComponents\" : { },\n      \"config\" : { }\n    }, {\n      \"id\" : \"e98e7d78-69d1-4f78-86a9-6aac95c7ce28\",\n      \"name\" : \"Trusted Hosts\",\n      \"providerId\" : \"trusted-hosts\",\n      \"subType\" : \"anonymous\",\n      \"subComponents\" : { },\n      \"config\" : {\n        \"host-sending-registration-request-must-match\" : [ \"true\" ],\n        \"client-uris-must-match\" : [ \"true\" ]\n      }\n    }, {\n      \"id\" : \"9643017a-e4a3-435e-9c92-a14298a5f7ed\",\n      \"name\" : \"Allowed Protocol Mapper Types\",\n      \"providerId\" : \"allowed-protocol-mappers\",\n      \"subType\" : \"anonymous\",\n      \"subComponents\" : { },\n      \"config\" : {\n        \"allowed-protocol-mapper-types\" : [ \"saml-user-attribute-mapper\", \"saml-user-property-mapper\", \"saml-role-list-mapper\", \"oidc-usermodel-attribute-mapper\", \"oidc-full-name-mapper\", \"oidc-sha256-pairwise-sub-mapper\", \"oidc-usermodel-property-mapper\", \"oidc-address-mapper\" ],\n        \"consent-required-for-all-mappers\" : [ \"true\" ]\n      }\n    }, {\n      \"id\" : \"a72ad67b-392d-462b-a24d-359584948a39\",\n      \"name\" : \"Max Clients Limit\",\n      \"providerId\" : \"max-clients\",\n      \"subType\" : \"anonymous\",\n      \"subComponents\" : { },\n      \"config\" : {\n        \"max-clients\" : [ \"200\" ]\n      }\n    }, {\n      \"id\" : \"39d518a7-6678-415f-aee0-497ddf0bbb8f\",\n      \"name\" : \"Allowed Protocol Mapper Types\",\n      \"providerId\" : \"allowed-protocol-mappers\",\n      \"subType\" : \"authenticated\",\n      \"subComponents\" : { },\n      \"config\" : {\n        \"allowed-protocol-mapper-types\" : [ \"oidc-usermodel-property-mapper\", \"oidc-sha256-pairwise-sub-mapper\", \"oidc-full-name-mapper\", \"oidc-address-mapper\", \"saml-role-list-mapper\", \"saml-user-attribute-mapper\", \"oidc-usermodel-attribute-mapper\", \"saml-user-property-mapper\" ],\n        \"consent-required-for-all-mappers\" : [ \"true\" ]\n      }\n    }, {\n      \"id\" : \"f690379c-6479-4533-ac55-660d4d519849\",\n      \"name\" : \"Full Scope Disabled\",\n      \"providerId\" : \"scope\",\n      \"subType\" : \"anonymous\",\n      \"subComponents\" : { },\n      \"config\" : { }\n    }, {\n      \"id\" : \"fda00934-5922-4028-9e7c-c123100c248f\",\n      \"name\" : \"Allowed Client Templates\",\n      \"providerId\" : \"allowed-client-templates\",\n      \"subType\" : \"authenticated\",\n      \"subComponents\" : { },\n      \"config\" : { }\n    } ],\n    \"org.keycloak.keys.KeyProvider\" : [ {\n      \"id\" : \"1cf453a3-7702-4d4d-8614-72c1fc6b17b6\",\n      \"name\" : \"hmac-generated\",\n      \"providerId\" : \"hmac-generated\",\n      \"subComponents\" : { },\n      \"config\" : {\n        \"kid\" : [ \"012044b2-dfa4-49cb-a4c5-916c19f9b96e\" ],\n        \"secret\" : [ \"nEC6RCMTKBsF49bfzb3Vv21Vh4TLEaFiRAfvQp2YOOE\" ],\n        \"priority\" : [ \"100\" ]\n      }\n    }, {\n      \"id\" : \"83881f72-2def-46a5-b8ba-99ad0b1e4c95\",\n      \"name\" : \"rsa-generated\",\n      \"providerId\" : \"rsa-generated\",\n      \"subComponents\" : { },\n      \"config\" : {\n        \"privateKey\" : [ \"MIIEowIBAAKCAQEAjc06HxUS54Afmxiw0GXEcD8LS05UVU5KF0hc77CPuT6Sj9atTc1ccRinc24QuE2YdTtYGpELsYGkyul+5r6849vbCsQdcrq1JpLhre/renbjUWz9wBqlphIwPcAR7sSJKHnh+g5K+iOQ7AQaiJGo+tlZrXKfERnahTNVWaZHCIM+82oUvyFaXhV0XyhxQy9RtDq47GnWEgZ9xCvCWPDZJjG6Gm/6rIfZpdqqN5h8GqsOoCUxnLJS0XZP/8Gt/oZF/Y8yMKrOigs83hm1ireMFZDsGgp+z/8+m92CpbASSbO5HXbphO9LZQTZ0BFHHH7DBjF9QZeifQbUH1tyGMzDLQIDAQABAoIBAAavkHf6tGN55QOZDG0m/zYTouKwFMXY5SFn5gnfF0eyrZJemtk6P4uNkAefPuaRsgiE/chy4kxCQpTWoYcboyhTK2a8jG7mYrgo4L8kusORa3JhYy11lC3aWa/vqGjLl3PzGzaBCgP1PVYDc4TQ6Vi6esH0z48s2uLA4ttRPbQm+gJWMTmJpLNydDUBzuQT6OERald4/Ssp0qgZm0Y5WUu0mMiRT8LhNMzJNbZt3S/a22lKA1G/HpyaFD9Fb5hq09TyJqHefzbrWCg6sch8+tKvH6mxqHV2TmrLUtMHzW7tC0tkMh2MShzqqEIYNVFuqzAMEzNczrAYk2L1J2u0JjkCgYEAzWzZW3w9IGAq2yfCiHic3WpgWyadZGHJXRq/x7bkXxowtaHi2A4yc4x0obGbSvqPvFRlYt2v9f5XLmDGLVvS34BeHbZIEK1GUV+5lpzejJ1GkYdSnhPquLbmRkDrYG1a/dU4DLSKvKc45jmhwRdheeTvFW3z1XZqshrTIxBwwLsCgYEAsLZvShoO9M5uhWCnsvMZ6gRm7Nw5FmCfZm0WM1Cj9mWngFCcWhxZEheTOhiqNcnGi8e8xlDJAI4iimUD4ZRqeTs/CIvbHNq8DICf6aSMAaba+jxycEzVu/xZsNkzV1SaKcPll+fjV8vRKA0JAaioQMkrmhRCsu/ODNjo4MYd4TcCgYB3b8oQfvOrVz6TnVJltnq94ZOUa6cnLhO9pkfK/nNZOAkKEc2qgNakiA1n1bPMrFHV1dv815fvFqnptSqERNceS6xs6gaMa7JurZFiGGLsrqTRCDTo4/uc2fqY7jXsIqi83LNx76aaeT+D3A5IDigGjyzS8NLMUcVHOIF56Z0k8QKBgAstLrLAHSwMll7nMxQVXhE4AA6BCzdIGyzOP3Y1ZnliCosKDimA231ScmRdRP6r6VvT4TOlzmCznKmmI+2zhlxui9kNh2k2yGf+Bp8vYg+ErxrekdpacbY3CrEtu5qNZka39iB6cR2PbYYb9PLe6O1YC+Lt3x4UHrMfUPNOdHtXAoGBAKpncRXGyL05nnzFvK68BfoxSpd4aJk0Wkr9nOxZGFJj8v/LeUuxN6LOGqw4z8Sfdx3AI/6+JJAWk9sUlQ4ejAMFwR67UXI1eLkvs5x+U9g6DaZUMpgTUQhkfinZ3b822L6B20O+5Xz6aOGDbcWR+X/MAyj/gfnYR/TvXCq5v+sE\" ],\n        \"certificate\" : [ \"MIIClzCCAX8CBgFi1H8iNDANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARkZW1vMB4XDTE4MDQxNzE2NDM0NFoXDTI4MDQxNzE2NDUyNFowDzENMAsGA1UEAwwEZGVtbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI3NOh8VEueAH5sYsNBlxHA/C0tOVFVOShdIXO+wj7k+ko/WrU3NXHEYp3NuELhNmHU7WBqRC7GBpMrpfua+vOPb2wrEHXK6tSaS4a3v63p241Fs/cAapaYSMD3AEe7EiSh54foOSvojkOwEGoiRqPrZWa1ynxEZ2oUzVVmmRwiDPvNqFL8hWl4VdF8ocUMvUbQ6uOxp1hIGfcQrwljw2SYxuhpv+qyH2aXaqjeYfBqrDqAlMZyyUtF2T//Brf6GRf2PMjCqzooLPN4ZtYq3jBWQ7BoKfs//PpvdgqWwEkmzuR126YTvS2UE2dARRxx+wwYxfUGXon0G1B9bchjMwy0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAavonr2grkWPCSLDRRCyTly2q/By5FYhkN5Bu7c2pxQy/k1OKJUBz+GIPxSL6MrPmHoWHM9fpD9nLCa1VHbHkEiu9p0c+2CDPVAyYvVbADVdgL+xp19TMyvETMfS1tJKVyJbqL8RsxzjWm1qI19VmVWNNHUGXpuPp35DL5tL/RkooY6+oNamsiNwR6xXmfqY7l6w8HA4y8It3yaeHy6N2ffjI/2AtXTyISuEEv1Lybr5op4jKRYLqv+ly7aBeNIGGnHFXlGyCqv8dSWSYXA1S83x4LeTHrj7rAC4fORY2Q5VNmhUAYYE5Vy+zxAHSoQn+cEf2qJsr9xRlYy8nzyXukw==\" ],\n        \"priority\" : [ \"100\" ]\n      }\n    }, {\n      \"id\" : \"46800710-eced-4804-a79e-32f7c5797b04\",\n      \"name\" : \"aes-generated\",\n      \"providerId\" : \"aes-generated\",\n      \"subComponents\" : { },\n      \"config\" : {\n        \"kid\" : [ \"2b922283-df55-4424-8bef-3f2ff5ba0bfa\" ],\n        \"secret\" : [ \"Ry49w356XdzGeEQbsupsvA\" ],\n        \"priority\" : [ \"100\" ]\n      }\n    } ]\n  },\n  \"internationalizationEnabled\" : false,\n  \"supportedLocales\" : [ ],\n  \"authenticationFlows\" : [ {\n    \"id\" : \"a48d9b79-b52f-4d29-b831-ecb9098352ad\",\n    \"alias\" : \"Handle Existing Account\",\n    \"description\" : \"Handle what to do if there is existing account with same email/username like authenticated identity provider\",\n    \"providerId\" : \"basic-flow\",\n    \"topLevel\" : false,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"idp-confirm-link\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 10,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"idp-email-verification\",\n      \"requirement\" : \"ALTERNATIVE\",\n      \"priority\" : 20,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"requirement\" : \"ALTERNATIVE\",\n      \"priority\" : 30,\n      \"flowAlias\" : \"Verify Existing Account by Re-authentication\",\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : true\n    } ]\n  }, {\n    \"id\" : \"03731267-4cd9-478d-ac04-403d1d832d46\",\n    \"alias\" : \"Verify Existing Account by Re-authentication\",\n    \"description\" : \"Reauthentication of existing account\",\n    \"providerId\" : \"basic-flow\",\n    \"topLevel\" : false,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"idp-username-password-form\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 10,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"auth-otp-form\",\n      \"requirement\" : \"OPTIONAL\",\n      \"priority\" : 20,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    } ]\n  }, {\n    \"id\" : \"bb3fec2b-49dc-4ca3-bb31-8acb74b3e1bd\",\n    \"alias\" : \"browser\",\n    \"description\" : \"browser based authentication\",\n    \"providerId\" : \"basic-flow\",\n    \"topLevel\" : true,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"auth-cookie\",\n      \"requirement\" : \"ALTERNATIVE\",\n      \"priority\" : 10,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"auth-spnego\",\n      \"requirement\" : \"DISABLED\",\n      \"priority\" : 20,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"identity-provider-redirector\",\n      \"requirement\" : \"ALTERNATIVE\",\n      \"priority\" : 25,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"requirement\" : \"ALTERNATIVE\",\n      \"priority\" : 30,\n      \"flowAlias\" : \"forms\",\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : true\n    } ]\n  }, {\n    \"id\" : \"84567fef-a17f-424c-9f30-c5ae041beeee\",\n    \"alias\" : \"clients\",\n    \"description\" : \"Base authentication for clients\",\n    \"providerId\" : \"client-flow\",\n    \"topLevel\" : true,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"client-secret\",\n      \"requirement\" : \"ALTERNATIVE\",\n      \"priority\" : 10,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"client-jwt\",\n      \"requirement\" : \"ALTERNATIVE\",\n      \"priority\" : 20,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    } ]\n  }, {\n    \"id\" : \"731a2721-79ff-46ec-8dcb-ea7d19f86d33\",\n    \"alias\" : \"direct grant\",\n    \"description\" : \"OpenID Connect Resource Owner Grant\",\n    \"providerId\" : \"basic-flow\",\n    \"topLevel\" : true,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"direct-grant-validate-username\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 10,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"direct-grant-validate-password\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 20,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"direct-grant-validate-otp\",\n      \"requirement\" : \"OPTIONAL\",\n      \"priority\" : 30,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    } ]\n  }, {\n    \"id\" : \"3c5c6d83-ccb5-420d-8370-253c43a6d598\",\n    \"alias\" : \"docker auth\",\n    \"description\" : \"Used by Docker clients to authenticate against the IDP\",\n    \"providerId\" : \"basic-flow\",\n    \"topLevel\" : true,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"docker-http-basic-authenticator\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 10,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    } ]\n  }, {\n    \"id\" : \"81f1a3b5-7737-4351-a4bd-25e98b536798\",\n    \"alias\" : \"first broker login\",\n    \"description\" : \"Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account\",\n    \"providerId\" : \"basic-flow\",\n    \"topLevel\" : true,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticatorConfig\" : \"review profile config\",\n      \"authenticator\" : \"idp-review-profile\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 10,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticatorConfig\" : \"create unique user config\",\n      \"authenticator\" : \"idp-create-user-if-unique\",\n      \"requirement\" : \"ALTERNATIVE\",\n      \"priority\" : 20,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"requirement\" : \"ALTERNATIVE\",\n      \"priority\" : 30,\n      \"flowAlias\" : \"Handle Existing Account\",\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : true\n    } ]\n  }, {\n    \"id\" : \"46ba7967-ea06-45e3-98af-11200a34473e\",\n    \"alias\" : \"forms\",\n    \"description\" : \"Username, password, otp and other auth forms.\",\n    \"providerId\" : \"basic-flow\",\n    \"topLevel\" : false,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"auth-username-password-form\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 10,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"auth-otp-form\",\n      \"requirement\" : \"OPTIONAL\",\n      \"priority\" : 20,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    } ]\n  }, {\n    \"id\" : \"4f2620ae-bb89-4d85-b81e-6e5d20c78a47\",\n    \"alias\" : \"registration\",\n    \"description\" : \"registration flow\",\n    \"providerId\" : \"basic-flow\",\n    \"topLevel\" : true,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"registration-page-form\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 10,\n      \"flowAlias\" : \"registration form\",\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : true\n    } ]\n  }, {\n    \"id\" : \"7fb032fb-dac9-4ea8-9d63-678753437440\",\n    \"alias\" : \"registration form\",\n    \"description\" : \"registration form\",\n    \"providerId\" : \"form-flow\",\n    \"topLevel\" : false,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"registration-user-creation\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 20,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"registration-profile-action\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 40,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"registration-password-action\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 50,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"registration-recaptcha-action\",\n      \"requirement\" : \"DISABLED\",\n      \"priority\" : 60,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    } ]\n  }, {\n    \"id\" : \"75600e80-cae6-4347-a506-ddf6477cd7e9\",\n    \"alias\" : \"reset credentials\",\n    \"description\" : \"Reset credentials for a user if they forgot their password or something\",\n    \"providerId\" : \"basic-flow\",\n    \"topLevel\" : true,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"reset-credentials-choose-user\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 10,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"reset-credential-email\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 20,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"reset-password\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 30,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    }, {\n      \"authenticator\" : \"reset-otp\",\n      \"requirement\" : \"OPTIONAL\",\n      \"priority\" : 40,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    } ]\n  }, {\n    \"id\" : \"4990dbc0-bb0b-48b5-8f72-945adcf77d39\",\n    \"alias\" : \"saml ecp\",\n    \"description\" : \"SAML ECP Profile Authentication Flow\",\n    \"providerId\" : \"basic-flow\",\n    \"topLevel\" : true,\n    \"builtIn\" : true,\n    \"authenticationExecutions\" : [ {\n      \"authenticator\" : \"http-basic-authenticator\",\n      \"requirement\" : \"REQUIRED\",\n      \"priority\" : 10,\n      \"userSetupAllowed\" : false,\n      \"autheticatorFlow\" : false\n    } ]\n  } ],\n  \"authenticatorConfig\" : [ {\n    \"id\" : \"da120730-f96f-4a0b-9f97-48d63823b067\",\n    \"alias\" : \"create unique user config\",\n    \"config\" : {\n      \"require.password.update.after.registration\" : \"false\"\n    }\n  }, {\n    \"id\" : \"0c76ade9-f703-4606-bae9-28f0bf131e11\",\n    \"alias\" : \"review profile config\",\n    \"config\" : {\n      \"update.profile.on.first.login\" : \"missing\"\n    }\n  } ],\n  \"requiredActions\" : [ {\n    \"alias\" : \"CONFIGURE_TOTP\",\n    \"name\" : \"Configure OTP\",\n    \"providerId\" : \"CONFIGURE_TOTP\",\n    \"enabled\" : true,\n    \"defaultAction\" : false,\n    \"config\" : { }\n  }, {\n    \"alias\" : \"UPDATE_PASSWORD\",\n    \"name\" : \"Update Password\",\n    \"providerId\" : \"UPDATE_PASSWORD\",\n    \"enabled\" : true,\n    \"defaultAction\" : false,\n    \"config\" : { }\n  }, {\n    \"alias\" : \"UPDATE_PROFILE\",\n    \"name\" : \"Update Profile\",\n    \"providerId\" : \"UPDATE_PROFILE\",\n    \"enabled\" : true,\n    \"defaultAction\" : false,\n    \"config\" : { }\n  }, {\n    \"alias\" : \"VERIFY_EMAIL\",\n    \"name\" : \"Verify Email\",\n    \"providerId\" : \"VERIFY_EMAIL\",\n    \"enabled\" : true,\n    \"defaultAction\" : false,\n    \"config\" : { }\n  }, {\n    \"alias\" : \"terms_and_conditions\",\n    \"name\" : \"Terms and Conditions\",\n    \"providerId\" : \"terms_and_conditions\",\n    \"enabled\" : false,\n    \"defaultAction\" : false,\n    \"config\" : { }\n  } ],\n  \"browserFlow\" : \"browser\",\n  \"registrationFlow\" : \"registration\",\n  \"directGrantFlow\" : \"direct grant\",\n  \"resetCredentialsFlow\" : \"reset credentials\",\n  \"clientAuthenticationFlow\" : \"clients\",\n  \"dockerAuthenticationFlow\" : \"docker auth\",\n  \"attributes\" : {\n    \"_browser_header.xXSSProtection\" : \"1; mode=block\",\n    \"_browser_header.xFrameOptions\" : \"SAMEORIGIN\",\n    \"_browser_header.strictTransportSecurity\" : \"max-age=31536000; includeSubDomains\",\n    \"permanentLockout\" : \"false\",\n    \"quickLoginCheckMilliSeconds\" : \"1000\",\n    \"_browser_header.xRobotsTag\" : \"none\",\n    \"maxFailureWaitSeconds\" : \"900\",\n    \"minimumQuickLoginWaitSeconds\" : \"60\",\n    \"failureFactor\" : \"30\",\n    \"actionTokenGeneratedByUserLifespan\" : \"300\",\n    \"maxDeltaTimeSeconds\" : \"43200\",\n    \"_browser_header.xContentTypeOptions\" : \"nosniff\",\n    \"actionTokenGeneratedByAdminLifespan\" : \"43200\",\n    \"bruteForceProtected\" : \"false\",\n    \"_browser_header.contentSecurityPolicy\" : \"frame-src 'self'; frame-ancestors 'self'; object-src 'none';\",\n    \"waitIncrementSeconds\" : \"60\"\n  },\n  \"keycloakVersion\" : \"3.4.3.Final\"\n}"
  },
  {
    "path": "mvnw",
    "content": "#!/bin/sh\n# ----------------------------------------------------------------------------\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n# ----------------------------------------------------------------------------\n\n# ----------------------------------------------------------------------------\n# Maven2 Start Up Batch script\n#\n# Required ENV vars:\n# ------------------\n#   JAVA_HOME - location of a JDK home dir\n#\n# Optional ENV vars\n# -----------------\n#   M2_HOME - location of maven2's installed home dir\n#   MAVEN_OPTS - parameters passed to the Java VM when running Maven\n#     e.g. to debug Maven itself, use\n#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\n#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files\n# ----------------------------------------------------------------------------\n\nif [ -z \"$MAVEN_SKIP_RC\" ] ; then\n\n  if [ -f /etc/mavenrc ] ; then\n    . /etc/mavenrc\n  fi\n\n  if [ -f \"$HOME/.mavenrc\" ] ; then\n    . \"$HOME/.mavenrc\"\n  fi\n\nfi\n\n# OS specific support.  $var _must_ be set to either true or false.\ncygwin=false;\ndarwin=false;\nmingw=false\ncase \"`uname`\" in\n  CYGWIN*) cygwin=true ;;\n  MINGW*) mingw=true;;\n  Darwin*) darwin=true\n    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home\n    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html\n    if [ -z \"$JAVA_HOME\" ]; then\n      if [ -x \"/usr/libexec/java_home\" ]; then\n        export JAVA_HOME=\"`/usr/libexec/java_home`\"\n      else\n        export JAVA_HOME=\"/Library/Java/Home\"\n      fi\n    fi\n    ;;\nesac\n\nif [ -z \"$JAVA_HOME\" ] ; then\n  if [ -r /etc/gentoo-release ] ; then\n    JAVA_HOME=`java-config --jre-home`\n  fi\nfi\n\nif [ -z \"$M2_HOME\" ] ; then\n  ## resolve links - $0 may be a link to maven's home\n  PRG=\"$0\"\n\n  # need this for relative symlinks\n  while [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n      PRG=\"$link\"\n    else\n      PRG=\"`dirname \"$PRG\"`/$link\"\n    fi\n  done\n\n  saveddir=`pwd`\n\n  M2_HOME=`dirname \"$PRG\"`/..\n\n  # make it fully qualified\n  M2_HOME=`cd \"$M2_HOME\" && pwd`\n\n  cd \"$saveddir\"\n  # echo Using m2 at $M2_HOME\nfi\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched\nif $cygwin ; then\n  [ -n \"$M2_HOME\" ] &&\n    M2_HOME=`cygpath --unix \"$M2_HOME\"`\n  [ -n \"$JAVA_HOME\" ] &&\n    JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\n  [ -n \"$CLASSPATH\" ] &&\n    CLASSPATH=`cygpath --path --unix \"$CLASSPATH\"`\nfi\n\n# For Migwn, ensure paths are in UNIX format before anything is touched\nif $mingw ; then\n  [ -n \"$M2_HOME\" ] &&\n    M2_HOME=\"`(cd \"$M2_HOME\"; pwd)`\"\n  [ -n \"$JAVA_HOME\" ] &&\n    JAVA_HOME=\"`(cd \"$JAVA_HOME\"; pwd)`\"\n  # TODO classpath?\nfi\n\nif [ -z \"$JAVA_HOME\" ]; then\n  javaExecutable=\"`which javac`\"\n  if [ -n \"$javaExecutable\" ] && ! [ \"`expr \\\"$javaExecutable\\\" : '\\([^ ]*\\)'`\" = \"no\" ]; then\n    # readlink(1) is not available as standard on Solaris 10.\n    readLink=`which readlink`\n    if [ ! `expr \"$readLink\" : '\\([^ ]*\\)'` = \"no\" ]; then\n      if $darwin ; then\n        javaHome=\"`dirname \\\"$javaExecutable\\\"`\"\n        javaExecutable=\"`cd \\\"$javaHome\\\" && pwd -P`/javac\"\n      else\n        javaExecutable=\"`readlink -f \\\"$javaExecutable\\\"`\"\n      fi\n      javaHome=\"`dirname \\\"$javaExecutable\\\"`\"\n      javaHome=`expr \"$javaHome\" : '\\(.*\\)/bin'`\n      JAVA_HOME=\"$javaHome\"\n      export JAVA_HOME\n    fi\n  fi\nfi\n\nif [ -z \"$JAVACMD\" ] ; then\n  if [ -n \"$JAVA_HOME\"  ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n      # IBM's JDK on AIX uses strange locations for the executables\n      JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n      JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n  else\n    JAVACMD=\"`which java`\"\n  fi\nfi\n\nif [ ! -x \"$JAVACMD\" ] ; then\n  echo \"Error: JAVA_HOME is not defined correctly.\" >&2\n  echo \"  We cannot execute $JAVACMD\" >&2\n  exit 1\nfi\n\nif [ -z \"$JAVA_HOME\" ] ; then\n  echo \"Warning: JAVA_HOME environment variable is not set.\"\nfi\n\nCLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher\n\n# traverses directory structure from process work directory to filesystem root\n# first directory with .mvn subdirectory is considered project base directory\nfind_maven_basedir() {\n\n  if [ -z \"$1\" ]\n  then\n    echo \"Path not specified to find_maven_basedir\"\n    return 1\n  fi\n\n  basedir=\"$1\"\n  wdir=\"$1\"\n  while [ \"$wdir\" != '/' ] ; do\n    if [ -d \"$wdir\"/.mvn ] ; then\n      basedir=$wdir\n      break\n    fi\n    # workaround for JBEAP-8937 (on Solaris 10/Sparc)\n    if [ -d \"${wdir}\" ]; then\n      wdir=`cd \"$wdir/..\"; pwd`\n    fi\n    # end of workaround\n  done\n  echo \"${basedir}\"\n}\n\n# concatenates all lines of a file\nconcat_lines() {\n  if [ -f \"$1\" ]; then\n    echo \"$(tr -s '\\n' ' ' < \"$1\")\"\n  fi\n}\n\nBASE_DIR=`find_maven_basedir \"$(pwd)\"`\nif [ -z \"$BASE_DIR\" ]; then\n  exit 1;\nfi\n\nexport MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-\"$BASE_DIR\"}\necho $MAVEN_PROJECTBASEDIR\nMAVEN_OPTS=\"$(concat_lines \"$MAVEN_PROJECTBASEDIR/.mvn/jvm.config\") $MAVEN_OPTS\"\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin; then\n  [ -n \"$M2_HOME\" ] &&\n    M2_HOME=`cygpath --path --windows \"$M2_HOME\"`\n  [ -n \"$JAVA_HOME\" ] &&\n    JAVA_HOME=`cygpath --path --windows \"$JAVA_HOME\"`\n  [ -n \"$CLASSPATH\" ] &&\n    CLASSPATH=`cygpath --path --windows \"$CLASSPATH\"`\n  [ -n \"$MAVEN_PROJECTBASEDIR\" ] &&\n    MAVEN_PROJECTBASEDIR=`cygpath --path --windows \"$MAVEN_PROJECTBASEDIR\"`\nfi\n\nWRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\n\nexec \"$JAVACMD\" \\\n  $MAVEN_OPTS \\\n  -classpath \"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar\" \\\n  \"-Dmaven.home=${M2_HOME}\" \"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}\" \\\n  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG \"$@\"\n"
  },
  {
    "path": "mvnw.cmd",
    "content": "@REM ----------------------------------------------------------------------------\n@REM Licensed to the Apache Software Foundation (ASF) under one\n@REM or more contributor license agreements.  See the NOTICE file\n@REM distributed with this work for additional information\n@REM regarding copyright ownership.  The ASF licenses this file\n@REM to you under the Apache License, Version 2.0 (the\n@REM \"License\"); you may not use this file except in compliance\n@REM with the License.  You may obtain a copy of the License at\n@REM\n@REM    http://www.apache.org/licenses/LICENSE-2.0\n@REM\n@REM Unless required by applicable law or agreed to in writing,\n@REM software distributed under the License is distributed on an\n@REM \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n@REM KIND, either express or implied.  See the License for the\n@REM specific language governing permissions and limitations\n@REM under the License.\n@REM ----------------------------------------------------------------------------\n\n@REM ----------------------------------------------------------------------------\n@REM Maven2 Start Up Batch script\n@REM\n@REM Required ENV vars:\n@REM JAVA_HOME - location of a JDK home dir\n@REM\n@REM Optional ENV vars\n@REM M2_HOME - location of maven2's installed home dir\n@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands\n@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending\n@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven\n@REM     e.g. to debug Maven itself, use\n@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\n@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files\n@REM ----------------------------------------------------------------------------\n\n@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'\n@echo off\n@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'\n@if \"%MAVEN_BATCH_ECHO%\" == \"on\"  echo %MAVEN_BATCH_ECHO%\n\n@REM set %HOME% to equivalent of $HOME\nif \"%HOME%\" == \"\" (set \"HOME=%HOMEDRIVE%%HOMEPATH%\")\n\n@REM Execute a user defined script before this one\nif not \"%MAVEN_SKIP_RC%\" == \"\" goto skipRcPre\n@REM check for pre script, once with legacy .bat ending and once with .cmd ending\nif exist \"%HOME%\\mavenrc_pre.bat\" call \"%HOME%\\mavenrc_pre.bat\"\nif exist \"%HOME%\\mavenrc_pre.cmd\" call \"%HOME%\\mavenrc_pre.cmd\"\n:skipRcPre\n\n@setlocal\n\nset ERROR_CODE=0\n\n@REM To isolate internal variables from possible post scripts, we use another setlocal\n@setlocal\n\n@REM ==== START VALIDATION ====\nif not \"%JAVA_HOME%\" == \"\" goto OkJHome\n\necho.\necho Error: JAVA_HOME not found in your environment. >&2\necho Please set the JAVA_HOME variable in your environment to match the >&2\necho location of your Java installation. >&2\necho.\ngoto error\n\n:OkJHome\nif exist \"%JAVA_HOME%\\bin\\java.exe\" goto init\n\necho.\necho Error: JAVA_HOME is set to an invalid directory. >&2\necho JAVA_HOME = \"%JAVA_HOME%\" >&2\necho Please set the JAVA_HOME variable in your environment to match the >&2\necho location of your Java installation. >&2\necho.\ngoto error\n\n@REM ==== END VALIDATION ====\n\n:init\n\n@REM Find the project base dir, i.e. the directory that contains the folder \".mvn\".\n@REM Fallback to current working directory if not found.\n\nset MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%\nIF NOT \"%MAVEN_PROJECTBASEDIR%\"==\"\" goto endDetectBaseDir\n\nset EXEC_DIR=%CD%\nset WDIR=%EXEC_DIR%\n:findBaseDir\nIF EXIST \"%WDIR%\"\\.mvn goto baseDirFound\ncd ..\nIF \"%WDIR%\"==\"%CD%\" goto baseDirNotFound\nset WDIR=%CD%\ngoto findBaseDir\n\n:baseDirFound\nset MAVEN_PROJECTBASEDIR=%WDIR%\ncd \"%EXEC_DIR%\"\ngoto endDetectBaseDir\n\n:baseDirNotFound\nset MAVEN_PROJECTBASEDIR=%EXEC_DIR%\ncd \"%EXEC_DIR%\"\n\n:endDetectBaseDir\n\nIF NOT EXIST \"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\" goto endReadAdditionalConfig\n\n@setlocal EnableExtensions EnableDelayedExpansion\nfor /F \"usebackq delims=\" %%a in (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a\n@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%\n\n:endReadAdditionalConfig\n\nSET MAVEN_JAVA_EXE=\"%JAVA_HOME%\\bin\\java.exe\"\n\nset WRAPPER_JAR=\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.jar\"\nset WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\n\n%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% \"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%\" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*\nif ERRORLEVEL 1 goto error\ngoto end\n\n:error\nset ERROR_CODE=1\n\n:end\n@endlocal & set ERROR_CODE=%ERROR_CODE%\n\nif not \"%MAVEN_SKIP_RC%\" == \"\" goto skipRcPost\n@REM check for post script, once with legacy .bat ending and once with .cmd ending\nif exist \"%HOME%\\mavenrc_post.bat\" call \"%HOME%\\mavenrc_post.bat\"\nif exist \"%HOME%\\mavenrc_post.cmd\" call \"%HOME%\\mavenrc_post.cmd\"\n:skipRcPost\n\n@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'\nif \"%MAVEN_BATCH_PAUSE%\" == \"on\" pause\n\nif \"%MAVEN_TERMINATE_CMD%\" == \"on\" exit %ERROR_CODE%\n\nexit /B %ERROR_CODE%\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\t<modelVersion>4.0.0</modelVersion>\n\n\t<groupId>de.tdlabs.training</groupId>\n\t<artifactId>spring-boot-2-oauth-example</artifactId>\n\t<version>0.0.1-SNAPSHOT</version>\n\t<packaging>jar</packaging>\n\n\t<name>spring-boot-2-oauth-example</name>\n\t<description>Demo project for Spring Boot</description>\n\n\t<parent>\n\t\t<groupId>org.springframework.boot</groupId>\n\t\t<artifactId>spring-boot-starter-parent</artifactId>\n\t\t<version>2.0.1.RELEASE</version>\n\t\t<relativePath /> <!-- lookup parent from repository -->\n\t</parent>\n\n\t<properties>\n\t\t<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\t\t<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n\t\t<java.version>1.8</java.version>\n\t\t<spring-cloud.version>Finchley.M9</spring-cloud.version>\n\t</properties>\n\n\t<dependencies>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-web</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-thymeleaf</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.thymeleaf.extras</groupId>\n\t\t\t<artifactId>thymeleaf-extras-springsecurity4</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-starter-security</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.security</groupId>\n\t\t\t<artifactId>spring-security-oauth2-client</artifactId>\n\t\t</dependency>\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.security</groupId>\n\t\t\t<artifactId>spring-security-oauth2-jose</artifactId>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.projectlombok</groupId>\n\t\t\t<artifactId>lombok</artifactId>\n\t\t\t<optional>true</optional>\n\t\t</dependency>\n\n\t\t<dependency>\n\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t<artifactId>spring-boot-devtools</artifactId>\n\t\t\t<optional>true</optional>\n\t\t\t<scope>runtime</scope>\n\t\t</dependency>\n\n\t</dependencies>\n\n\t<dependencyManagement>\n\t\t<dependencies>\n\t\t\t<dependency>\n\t\t\t\t<groupId>org.springframework.cloud</groupId>\n\t\t\t\t<artifactId>spring-cloud-dependencies</artifactId>\n\t\t\t\t<version>${spring-cloud.version}</version>\n\t\t\t\t<type>pom</type>\n\t\t\t\t<scope>import</scope>\n\t\t\t</dependency>\n\t\t</dependencies>\n\t</dependencyManagement>\n\n\t<build>\n\t\t<plugins>\n\t\t\t<plugin>\n\t\t\t\t<groupId>org.springframework.boot</groupId>\n\t\t\t\t<artifactId>spring-boot-maven-plugin</artifactId>\n\t\t\t</plugin>\n\t\t</plugins>\n\t</build>\n\n\t<repositories>\n\t\t<repository>\n\t\t\t<id>spring-snapshots</id>\n\t\t\t<name>Spring Snapshots</name>\n\t\t\t<url>https://repo.spring.io/snapshot</url>\n\t\t\t<snapshots>\n\t\t\t\t<enabled>true</enabled>\n\t\t\t</snapshots>\n\t\t</repository>\n\t\t<repository>\n\t\t\t<id>spring-milestones</id>\n\t\t\t<name>Spring Milestones</name>\n\t\t\t<url>https://repo.spring.io/milestone</url>\n\t\t\t<snapshots>\n\t\t\t\t<enabled>false</enabled>\n\t\t\t</snapshots>\n\t\t</repository>\n\t</repositories>\n\n\t<pluginRepositories>\n\t\t<pluginRepository>\n\t\t\t<id>spring-snapshots</id>\n\t\t\t<name>Spring Snapshots</name>\n\t\t\t<url>https://repo.spring.io/snapshot</url>\n\t\t\t<snapshots>\n\t\t\t\t<enabled>true</enabled>\n\t\t\t</snapshots>\n\t\t</pluginRepository>\n\t\t<pluginRepository>\n\t\t\t<id>spring-milestones</id>\n\t\t\t<name>Spring Milestones</name>\n\t\t\t<url>https://repo.spring.io/milestone</url>\n\t\t\t<snapshots>\n\t\t\t\t<enabled>false</enabled>\n\t\t\t</snapshots>\n\t\t</pluginRepository>\n\t</pluginRepositories>\n\n\n</project>\n"
  },
  {
    "path": "readme.md",
    "content": "# PoC for Spring Boot 2 + Spring Security 5 + Keycloak 3.4.3\n \nThis example project uses the OpenID Connect support in Spring Security 5 without using the Keycloak adapter  \nand is inspired by [this](http://info.michael-simons.eu/2017/12/28/use-keycloak-with-your-spring-boot-2-application/) blog post by Michael Simons.\n \n Features:\n - SSO / SLO\n - Support for extracting roles from Keycloak AccessToken\n - Link to Keycloak Account page with back-link to the application\n\n## Setup\n\nImport the `demo` realm into Keycloak via\n\n```\nbin/standalone.sh -Dkeycloak.migration.action=import\n-Dkeycloak.migration.provider=singleFile -Dkeycloak.migration.file=/path/to/demo-realm.json\n-Dkeycloak.migration.strategy=OVERWRITE_EXISTING\n```\n\nKeycloak is assumed to run on port 8080 on localhost.  \nThe demo realm contains two users `tester` and `admin` both with password `test`.\n \nThe example runs on port 8082.\n\n"
  },
  {
    "path": "src/main/java/demo/SpringBoot2App.java",
    "content": "package demo;\n\nimport static org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI;\n\nimport java.security.Principal;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.security.access.prepost.PreAuthorize;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.config.http.SessionCreationPolicy;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.GrantedAuthority;\nimport org.springframework.security.core.annotation.AuthenticationPrincipal;\nimport org.springframework.security.core.authority.AuthorityUtils;\nimport org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;\nimport org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;\nimport org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;\nimport org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;\nimport org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;\nimport org.springframework.security.oauth2.core.OAuth2AuthenticationException;\nimport org.springframework.security.oauth2.core.OAuth2Error;\nimport org.springframework.security.oauth2.core.OAuth2ErrorCodes;\nimport org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;\nimport org.springframework.security.oauth2.core.oidc.user.OidcUser;\nimport org.springframework.security.oauth2.jwt.Jwt;\nimport org.springframework.security.oauth2.jwt.JwtDecoder;\nimport org.springframework.security.oauth2.jwt.JwtException;\nimport org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport;\nimport org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.client.RestTemplate;\nimport org.springframework.web.servlet.ModelAndView;\nimport org.springframework.web.util.UriComponentsBuilder;\n\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n@SpringBootApplication\npublic class SpringBoot2App {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(SpringBoot2App.class, args);\n\t}\n}\n\n@Configuration\n@EnableGlobalMethodSecurity(prePostEnabled = true)\nclass WebSecurityConfig {\n\n\t@Bean\n\tpublic WebSecurityConfigurerAdapter webSecurityConfigurer( //\n\t\t\t@Value(\"${kc.realm}\") String realm, //\n\t\t\tKeycloakOauth2UserService keycloakOidcUserService, //\n\t\t\tKeycloakLogoutHandler keycloakLogoutHandler //\n\t) {\n\t\treturn new WebSecurityConfigurerAdapter() {\n\t\t\t@Override\n\t\t\tpublic void configure(HttpSecurity http) throws Exception {\n\n\t\t\t\thttp\n\t\t\t\t\t\t// Configure session management to your needs.\n\t\t\t\t\t\t// I need this as a basis for a classic, server side rendered application\n\t\t\t\t\t\t.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and()\n\t\t\t\t\t\t// Depends on your taste. You can configure single paths here\n\t\t\t\t\t\t// or allow everything a I did and then use method based security\n\t\t\t\t\t\t// like in the controller below\n\t\t\t\t\t\t.authorizeRequests().anyRequest().permitAll().and()\n\t\t\t\t\t\t// Propagate logouts via /logout to Keycloak\n\t\t\t\t\t\t.logout().addLogoutHandler(keycloakLogoutHandler).and()\n\t\t\t\t\t\t// This is the point where OAuth2 login of Spring 5 gets enabled\n\t\t\t\t\t\t.oauth2Login().userInfoEndpoint().oidcUserService(keycloakOidcUserService).and()\n\t\t\t\t\t\t// I don't want a page with different clients as login options\n\t\t\t\t\t\t// So i use the constant from OAuth2AuthorizationRequestRedirectFilter\n\t\t\t\t\t\t// plus the configured realm as immediate redirect to Keycloak\n\t\t\t\t\t\t.loginPage(DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + \"/\" + realm);\n\t\t\t}\n\t\t};\n\t}\n\n\t@Bean\n\tKeycloakOauth2UserService keycloakOidcUserService(OAuth2ClientProperties oauth2ClientProperties) {\n\n\t\t// TODO use default JwtDecoder - where to grab?\n\t\tNimbusJwtDecoderJwkSupport jwtDecoder = new NimbusJwtDecoderJwkSupport(\n\t\t\t\toauth2ClientProperties.getProvider().get(\"keycloak\").getJwkSetUri());\n\n\t\tSimpleAuthorityMapper authoritiesMapper = new SimpleAuthorityMapper();\n\t\tauthoritiesMapper.setConvertToUpperCase(true);\n\n\t\treturn new KeycloakOauth2UserService(jwtDecoder, authoritiesMapper);\n\t}\n\n\t@Bean\n\tKeycloakLogoutHandler keycloakLogoutHandler() {\n\t\treturn new KeycloakLogoutHandler(new RestTemplate());\n\t}\n}\n\n@RequiredArgsConstructor\nclass KeycloakOauth2UserService extends OidcUserService {\n\n\tprivate final OAuth2Error INVALID_REQUEST = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST);\n\n\tprivate final JwtDecoder jwtDecoder;\n\n\tprivate final GrantedAuthoritiesMapper authoritiesMapper;\n\n\t/**\n\t * Augments {@link OidcUserService#loadUser(OidcUserRequest)} to add authorities\n\t * provided by Keycloak.\n\t * \n\t * Needed because {@link OidcUserService#loadUser(OidcUserRequest)} (currently)\n\t * does not provide a hook for adding custom authorities from a\n\t * {@link OidcUserRequest}.\n\t */\n\t@Override\n\tpublic OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {\n\n\t\tOidcUser user = super.loadUser(userRequest);\n\n\t\tSet<GrantedAuthority> authorities = new LinkedHashSet<>();\n\t\tauthorities.addAll(user.getAuthorities());\n\t\tauthorities.addAll(extractKeycloakAuthorities(userRequest));\n\n\t\treturn new DefaultOidcUser(authorities, userRequest.getIdToken(), user.getUserInfo(), \"preferred_username\");\n\t}\n\n\t/**\n\t * Extracts {@link GrantedAuthority GrantedAuthorities} from the AccessToken in\n\t * the {@link OidcUserRequest}.\n\t * \n\t * @param userRequest\n\t * @return\n\t */\n\tprivate Collection<? extends GrantedAuthority> extractKeycloakAuthorities(OidcUserRequest userRequest) {\n\n\t\tJwt token = parseJwt(userRequest.getAccessToken().getTokenValue());\n\n\t\t// Would be great if Spring Security would provide something like a plugable\n\t\t// OidcUserRequestAuthoritiesExtractor interface to hide the junk below...\n\n\t\t@SuppressWarnings(\"unchecked\")\n\t\tMap<String, Object> resourceMap = (Map<String, Object>) token.getClaims().get(\"resource_access\");\n\t\tString clientId = userRequest.getClientRegistration().getClientId();\n\n\t\t@SuppressWarnings(\"unchecked\")\n\t\tMap<String, Map<String, Object>> clientResource = (Map<String, Map<String, Object>>) resourceMap.get(clientId);\n\t\tif (CollectionUtils.isEmpty(clientResource)) {\n\t\t\treturn Collections.emptyList();\n\t\t}\n\n\t\t@SuppressWarnings(\"unchecked\")\n\t\tList<String> clientRoles = (List<String>) clientResource.get(\"roles\");\n\t\tif (CollectionUtils.isEmpty(clientRoles)) {\n\t\t\treturn Collections.emptyList();\n\t\t}\n\n\t\tCollection<? extends GrantedAuthority> authorities = AuthorityUtils\n\t\t\t\t.createAuthorityList(clientRoles.toArray(new String[0]));\n\t\tif (authoritiesMapper == null) {\n\t\t\treturn authorities;\n\t\t}\n\n\t\treturn authoritiesMapper.mapAuthorities(authorities);\n\t}\n\n\tprivate Jwt parseJwt(String accessTokenValue) {\n\t\ttry {\n\t\t\t// Token is already verified by spring security infrastructure\n\t\t\treturn jwtDecoder.decode(accessTokenValue);\n\t\t} catch (JwtException e) {\n\t\t\tthrow new OAuth2AuthenticationException(INVALID_REQUEST, e);\n\t\t}\n\t}\n}\n\n/**\n * Propagates logouts to Keycloak.\n * \n * Necessary because Spring Security 5 (currently) doesn't support\n * end-session-endpoints.\n */\n@Slf4j\n@RequiredArgsConstructor\nclass KeycloakLogoutHandler extends SecurityContextLogoutHandler {\n\n\tprivate final RestTemplate restTemplate;\n\n\t@Override\n\tpublic void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {\n\t\tsuper.logout(request, response, authentication);\n\n\t\tpropagateLogoutToKeycloak((OidcUser) authentication.getPrincipal());\n\t}\n\n\tprivate void propagateLogoutToKeycloak(OidcUser user) {\n\n\t\tString endSessionEndpoint = user.getIssuer() + \"/protocol/openid-connect/logout\";\n\n\t\tUriComponentsBuilder builder = UriComponentsBuilder //\n\t\t\t\t.fromUriString(endSessionEndpoint) //\n\t\t\t\t.queryParam(\"id_token_hint\", user.getIdToken().getTokenValue());\n\n\t\tResponseEntity<String> logoutResponse = restTemplate.getForEntity(builder.toUriString(), String.class);\n\t\tif (logoutResponse.getStatusCode().is2xxSuccessful()) {\n\t\t\tlog.info(\"Successfulley logged out in Keycloak\");\n\t\t} else {\n\t\t\tlog.info(\"Could not propagate logout to Keycloak\");\n\t\t}\n\t}\n}\n\n@Controller\nclass DemoController {\n\n\t@PreAuthorize(\"hasRole('ROLE_USER')\")\n\t@GetMapping(\"/protected\")\n\tpublic ModelAndView protectedPage(Principal principal) {\n\t\treturn new ModelAndView(\"app\", Collections.singletonMap(\"principal\", principal));\n\t}\n\n\t@PreAuthorize(\"hasRole('ROLE_ADMIN')\")\n\t@GetMapping(\"/admin\")\n\tpublic ModelAndView adminPage(Principal principal) {\n\t\treturn new ModelAndView(\"admin\", Collections.singletonMap(\"principal\", principal));\n\t}\n\n\t@GetMapping(\"/\")\n\tpublic String unprotectedPage(Model model, Principal principal) {\n\t\tmodel.addAttribute(\"principal\", principal);\n\t\treturn \"index\";\n\t}\n\n\t@GetMapping(\"/account\")\n\tpublic String redirectToAccountPage(@AuthenticationPrincipal OAuth2AuthenticationToken authToken) {\n\n\t\tif (authToken == null) {\n\t\t\treturn \"redirect:/\";\n\t\t}\n\n\t\tOidcUser user = (OidcUser) authToken.getPrincipal();\n\n\t\t// Provides a back-link to the application\n\t\treturn \"redirect:\" + user.getIssuer() + \"/account?referrer=\" + user.getIdToken().getAuthorizedParty();\n\t}\n}"
  },
  {
    "path": "src/main/resources/application.yml",
    "content": "server:\n  port: 8082\n\nkc:\n  base-url: http://localhost:8080/auth\n  realm: demo\n  realm-url: ${kc.base-url}/realms/${kc.realm}\n\nspring:\n  security:\n    oauth2:\n      client:\n        registration:\n          demo:\n            client-id: app-demo\n            client-name: Demo App\n            client-secret: e3f519b4-0272-4261-9912-8b7453ac4ecd\n            provider: keycloak\n            authorization-grant-type: authorization_code\n            scope: openid, profile\n            redirect-uri-template: \"{baseUrl}/login/oauth2/code/{registrationId}\"\n        provider:\n          keycloak:\n            authorization-uri: ${kc.realm-url}/protocol/openid-connect/auth\n            jwk-set-uri: ${kc.realm-url}/protocol/openid-connect/certs\n            token-uri: ${kc.realm-url}/protocol/openid-connect/token\n# would be cool if there was a end-session-uri to propagate logouts \n\n#  User info endpoint not needed since Keycloak uses self-contained value tokens\n#            user-info-uri: ${kc.realm-url}/protocol/openid-connect/userinfo\n            user-name-attribute: preferred_username"
  },
  {
    "path": "src/main/resources/templates/admin.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<title>Admin Area</title>\n</head>\n<body>\n   <h1>My cool App (Admin)</h1>\n   <div th:if=\"${principal}\">\n      <p th:text=\"${principal.getName()}\">Current User</p>\n   </div>\n   <a href=\"/\">Home</a>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/app.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<title>App</title>\n</head>\n<body>\n\t<h1>My cool App</h1>\n\t<div th:if=\"${principal}\">\n\t\t<p th:text=\"${principal.getName()}\">Current User</p>\n\t</div>\n\t<a href=\"/\">Home</a>\n</body>\n</html>"
  },
  {
    "path": "src/main/resources/templates/index.html",
    "content": "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\"\n\txmlns:th=\"http://www.thymeleaf.org\"\n\txmlns:sec=\"http://www.thymeleaf.org/extras/spring-security\">\n<head>\n<title>Demo App</title>\n</head>\n<body>\n\t<ul>\n\t\t<li><a href=\"#\" th:href=\"@{/protected}\">App</a></li>\n\t\t<li sec:authorize=\"hasRole('ROLE_ADMIN')\"><a href=\"#\"\n\t\t\tth:href=\"@{/admin}\">Admin</a></li>\n\t\t<li th:if=\"${principal}\"><a href=\"#\" th:href=\"@{/account}\">Account</a></li>\n\t</ul>\n\n\t<form action=\"logout\" method=\"post\" th:if=\"${principal}\">\n\t\t<input type=\"hidden\" th:name=\"${_csrf.parameterName}\"\n\t\t\tth:value=\"${_csrf.token}\" />\n\n\t\t<button>Logout</button>\n\t</form>\n</body>\n</html>"
  }
]