Авторизация на основе ролей: Oauth с OneLogin и Spring Security

У меня есть приложение весенней загрузки, которое использует Oauth с OneLogin в качестве сервера авторизации. Теперь я хочу реализовать авторизацию на основе ролей, чтобы предоставлять определенные API только пользователям с определенными привилегиями.

У меня есть пользователи, принадлежащие к группам. Скажем, пользователь A принадлежит к группе администраторов, а пользователь B не принадлежит к группе администраторов. Мой вопрос заключается в том, как я могу использовать эти группы, чтобы разрешить только пользователю A доступ к определенным API.

Это информация об аутентифицированном пользователе для справки:

authorities 
0   
authority   "ROLE_USER"           **//says ROLE_USER even when the user belongs to the admin group** 
attributes  
at_hash "xxxxx"
sub "xxxx"
iss "https://******/oidc/2"
groups  
0   "Group A"
1   "Group B"
2   **"DEMO"**
3   **"DEMO Admin"**               **//presence in this group should be considered for authorisation**
preferred_username  "xxx"
given_name  "xxxx"
nonce   "xxxxxxx"
sid "xxxxxxx"
aud 
0   "xxxxxxx"
updated_at  "xxxxxx"
name    "xxxxxx"
exp "xxxxxxx"
family_name "xxxxxx"
iat "xxxxxxxx"
email   "xxxxxxxx"
idToken {…}
userInfo    {…}
1   
authority   "SCOPE_email"
2   
authority   "SCOPE_groups"
3   
authority   "SCOPE_openid"
4   
authority   "SCOPE_profile"

Я хочу защитить свои остальные контроллеры примерно так:

@PreAuthorize("Belongs to group admin")
@RequestMapping(value = "/delete", method = RequestMethod.GET)
public string delete() {
  System.out.println("delete");
}

Это мой файл application.yaml

server:
  servlet:
    context-path: /demo


spring:
  security:
    oauth2:
      client:
        registration:
          onelogin:
            client-id: *****
            client-secret: *******
            scope: openid,profile,email,groups
            provider: onelogin
        provider:
          onelogin:
            issuer-uri: https://******/oidc/2

person Coder    schedule 02.11.2020    source источник
comment
Правильно ли я понимаю, что ваше приложение является одновременно клиентом OAuth2 и сервером ресурсов?   -  person Eleftheria Stein-Kousathana    schedule 03.11.2020
comment
Да. Это правильно!   -  person Coder    schedule 04.11.2020


Ответы (1)


Поскольку ваше приложение также является сервером ресурсов, вы можете использовать пользовательский JwtAuthenticationConverter для настройки преобразования JWT в объект Authentication. Специально для этого случая вы можете настроить преобразование JWT в список GrantedAuthorities.

По умолчанию сервер ресурсов заполняет GrantedAuthorities на основе утверждения "scope".
Если JWT содержит утверждение с именем "scope" или "scp", тогда Spring Security будет использовать значение в этом утверждении для создания полномочий, добавляя префикс к каждому значению. с "SCOPE_". Вот почему вы видите полномочия SCOPE_email, SCOPE_groups и т. д.

Если вы хотите вместо этого заполнить GrantedAuthorities на основе утверждения групп, вы можете сделать это следующим образом:

@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
    JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
    converter.setJwtGrantedAuthoritiesConverter(new CustomJwtGrantedAuthoritiesConverter());
    return converter;
}

public class CustomJwtGrantedAuthoritiesConverter implements Converter<Jwt, Collection<GrantedAuthority>> {
    @Override
    public Collection<GrantedAuthority> convert(Jwt jwt) {
        Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        for (String group : getGroups(jwt)) {
            grantedAuthorities.add(new SimpleGrantedAuthority(group));
        }
        return grantedAuthorities;
    }
}

private Collection<String> getGroups(Jwt jwt) {
    Object groups = jwt.getClaim("groups");
    // Convert groups to Collection of Strings based on your logic
}

Затем вы можете использовать выражение "hasAuthority('YOUR_CUSTOM_GROUP_NAME')" для ограничения доступа к определенным конечным точкам.

person Eleftheria Stein-Kousathana    schedule 04.11.2020
comment
Спасибо за ваш ответ. Но я получаю следующую ошибку, когда добавляю ваш код конвертера. Для метода springSecurityFilterChain в org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration требуется bean-компонент типа org.springframework.security.oauth2.jwt.JwtDecoder, который не удалось найти. - person Coder; 04.11.2020
comment
Вам также нужно будет установить issuer-uri на сервере ресурсов. YML очень похож на то, что у вас есть сейчас. Взгляните на этот раздел в документации docs.spring.io/spring-security/site/docs/current/reference/ - person Eleftheria Stein-Kousathana; 04.11.2020