3
votes

JHipster ne reçoit pas les rôles des utilisateurs Keycloak lors de la connexion

J'ai une application monolithique JHipster avec oauth2 exécutant Keycloak localement. Je ne sais pas exactement comment jhipster devrait fonctionner avec oauth2 ... j'ai d'abord pensé qu'il créerait l'utilisateur automatiquement, mais ce n'est pas le cas, alors j'ai configuré keycloak: j'ai créé le royaume jhipster , le Client web_app , les rôles client ROLE_ADMIN et ROLE_USER , et les utilisateurs admin et user code > avec leurs rôles corrects. Le problème est que lorsque je me connecte en tant qu'administrateur, il n'est pas reconnu comme ROLE_ADMIN , par conséquent je ne peux pas accéder au menu administrateur. J'ai donc commencé à parcourir le code, en essayant de comprendre comment Jhipster reçoit les informations d'identification de Keycloak, et j'ai réalisé que l'objet OAuth2Authentication dans AccountResource.java n'apportait pas le ROLE_ADMIN , mais le ROLE_USER dont je ne comprends pas pourquoi. L'objet OAuth2Authentication dans json ressemble à ceci:

{
    "generator-jhipster": {
        "promptValues": {
            "packageName": "xxxxxxxxxxx"
        },
        "jhipsterVersion": "5.7.2",
        "applicationType": "monolith",
        "baseName": "XXXXXXXXXX",
        "packageName": "xxxxxxxxxxxxxx",
        "packageFolder": "xxxxxxxxxxxxxx",
        "serverPort": "8080",
        "authenticationType": "oauth2",
        "cacheProvider": "ehcache",
        "enableHibernateCache": true,
        "websocket": false,
        "databaseType": "sql",
        "devDatabaseType": "h2Disk",
        "prodDatabaseType": "mysql",
        "searchEngine": false,
        "messageBroker": false,
        "serviceDiscoveryType": false,
        "buildTool": "maven",
        "enableSwaggerCodegen": false,
        "clientFramework": "angularX",
        "useSass": false,
        "clientPackageManager": "npm",
        "testFrameworks": [],
        "jhiPrefix": "jhi",
        "otherModules": [],
        "enableTranslation": false
    }
}

voici le yo-rc.json:

    {    
"authorities": [
        {
          "authority": "ROLE_USER"
        }
      ],
      "details": {
        "remoteAddress": "0:0:0:0:0:0:0:1",
        "sessionId": "rkkveY_Xa5zFFd0SKu9Of_FLGRnbdiTPHdnpj4gc",
        "tokenValue": "eyJhbGciOiJSUzI1...",
        "tokenType": "bearer",
        "decodedDetails": null
      },
      "authenticated": true,
      "userAuthentication": {
        "authorities": [
          {
            "authority": "ROLE_USER"
          }
        ],
        "details": {
          "sub": "f348bbbb-9441-4543-9940-9da31e50d877",
          "email _verified": true,
          "name": "Admin Administrator",
          "preferred_username": "admin",
          "given_name": "Admin",
          "family_name": "Administrator",
          "email": "admin@localhost"
        },
        "authenticated": true,
        "principal": "Admin Administrator",
        "credentials": "N/A",
        "name": "Admin Administrator"
      },
      "clientO nly": false,
      "principal": "Admin Administrator",
      "oauth2Request": {
        "clientId": "web_app",
        "scope": [

        ],
        "requestParameters": {

        },
        "resourceIds": [

        ],
        "authorities": [

        ],
        "approved": true,
        "refresh": false,
        "redirectUri": null,
        "responseTypes": [

        ],
        "extensions": {

        },
        "grantType": null,
        "refreshTok enRequest": null
      },
      "credentials": "",
      "name": "Admin Administrator"
    }

Comment puis-je résoudre ce problème?


0 commentaires

3 Réponses :


1
votes

J'ai eu le même problème, je suppose que c'est parce que Keycloak attribue les rôles client dans une autre revendication "resource_access" et que la bibliothèque Spring Boot Security Oauth2 ne lit pas les rôles ici.

