JHipster не получает роли от пользователей Keycloak при входе в систему

У меня есть монолитное приложение JHipster с oauth2, запускающим Keycloak локально. Я не знаю, как именно jhipster должен работать с oauth2... сначала я думал, что он создаст пользователя автоматически, но это не так, поэтому я настроил keycloak: я создал область jhipster, клиент web_app, клиентские роли ROLE_ADMIN. и ROLE_USER, и пользователи admin и user с их правильными ролями. Проблема в том, что когда я вхожу в систему как администратор, он не распознается как ROLE_ADMIN, в результате чего я не могу получить доступ к меню администратора. Итак, я начал просматривать код, пытаясь понять, как Jhipster получает учетные данные от Keycloak, и я понял, что объект OAuth2Authentication в AccountResource.java приносит не ROLE_ADMIN, а ROLE_USER, который я не понимаю, почему. Объект OAuth2Authentication в 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"
    }

вот yo-rc.json:

{
    "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
    }
}

Как я могу это исправить?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
3
0
2 864
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

У меня была та же проблема, я думаю, это связано с тем, что Keycloak дает роли клиента в другом утверждении «resource_access», а библиотека Spring Boot Security Oauth2 не читает роли здесь.

Я изменил UserService.java, чтобы попытаться сначала прочитать это утверждение и подзначение, соответствующее clientId, путем декодирования токена JWT, это чище, потому что он читает только клиентские роли.

   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());
...

Привет @Fabrice Dominguez Я пытался установить ваш код, но он говорит, что этот класс OAuth2Authentication или OAuth2AuthenticationDetails не существует. Какие-либо предложения

Inês Gomes 02.07.2020 15:26

В администрировании keycloak перейдите в раздел «Клиенты» >> YOUR_CLIENT >> Mappers -> Добавить новый преобразователь -> Установите тип преобразователя на «Роль клиента пользователя», а «Имя утверждения токена» установите на «полномочия» и укажите тип JSON на строку.

спасибо за ответ, к сожалению, я все еще учусь использовать картографы в keycloak, и теперь у меня другая проблема с более новой версией JHipster. Буду благодарен, если проверите: stackoverflow.com/questions/56437540/…

J. Gatica 04.06.2019 07:12

Новое решение

Вы можете увидеть больше по ссылке ниже конфигурации Keycloak, поэтому он отправляет роли в токене, и нам не нужно менять исходный код.

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

Старое решение. Не так хорошо работает, потому что РОЛИ не идут в обычных привилегиях предоставления В UserService.java я изменил так:

 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));
    }

и установите «полномочия» в имени претензии токена, например:

Другие вопросы по теме