Переопределение аутентификации Oauth2 в Spring Security - PullRequest
0 голосов
/ 22 марта 2020

Мой пример использования таков: в многопользовательском приложении каждый арендатор может настроить свой собственный механизм аутентификации SSP IDP. Они также могут настроить, следует ли автоматически создавать новых пользователей в локальном приложении при аутентификации нового пользователя.

Я использую Spring Security и у меня работают несколько поставщиков Oauth2.

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

И также, где я должен добавить код для создания нового пользователя, если разрешено автоматическое создание?

ОБНОВЛЕНИЕ:

Кажется, Основы таковы - для Spring Security 5 вам необходимо реализовать свой собственный OAuth2UserService, либо (или оба) из того, который принимает OAuth2UserRequest и возвращает OAuth2User или тот, который принимает OidcUserRequest и возвращает OidcUser.

Они могут быть настроены следующим образом:

   protected void configure(HttpSecurity http) throws Exception
   {
      http...
              .userInfoEndpoint()
              .userService(securityUserService)
              .oidcUserService(commonOAuth2UserService)
      ...;
   }

, где securityUserService является @Component, реализующим OAuth2UserService, а commonOAuth2UserService является @Component, реализующим OAuth2UserService. Обратите внимание, что вам может понадобиться только один из них - я использую оба, потому что у меня несколько разных типов ВПЛ.

Однако это еще не полный ответ, потому что я все еще борюсь с одной вещью: мне нужно получить надежное значение из idToken, которое говорит мне, какого пользователя мне нужно искать. Я ожидал, что смогу передать это состояние как исходный запрос (путем реализации моего собственного OAuth2AuthorizationRequestResolver), но я обнаружил, что установленное там состояние не отображается в idToken ни для Okta, ни для Azure AD.

Кто-нибудь знает, почему значение состояния не выделяет его с другой стороны?

Кажется, что обходным решением может быть использование полученного мной адреса электронной почты, но каждый ВПЛ предоставляет это по-другому, и все они предостерегают от использования этих атрибутов для чего-то критического, так что это выглядит как очень простое решение, которое может работать сейчас, но не позже.

Предупреждение для тех, кто может следовать это: не отвлекайтесь на обильные ссылки на использование PrincipalExtractor и AuthoritiesExtractor, которые вы можете найти в Googling - эта старая технология больше не поддерживается в последней версии Spring Security.

Реализация OAuth2UserService:

@Component
public class CommonOAuth2UserService
        implements OAuth2UserService<OidcUserRequest, OidcUser>
{
    final OidcUserService delegate = new OidcUserService();

    @Override
    public OidcUser loadUser(OidcUserRequest userRequest)
            throws OAuth2AuthenticationException
    {
        // Delegate to the default implementation for loading a user
        OidcUser oidcUser = delegate.loadUser(userRequest);
        Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
        mappedAuthorities.add(new SecurityRole("ROLE_USER"));
        oidcUser = new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo());
        return oidcUser;
    }
}

и запрос OAuth2AuthorizationRequestResolver:

public class CustomAuthorizationRequestResolver
        implements OAuth2AuthorizationRequestResolver
{
    private OAuth2AuthorizationRequestResolver defaultResolver;

    public CustomAuthorizationRequestResolver(
            ClientRegistrationRepository repo
                                             )
    {
        defaultResolver = new DefaultOAuth2AuthorizationRequestResolver(repo, "/oauth2/authorization");
    }

    @Override
    public OAuth2AuthorizationRequest resolve(HttpServletRequest httpServletRequest)
    {
        OAuth2AuthorizationRequest request = defaultResolver.resolve(httpServletRequest);
        if (request == null) return null;
        OAuth2AuthorizationRequest returnreq = OAuth2AuthorizationRequest.from(request)
                .state(request.getState() + ";euamid=kdc123")
                .build();
        return returnreq;
    }

    @Override
    public OAuth2AuthorizationRequest resolve(HttpServletRequest httpServletRequest, String s)
    {
        OAuth2AuthorizationRequest request = defaultResolver.resolve(httpServletRequest, s);
        if (request == null) return null;
        return OAuth2AuthorizationRequest.from(request)
                .state(request.getState()+";euamid=kdc123")
                .build();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...