Keycloak 403 Error: Forbidden. Podczas pobierania listy ról.

0

Cześć, potrzebuję utworzyć dwa rodzaje użytkowników, jeden z rolą zwykłego użytkownika (który może wykonywać akcje związane z logiką biznesową), drugi z rolą realm-admina (możliwość modyfikacji ról innych użytkowników itd.)

Utworzyłem dwa klienty: (może tu jest problem?)

  1. public - do odpytywania o token
  2. confidential - dla serwisu backend

Użytkownik admin:
screenshot-20220621120738.png
W jaki sposób wyobrażam sobie komunikację:

  1. Użytkownik odpytuje klienta public o token
  2. Po otrzymaniu tokena - wysyła request na backend i pobiera role

Realizacja:

  1. Po uwieżytelnieniu otrzymałem token (zdekodowany peyload - jak widać ma on role niezbędne do realm-managementu):
{
  "exp": 1655806320,
  "iat": 1655806020,
  "jti": "98391bd2-3174-4209-9a0e-0b2dc7a9579e",
  "iss": "http://localhost:28080/auth/realms/smartcity",
  "aud": [
    "realm-management",
    "account"
  ],
  "sub": "04629e3f-e3f5-431d-bf4d-3d3c8d56b46f",
  "typ": "Bearer",
  "azp": "smartcity-front",
  "session_state": "90d27be7-6c82-49b3-83eb-69fc760efb5a",
  "acr": "1",
  "allowed-origins": [
    "http://localhost:28080"
  ],
  "realm_access": {
    "roles": [
      "offline_access",
      "uma_authorization",
      "default-roles-smartcity"
    ]
  },
  "resource_access": {
    "realm-management": {
      "roles": [
        "view-identity-providers",
        "view-realm",
        "manage-identity-providers",
        "impersonation",
        "realm-admin",
        "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": "openid email profile",
  "sid": "90d27be7-6c82-49b3-83eb-69fc760efb5a",
  "email_verified": false,
  "preferred_username": "admin2"
}
  1. Po wejściu w endpoint wywołuję metodę getRoles()
    private final KeycloakProvider keycloakProvider;

    public Response getRoles() {

       var test =  keycloakProvider.getInstance().realm(realm).roles().list();
       return null; // tu mam breakpointa
    }

gdzie keycloakProvider to komponent z metodą: (z racji tego, że ten klient jest confidential, mam ustalony secret)

    public Keycloak getInstance() {
        if (keycloak == null) {

            return KeycloakBuilder.builder()
                .realm(realm)
                .serverUrl(serverURL)
                .clientId(clientID)
                .clientSecret(clientSecret)
                .grantType(OAuth2Constants.CLIENT_CREDENTIALS)
                .build();
        }
        return keycloak;
    }

Po wywołaniu metody keycloakProvider.getInstance().realm(realm).roles().list(); dostaję błąd 403.

Mam pytanie czy sposób w jaki to robię jest poprawny? Jeśli nie to w jaki inny sposób mógłbym stworzyć użytkownika administratora (logującego się przez zwykłe username i password - bez sekretu).

0

Ten token którym się zalogowałeś nie jest używany do pobierania ról. W momencie wywoływania tego keycloakProvider.getInstance().realm(realm).roles().list(); gdzieś pod spodem jest wołany jakiś TokenManager który robi Ci grantToken i loguje się jako ten klient prywatny.
Żeby to zadziałało to musisz dla tego clienta prywatnego w ustawieniach włączyć opcję Service Accounts Enabled. Powinna pojawić Ci się zakładka Service Account Roles i tam możesz sobie ustawić wszystkie Client Roles z clienta realm-management

0

Tak jak pisał @Baniowy wołając getInstance() inny użytkownik (service account user) był wykorzystywany do operacji. Z jakiegoś powodu to też nie chciało działać:
screenshot-20220621144700.png
screenshot-20220621144725.png
więc zdecydowałem się na utworzenie jednego klienta (publicznego) a następnie:

    public Keycloak getInstance(String token) {
        if (keycloak != null && this.token.equals(token)) {
            return keycloak;
        }
        this.token = token;
        keycloak = KeycloakBuilder.builder()
            .realm(realm)
            .serverUrl(serverURL)
            .clientId(clientID)
            .authorization(token)
            .build();
        return keycloak;
    }

do metody przekazuje bearer token.

1 użytkowników online, w tym zalogowanych: 0, gości: 1