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