OAuth2 GrantedAuthorities отсутствует в JWT при использовании пользовательской службы UserDetailsService

Используя новый spring-authorization-server 0.2.3 и следуя https://github.com/spring-projects/spring-authorization-server/tree/main/samples в качестве ссылки, я смог успешно настроить сервер авторизации, сервер ресурсов и клиент при использовании InMemoryUserDetailsManager следующим образом.


@EnableWebSecurity
public class DefaultSecurityConfig {

    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeRequests(authorizeRequests ->
                        authorizeRequests.anyRequest().authenticated()
                )
                .formLogin(Customizer.withDefaults())
                .build();
    }


    @Bean
    UserDetailsService users() {
        User.UserBuilder users = User.withDefaultPasswordEncoder();
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(users.username("user1").password("password").roles("USER").build());
        manager.createUser(users.username("admin").password("password").roles("USER", "ADMIN").authorities("r1","r2","r3").build());
        return manager;
    }

}

Это хорошо работает. В клиенте я вижу присутствие властей Granted Authorities=["r1","r2","r3"].

Теперь, когда я пытаюсь реализовать свой собственный UserDetailsService, который извлекает пользователей из базы данных Mongo, я перестаю видеть передачу GrantedAuthorities клиенту и вижу только Granted Authorities=[ROLE_USER, SCOPE_openid]

Это то, что у меня сейчас есть в DefaultSecurityConfig


@EnableWebSecurity
public class DefaultSecurityConfig {

    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeRequests(authorizeRequests ->
                        authorizeRequests.anyRequest().authenticated()
                )
                .formLogin(Customizer.withDefaults())
                .build();
    }

    @Autowired
    private MongoTemplate mongoTemplate;

    @Bean
    UserDetailsService users() {
        return new CustomUserDetailsService(mongoTemplate);
    }
}

И мой CustomUserDetailsService выглядит следующим образом:


public class CustomUserDetailsService implements UserDetailsService {

    private final MongoTemplate mongoTemplate;

    public CustomUserDetailsService(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Criteria criteria = Criteria.where("email").is(username);
        CustomUser user = mongoTemplate.findOne(new Query(criteria), CustomUser.class, "vOAuthUser");
        if (user != null) {
            log.info("Found user {}", user.email());
            List<GrantedAuthority> authorities = getUserAuthority(user.groups());
            return buildUserForAuthentication(user, authorities);
        } else {
            throw new UsernameNotFoundException("username not found");
        }
    }

    private UserDetails buildUserForAuthentication(CustomUser user, List<GrantedAuthority> authorities) {
        return new org.springframework.security.core.userdetails.User(user.email(), user.password(), authorities);
    }

    private List<GrantedAuthority> getUserAuthority(Set<String> groups) {
        List<GrantedAuthority> authorities = new ArrayList<>();
        groups.forEach(s -> {
            Criteria criteria = Criteria.where("name").is(s);
            CustomRole role = mongoTemplate.findOne(new Query(criteria), CustomRole.class, "vRole");
            if (role != null) {
                authorities.addAll(role.grantedAuthorities());
            }
        });
        return authorities;
    }

}


Any help is greatly appreciated.

Пользовательский скаляр 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 .
0
0
27
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы определили bean-компонент OAuth2TokenCustomizer в своей конфигурации безопасности? Вы можете добавить предоставленные полномочия туда, если вам нужно, как в следующем коде:

   @Bean
   @SuppressWarnings("unused")
   OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
      return context -> {
         JoseHeader.Builder headers = context.getHeaders();
         JwtClaimsSet.Builder claims = context.getClaims();

         Authentication principal = context.getPrincipal();
         Set<String> authorities = principal.getAuthorities().stream()
               .map(GrantedAuthority::getAuthority)
               .collect(Collectors.toSet());
         claims.claim("authorities", authorities);
      };
   }

Работает хорошо, спасибо. Есть ли способ сопоставить утверждения ["полномочия"] от принципала oidc с корневой аутентификацией getAuthorities(), поскольку я хочу использовать авторизацию метода Pre/Post в моем клиенте.

Antony Jukes 08.04.2022 16:05

Может быть, это поможет stackoverflow.com/questions/59379645/…

Andrey Grigoriev 09.04.2022 13:46

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

Поддержка одновременной аутентификации MVC (сеанса) с полным стеком, а также аутентификации JWT без сохранения состояния в Spring Authorization Server (0.2.3+)
Как я могу получить атрибут из запроса Jmeter
Почему конечная точка не отвечает?
Отладка Интерфейс между сервером ресурсов и сервером авторизации (маркер доступа для проверки подлинности oauth 2.0)
Как включить секрет jwt в application.yaml для Java Spring
Защитите мое приложение от атак CSRF с помощью Spring Boot 2.6.X и JDK 1.11.XX в приложении постоянного входа
Не удалось запустить приложение. Зависимости некоторых компонентов образуют цикл... Почему?
Spring Authorization Server 0.2.2, как отключить поставщика аутентификации по умолчанию, например (OAuth2TokenRevocation), и заменить его на собственный?
Страница не перенаправляется должным образом при попытке войти в Spring Authorization Server с помощью пользовательской службы сведений о пользователе
Модуль Spring Boot Security выдает ошибку 403 при вызове с использованием axios из реакции, но отлично работает в почтальоне