package org.pac4j.oidc.authorization.generator;

import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import org.pac4j.core.authorization.generator.AuthorizationGenerator;
import org.pac4j.core.context.WebContext;
import org.pac4j.oidc.profile.keycloak.KeycloakOidcProfile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Specific {@link AuthorizationGenerator} to Keycloak.
 *
 * @author Jerome Leleu
 * @since 3.4.0
 */
public class KeycloakRolesAuthorizationGenerator implements AuthorizationGenerator<KeycloakOidcProfile> {

    private static final Logger LOGGER = LoggerFactory.getLogger(KeycloakRolesAuthorizationGenerator.class);

    private final String clientId;

    public KeycloakRolesAuthorizationGenerator(final String clientId) {
        this.clientId = clientId;
    }

    @Override
    public KeycloakOidcProfile generate(final WebContext context, final KeycloakOidcProfile profile) {

        try {
            final JWT jwt = SignedJWT.parse(profile.getAccessToken().getValue());
            final JWTClaimsSet jwtClaimsSet = jwt.getJWTClaimsSet();

            final JSONArray realmRolesJsonArray = (JSONArray) jwtClaimsSet.getJSONObjectClaim("realm_access").get("roles");
            if (realmRolesJsonArray != null) {
                realmRolesJsonArray.forEach(role -> profile.addRole((String) role));
            }

            if (clientId != null) {
                final JSONObject clientRolesJsonObject = (JSONObject) jwtClaimsSet.getJSONObjectClaim("resource_access").get(clientId);
                if (clientRolesJsonObject != null) {
                    final JSONArray vmsRolesJsonArray = (JSONArray) clientRolesJsonObject.get("roles");
                    if (vmsRolesJsonArray != null) {
                        vmsRolesJsonArray.forEach(role -> profile.addRole((String) role));
                    }
                }
            }
        } catch (final Exception e) {
            LOGGER.warn("Cannot parse Keycloak roles", e);
        }
        return profile;
    }
}

@@ -1224,21 +1224,22 @@
 nal JSON
-Array
+Object
  realmRo
@@ -1245,35 +1245,24 @@
 olesJson
-Array = (JSONArray)
+Object =
  jwtClai
@@ -1297,24 +1297,161 @@
 alm_access%22)
+;%0A            if (realmRolesJsonObject != null) %7B%0A                final JSONArray realmRolesJsonArray = (JSONArray)  realmRolesJsonObject
 .get(%22roles%22
@@ -1457,32 +1457,36 @@
 %22);%0A            
+  
+  
 if (realmRolesJs
@@ -1496,32 +1496,36 @@
 rray != null) %7B%0A
+    
                 
@@ -1585,32 +1585,50 @@
 String) role));%0A
+                %7D%0A
             %7D%0A%0A 

Fix NPE on the KeycloakRolesAuthorizationGenerator