J'ai modifié UserService.java pour essayer dans un premier temps pour lire cette revendication et la sous-valeur correspondant au clientId en décodant le jeton JWT, c'est plus propre car il ne lit que les rôles clients.

   public UserDTO getUserFromAuthentication(OAuth2Authentication authentication) {
    OAuth2AuthenticationDetails oauth2AuthenticationDetails = (OAuth2AuthenticationDetails) authentication
            .getDetails(); // should be an OAuth2AuthenticationDetails

    Map<String, Object> details = (Map<String, Object>) authentication.getUserAuthentication().getDetails();
    User user = getUser(details);
    String tokenValue = oauth2AuthenticationDetails.getTokenValue();
    DecodedJWT jwt = JWT.decode(tokenValue);

    Map<String, Object> resourceAccessClaim = jwt.getClaim("resource_access").asMap();
    String clientId = authentication.getOAuth2Request().getClientId();

    if (resourceAccessClaim.containsKey(clientId)) {
        ((Map<String, Object>) resourceAccessClaim.get(clientId)).values().forEach(rn -> {
            user.setAuthorities(extractAuthorities((List<String>) rn));
        });
    }
    if (user.getAuthorities() == null || user.getAuthorities().size() == 0) {
        user.setAuthorities(extractAuthorities(authentication, details));
    }

    // convert Authorities to GrantedAuthorities
    Set<GrantedAuthority> grantedAuthorities = user.getAuthorities().stream().map(Authority::getName)
            .map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
...


1 commentaires

Salut @Fabrice Dominguez J'ai essayé de définir votre code, mais il dit que cette classe OAuth2Authentication ou OAuth2AuthenticationDetails n'existe pas. Aucune suggestion



6
votes

Dans l'administration de keycloak, accédez à Clients >> VOTRE_CLIENT >> Mappeurs -> Ajouter un nouveau mappeur -> Définissez le type de mappeur sur "Rôle client utilisateur" et "Nom de revendication de jeton" sur "Autorités" et Réclamez le type JSON sur chaîne.

/ p>


1 commentaires

merci pour la réponse, malheureusement, j'apprends toujours à utiliser les mappeurs dans keycloak et maintenant j'ai un autre problème avec la nouvelle version de JHipster. Je vous serais reconnaissant si vous pouviez le vérifier: stackoverflow.com/questions/56437540/...



1
votes

Nouvelle solution

Vous pouvez voir plus dans le lien ci-dessous la configuration de Keycloak, donc il envoie les rôles dans le jeton et nous n'avons pas besoin de changer le code d'origine. p>

https://medium.com/@mobilegotop/how-to-configure-keycloak-for-jhipster-a-spring-boot-app-with-roles-709491e0b5c6

Ancienne solution. Ne fonctionne pas très bien, car les RÔLES ne sont pas inclus dans les privilèges d'octroi normaux Dans UserService.java, j'ai changé comme ceci:

 public UserDTO getUserFromAuthentication(final AbstractAuthenticationToken authToken) {
        Map<String, Object> attributes;
        if (authToken instanceof OAuth2AuthenticationToken) {
            attributes = ((OAuth2AuthenticationToken) authToken).getPrincipal().getAttributes();
        } else if (authToken instanceof JwtAuthenticationToken) {
            attributes = ((JwtAuthenticationToken) authToken).getTokenAttributes();
        } else {
            throw new IllegalArgumentException("AuthenticationToken is not OAuth2 or JWT!");
        }
        User user = getUser(attributes);

        JSONArray auths =  (JSONArray) attributes.get("authorities");
        Set<Authority> authorities = new HashSet<Authority>();
        for(int i=0; i<auths.size(); i++){
          Authority  au = new Authority();
          au.setName(auths.get(i).toString());
          authorities.add(au);
        }

        user.setAuthorities(authorities);
        return new UserDTO(syncUserWithIdP(attributes, user));
    }

et définissez les "autorités" dans le nom de la revendication du jeton comme: entrez la description de l'image ici


0 commentaires