question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Creation of realm with client_credentials authentication flow fails with 403 Forbidden

See original GitHub issue

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 using client_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.
    
    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 realm `mynode` was nevertheless created but (no further configuration would occur due to the error).
  • 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

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:22 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
jkroepkecommented, Dec 23, 2021

I guess it’s something like this

  keycloak-config-cli:
    container_name: keycloak-config-cli
    image: quay.io/adorsys/keycloak-config-cli:v4.5.0-15.1.1
...
    network_mode: "service:keycloak"

and remove the networks from that service completly.

Looks like you found already a alternative solution.

1reaction
jkroepkecommented, Dec 23, 2021

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Keycloak Get Users returns 403 forbidden - Stack Overflow
using a client-credential-Token of "tmp" for the user-Search-Endpoint (/auth/admin/realms/b2c/users/) leads to 403; using a manually created ...
Read more >
Forbidden (403), Unauthorized (401), or What Else? - Auth0
403 Forbidden is the status code to return when a client has valid credentials but not enough privileges to perform an action on...
Read more >
403 Forbidden on a newly created Realm · Issue #468 - GitHub
When creating a new realm (using a client with all needed roles), it seems the promise is resolved BEFORE the realm is completely...
Read more >
Custom Connector with Code enabled always returns
403 Forbidden status code means that the client credentials (access token) are valid but refuses to authorize it. Following are the possible ...
Read more >
HTTP Error 403 Forbidden: What It Means and How to Fix It
The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it...If authentication credentials ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found