Как настроить OAuth2RestTemplate с учетными данными клиента и автоматическим обновлением токена в spring-security-oauth 2.2.1.RELEASE

Я внедряю клиента, который аутентифицируется с помощью OAuth2 против WSO2, и у меня серьезные проблемы с обновлением токена доступа, получая 401 НЕСАНКЦИОНИРОВАННО. Хотя я уже выяснил, что делает код Spring OAuth2, я не знаю, почему его поведение было изменено в 2.2.1.RELEASE, и мне кажется, что это неправильно. На самом деле с помощью 2.0.14. РЕЛИЗ работает.

Прежде чем я покажу вам, что я сделал и что я уже выяснил, позвольте мне сформулировать свой вопрос:

Как мне реализовать клиент OAuth2 с автоматическим обновлением токена с учетными данными клиента вместо учетных данных пользователя?

Так вот, что я реализовал до сих пор. Клиент настраивает OAuth2RestTemplate с ResourceOwnerPasswordResourceDetails с isClientOnly флаг true, так как нет пользовательских сессий. Сеанс клиента может быть успешно установлен, а также установлены токен доступа и токен обновления.

@Bean
protected OAuth2ProtectedResourceDetails resource() {
    ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails() {
        @Override
        public boolean isClientOnly() {
            return true;
        }               
    };
    List<String> scopes = new ArrayList<>(2);
    scopes.add("write");
    scopes.add("read");
    resource.setScope(scopes);
    resource.setGrantType("password");
    resource.setAccessTokenUri(TOKEN_URL);
    resource.setClientId(MY_CLIENT_ID);
    resource.setClientSecret(MY_CLIENT_SECRET);
    resource.setUsername(MY_SERVICE_USER);
    resource.setPassword(MY_SERVICE_USER_PW);
    return resource;
}


@Bean
public OAuth2RestOperations restTemplate() {
    AccessTokenRequest atr = new DefaultAccessTokenRequest();
    OAuth2RestTemplate template = new OAuth2RestTemplateWithBasicAuth(resource(), new DefaultOAuth2ClientContext(atr));
    List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
    interceptors.add(new LoggingRequestInterceptor());      
    template.setInterceptors(interceptors);
    template.setRetryBadAccessTokens(true);
    return template;
}

Все идет нормально. Я убедился, что это в основном работает.

Но как только истекает токен доступа, я часто сталкиваюсь с ошибками 401, потому что обновление токена не выполняется. Вместо этого выполняется обычный запрос аутентификации, но с использованием клиентского ключа и секрета вместо имени пользователя / пароля. Короче говоря, я отладил свой путь через spring-security-oauth2 в AccessTokenProviderChain#obtainAccessToken и выяснил, что выполняется ли запрос на обновление токена, определяется следующим фрагментом кода. Смотрите на Github

    if (resource.isClientOnly() || (auth != null && auth.isAuthenticated())) {   // P1
        existingToken = request.getExistingToken();
        if (existingToken == null && clientTokenServices != null) {
            existingToken = clientTokenServices.getAccessToken(resource, auth);
        }

        if (existingToken != null) {
            if (existingToken.isExpired()) {
                if (clientTokenServices != null) {
                    clientTokenServices.removeAccessToken(resource, auth);
                }
                OAuth2RefreshToken refreshToken = existingToken.getRefreshToken();
                if (refreshToken != null && !resource.isClientOnly()) {  // P2
                    accessToken = refreshAccessToken(resource, refreshToken, request);
                }
            }
            else {
                accessToken = existingToken;
            }
        }
    }

Как вы можете видеть на P1, блок вводится, если существует сеанс авторизованного пользователя (auth) или ресурс настроен как clientOnly, Поскольку у меня нет пользователей, но я нахожусь в связанном сценарии службы, у меня есть isClientOnly() == true && auth == null, Но на P2 окончательное решение по фактическому обновлению противоречит требованию !isClientOnly(), Таким образом, это эффективно запрещает запросы на обновление в клиентских сценариях.

Это был путь в версиях до 2.2.1, и я обнаружил, что это, кажется, исправление следующей проблемы. Мне это кажется совершенно неправильным.

Кроме того, мне кажется, что патч нарушает функциональность клиента, чтобы исправить фактическое неправильное поведение сервера. Как вы можете видеть в обсуждении проблемы, я уже прокомментировал там. Но так как эта проблема закрыта, и форум spring-security-oauth2 утверждает, что здесь, на Stackru, должны быть проведены обсуждения, я прошу помощи здесь.

Снова вопрос: как клиентское приложение должно быть настроено на использование защищенных сервисов OAuth2 через OAuth2RestTemplate и время работы токена доступа в час и время обновления токена, скажем, два часа.

0 ответов

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