keycloak-config-cli: Creation of realm with client_credentials authentication flow fails with 403 Forbidden
Describe the bug
Creation of a new realm fails with HTTP 403 Forbidden
if client_credentials
authentication flow with ClientId
/ClientSecret
is used (although the realm actually got created).
To Reproduce
-
Create client
my-cli
at master realm (with user based authentication) [click to expand]The client gets the service account role
admin
which enables management of realms.JSON (
realm-master.json
):{ "realm": "master", "users": [ { "username": "service-account-my-cli", "enabled": true, "serviceAccountClientId": "my-cli", "realmRoles": [ "uma_authorization", "offline_access", "admin" ], "clientRoles": { "account": [ "view-profile", "manage-account" ] } } ], "clients": [ { "clientId": "my-cli", "enabled": true, "clientAuthenticatorType": "client-secret", "secret": "my-secret", "bearerOnly": false, "consentRequired": false, "standardFlowEnabled": false, "implicitFlowEnabled": false, "directAccessGrantsEnabled": false, "serviceAccountsEnabled": true, "publicClient": false, "frontchannelLogout": false, "protocol": "openid-connect", "protocolMappers": [ { "name": "security-admin-console-audience-mapper", "protocol": "openid-connect", "protocolMapper": "oidc-audience-mapper", "consentRequired": false, "config": { "included.client.audience": "security-admin-console", "id.token.claim": "false", "access.token.claim": "true" } } ] } ], "keycloakVersion": "12.0.4" }
CMD:
docker run -it --rm -e KEYCLOAK_URL=http://localhost:8080/auth -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=<my-admin-pw> -e KEYCLOAK_GRANTTYPE=password -e IMPORT_PATH=/config/realm-master.json -e SPRING_PROFILES_INCLUDE=debug -v ./config:/config adorsys/keycloak-config-cli:v3.1.0-12.0.3
based on https://www.keycloak.org/docs/latest/server_development/#authenticate-with-a-service-account
-
Try to create realm
mynode
usingclient_credentials
authentication flow [click to expand]JSON (
realm-node.json
):{ "realm": "mynode", "displayName": "mynode" }
CMD:
docker run -it --rm -e KEYCLOAK_URL=http://localhost:8080/auth -e KEYCLOAK_CLIENTID=my-cli -e KEYCLOAK_CLIENTSECRET=my-secret -e KEYCLOAK_GRANTTYPE=client_credentials -e IMPORT_PATH=/config/realm-node.json -e SPRING_PROFILES_INCLUDE=debug -v ./config/:/config adorsys/keycloak-config-cli:v3.1.0-12.0.3
-
Causes the following error:
INFO 1 [main] d.a.k.config.KeycloakConfigApplication : Starting KeycloakConfigApplication v3.1.0 using Java 11.0.10 on e3b541095cad with PID 1 (/opt/keycloak-config-cli.jar started by ? in /) INFO 1 [main] d.a.k.config.KeycloakConfigApplication : The following profiles are active: debug INFO 1 [main] d.a.k.config.KeycloakConfigApplication : Started KeycloakConfigApplication in 1.272 seconds (JVM running for 1.696) INFO 1 [main] d.a.k.c.provider.KeycloakImportProvider : Importing file '/config/realm-node.json' INFO 1 [main] d.a.k.config.provider.KeycloakProvider : Wait 60 seconds until http://localhost:8080/auth is available ... DEBUG 1 [main] d.a.k.config.service.RealmImportService : Creating realm 'mynode' ... ERROR 1 [main] d.a.k.config.KeycloakConfigRunner : HTTP 403 Forbidden INFO 1 [main] d.a.k.config.KeycloakConfigRunner : keycloak-config-cli running in 00:02.024.
The realm `mynode` was nevertheless created but (no further configuration would occur due to the error).Stack-Trace [click to expand]
ERROR 1 [main] o.s.boot.SpringApplication : Application run failed java.lang.IllegalStateException: Failed to execute CommandLineRunner at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:807) ~[spring-boot-2.4.3.jar!/:2.4.3] at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:788) ~[spring-boot-2.4.3.jar!/:2.4.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) ~[spring-boot-2.4.3.jar!/:2.4.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.3.jar!/:2.4.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.3.jar!/:2.4.3] at de.adorsys.keycloak.config.KeycloakConfigApplication.main(KeycloakConfigApplication.java:35) ~[classes!/:3.1.0] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na] at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[keycloak-config-cli.jar:3.1.0] at org.springframework.boot.loader.Launcher.launch(Launcher.java:107) ~[keycloak-config-cli.jar:3.1.0] at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[keycloak-config-cli.jar:3.1.0] at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:467) ~[keycloak-config-cli.jar:3.1.0] Caused by: javax.ws.rs.ForbiddenException: HTTP 403 Forbidden at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.handleErrorStatus(ClientInvocation.java:266) ~[resteasy-client-4.6.0.Final.jar!/:4.6.0.Final] at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.extractResult(ClientInvocation.java:238) ~[resteasy-client-4.6.0.Final.jar!/:4.6.0.Final] at org.jboss.resteasy.client.jaxrs.internal.proxy.extractors.BodyEntityExtractor.extractEntity(BodyEntityExtractor.java:64) ~[resteasy-client-4.6.0.Final.jar!/:4.6.0.Final] at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:154) ~[resteasy-client-4.6.0.Final.jar!/:4.6.0.Final] at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:115) ~[resteasy-client-4.6.0.Final.jar!/:4.6.0.Final] at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76) ~[resteasy-client-4.6.0.Final.jar!/:4.6.0.Final] at com.sun.proxy.$Proxy87.toRepresentation(Unknown Source) ~[na:na] at de.adorsys.keycloak.config.repository.RealmRepository.get(RealmRepository.java:69) ~[classes!/:3.1.0] at de.adorsys.keycloak.config.repository.StateRepository.retrieveCustomAttributes(StateRepository.java:118) ~[classes!/:3.1.0] at de.adorsys.keycloak.config.repository.StateRepository.loadCustomAttributes(StateRepository.java:68) ~[classes!/:3.1.0] at de.adorsys.keycloak.config.service.state.StateService.loadState(StateService.java:53) ~[classes!/:3.1.0] at de.adorsys.keycloak.config.service.RealmImportService.configureRealm(RealmImportService.java:171) ~[classes!/:3.1.0] at de.adorsys.keycloak.config.service.RealmImportService.createRealm(RealmImportService.java:158) ~[classes!/:3.1.0] at de.adorsys.keycloak.config.service.RealmImportService.doImport(RealmImportService.java:134) ~[classes!/:3.1.0] at de.adorsys.keycloak.config.KeycloakConfigRunner.run(KeycloakConfigRunner.java:70) ~[classes!/:3.1.0] at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804) ~[spring-boot-2.4.3.jar!/:2.4.3] ... 13 common frames omitted
-
The log from keycloak shows no authentication problems:
DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) new JtaTransactionWrapper DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) was existing? false DEBUG [org.keycloak.authentication.AuthenticationProcessor] (default task-5) AUTHENTICATE CLIENT DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-5) client authenticator: client-secret DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-5) client authenticator SUCCESS: client-secret DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-5) Client my-cli authenticated by client-secret DEBUG [org.keycloak.services.managers.AuthenticationSessionManager] (default task-5) Removing authSession 'a3147fc7-6d89-489e-97bb-001ba846226e'. Expire restart cookie: true DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) JtaTransactionWrapper commit DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) JtaTransactionWrapper end DEBUG [org.keycloak.events] (default task-5) type=CLIENT_LOGIN, realmId=master, clientId=my-cli, userId=593bf4b3-be03-42f0-9668-28f3da5d874a, ipAddress=192.168.48.1, token_id=fc1e7fa0-ecd3-4f5e-a89f-261db53c7b4c, grant_type=client_credentials, scope='profile email', client_auth_method=client-secret, username=service-account-my-cli, authSessionParentId=a3147fc7-6d89-489e-97bb-001ba846226e, authSessionTabId=til6nfT4y9w DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) new JtaTransactionWrapper DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) was existing? false DEBUG [org.keycloak.services.resources.admin.AdminRoot] (default task-5) authenticated admin access for: service-account-my-cli DEBUG [org.keycloak.saml.common] (default task-5) Using logger implementation: org.keycloak.saml.common.DefaultPicketLinkLogger DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) JtaTransactionWrapper commit DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) JtaTransactionWrapper end DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) new JtaTransactionWrapper DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) was existing? false DEBUG [org.keycloak.services.resources.admin.AdminRoot] (default task-5) authenticated admin access for: service-account-my-cli DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) JtaTransactionWrapper rollback DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) JtaTransactionWrapper end DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) new JtaTransactionWrapper DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) was existing? false DEBUG [org.keycloak.services.resources.admin.AdminRoot] (default task-5) authenticated admin access for: service-account-my-cli DEBUG [org.keycloak.services.resources.admin.RealmsAdminResource] (default task-5) importRealm: mynode DEBUG [org.keycloak.keys.GeneratedRsaKeyProviderFactory] (default task-5) Generated keys for mynode DEBUG [org.keycloak.keys.GeneratedHmacKeyProviderFactory] (default task-5) Generated secret for mynode DEBUG [org.keycloak.keys.GeneratedAesKeyProviderFactory] (default task-5) Generated secret for mynode DEBUG [org.keycloak.services.resources.admin.RealmsAdminResource] (default task-5) imported realm success, sending back: http://localhost:8080/auth/admin/realms/mynode DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) JtaTransactionWrapper commit DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) JtaTransactionWrapper end DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) new JtaTransactionWrapper DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-5) was existing? false DEBUG [org.keycloak.services.resources.admin.AdminRoot] (default task-5) authenticated admin access for: service-account-my-cli
Expected behavior The realm should be created without any errors and further configuration of the realm (e.g. creation of clients) should occur.
Possible issue?
Could it be that the CLI needs to refresh the access-token after the creation of the realm? Since otherwise there are no claims for the new realm mynode-realm
on the token. See comparison of a token manually issued before and after creation of the realm.
This theory would fit if the RealmRepository.get() method triggers some requests. However I couldn’t see any logs on the keycloak server regarding 403 forbidden.
Access token before creation of new realm [click to expand]
{
"exp": 1614968632,
"iat": 1614968572,
"jti": "a5e103b1-82ec-4cad-93c9-c1de835e79ff",
"iss": "http://localhost:8080/auth/realms/master",
"aud": [
"security-admin-console",
"master-realm",
"account"
],
"sub": "5255a1fd-0f3c-4b28-baf9-4bfc11f4d7fc",
"typ": "Bearer",
"azp": "my-cli",
"acr": "1",
"realm_access": {
"roles": [
"create-realm",
"offline_access",
"admin",
"uma_authorization"
]
},
"resource_access": {
"master-realm": {
"roles": [
"view-identity-providers",
"view-realm",
"manage-identity-providers",
"impersonation",
"create-client",
"manage-users",
"query-realms",
"view-authorization",
"query-clients",
"query-users",
"manage-events",
"manage-realm",
"view-events",
"view-users",
"view-clients",
"manage-authorization",
"manage-clients",
"query-groups"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "email profile",
"clientHost": "192.168.80.1",
"email_verified": false,
"clientId": "my-cli",
"preferred_username": "service-account-my-cli",
"clientAddress": "192.168.80.1"
}
Access token after creation of new realm [click to expand]
{
"exp": 1614968495,
"iat": 1614968435,
"jti": "899b7864-12fb-4461-aa72-0e0383575260",
"iss": "http://localhost:8080/auth/realms/master",
"aud": [
"security-admin-console",
"mynode-realm",
"master-realm",
"account"
],
"sub": "593bf4b3-be03-42f0-9668-28f3da5d874a",
"typ": "Bearer",
"azp": "my-cli",
"acr": "1",
"realm_access": {
"roles": [
"create-realm",
"offline_access",
"admin",
"uma_authorization"
]
},
"resource_access": {
"mynode-realm": {
"roles": [
"view-identity-providers",
"view-realm",
"manage-identity-providers",
"impersonation",
"create-client",
"manage-users",
"query-realms",
"view-authorization",
"query-clients",
"query-users",
"manage-events",
"manage-realm",
"view-events",
"view-users",
"view-clients",
"manage-authorization",
"manage-clients",
"query-groups"
]
},
"master-realm": {
"roles": [
"view-realm",
"view-identity-providers",
"manage-identity-providers",
"impersonation",
"create-client",
"manage-users",
"query-realms",
"view-authorization",
"query-clients",
"query-users",
"manage-events",
"manage-realm",
"view-events",
"view-users",
"view-clients",
"manage-authorization",
"manage-clients",
"query-groups"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "profile email",
"clientHost": "192.168.48.1",
"email_verified": false,
"clientId": "my-cli",
"preferred_username": "service-account-my-cli",
"clientAddress": "192.168.48.1"
}
Only workaround we know so far is to use a kind of “service”-user instead of the client (since everything works with user authentication).
Environment (please complete the following information):
- Keycloak Version: 12.0.4
- keycloak-config-cli Version: v3.1.0-12.0.3
- Java Version: 11.0.10+9
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 22 (11 by maintainers)
I guess it’s something like this
and remove the
networks
from that service completly.Looks like you found already a alternative solution.
Checkout compose network_mode
https://docs.docker.com/compose/compose-file/compose-file-v3/#network_mode
You can configure that the keycloak-config-cli container will join the keycloak network namespace. If both containers share the same namespace, then you can reach keycloak via localhost.
I appreciate the detailed bug description. It helps a lot to reproduce the case and find the error quickly.
I tried this and this resolves the error. Godlike hint.