.NET Aspire Keycloak 整合 (預覽)
Keycloak 是針對新式應用程式和服務的開放原始碼身分識別和存取管理解決方案。
.NET Aspire
Keycloak 整合可讓您連線到現有的 Keycloak 實例,或使用 quay.io/keycloak/keycloak
容器映射從 .NET 建立新的實例。
主機整合
.NET Aspire作為托管整合,Keycloak 會將 server 模型化為 KeycloakResource 類型。 若要存取這些類型和 API,請在 應用程式主機 專案中新增 📦Aspire.Hosting.Keycloak NuGet 套件。
dotnet add package Aspire.Hosting.Keycloak --prerelease
如需詳細資訊,請參閱 dotnet add package 或 在 .NET 應用程式中管理套件相依性。
新增 Keycloak 資源
在您的應用程式主專案中,呼叫 AddKeycloak 以新增並傳回 Keycloak 資源產生器。 將呼叫鏈結至傳回的資源產生器,以設定 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...
提示
針對本機開發,請使用穩定端口作為 Keycloak 資源(上述範例中的8080
)。 它可以是任何埠,但必須保持穩定,以避免讓瀏覽器 Cookie 在 應用程式主機的存續期間內持續保留 OIDC 令牌(其中包括授權 URL 及其埠號)的問題。
當 .NET.NET Aspire 將容器映射新增至應用程式主機時,如上述範例中的 quay.io/keycloak/keycloak
映射所示,它會在本機計算機上建立新的 Keycloak 實例。
Keycloak 資源包含預設認證:
-
KEYCLOAK_ADMIN
:admin
的值。 -
KEYCLOAK_ADMIN_PASSWORD
:使用 CreateDefaultPasswordParameter 方法產生的隨機password
。
當應用程式主機執行時,密碼會儲存在應用程式主機的秘密存放區中。 它已加入至 Parameters
區段,例:
{
"Parameters:keycloak-password": "<THE_GENERATED_PASSWORD>"
}
參數的名稱是 keycloak-password
,但實際上只是使用 -password
後綴來格式化資源名稱。 如需詳細資訊,請參閱 開發環境下應用程式秘密的安全儲存,並在 ASP.NET Core 和 中新增 Keycloak 資源。
WithReference 方法會在名為 keycloak
的 ExampleProject
中設定連線,WaitFor 會指示應用程式主機在 keycloak
資源就緒之前,不要啟動相依服務。
提示
如果您想要連線到現有的 Keycloak 實例,請改為呼叫 AddConnectionString。 如需詳細資訊,請參閱 參考現有資源。
將具有數據量的 Keycloak 資源新增
若要將數據磁碟區新增至 Keycloak 資源,請在 Keycloak 資源上呼叫 WithDataVolume 方法:
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...
數據磁碟區可用來將 Keycloak 數據保存在其容器生命週期之外。 資料量會掛載在 Keycloak 容器內的 /opt/keycloak/data
路徑上,且未提供 name
參數時,名稱將被隨機生成。 如需有關資料卷的更多資訊,以及它們為何勝過 系結掛接的原因,請參閱 Docker 文件:卷。
警告
系統管理員認證會儲存在數據磁碟區中。 使用數據磁碟區時,如果認證變更,在刪除磁碟區之前將無法運作。
新增具資料綁定掛載的 Keycloak 資源
若要將數據系結掛接新增至 Keycloak 資源,請呼叫 WithDataBindMount 方法:
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...
數據系結裝載依賴主計算機的檔案系統,在容器重新啟動時保存 Keycloak 數據。 數據系結掛接會掛接在 Keycloak 容器中主計算機上的 C:\Keycloak\Data
上(或 Unix上 /Keycloak/Data
)。 如需資料系結掛接的詳細資訊,請參閱 Docker 檔:系結掛接。
透過參數新增 Keycloak 資源
當您想要明確提供容器映像所使用的系統管理員使用者名稱和密碼時,您可以提供這些認證作為參數。 請考慮下列替代範例:
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...
username
和 password
參數通常會以環境變數或秘密的形式提供。 參數可用來設定容器中的 KEYCLOAK_ADMIN
和 KEYCLOAK_ADMIN_PASSWORD
環境變數。 如需提供參數的詳細資訊,請參閱
使用領域匯入添加 Keycloak 資源
若要將領域匯入 Keycloak,請呼叫 WithRealmImport 方法:
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();
領域匯入檔案會掛接在 /opt/keycloak/data/import
,位於 Keycloak 容器中。 領域匯入檔案是 JSON 檔案,代表領域配置檔案。 如需領域匯入的詳細資訊,請參閱 Keycloak 檔:匯入領域。
例如,下列 JSON 檔案可以新增至 /Realms 資料夾中的應用程式主專案,做為來源領域組態檔:
切換領域 JSON 範例。
{
"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": []
}
}
主機整合健康檢查
Keycloak 裝載整合目前不支援健康檢查,也不會自動新增它們。
Client 整合
若要開始使用 .NET AspireKeycloakclient 整合,請在 client取用專案中安裝 📦AspireKeycloak驗證 NuGet 套件,也就是那個使用 Keycloakclient的應用程式的專案。 Keycloak client 整合會在 DI 容器中註冊 JwtBearer 和 OpenId Connect 驗證處理程式,以連線到 Keycloak。
dotnet add package Aspire.Keycloak.Authentication
新增 JWT 持有人驗證
在 ASP.NET Core API 專案的 Program.cs 檔案中,呼叫 AddKeycloakJwtBearer 擴充方法,以使用連線名稱、領域和任何必要的 JWT 持有人選項來新增 JwtBearer 驗證:
builder.Services.AddAuthentication()
.AddKeycloakJwtBearer(
serviceName: "keycloak",
realm: "api",
options =>
{
options.Audience = "store.api";
});
您可以透過 Action<JwtBearerOptions> configureOptions
委派來設定許多其他選項。
JWT 持有人驗證範例
若要進一步示範 JWT 持有人驗證,請考慮下列範例:
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);
}
上述 ASP.NET Core Minimal API Program
類別示範:
- 使用 AddAuthentication API 將驗證服務新增至 DI 容器。
- 使用 AddKeycloakJwtBearer API 新增 JWT 持有人驗證並設定:
- 作為
keycloak
的serviceName
。 -
realm
作為WeatherShop
。 - 將
options
設置成Audience
並將weather.api
設置為false
的RequireHttpsMetadata
。
- 作為
- 使用 AddAuthorizationBuilder API 將授權服務新增至 DI 容器。
- 呼叫 RequireAuthorization API,要求
/weatherforecast
端點的授權。
如需完整的工作範例,請參閱 .NET Aspire 遊樂場:Keycloak 整合。
新增 OpenId Connect 驗證
在 API 取用專案的 Program.cs 檔案中(例如,Blazor),呼叫 AddKeycloakOpenIdConnect 擴充方法,以使用連線名稱、領域和任何必要的 OpenId Connect 選項來新增 OpenId Connect 驗證:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddKeycloakOpenIdConnect(
serviceName: "keycloak",
realm: "api",
options =>
{
options.ClientId = "StoreWeb";
options.ResponseType = OpenIdConnectResponseType.Code;
options.Scope.Add("store:all");
});
您可以透過 Action<OpenIdConnectOptions>? configureOptions
代理來設定許多其他選項。
OpenId Connect 驗證範例
若要進一步示範 OpenId Connect 驗證,請考慮下列範例:
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();
上述 ASP.NET CoreBlazorProgram
類別:
- 使用 AddHttpContextAccessor API 將
HttpContextAccessor
新增至 DI 容器。 - 使用 AddTransient<TService>(IServiceCollection) API 將自訂
AuthorizationHandler
當做暫時性服務新增至 DI 容器。 - 使用 AddHttpClient<TClient>(IServiceCollection) API 將 HttpClient 新增至
WeatherApiClient
服務,並透過 服務發現 語意來配置基位址,該位址會解析至apiservice
。- 將對 AddHttpMessageHandler API 的呼叫鏈結起來,並將
AuthorizationHandler
新增到HttpClient
管線中。
- 將對 AddHttpMessageHandler API 的呼叫鏈結起來,並將
- 使用 AddAuthentication API 傳入 OpenId Connect 預設驗證機制,將驗證服務新增至 DI 容器。
- 呼叫 AddKeycloakOpenIdConnect,並將
serviceName
設定為keycloak
、將realm
設定為WeatherShop
,以及具有各種設定的options
物件。 - 使用 AddCascadingAuthenticationState API 將串聯驗證狀態新增至 Blazor 應用程式。
最後提到的是 MapLoginAndLogout
擴充方法,可以將登入和登出路徑新增至 Blazor 應用程式。 這的定義如下:
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
]);
}
上述程式代碼:
- 對
authentication
路線進行群組映射,並將兩個端點映射到login
和logout
路線:- 將
GET
要求映射到處理程式是OnLogin
方法的/login
路由,這是一個匿名端點。 - 將
GET
要求對應到/logout
路由,其處理程式為OnLogout
方法。
- 將
AuthorizationHandler
是自定義處理程式,可將 Bearer
令牌新增至 HttpClient
要求。 處理程式定義如下:
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);
}
}
上述程式代碼:
- 這是 DelegatingHandler 類別的子類別。
- 在主要建構函式中插入
IHttpContextAccessor
服務。 - 覆寫
SendAsync
方法,將Bearer
令牌新增至HttpClient
要求:-
access_token
會從HttpContext
擷取,並新增至Authorization
標頭。
-
若要協助可視化驗證流程,請考慮下列順序圖表:
如需完整的工作範例,請參閱 .NET Aspire 遊樂場:Keycloak 整合。