.NET Aspire Keycloak integration (Preview)
Includes: Hosting integration and Client integration
Keycloak is an open-source Identity and Access Management solution aimed at modern applications and services. The .NET Aspire Keycloak integration enables you to connect to existing Keycloak instances or create new instances from .NET with the quay.io/keycloak/keycloak
container image.
Hosting integration
The .NET Aspire Keycloak hosting integration models the server as the KeycloakResource type. To access these types and APIs, add the 📦 Aspire.Hosting.Keycloak NuGet package in the app host project.
dotnet add package Aspire.Hosting.Keycloak --prerelease
For more information, see dotnet add package or Manage package dependencies in .NET applications.
Add Keycloak resource
In your app host project, call AddKeycloak to add and return a Keycloak resource builder. Chain a call to the returned resource builder to configure the Keycloak.
var builder = DistributedApplication.CreateBuilder(args);
var keycloak = builder.AddKeycloak("keycloak", 8080);
var apiService = builder.AddProject<Projects.Keycloak_ApiService>("apiservice")
.WithReference(keycloak)
.WaitFor(keycloak);
builder.AddProject<Projects.Keycloak_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(keycloak)
.WithReference(apiService)
.WaitFor(apiService);
// After adding all resources, run the app...
Tip
For local development use a stable port for the Keycloak resource (8080
in the preceding example). It can be any port, but it should be stable to avoid issues with browser cookies that will persist OIDC tokens (which include the authority URL, with port) beyond the lifetime of the app host.
When .NET Aspire adds a container image to the app host, as shown in the preceding example with the quay.io/keycloak/keycloak
image, it creates a new Keycloak instance on your local machine. The Keycloak resource includes default credentials:
KEYCLOAK_ADMIN
: A value ofadmin
.KEYCLOAK_ADMIN_PASSWORD
: Randompassword
generated using the CreateDefaultPasswordParameter method.
When the app host runs, the password is stored in the app host's secret store. It's added to the Parameters
section, for example:
{
"Parameters:keycloak-password": "<THE_GENERATED_PASSWORD>"
}
The name of the parameter is keycloak-password
, but really it's just formatting the resource name with a -password
suffix. For more information, see Safe storage of app secrets in development in ASP.NET Core and Add Keycloak resource.
The WithReference method configures a connection in the ExampleProject
named keycloak
and the WaitFor instructs the app host to not start the dependant service until the keycloak
resource is ready.
Tip
If you'd rather connect to an existing Keycloak instance, call AddConnectionString instead. For more information, see Reference existing resources.
Add Keycloak resource with data volume
To add a data volume to the Keycloak resource, call the WithDataVolume method on the Keycloak resource:
var keycloak = builder.AddKeycloak("keycloak", 8080)
.WithDataVolume();
var apiService = builder.AddProject<Projects.Keycloak_ApiService>("apiservice")
.WithReference(keycloak)
.WaitFor(keycloak);
builder.AddProject<Projects.Keycloak_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(keycloak)
.WithReference(apiService)
.WaitFor(apiService);
// After adding all resources, run the app...
The data volume is used to persist the Keycloak data outside the lifecycle of its container. The data volume is mounted at the /opt/keycloak/data
path in the Keycloak container and when a name
parameter isn't provided, the name is generated at random. For more information on data volumes and details on why they're preferred over bind mounts, see Docker docs: Volumes.
Warning
The admin credentials are stored in the data volume. When using a data volume and if the credentials change, it will not work until you delete the volume.
Add Keycloak resource with data bind mount
To add a data bind mount to the Keycloak resource, call the WithDataBindMount method:
var keycloak = builder.AddKeycloak("keycloak", 8080)
.WithDataBindMount(@"C:\Keycloak\Data");
var apiService = builder.AddProject<Projects.Keycloak_ApiService>("apiservice")
.WithReference(keycloak)
.WaitFor(keycloak);
builder.AddProject<Projects.Keycloak_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(keycloak)
.WithReference(apiService)
.WaitFor(apiService);
// After adding all resources, run the app...
Important
Data bind mounts have limited functionality compared to volumes, which offer better performance, portability, and security, making them more suitable for production environments. However, bind mounts allow direct access and modification of files on the host system, ideal for development and testing where real-time changes are needed.
Data bind mounts rely on the host machine's filesystem to persist the Keycloak data across container restarts. The data bind mount is mounted at the C:\Keycloak\Data
on Windows (or /Keycloak/Data
on Unix) path on the host machine in the Keycloak container. For more information on data bind mounts, see Docker docs: Bind mounts.
Add Keycloak resource with parameters
When you want to explicitly provide the admin username and password used by the container image, you can provide these credentials as parameters. Consider the following alternative example:
var builder = DistributedApplication.CreateBuilder(args);
var username = builder.AddParameter("username");
var password = builder.AddParameter("password", secret: true);
var keycloak = builder.AddKeycloak("keycloak", 8080, username, password);
var apiService = builder.AddProject<Projects.Keycloak_ApiService>("apiservice")
.WithReference(keycloak)
.WaitFor(keycloak);
builder.AddProject<Projects.Keycloak_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(keycloak)
.WithReference(apiService)
.WaitFor(apiService);
// After adding all resources, run the app...
The username
and password
parameters are usually provided as environment variables or secrets. The parameters are used to set the KEYCLOAK_ADMIN
and KEYCLOAK_ADMIN_PASSWORD
environment variables in the container. For more information on providing parameters, see External parameters.
Add Keycloak resource with realm import
To import a realm into Keycloak, call the WithRealmImport method:
var builder = DistributedApplication.CreateBuilder(args);
var keycloak = builder.AddKeycloak("keycloak", 8080)
.WithDataVolume()
.WithRealmImport("./Realms");
var apiService = builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
.WithReference(keycloak)
.WaitFor(keycloak);
builder.AddProject<Projects.AspireApp_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(keycloak)
.WithReference(apiService)
.WaitFor(apiService);
builder.Build().Run();
The realm import files are mounted at /opt/keycloak/data/import
in the Keycloak container. Realm import files are JSON files that represent the realm configuration. For more information on realm import, see Keycloak docs: Importing a realm.
As an example, the following JSON file could be added to the app host project in a /Realms folder—to serve as a source realm configuration file:
Toggle realm JSON example.
{
"id": "86683c73-be28-4380-a014-6316c0404192",
"realm": "WeatherShop",
"notBefore": 0,
"defaultSignatureAlgorithm": "RS256",
"revokeRefreshToken": false,
"refreshTokenMaxReuse": 0,
"accessTokenLifespan": 300,
"accessTokenLifespanForImplicitFlow": 900,
"ssoSessionIdleTimeout": 1800,
"ssoSessionMaxLifespan": 36000,
"ssoSessionIdleTimeoutRememberMe": 0,
"ssoSessionMaxLifespanRememberMe": 0,
"offlineSessionIdleTimeout": 2592000,
"offlineSessionMaxLifespanEnabled": false,
"offlineSessionMaxLifespan": 5184000,
"clientSessionIdleTimeout": 0,
"clientSessionMaxLifespan": 0,
"clientOfflineSessionIdleTimeout": 0,
"clientOfflineSessionMaxLifespan": 0,
"accessCodeLifespan": 60,
"accessCodeLifespanUserAction": 300,
"accessCodeLifespanLogin": 1800,
"actionTokenGeneratedByAdminLifespan": 43200,
"actionTokenGeneratedByUserLifespan": 300,
"oauth2DeviceCodeLifespan": 600,
"oauth2DevicePollingInterval": 5,
"enabled": true,
"sslRequired": "external",
"registrationAllowed": true,
"registrationEmailAsUsername": false,
"rememberMe": false,
"verifyEmail": false,
"loginWithEmailAllowed": true,
"duplicateEmailsAllowed": false,
"resetPasswordAllowed": false,
"editUsernameAllowed": false,
"bruteForceProtected": false,
"permanentLockout": false,
"maxTemporaryLockouts": 0,
"maxFailureWaitSeconds": 900,
"minimumQuickLoginWaitSeconds": 60,
"waitIncrementSeconds": 60,
"quickLoginCheckMilliSeconds": 1000,
"maxDeltaTimeSeconds": 43200,
"failureFactor": 30,
"roles": {
"realm": [
{
"id": "79e15e0c-7084-4595-9066-c852bc5a6aca",
"name": "uma_authorization",
"description": "${role_uma_authorization}",
"composite": false,
"clientRole": false,
"containerId": "86683c73-be28-4380-a014-6316c0404192",
"attributes": {}
},
{
"id": "f2bd959d-ed9d-4409-af6d-206a4a52cc23",
"name": "default-roles-weathershop",
"description": "${role_default-roles}",
"composite": true,
"composites": {
"realm": [ "offline_access", "uma_authorization" ],
"client": {
"account": [ "view-profile", "manage-account" ]
}
},
"clientRole": false,
"containerId": "86683c73-be28-4380-a014-6316c0404192",
"attributes": {}
},
{
"id": "5e1d3cf6-c7ac-478d-a70c-4299abf58490",
"name": "offline_access",
"description": "${role_offline-access}",
"composite": false,
"clientRole": false,
"containerId": "86683c73-be28-4380-a014-6316c0404192",
"attributes": {}
}
],
"client": {
"realm-management": [
{
"id": "fe6e42fe-8629-40da-9afe-1179fc964988",
"name": "manage-users",
"description": "${role_manage-users}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "f82abb6c-239c-4533-afbd-a7aa03937204",
"name": "view-users",
"description": "${role_view-users}",
"composite": true,
"composites": {
"client": {
"realm-management": [ "query-groups", "query-users" ]
}
},
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "1eb57351-1302-45e5-924a-9b0dc337a2bb",
"name": "view-events",
"description": "${role_view-events}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "df3a077e-9bd4-4924-8281-cab7c7fd73e3",
"name": "manage-authorization",
"description": "${role_manage-authorization}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "d9fcb43a-3bad-492c-9af9-f199a6382064",
"name": "query-groups",
"description": "${role_query-groups}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "1dbdaf2b-a29c-4c54-86b7-d7c338e7672f",
"name": "realm-admin",
"description": "${role_realm-admin}",
"composite": true,
"composites": {
"client": {
"realm-management": [ "view-users", "manage-users", "view-events", "query-groups", "manage-authorization", "query-users", "manage-realm", "view-identity-providers", "create-client", "view-authorization", "query-clients", "view-clients", "query-realms", "impersonation", "view-realm", "manage-events", "manage-identity-providers", "manage-clients" ]
}
},
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "4c1ff7e3-cc1d-4b1d-a88f-fb71416c742a",
"name": "query-users",
"description": "${role_query-users}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "284b35f8-5bc2-4482-8769-81d3594df5a3",
"name": "manage-realm",
"description": "${role_manage-realm}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "7e872c38-8a22-469f-92ca-ec67e95d3c33",
"name": "view-identity-providers",
"description": "${role_view-identity-providers}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "9f4c2563-7575-461e-b2c8-b2b87f314cb9",
"name": "create-client",
"description": "${role_create-client}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "8f92f45c-bfa0-4a66-9812-334fe223c8be",
"name": "query-clients",
"description": "${role_query-clients}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "2a0143cf-ad90-4f68-bcb2-a50aa358b070",
"name": "view-authorization",
"description": "${role_view-authorization}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "95cc13bf-1342-445a-99fd-141522a7e777",
"name": "view-clients",
"description": "${role_view-clients}",
"composite": true,
"composites": {
"client": {
"realm-management": [ "query-clients" ]
}
},
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "109f4b83-ba7d-4036-91e7-7e169cd4c30c",
"name": "query-realms",
"description": "${role_query-realms}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "17bcb2b7-3a35-4089-85ea-1d034303b5d6",
"name": "impersonation",
"description": "${role_impersonation}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "21c51846-5f22-4318-82b7-9e64e2d256f4",
"name": "view-realm",
"description": "${role_view-realm}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "a0599e32-b53b-43bf-a7f6-ac0507ed277d",
"name": "manage-events",
"description": "${role_manage-events}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "e732e665-efb7-4df0-8843-b22bf2fe4717",
"name": "manage-identity-providers",
"description": "${role_manage-identity-providers}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
},
{
"id": "6d1b10f2-4c51-4279-8418-d4b82c17f203",
"name": "manage-clients",
"description": "${role_manage-clients}",
"composite": false,
"clientRole": true,
"containerId": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"attributes": {}
}
],
"WeatherWeb": [],
"security-admin-console": [],
"admin-cli": [],
"account-console": [],
"broker": [
{
"id": "7184260f-55c4-454a-bf67-dade5b74df7e",
"name": "read-token",
"description": "${role_read-token}",
"composite": false,
"clientRole": true,
"containerId": "db2ab30c-b83b-499e-9545-decdc906a372",
"attributes": {}
}
],
"Postman": [],
"weather.api": [],
"account": [
{
"id": "b4a01a53-3ed0-4e96-8fd1-efb0c143a45d",
"name": "view-groups",
"description": "${role_view-groups}",
"composite": false,
"clientRole": true,
"containerId": "65816a45-48d3-4856-b052-c65cb03881d3",
"attributes": {}
},
{
"id": "e9af1e5f-c0a5-4515-a77a-38fec79135d0",
"name": "delete-account",
"description": "${role_delete-account}",
"composite": false,
"clientRole": true,
"containerId": "65816a45-48d3-4856-b052-c65cb03881d3",
"attributes": {}
},
{
"id": "526cc4f7-6cf8-4f2b-8241-de0e60d2fd47",
"name": "manage-consent",
"description": "${role_manage-consent}",
"composite": true,
"composites": {
"client": {
"account": [ "view-consent" ]
}
},
"clientRole": true,
"containerId": "65816a45-48d3-4856-b052-c65cb03881d3",
"attributes": {}
},
{
"id": "cf93d42f-ffd9-4b3f-bf8d-55aa934f2fe3",
"name": "view-applications",
"description": "${role_view-applications}",
"composite": false,
"clientRole": true,
"containerId": "65816a45-48d3-4856-b052-c65cb03881d3",
"attributes": {}
},
{
"id": "f3b44155-fe06-4fea-8b8f-6954f54d48bb",
"name": "view-profile",
"description": "${role_view-profile}",
"composite": false,
"clientRole": true,
"containerId": "65816a45-48d3-4856-b052-c65cb03881d3",
"attributes": {}
},
{
"id": "65a74b6a-a00f-46b6-8ead-6c051e78c37e",
"name": "manage-account",
"description": "${role_manage-account}",
"composite": true,
"composites": {
"client": {
"account": [ "manage-account-links" ]
}
},
"clientRole": true,
"containerId": "65816a45-48d3-4856-b052-c65cb03881d3",
"attributes": {}
},
{
"id": "c914cc47-8a49-4f30-9851-6f639c4e7adf",
"name": "manage-account-links",
"description": "${role_manage-account-links}",
"composite": false,
"clientRole": true,
"containerId": "65816a45-48d3-4856-b052-c65cb03881d3",
"attributes": {}
},
{
"id": "261d0db4-28c7-4900-a156-01ab4e2483e5",
"name": "view-consent",
"description": "${role_view-consent}",
"composite": false,
"clientRole": true,
"containerId": "65816a45-48d3-4856-b052-c65cb03881d3",
"attributes": {}
}
]
}
},
"groups": [],
"defaultRole": {
"id": "f2bd959d-ed9d-4409-af6d-206a4a52cc23",
"name": "default-roles-weathershop",
"description": "${role_default-roles}",
"composite": true,
"clientRole": false,
"containerId": "86683c73-be28-4380-a014-6316c0404192"
},
"requiredCredentials": [ "password" ],
"otpPolicyType": "totp",
"otpPolicyAlgorithm": "HmacSHA1",
"otpPolicyInitialCounter": 0,
"otpPolicyDigits": 6,
"otpPolicyLookAheadWindow": 1,
"otpPolicyPeriod": 30,
"otpPolicyCodeReusable": false,
"otpSupportedApplications": [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ],
"localizationTexts": {},
"webAuthnPolicyRpEntityName": "keycloak",
"webAuthnPolicySignatureAlgorithms": [ "ES256" ],
"webAuthnPolicyRpId": "",
"webAuthnPolicyAttestationConveyancePreference": "not specified",
"webAuthnPolicyAuthenticatorAttachment": "not specified",
"webAuthnPolicyRequireResidentKey": "not specified",
"webAuthnPolicyUserVerificationRequirement": "not specified",
"webAuthnPolicyCreateTimeout": 0,
"webAuthnPolicyAvoidSameAuthenticatorRegister": false,
"webAuthnPolicyAcceptableAaguids": [],
"webAuthnPolicyExtraOrigins": [],
"webAuthnPolicyPasswordlessRpEntityName": "keycloak",
"webAuthnPolicyPasswordlessSignatureAlgorithms": [ "ES256" ],
"webAuthnPolicyPasswordlessRpId": "",
"webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
"webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
"webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
"webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
"webAuthnPolicyPasswordlessCreateTimeout": 0,
"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
"webAuthnPolicyPasswordlessAcceptableAaguids": [],
"webAuthnPolicyPasswordlessExtraOrigins": [],
"scopeMappings": [
{
"clientScope": "offline_access",
"roles": [ "offline_access" ]
}
],
"clientScopeMappings": {
"account": [
{
"client": "account-console",
"roles": [ "manage-account", "view-groups" ]
}
]
},
"clients": [
{
"id": "bd03dd61-71bf-4f50-acfa-bfc2444ee1d2",
"clientId": "Postman",
"name": "",
"description": "",
"rootUrl": "",
"adminUrl": "",
"baseUrl": "",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [ "https://oauth.pstmn.io/v1/callback" ],
"webOrigins": [ "https://oauth.pstmn.io" ],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false,
"publicClient": true,
"frontchannelLogout": true,
"protocol": "openid-connect",
"attributes": {
"oidc.ciba.grant.enabled": "false",
"client.secret.creation.time": "1718111570",
"backchannel.logout.session.required": "true",
"post.logout.redirect.uris": "+",
"oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false",
"backchannel.logout.revoke.offline.tokens": "false"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true,
"nodeReRegistrationTimeout": -1,
"defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email" ],
"optionalClientScopes": [ "address", "phone", "offline_access", "weather:all", "microprofile-jwt" ]
},
{
"id": "016c17d1-8e0f-4a67-9116-86b4691ba99c",
"clientId": "WeatherWeb",
"name": "",
"description": "",
"rootUrl": "",
"adminUrl": "",
"baseUrl": "",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [ "https://localhost:7085/signin-oidc" ],
"webOrigins": [ "https://localhost:7085" ],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false,
"publicClient": true,
"frontchannelLogout": true,
"protocol": "openid-connect",
"attributes": {
"oidc.ciba.grant.enabled": "false",
"post.logout.redirect.uris": "https://localhost:7085/signout-callback-oidc",
"oauth2.device.authorization.grant.enabled": "false",
"backchannel.logout.session.required": "true",
"backchannel.logout.revoke.offline.tokens": "false"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true,
"nodeReRegistrationTimeout": -1,
"defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email" ],
"optionalClientScopes": [ "address", "phone", "offline_access", "weather:all", "microprofile-jwt" ]
},
{
"id": "65816a45-48d3-4856-b052-c65cb03881d3",
"clientId": "account",
"name": "${client_account}",
"rootUrl": "${authBaseUrl}",
"baseUrl": "/realms/WeatherShop/account/",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [ "/realms/WeatherShop/account/*" ],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false,
"publicClient": true,
"frontchannelLogout": false,
"protocol": "openid-connect",
"attributes": {
"post.logout.redirect.uris": "+"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": false,
"nodeReRegistrationTimeout": 0,
"defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email" ],
"optionalClientScopes": [ "address", "phone", "offline_access", "microprofile-jwt" ]
},
{
"id": "437fda77-3ba1-4d7b-b192-808e4e62833b",
"clientId": "account-console",
"name": "${client_account-console}",
"rootUrl": "${authBaseUrl}",
"baseUrl": "/realms/WeatherShop/account/",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [ "/realms/WeatherShop/account/*" ],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false,
"publicClient": true,
"frontchannelLogout": false,
"protocol": "openid-connect",
"attributes": {
"post.logout.redirect.uris": "+",
"pkce.code.challenge.method": "S256"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": false,
"nodeReRegistrationTimeout": 0,
"protocolMappers": [
{
"id": "e4606d8a-a581-402c-9290-4e3b988f2090",
"name": "audience resolve",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-resolve-mapper",
"consentRequired": false,
"config": {}
}
],
"defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email" ],
"optionalClientScopes": [ "address", "phone", "offline_access", "microprofile-jwt" ]
},
{
"id": "f13fd042-6931-4032-a0ba-f63b364f8d56",
"clientId": "admin-cli",
"name": "${client_admin-cli}",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": false,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": true,
"serviceAccountsEnabled": false,
"publicClient": true,
"frontchannelLogout": false,
"protocol": "openid-connect",
"attributes": {
"post.logout.redirect.uris": "+"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": false,
"nodeReRegistrationTimeout": 0,
"defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email" ],
"optionalClientScopes": [ "address", "phone", "offline_access", "microprofile-jwt" ]
},
{
"id": "db2ab30c-b83b-499e-9545-decdc906a372",
"clientId": "broker",
"name": "${client_broker}",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": true,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false,
"publicClient": false,
"frontchannelLogout": false,
"protocol": "openid-connect",
"attributes": {
"post.logout.redirect.uris": "+"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": false,
"nodeReRegistrationTimeout": 0,
"defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email" ],
"optionalClientScopes": [ "address", "phone", "offline_access", "microprofile-jwt" ]
},
{
"id": "0aa2db92-8cc4-490f-a084-55f5b889613a",
"clientId": "realm-management",
"name": "${client_realm-management}",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [],
"webOrigins": [],
"notBefore": 0,
"bearerOnly": true,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false,
"publicClient": false,
"frontchannelLogout": false,
"protocol": "openid-connect",
"attributes": {
"post.logout.redirect.uris": "+"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": false,
"nodeReRegistrationTimeout": 0,
"defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email" ],
"optionalClientScopes": [ "address", "phone", "offline_access", "microprofile-jwt" ]
},
{
"id": "e0cc9cef-924e-4799-a921-4811f3bb5d65",
"clientId": "security-admin-console",
"name": "${client_security-admin-console}",
"rootUrl": "${authAdminUrl}",
"baseUrl": "/admin/WeatherShop/console/",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [ "/admin/WeatherShop/console/*" ],
"webOrigins": [ "+" ],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false,
"publicClient": true,
"frontchannelLogout": false,
"protocol": "openid-connect",
"attributes": {
"post.logout.redirect.uris": "+",
"pkce.code.challenge.method": "S256"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": false,
"nodeReRegistrationTimeout": 0,
"protocolMappers": [
{
"id": "254ac20c-6701-4095-82c6-6abd6669b9de",
"name": "locale",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "locale",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "locale",
"jsonType.label": "String"
}
}
],
"defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email" ],
"optionalClientScopes": [ "address", "phone", "offline_access", "microprofile-jwt" ]
},
{
"id": "4b5953fd-b218-41be-b061-58f37c1c7d26",
"clientId": "weather.api",
"name": "",
"description": "",
"rootUrl": "",
"adminUrl": "",
"baseUrl": "",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"secret": "**********",
"redirectUris": [ "/*" ],
"webOrigins": [ "/*" ],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"serviceAccountsEnabled": false,
"publicClient": false,
"frontchannelLogout": true,
"protocol": "openid-connect",
"attributes": {
"oidc.ciba.grant.enabled": "false",
"client.secret.creation.time": "1718111354",
"backchannel.logout.session.required": "true",
"post.logout.redirect.uris": "+",
"oauth2.device.authorization.grant.enabled": "false",
"backchannel.logout.revoke.offline.tokens": "false"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true,
"nodeReRegistrationTimeout": -1,
"defaultClientScopes": [ "web-origins", "acr", "profile", "roles", "email" ],
"optionalClientScopes": [ "address", "phone", "offline_access", "microprofile-jwt" ]
}
],
"clientScopes": [
{
"id": "2a6322a2-2f6a-469f-b3c7-d0922db4ad46",
"name": "phone",
"description": "OpenID Connect built-in scope: phone",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "true",
"consent.screen.text": "${phoneScopeConsentText}"
},
"protocolMappers": [
{
"id": "ab515c55-d65b-42d3-9d3c-18921a8df065",
"name": "phone number",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "phoneNumber",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "phone_number",
"jsonType.label": "String"
}
},
{
"id": "bfaa5db4-137c-4824-bfae-ed77762872c2",
"name": "phone number verified",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "phoneNumberVerified",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "phone_number_verified",
"jsonType.label": "boolean"
}
}
]
},
{
"id": "52fc55cb-995e-4aa2-95ae-3b3d6601dc41",
"name": "weather:all",
"description": "",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "true",
"gui.order": "",
"consent.screen.text": ""
},
"protocolMappers": [
{
"id": "06d03e02-1e56-4bde-911d-bcf28aeba90f",
"name": "weather api audience",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-mapper",
"consentRequired": false,
"config": {
"included.client.audience": "weather.api",
"introspection.token.claim": "true",
"userinfo.token.claim": "false",
"id.token.claim": "false",
"lightweight.claim": "false",
"access.token.claim": "true"
}
}
]
},
{
"id": "292ded65-c85e-4c56-ad4d-8e886b9bb261",
"name": "email",
"description": "OpenID Connect built-in scope: email",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "true",
"consent.screen.text": "${emailScopeConsentText}"
},
"protocolMappers": [
{
"id": "42743882-7e0a-455e-b6a3-794ec8bf0f22",
"name": "email verified",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-property-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "emailVerified",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "email_verified",
"jsonType.label": "boolean"
}
},
{
"id": "b6dd2af9-e583-4d01-95fa-3f0db3ab0129",
"name": "email",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "email",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "email",
"jsonType.label": "String"
}
}
]
},
{
"id": "09a76939-4997-49f5-b88e-dfe54a2819f5",
"name": "offline_access",
"description": "OpenID Connect built-in scope: offline_access",
"protocol": "openid-connect",
"attributes": {
"consent.screen.text": "${offlineAccessScopeConsentText}",
"display.on.consent.screen": "true"
}
},
{
"id": "95ff8627-716e-49f0-b960-52185409d628",
"name": "profile",
"description": "OpenID Connect built-in scope: profile",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "true",
"consent.screen.text": "${profileScopeConsentText}"
},
"protocolMappers": [
{
"id": "b1ae43d1-9d52-40cd-9c6a-a8557ea63f9a",
"name": "picture",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "picture",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "picture",
"jsonType.label": "String"
}
},
{
"id": "b9e09b82-3e67-4175-b34a-419b24a13a7f",
"name": "zoneinfo",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "zoneinfo",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "zoneinfo",
"jsonType.label": "String"
}
},
{
"id": "06e88533-d2cc-4ae3-a25a-a17e93f69dee",
"name": "nickname",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "nickname",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "nickname",
"jsonType.label": "String"
}
},
{
"id": "b697c055-2fb9-4985-8919-33d9f524eaa9",
"name": "full name",
"protocol": "openid-connect",
"protocolMapper": "oidc-full-name-mapper",
"consentRequired": false,
"config": {
"id.token.claim": "true",
"introspection.token.claim": "true",
"access.token.claim": "true",
"userinfo.token.claim": "true"
}
},
{
"id": "70663048-2110-4271-a8f4-105e77fe2905",
"name": "profile",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "profile",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "profile",
"jsonType.label": "String"
}
},
{
"id": "85c992ed-4971-41f1-a4b8-c6263b29dff8",
"name": "website",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "website",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "website",
"jsonType.label": "String"
}
},
{
"id": "49e1d494-a72e-49de-a5de-8c2ad752205c",
"name": "birthdate",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "birthdate",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "birthdate",
"jsonType.label": "String"
}
},
{
"id": "a746724f-7622-4ad4-91ef-811da6c735ad",
"name": "updated at",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "updatedAt",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "updated_at",
"jsonType.label": "long"
}
},
{
"id": "d647d13f-9f96-49f3-b32a-62ad63c37d0e",
"name": "gender",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "gender",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "gender",
"jsonType.label": "String"
}
},
{
"id": "86204f6f-16ce-4c9f-9fca-f66b3f292554",
"name": "given name",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "firstName",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "given_name",
"jsonType.label": "String"
}
},
{
"id": "f4005bd9-18d2-4456-9e7c-98c5a637f063",
"name": "locale",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "locale",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "locale",
"jsonType.label": "String"
}
},
{
"id": "04b20a5a-1588-476c-a465-26a691320510",
"name": "family name",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "lastName",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "family_name",
"jsonType.label": "String"
}
},
{
"id": "f812580a-7863-44c3-bcf0-c3f441f0194e",
"name": "middle name",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "middleName",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "middle_name",
"jsonType.label": "String"
}
},
{
"id": "c2ae83c9-62c2-4a65-adef-c1d6fd126ec4",
"name": "username",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "username",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "preferred_username",
"jsonType.label": "String"
}
}
]
},
{
"id": "3ab2520f-feb4-43fd-9256-fa9f3e521aa7",
"name": "address",
"description": "OpenID Connect built-in scope: address",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "true",
"consent.screen.text": "${addressScopeConsentText}"
},
"protocolMappers": [
{
"id": "b083371e-07ae-4b01-9e8c-6a54b396359f",
"name": "address",
"protocol": "openid-connect",
"protocolMapper": "oidc-address-mapper",
"consentRequired": false,
"config": {
"user.attribute.formatted": "formatted",
"user.attribute.country": "country",
"introspection.token.claim": "true",
"user.attribute.postal_code": "postal_code",
"userinfo.token.claim": "true",
"user.attribute.street": "street",
"id.token.claim": "true",
"user.attribute.region": "region",
"access.token.claim": "true",
"user.attribute.locality": "locality"
}
}
]
},
{
"id": "fda66a99-e8b6-49e6-9186-0a7026ec0275",
"name": "web-origins",
"description": "OpenID Connect scope for add allowed web origins to the access token",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "false",
"display.on.consent.screen": "false",
"consent.screen.text": ""
},
"protocolMappers": [
{
"id": "4b12d4de-8c05-4251-9c8f-f801cfa3bf2a",
"name": "allowed web origins",
"protocol": "openid-connect",
"protocolMapper": "oidc-allowed-origins-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"access.token.claim": "true"
}
}
]
},
{
"id": "581928cd-35d7-4c79-a9d1-4e1c9c8ade7e",
"name": "acr",
"description": "OpenID Connect scope for add acr (authentication context class reference) to the token",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "false",
"display.on.consent.screen": "false"
},
"protocolMappers": [
{
"id": "d664d3db-be9f-4fee-a72a-be6a295c47f5",
"name": "acr loa level",
"protocol": "openid-connect",
"protocolMapper": "oidc-acr-mapper",
"consentRequired": false,
"config": {
"id.token.claim": "true",
"introspection.token.claim": "true",
"access.token.claim": "true",
"userinfo.token.claim": "true"
}
}
]
},
{
"id": "9ac2f136-a665-4550-ac77-cc61a1cd1e95",
"name": "role_list",
"description": "SAML role list",
"protocol": "saml",
"attributes": {
"consent.screen.text": "${samlRoleListScopeConsentText}",
"display.on.consent.screen": "true"
},
"protocolMappers": [
{
"id": "040520c7-9dfb-4f9d-a93e-17e3267b1517",
"name": "role list",
"protocol": "saml",
"protocolMapper": "saml-role-list-mapper",
"consentRequired": false,
"config": {
"single": "false",
"attribute.nameformat": "Basic",
"attribute.name": "Role"
}
}
]
},
{
"id": "f0ff8363-c507-4113-adc0-47f6b346de26",
"name": "roles",
"description": "OpenID Connect scope for add user roles to the access token",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "false",
"display.on.consent.screen": "true",
"consent.screen.text": "${rolesScopeConsentText}"
},
"protocolMappers": [
{
"id": "13aa2234-81bf-4018-a67c-d657045eac1f",
"name": "client roles",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-client-role-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"multivalued": "true",
"user.attribute": "foo",
"access.token.claim": "true",
"claim.name": "resource_access.${client_id}.roles",
"jsonType.label": "String"
}
},
{
"id": "d0b63e0d-5543-41dc-baf6-1c6987d6a18d",
"name": "audience resolve",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-resolve-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"access.token.claim": "true"
}
},
{
"id": "38881c98-4009-412b-b924-d36f55273f3e",
"name": "realm roles",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-realm-role-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"multivalued": "true",
"user.attribute": "foo",
"access.token.claim": "true",
"claim.name": "realm_access.roles",
"jsonType.label": "String"
}
}
]
},
{
"id": "b8a70a2a-a24d-4862-ad4b-dd737b60f7ce",
"name": "microprofile-jwt",
"description": "Microprofile - JWT built-in scope",
"protocol": "openid-connect",
"attributes": {
"include.in.token.scope": "true",
"display.on.consent.screen": "false"
},
"protocolMappers": [
{
"id": "4eb888ff-b503-4506-b35c-ea0ac0ff3cd3",
"name": "groups",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-realm-role-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"multivalued": "true",
"userinfo.token.claim": "true",
"user.attribute": "foo",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "groups",
"jsonType.label": "String"
}
},
{
"id": "d39896cb-3f45-4a62-a254-f7d0eb10e60a",
"name": "upn",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"userinfo.token.claim": "true",
"user.attribute": "username",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "upn",
"jsonType.label": "String"
}
}
]
}
],
"defaultDefaultClientScopes": [ "role_list", "profile", "email", "roles", "web-origins", "acr" ],
"defaultOptionalClientScopes": [ "offline_access", "address", "phone", "microprofile-jwt", "weather:all" ],
"browserSecurityHeaders": {
"contentSecurityPolicyReportOnly": "",
"xContentTypeOptions": "nosniff",
"referrerPolicy": "no-referrer",
"xRobotsTag": "none",
"xFrameOptions": "SAMEORIGIN",
"contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
"xXSSProtection": "1; mode=block",
"strictTransportSecurity": "max-age=31536000; includeSubDomains"
},
"smtpServer": {},
"eventsEnabled": false,
"eventsListeners": [ "jboss-logging" ],
"enabledEventTypes": [],
"adminEventsEnabled": false,
"adminEventsDetailsEnabled": false,
"identityProviders": [],
"identityProviderMappers": [],
"components": {
"org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [
{
"id": "887848c6-60f6-47ac-ae7f-62f8a5608a4b",
"name": "Trusted Hosts",
"providerId": "trusted-hosts",
"subType": "anonymous",
"subComponents": {},
"config": {
"host-sending-registration-request-must-match": [ "true" ],
"client-uris-must-match": [ "true" ]
}
},
{
"id": "4333143f-bf59-419a-99e2-2cce8a5d414a",
"name": "Consent Required",
"providerId": "consent-required",
"subType": "anonymous",
"subComponents": {},
"config": {}
},
{
"id": "1ac2db3a-57a1-4567-bc2b-80a2b0c96b71",
"name": "Max Clients Limit",
"providerId": "max-clients",
"subType": "anonymous",
"subComponents": {},
"config": {
"max-clients": [ "200" ]
}
},
{
"id": "adb4b546-6386-46e0-8ce9-80bacbba2afe",
"name": "Allowed Protocol Mapper Types",
"providerId": "allowed-protocol-mappers",
"subType": "authenticated",
"subComponents": {},
"config": {
"allowed-protocol-mapper-types": [ "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper", "oidc-usermodel-property-mapper" ]
}
},
{
"id": "241c5dea-68b9-4684-a816-80b08ef86bff",
"name": "Full Scope Disabled",
"providerId": "scope",
"subType": "anonymous",
"subComponents": {},
"config": {}
},
{
"id": "6b0e159c-33dc-492b-9d88-421973015466",
"name": "Allowed Protocol Mapper Types",
"providerId": "allowed-protocol-mappers",
"subType": "anonymous",
"subComponents": {},
"config": {
"allowed-protocol-mapper-types": [ "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-full-name-mapper" ]
}
},
{
"id": "730409bc-ce7e-4b64-a870-946aeba9f65b",
"name": "Allowed Client Scopes",
"providerId": "allowed-client-templates",
"subType": "anonymous",
"subComponents": {},
"config": {
"allow-default-scopes": [ "true" ]
}
},
{
"id": "0b4b8c74-20b6-4902-b971-9b97001da41e",
"name": "Allowed Client Scopes",
"providerId": "allowed-client-templates",
"subType": "authenticated",
"subComponents": {},
"config": {
"allow-default-scopes": [ "true" ]
}
}
],
"org.keycloak.keys.KeyProvider": [
{
"id": "c08db9a9-0d9d-4b56-96d5-7f2b1d4528df",
"name": "rsa-generated",
"providerId": "rsa-generated",
"subComponents": {},
"config": {
"privateKey": [ "MIIEowIBAAKCAQEAyJtAKWr1DdQmh9Nxp2LUGOrc5OA+rdXkV6+kOT21wVsIP/1bg6HekqfMySZhIxlALfegc90j0mrqkolb5s7axotTwwABwIvgxW5hHIQ4huntiZUYPUuf4m51dwyLs/GM1gSbzs9ciBKC5i4S21CQzuGp0QHpyOOn1kQZd0vYSGjpG3ewMYphJEfd60TQP74RcqASNoOaS3lU7+5SCQuiff1fSZYqYvIFmK3rcNrauTSryx6rh935ODSdYzQN0XA6g1WJK2hbBlBJJzeAj/CXXcBaw7aB1AoC7kjJ7XaYmHdC+7zIYhvNKcGtFhrMjoOVnJM9PiRMrk7ous7XAmKc6QIDAQABAoIBAC4qjm5Js1oqnfBpwJDrPVD7sfjJQ5t5azqjzQkwUrUMGF6zlZ06QhDhpY8QMlAjxkGd6JLpjE4nNVMiYeBA8Be7pjvs8zpG5qRBBf/MTP79dGFSitjGX+X6EjXi0P7JIuZ4+otybMLS8cV7ynKm/KBjzhMv28fT3oMAupSaA40MESKVD8BDR0bNQ6H3h1xrq2+81xViFsle9qcrZjJzCz/rttNi3DUct5IeJwc9Wai937L6H/BU5eBd9vQHM5raLL0iDSF5CQF2tE/j3hq8kdpRm9XRUm/0WaXOz8Il96GfSEUXLVvKnLdHu7qYbqKKBYI7B3xz8VYiHgDvBMqiBzUCgYEA9Sd/EijWpXAAaFOJk75BOu0sSjZHjoGbaLE1XWsQyM1fkFT9kxQ+8/kDiHSJal+utoEIrMWK/KdrrIjT0TXbWKCarV+ebgCt9dkTd6Or2SUku5k0TMSMoVEI2KxI6ZHvCz2Vxe8Ahbao28u8xOGRQYSs5ynvH0oBTex+RP3sv6UCgYEA0Xs55XdSn1PGazAuZYk9ZKJhCovdalYdjnJYxuSPfBgHV4CIHdhHvd/hohumMakQsnRDmJzbk/uFlqJecZtcQ/DukGylC/6dvfp6prUrVhghK+7+Bnry7zfQ9rMWslrlhf9ZTrQ8F9pssCtgAfs+Pfj0zF5DxQqFqF3wz12sJPUCgYATR5HkubV3uUEu8zLknZe/rJtJEs+501OHfjg2Ko9dW1linmx6vqLcyP6QIqoT5YZ179vgyoBNslTzcqdF0rh3VdoUPGrXN9J2fSXcyNBg+VzULA5C40oz/Y12jMYHKGTmO2el80/VNDI/Ztxnl123C1oVq+SUT1ue5zRe9KFDyQKBgBihnqsmnqZxWVFdNvdlbbyZg0OUMpLAUXVgaKPqWBzFToexa0/nEHh5DLTc/2uzb20sUo5tUzxRROHzcZt2IyEyATsmKzn/1Fh0TVuwzcmvyKa70U69wjbynzWC1VZfbcGVxtCETNSZMFJ+pylUe3sZ/N7S7rEKjbDAawJXB1jJAoGBAOZF4M9C1GLCZqt4RrF1MBI0Q+7Im45Hvr0FSck0y9xLpl9yolQREWoiCo5+WM54YMeSWu0rzBsLAjCoFpIX2cWcICsdPAnyyjIMPmuGt/uUaIWmq/ZRAsqkOW0sqxUMggjytNCtvdCyfQOcKsEHpBKrA6z+8l/3Z1RQFwan+VPs" ],
"certificate": [ "MIICpTCCAY0CBgGQcJfMUjANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtXZWF0aGVyU2hvcDAeFw0yNDA3MDEyMzE2NTRaFw0zNDA3MDEyMzE4MzRaMBYxFDASBgNVBAMMC1dlYXRoZXJTaG9wMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyJtAKWr1DdQmh9Nxp2LUGOrc5OA+rdXkV6+kOT21wVsIP/1bg6HekqfMySZhIxlALfegc90j0mrqkolb5s7axotTwwABwIvgxW5hHIQ4huntiZUYPUuf4m51dwyLs/GM1gSbzs9ciBKC5i4S21CQzuGp0QHpyOOn1kQZd0vYSGjpG3ewMYphJEfd60TQP74RcqASNoOaS3lU7+5SCQuiff1fSZYqYvIFmK3rcNrauTSryx6rh935ODSdYzQN0XA6g1WJK2hbBlBJJzeAj/CXXcBaw7aB1AoC7kjJ7XaYmHdC+7zIYhvNKcGtFhrMjoOVnJM9PiRMrk7ous7XAmKc6QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAeDhADaUkVzu1o8CvCfU9oa6hGsJa+2qFeUPQnG7HZAQ07MjQ/RZgMMOmdhspZIuaf+Yrx/My8VDphKzNtb2eNHgFVVQDy1F1jVy9z+t7xCwX3UfjtVNMp3tMmzWUEi0pckW0mq4Bz3w0+dKPw8z0K2c19dVN1NHDViqFghB+77tO8JguwTDE8fkmXjLixDCcenBCPXjxNWmhXgOMF1wKhlq1h0+SaKt/F2P/WzyoYu6tz8qVysQvv4knB/HEGjSji+DN+uJFE4RJG+B5X+vp5LHvlYKIROQ7/aSzvCjx7zrslmcTsSTL3F1k2Ox2Hz+rGIcA8sGqbj+W5+nKxRbad" ],
"priority": [ "100" ]
}
},
{
"id": "9adc7ed1-f51b-48d4-9d52-96b46abefa18",
"name": "aes-generated",
"providerId": "aes-generated",
"subComponents": {},
"config": {
"kid": [ "eb1853e7-ac8c-4e8f-8b4f-9ea28a71da76" ],
"secret": [ "Jges9iPdpfx0aivf3RUUpw" ],
"priority": [ "100" ]
}
},
{
"id": "f4b81876-91be-46f3-9050-c351cd1531af",
"name": "rsa-enc-generated",
"providerId": "rsa-enc-generated",
"subComponents": {},
"config": {
"privateKey": [ "MIIEowIBAAKCAQEAlP+NrT2KVZpdrbPoTsMO7MqeXYDeJNl7IXjY0hCb7p1iB6YLOr/lA5ryk/CIHI05HRt+AEYFac87mb51SEvAa9cHjQ00v7t6hoYV1esyRmB0Nnf8AAEq9GoZxX9nUsIMcExQ3gHkF56kidYtjQSgl5SlwgdvlsjRiDP9ZJlsWTBb+8v0OCCbQLZFl93IlTZ7QlaxXoB0dCuuLNyBpELFbc0+JeB+1P/Dw5azUKGdp3ng2K9IrtDBiMh+KicpLZeBpUlqdKqyI2WvwruL1SlqH/ymWCxseRH0Z9VZ30MfW8C5fHq3qnLQp0OWDa7Re/pRbCZPabivDkZCtuWUeAVbRwIDAQABAoIBAAoioBaKuyA7kefA9yp0Zk2BMuiVXYcQLCoIuGcBrjm7BvISP21NpFxsa9fYYsneaWYrepS2LqQV7q30oLG8RWiQhfj4TwBD1n/UGyQkDZVv9jfGTaQKcEuT9BDVK8gbXxE8f7u6UTOyHOsrYInZKLtm5yedrd+J5YboUnJHZXFjmCpuyap8zJQdczUpZeLkj4bRqEHYlM1a5vfMFpr2+k4/Nqo36CCaGzIcwtYxnC002rL7ra9MaR1fy5KHtcoYQeePuPvXu1UxBU01+W1QmIsw+KmXftdtWYAMcVFkHDs+22h3mCxRhQqcxmL1LUP9FfGzrWiX4eTduw4YOkzO7+ECgYEAx732U2G7Qdp1uXsVGE7ceFcrpl/LOTaL8eEtULBiFRdrn5LOTAptpoDPB8vYCwIQSNrBWXNqTiDubOBcL7sumBK2i4Omtzk/USuMcJmSiMcHaANa/ZNK9nqtwMACqXpIPEkpofzfgBSaRYY1KxaWLbepyLjqviADV98zOI4qY28CgYEAvvbNd+C0pi5u/EkUxhRdxwCxICfkDYjArcjPU3ZBjIyAzmJ08wU+3CDm2sgts1TX+D7MPsRLqsaM8vMB+BR1xo3FfP/nqNvjYkChACtHhvkWGVE/qf3/53NNa4lKeVz8h1iV18dvLICj+V+lvUyQPuER4cA8Kzs7dObl52V6OakCgYB5bSkvPW2aNhV1QbbsRRzQZ6XYicnAqUFgNRTYRbIKwmch5hxVq81G+G1jfu+CmamOsLX0DC7m+iwXsjk4pyFHP7ELlWgnYLz2OnQxC5tCXURKXifVmdJrjt7MG65Cm10IkS2nFVRFx8CVXWY7IIsBlfK4XHoQROPjaoP38K0iLwKBgQCho6RdkR04ANu+vllQJNMP7B0Be+KENjnpn60mF1X6kr9AcoRNZCZGC698hq5wOiOoo/ccNelafz+1MU58X00lqMD+QlojSySX+N6OlxOvQs2a1nQN/sqKbcWdfZNFURkLs0b6Y3xN7gFdxsEyj0kVgEszjBUh/rwgAoWdrP6dKQKBgD2b7GG1/TPTBfOvvE7q7xa5IlTMUbBU2yY8H6XvDgfG5KUXXFpqINTOE4OjuyVwJRwE2/GQGayfZvfa+LGkW8Hy6Iz/vaa1Brjodza/2PblM5v1t96xA0WQDime8okJN0q7ocbLfQnT0+3TVMbvCjeBtOqmMOJT3EijpAqVbR6N" ],
"certificate": [ "MIICpTCCAY0CBgGQcJfM/jANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtXZWF0aGVyU2hvcDAeFw0yNDA3MDEyMzE2NTVaFw0zNDA3MDEyMzE4MzVaMBYxFDASBgNVBAMMC1dlYXRoZXJTaG9wMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlP+NrT2KVZpdrbPoTsMO7MqeXYDeJNl7IXjY0hCb7p1iB6YLOr/lA5ryk/CIHI05HRt+AEYFac87mb51SEvAa9cHjQ00v7t6hoYV1esyRmB0Nnf8AAEq9GoZxX9nUsIMcExQ3gHkF56kidYtjQSgl5SlwgdvlsjRiDP9ZJlsWTBb+8v0OCCbQLZFl93IlTZ7QlaxXoB0dCuuLNyBpELFbc0+JeB+1P/Dw5azUKGdp3ng2K9IrtDBiMh+KicpLZeBpUlqdKqyI2WvwruL1SlqH/ymWCxseRH0Z9VZ30MfW8C5fHq3qnLQp0OWDa7Re/pRbCZPabivDkZCtuWUeAVbRwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAUIS+ce3NPCSk7iiA4vzm1hGrEq7Q+1CwE9hq/p8oKowOEVvg68tE+yzNsYw6qM+KKdzQfmiVeT8skDhNwL+5+Oxsg9dw7KW1me+g/pjiFx1eXt/rHN5aVDz7/F3QAP0G/CUF6dVNh0ggoGhwAH74iH91apmJgDUEBVzwaYCrHDJ81nWZOGZm4MF6FFvc8Kwf/+KEefL7psH5I4BqS+gRaPFWjBnABS7WkJ879gv0Q3tHE4KXF1b3eudGFrW4rG048pqNJgxAXdoDqFR5qIi9pfuE+HCmuhPv2Xq+I7S4PpUYnUM7o0Ng+1hJsRLhiG0Kmcepy7thiJJI619miVXdF" ],
"priority": [ "100" ],
"algorithm": [ "RSA-OAEP" ]
}
},
{
"id": "c962c2d9-ac19-4a91-88b3-959c6fcfc4c4",
"name": "hmac-generated-hs512",
"providerId": "hmac-generated",
"subComponents": {},
"config": {
"kid": [ "f43f7c3d-e27c-4a86-bda1-e1f9fa0b2c0b" ],
"secret": [ "FAyCBV9_zIF2oQO0XqgwCJz09iJDMKPHORhWI1ZV4OA9cLFVJCA-z4tEXq2QNU48xDMwv_z_UYIEm73nnJEypuaVwacu6N7jexaKjhqROYidQyPzXAr7QwD6Du1LaLdCAHaBo7rRP3Pl5fDmcX6K3C1Qe1OK86fkZVuD_2TX6No" ],
"priority": [ "100" ],
"algorithm": [ "HS512" ]
}
}
]
},
"internationalizationEnabled": false,
"supportedLocales": [],
"authenticationFlows": [
{
"id": "57c6972a-8262-4fdd-9a3d-6454f7e4804d",
"alias": "Account verification options",
"description": "Method with which to verity the existing account",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "idp-email-verification",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "ALTERNATIVE",
"priority": 20,
"autheticatorFlow": true,
"flowAlias": "Verify Existing Account by Re-authentication",
"userSetupAllowed": false
}
]
},
{
"id": "12219f2a-a63e-4e35-87b0-0c1fc82e9e00",
"alias": "Browser - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "conditional-user-configured",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "auth-otp-form",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
}
]
},
{
"id": "16a216e0-2305-4a26-8b3c-a1ad95ee0551",
"alias": "Direct Grant - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "conditional-user-configured",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "direct-grant-validate-otp",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
}
]
},
{
"id": "973a2638-3205-40a5-9ae1-171e862f98c2",
"alias": "First broker login - Conditional OTP",
"description": "Flow to determine if the OTP is required for the authentication",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "conditional-user-configured",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "auth-otp-form",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
}
]
},
{
"id": "d024eba2-74d6-4cd2-a149-eda663682a7b",
"alias": "Handle Existing Account",
"description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "idp-confirm-link",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": true,
"flowAlias": "Account verification options",
"userSetupAllowed": false
}
]
},
{
"id": "37b5496c-9e09-402f-b079-9c588322f91d",
"alias": "Reset - Conditional OTP",
"description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "conditional-user-configured",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "reset-otp",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
}
]
},
{
"id": "62d51e78-668a-4d31-9369-0611a7507ed5",
"alias": "User creation or linking",
"description": "Flow for the existing/non-existing user alternatives",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticatorConfig": "create unique user config",
"authenticator": "idp-create-user-if-unique",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "ALTERNATIVE",
"priority": 20,
"autheticatorFlow": true,
"flowAlias": "Handle Existing Account",
"userSetupAllowed": false
}
]
},
{
"id": "ab6b9698-fd26-40a7-8edf-fa456a395394",
"alias": "Verify Existing Account by Re-authentication",
"description": "Reauthentication of existing account",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "idp-username-password-form",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "CONDITIONAL",
"priority": 20,
"autheticatorFlow": true,
"flowAlias": "First broker login - Conditional OTP",
"userSetupAllowed": false
}
]
},
{
"id": "74b79e04-bf44-4d84-92e7-04b753801622",
"alias": "browser",
"description": "browser based authentication",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "auth-cookie",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "auth-spnego",
"authenticatorFlow": false,
"requirement": "DISABLED",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "identity-provider-redirector",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 25,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "ALTERNATIVE",
"priority": 30,
"autheticatorFlow": true,
"flowAlias": "forms",
"userSetupAllowed": false
}
]
},
{
"id": "bb15232e-9f1c-4dfd-8d10-e1d35cd1bfde",
"alias": "clients",
"description": "Base authentication for clients",
"providerId": "client-flow",
"topLevel": true,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "client-secret",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "client-jwt",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "client-secret-jwt",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 30,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "client-x509",
"authenticatorFlow": false,
"requirement": "ALTERNATIVE",
"priority": 40,
"autheticatorFlow": false,
"userSetupAllowed": false
}
]
},
{
"id": "dd3fe894-1594-40fb-949d-9986f36bd725",
"alias": "direct grant",
"description": "OpenID Connect Resource Owner Grant",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "direct-grant-validate-username",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "direct-grant-validate-password",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "CONDITIONAL",
"priority": 30,
"autheticatorFlow": true,
"flowAlias": "Direct Grant - Conditional OTP",
"userSetupAllowed": false
}
]
},
{
"id": "5c277901-3d67-470e-baf1-e47e9ab92dbd",
"alias": "docker auth",
"description": "Used by Docker clients to authenticate against the IDP",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "docker-http-basic-authenticator",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
}
]
},
{
"id": "e14e1d45-149f-4090-ad79-7c2d0c2f185c",
"alias": "first broker login",
"description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": true,
"authenticationExecutions": [
{
"authenticatorConfig": "review profile config",
"authenticator": "idp-review-profile",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": true,
"flowAlias": "User creation or linking",
"userSetupAllowed": false
}
]
},
{
"id": "aa2e5d63-a8e9-43e4-8461-994827de67f5",
"alias": "forms",
"description": "Username, password, otp and other auth forms.",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "auth-username-password-form",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "CONDITIONAL",
"priority": 20,
"autheticatorFlow": true,
"flowAlias": "Browser - Conditional OTP",
"userSetupAllowed": false
}
]
},
{
"id": "d88b5042-8af8-4797-9c6a-ae44a9a0fff2",
"alias": "registration",
"description": "registration flow",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "registration-page-form",
"authenticatorFlow": true,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": true,
"flowAlias": "registration form",
"userSetupAllowed": false
}
]
},
{
"id": "2a9320cb-970e-4b4d-b585-60d2299a043f",
"alias": "registration form",
"description": "registration form",
"providerId": "form-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "registration-user-creation",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "registration-password-action",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 50,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "registration-recaptcha-action",
"authenticatorFlow": false,
"requirement": "DISABLED",
"priority": 60,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "registration-terms-and-conditions",
"authenticatorFlow": false,
"requirement": "DISABLED",
"priority": 70,
"autheticatorFlow": false,
"userSetupAllowed": false
}
]
},
{
"id": "528ba840-6b22-4c32-ba17-40c99783883e",
"alias": "reset credentials",
"description": "Reset credentials for a user if they forgot their password or something",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "reset-credentials-choose-user",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "reset-credential-email",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "reset-password",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 30,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "CONDITIONAL",
"priority": 40,
"autheticatorFlow": true,
"flowAlias": "Reset - Conditional OTP",
"userSetupAllowed": false
}
]
},
{
"id": "bf172b2d-052a-4ce4-9084-c59e9b82bc10",
"alias": "saml ecp",
"description": "SAML ECP Profile Authentication Flow",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "http-basic-authenticator",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
}
]
}
],
"authenticatorConfig": [
{
"id": "796c70f7-6391-45ed-aafa-4ed82c84d14e",
"alias": "create unique user config",
"config": {
"require.password.update.after.registration": "false"
}
},
{
"id": "e007b422-2050-43af-b132-10ea16d92f5c",
"alias": "review profile config",
"config": {
"update.profile.on.first.login": "missing"
}
}
],
"requiredActions": [
{
"alias": "CONFIGURE_TOTP",
"name": "Configure OTP",
"providerId": "CONFIGURE_TOTP",
"enabled": true,
"defaultAction": false,
"priority": 10,
"config": {}
},
{
"alias": "TERMS_AND_CONDITIONS",
"name": "Terms and Conditions",
"providerId": "TERMS_AND_CONDITIONS",
"enabled": false,
"defaultAction": false,
"priority": 20,
"config": {}
},
{
"alias": "UPDATE_PASSWORD",
"name": "Update Password",
"providerId": "UPDATE_PASSWORD",
"enabled": true,
"defaultAction": false,
"priority": 30,
"config": {}
},
{
"alias": "UPDATE_PROFILE",
"name": "Update Profile",
"providerId": "UPDATE_PROFILE",
"enabled": true,
"defaultAction": false,
"priority": 40,
"config": {}
},
{
"alias": "VERIFY_EMAIL",
"name": "Verify Email",
"providerId": "VERIFY_EMAIL",
"enabled": true,
"defaultAction": false,
"priority": 50,
"config": {}
},
{
"alias": "delete_account",
"name": "Delete Account",
"providerId": "delete_account",
"enabled": false,
"defaultAction": false,
"priority": 60,
"config": {}
},
{
"alias": "webauthn-register",
"name": "Webauthn Register",
"providerId": "webauthn-register",
"enabled": true,
"defaultAction": false,
"priority": 70,
"config": {}
},
{
"alias": "webauthn-register-passwordless",
"name": "Webauthn Register Passwordless",
"providerId": "webauthn-register-passwordless",
"enabled": true,
"defaultAction": false,
"priority": 80,
"config": {}
},
{
"alias": "VERIFY_PROFILE",
"name": "Verify Profile",
"providerId": "VERIFY_PROFILE",
"enabled": true,
"defaultAction": false,
"priority": 90,
"config": {}
},
{
"alias": "delete_credential",
"name": "Delete Credential",
"providerId": "delete_credential",
"enabled": true,
"defaultAction": false,
"priority": 100,
"config": {}
},
{
"alias": "update_user_locale",
"name": "Update User Locale",
"providerId": "update_user_locale",
"enabled": true,
"defaultAction": false,
"priority": 1000,
"config": {}
}
],
"browserFlow": "browser",
"registrationFlow": "registration",
"directGrantFlow": "direct grant",
"resetCredentialsFlow": "reset credentials",
"clientAuthenticationFlow": "clients",
"dockerAuthenticationFlow": "docker auth",
"firstBrokerLoginFlow": "first broker login",
"attributes": {
"cibaBackchannelTokenDeliveryMode": "poll",
"cibaExpiresIn": "120",
"cibaAuthRequestedUserHint": "login_hint",
"oauth2DeviceCodeLifespan": "600",
"clientOfflineSessionMaxLifespan": "0",
"oauth2DevicePollingInterval": "5",
"clientSessionIdleTimeout": "0",
"parRequestUriLifespan": "60",
"clientSessionMaxLifespan": "0",
"clientOfflineSessionIdleTimeout": "0",
"cibaInterval": "5",
"realmReusableOtpCode": "false"
},
"keycloakVersion": "24.0.5",
"userManagedAccessAllowed": false,
"clientProfiles": {
"profiles": []
},
"clientPolicies": {
"policies": []
}
}
Hosting integration health checks
The Keycloak hosting integration doesn't currently support a health checks, nor does it automatically add them.
Client integration
To get started with the .NET Aspire Keycloak client integration, install the 📦 Aspire.Keycloak.Authentication NuGet package in the client-consuming project, that is, the project for the application that uses the Keycloak client. The Keycloak client integration registers JwtBearer and OpenId Connect authentication handlers in the DI container for connecting to a Keycloak.
dotnet add package Aspire.Keycloak.Authentication
Add JWT bearer authentication
In the Program.cs file of your ASP.NET Core API project, call the AddKeycloakJwtBearer extension method to add JwtBearer authentication, using a connection name, realm and any required JWT Bearer options:
builder.Services.AddAuthentication()
.AddKeycloakJwtBearer(
serviceName: "keycloak",
realm: "api",
options =>
{
options.Audience = "store.api";
});
You can set many other options via the Action<JwtBearerOptions> configureOptions
delegate.
JWT bearer authentication example
To further exemplify the JWT bearer authentication, consider the following example:
var builder = WebApplication.CreateBuilder(args);
// Add service defaults & Aspire client integrations.
builder.AddServiceDefaults();
// Add services to the container.
builder.Services.AddProblemDetails();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddAuthentication()
.AddKeycloakJwtBearer(
serviceName: "keycloak",
realm: "WeatherShop",
configureOptions: options =>
{
options.RequireHttpsMetadata = false;
options.Audience = "weather.api";
});
builder.Services.AddAuthorizationBuilder();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseExceptionHandler();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
string[] summaries = ["Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"];
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.RequireAuthorization();
app.MapDefaultEndpoints();
app.Run();
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
The preceding ASP.NET Core Minimal API Program
class demonstrates:
- Adding authentication services to the DI container with the AddAuthentication API.
- Adding JWT bearer authentication with the AddKeycloakJwtBearer API and configuring:
- The
serviceName
askeycloak
. - The
realm
asWeatherShop
. - The
options
with theAudience
set toweather.api
and setsRequireHttpsMetadata
tofalse
.
- The
- Adds authorization services to the DI container with the AddAuthorizationBuilder API.
- Calls the RequireAuthorization API to require authorization on the
/weatherforecast
endpoint.
For a complete working sample, see .NET Aspire playground: Keycloak integration.
Add OpenId Connect authentication
In the Program.cs file of your API-consuming project (for example, Blazor), call the AddKeycloakOpenIdConnect extension method to add OpenId Connect authentication, using a connection name, realm and any required OpenId Connect options:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddKeycloakOpenIdConnect(
serviceName: "keycloak",
realm: "api",
options =>
{
options.ClientId = "StoreWeb";
options.ResponseType = OpenIdConnectResponseType.Code;
options.Scope.Add("store:all");
});
You can set many other options via the Action<OpenIdConnectOptions>? configureOptions
delegate.
OpenId Connect authentication example
To further exemplify the OpenId Connect authentication, consider the following example:
using System.IdentityModel.Tokens.Jwt;
using AspireApp.Web;
using AspireApp.Web.Components;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
var builder = WebApplication.CreateBuilder(args);
// Add service defaults & Aspire client integrations.
builder.AddServiceDefaults();
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.AddOutputCache();
builder.Services.AddHttpContextAccessor()
.AddTransient<AuthorizationHandler>();
builder.Services.AddHttpClient<WeatherApiClient>(client =>
{
// This URL uses "https+http://" to indicate HTTPS is preferred over HTTP.
// Learn more about service discovery scheme resolution at https://aka.ms/dotnet/sdschemes.
client.BaseAddress = new("https+http://apiservice");
})
.AddHttpMessageHandler<AuthorizationHandler>();
var oidcScheme = OpenIdConnectDefaults.AuthenticationScheme;
builder.Services.AddAuthentication(oidcScheme)
.AddKeycloakOpenIdConnect("keycloak", realm: "WeatherShop", oidcScheme, options =>
{
options.ClientId = "WeatherWeb";
options.ResponseType = OpenIdConnectResponseType.Code;
options.Scope.Add("weather:all");
options.RequireHttpsMetadata = false;
options.TokenValidationParameters.NameClaimType = JwtRegisteredClaimNames.Name;
options.SaveTokens = true;
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme);
builder.Services.AddCascadingAuthenticationState();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAntiforgery();
app.UseOutputCache();
app.MapStaticAssets();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.MapDefaultEndpoints();
app.MapLoginAndLogout();
app.Run();
The preceding ASP.NET Core Blazor Program
class:
- Adds the
HttpContextAccessor
to the DI container with the AddHttpContextAccessor API. - Adds a custom
AuthorizationHandler
as a transient service to the DI container with the AddTransient<TService>(IServiceCollection) API. - Adds an HttpClient to the
WeatherApiClient
service with the AddHttpClient<TClient>(IServiceCollection) API and configuring it's base address with service discovery semantics that resolves to theapiservice
.- Chains a call to the AddHttpMessageHandler API to add a
AuthorizationHandler
to theHttpClient
pipeline.
- Chains a call to the AddHttpMessageHandler API to add a
- Adds authentication services to the DI container with the AddAuthentication API passing int the OpenId Connect default authentication scheme.
- Calls AddKeycloakOpenIdConnect and configures the
serviceName
askeycloak
, therealm
asWeatherShop
, and theoptions
object with various settings. - Adds cascading authentication state to the Blazor app with the AddCascadingAuthenticationState API.
The final callout is the MapLoginAndLogout
extension method that adds login and logout routes to the Blazor app. This is defined as follows:
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http.HttpResults;
namespace AspireApp.Web;
internal static class LoginLogoutEndpointRouteBuilderExtensions
{
internal static IEndpointConventionBuilder MapLoginAndLogout(
this IEndpointRouteBuilder endpoints)
{
var group = endpoints.MapGroup("authentication");
group.MapGet(pattern: "/login", OnLogin).AllowAnonymous();
group.MapPost(pattern: "/logout", OnLogout);
return group;
}
static ChallengeHttpResult OnLogin() =>
TypedResults.Challenge(properties: new AuthenticationProperties
{
RedirectUri = "/"
});
static SignOutHttpResult OnLogout() =>
TypedResults.SignOut(properties: new AuthenticationProperties
{
RedirectUri = "/"
},
[
CookieAuthenticationDefaults.AuthenticationScheme,
OpenIdConnectDefaults.AuthenticationScheme
]);
}
The preceding code:
- Maps a group for the
authentication
route and maps two endpoints for thelogin
andlogout
routes:- Maps a
GET
request to the/login
route that's handler is theOnLogin
method—this is an anonymous endpoint. - Maps a
GET
request to the/logout
route that's handler is theOnLogout
method.
- Maps a
The AuthorizationHandler
is a custom handler that adds the Bearer
token to the HttpClient
request. The handler is defined as follows:
using Microsoft.AspNetCore.Authentication;
using System.Net.Http.Headers;
namespace AspireApp.Web;
public class AuthorizationHandler(IHttpContextAccessor httpContextAccessor)
: DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var httpContext = httpContextAccessor.HttpContext ??
throw new InvalidOperationException("""
No HttpContext available from the IHttpContextAccessor.
""");
var accessToken = await httpContext.GetTokenAsync("access_token");
if (!string.IsNullOrWhitespace(accessToken))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}
return await base.SendAsync(request, cancellationToken);
}
}
The preceding code:
- Is a subclass of the DelegatingHandler class.
- Injects the
IHttpContextAccessor
service in the primary constructor. - Overrides the
SendAsync
method to add theBearer
token to theHttpClient
request:- The
access_token
is retrieved from theHttpContext
and added to theAuthorization
header.
- The
To help visualize the auth flow, consider the following sequence diagram:
For a complete working sample, see .NET Aspire playground: Keycloak integration.
See also
.NET Aspire