Можно ли добавить полномочия access_token в OAuth2LoginAuthenticationToken? - PullRequest
0 голосов
/ 06 апреля 2019

У меня есть простое приложение с весенней загрузкой с двумя службами - ui и resource. Я пытаюсь настроить аутентификацию oauth2 + oidc, используя сервер uaa.

Когда я вхожу в сервис ui, Spring Security создает результат аутентификации (в OidcAuthorizationCodeAuthenticationProvider), используя id_token, и не содержит никаких областей, кроме openid. Когда создается результат аутентификации, он содержит только одно право доступа - ROLE_USER, поэтому нельзя использовать авторизацию на стороне клиента.

Можно ли переопределить OidcUserService и добавить области полномочий пользователя из access_token для проверки доступа на стороне клиента?

    @Override
    public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
        OidcUser user = super.loadUser(userRequest);
        Collection<? extends GrantedAuthority> authorities = buildAuthorities(
                user,
                userRequest.getAccessToken().getScopes()
        );
        return new DefaultOidcUser(
                authorities,
                userRequest.getIdToken(),
                user.getUserInfo()
        );
    }

Конфигурация безопасности:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .mvcMatchers("/protected/**").hasAuthority("SCOPE_protected")
                .anyRequest().authenticated()
                .and()
            .oauth2Login()
                .userInfoEndpoint().oidcUserService(oidcUserService())
                .and()
            ...

Это работает, но я не уверен, что это хорошая идея.

1 Ответ

1 голос
/ 03 мая 2019

Это подход, описанный в документации Spring Security , поэтому подход хорош.Единственное, что, когда я его реализовал, я не добавил все области к набору полномочий - я вытащил конкретное утверждение, содержащее информацию о роли, - пользовательское утверждение groups, которое я настроил в авторизации провайдера идентификации.сервер.

Я включил пример кода для того, как сделать это с Spring Webflux, так как большинство примеров показывают, как сделать это с Spring MVC в соответствии с вашим кодом.

примечание: я очень неопытныйс использованием реактора!

public class CustomClaimsOidcReactiveOAuth2UserService implements ReactiveOAuth2UserService<OidcUserRequest, OidcUser> {

    private final OidcReactiveOAuth2UserService service = new OidcReactiveOAuth2UserService();

    public Mono<OidcUser> loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
        log.debug("inside CustomClaimsOidcReactiveOAuth2UserService..");

        Mono<OidcUser> mOidcUser = service.loadUser(userRequest);

        return mOidcUser
                .log()
                .cast(DefaultOidcUser.class)
                .map(DefaultOidcUser::getClaims)
                .flatMapIterable(Map::entrySet)
                .filter(entry -> entry.getKey().equals("groups"))
                .flatMapIterable(roleEntry -> (JSONArray) roleEntry.getValue())
                .map(roleString -> {
                    log.debug("roleString={}", roleString);
                    return new OidcUserAuthority((String) roleString, userRequest.getIdToken(), null);
                })
                .collect(Collectors.toSet())
                .map(authorities -> {
                    log.debug("authorities={}", authorities);
                    return new DefaultOidcUser(authorities, userRequest.getIdToken());
                });
    }
}
...
@Bean
ReactiveOAuth2UserService<OidcUserRequest, OidcUser> userService() {
    return new CustomClaimsOidcReactiveOAuth2UserService();
}
...