Spring OAuth2 - аутентификации клиента нет. Попробуйте добавить соответствующий фильтр проверки подлинности
У нас есть приложение, которое использует spring-security-oauth2:1.0
. Я пытался изменить его на более новую версию, spring-security-oauth2:2.0.7.RELEASE
. Некоторые классы были удалены, некоторая структура пакета изменилась, мне удалось разобраться во всех этих вещах, и я смог запустить сервер без каких-либо проблем. Но здесь я сталкиваюсь со странной проблемой.
В OAuth2 - 1.0 version
, когда пользователь входит в систему, мы использовали GET
запрос к /oauth/token
, например:
HTTP://локальный: 8080/эхо /OAuth/маркер grant_type = пароль и client_id = WS & client_secret = секрет и сфера = читать, писать и имя пользователя = джон @abc.com и пароль = password123
И раньше он работал просто отлично.
Когда я пытаюсь сделать то же самое, во-первых, я не могу сделать запрос GET
из-за логики в TokenEndPoint.java
private Set<HttpMethod> allowedRequestMethods = new HashSet<HttpMethod>(Arrays.asList(HttpMethod.POST));
@RequestMapping(value = "/oauth/token", method=RequestMethod.GET)
public ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
if (!allowedRequestMethods.contains(HttpMethod.GET)) {
throw new HttpRequestMethodNotSupportedException("GET");
}
return postAccessToken(principal, parameters);
}
Я попытался сделать POST
запрос, такой же, как приведенный выше URL-адрес, но я получаю InsufficientAuthenticationException
с сообщением об ошибке
Нет аутентификации клиента. Попробуйте добавить соответствующий фильтр аутентификации
Это из-за следующего контроллера запросов POST
в TokenEndpoint.java
. Когда я отлаживаю, я вижу, что principal
является нулевым.
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
//principal is null here
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException(
"There is no client authentication. Try adding an appropriate authentication filter.");
}
.............
}
У меня есть фильтр аутентификации, и он работал хорошо, когда я использовал version 1.0
. Это соответствующие прароды моего конфига:
<authentication-manager xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="userDetailsService"/>
</authentication-manager>
<bean id="userDetailsService" class="com.hcl.nc.service.UserDetailsService">
<constructor-arg><ref bean="sessionFactory" /></constructor-arg>
</bean>
Я всегда думал, что запрос будет аутентифицирован authentication-provider
и отправляется в token-endpoint
но это не похоже на правильный поток. После отладки приложения с version 2.0.7
теперь я действительно сомневаюсь в своем понимании потока.
Может кто-нибудь объяснить, почему он работал в предыдущей версии и почему он не работает сейчас?
Должен ли я сделать что-то другое, чтобы получить токен OAuth?
ПРИМЕЧАНИЕ: я уже проверил эти вопросы: здесь, здесь, здесь. Но я не смог найти правильного решения.
Ответы
Ответ 1
Я не знаю предыдущей версии, но я немного знаю о 2.0.7.
Я подозреваю, что ваша проблема заключается в том, что ваша защита TokenEndpoint пытается аутентифицировать ваших клиентов в отношении вашей пользовательской службы.
TokenEndpoint защищен BasicAuthenticationFilter
. По умолчанию этот фильтр будет использовать экземпляр AuthenticationManager
, который сам содержит AuthenticationProvider
, который сам по себе зависит от экземпляра UserDetailsService
.
Фокус в том, что этот конкретный экземпляр UserDetailsService
должен быть клиент, а не пользователем: почему существует ClientDetailsUserDetailsService
, который адаптирует ClientDetailsService
к UserDetailsService
.
Обычно все это делается по умолчанию, когда вы используете классы конфигурации фрейма AuthorizationServerConfigurerAdapter
, @EnableAuthorizationServer
и т.д.
Ответ 2
У меня была такая же проблема, и мой application.yml имел следующую строку:
servlet:
path: /auth
поэтому адрес токена был: /auth/oauth/token
Я удаляю путь из application.yml, чтобы путь токена стал:
/oauth/token
И все работает отлично.
Надеюсь это поможет
Ответ 3
в моем случае, я нашел эту конфигурацию:
security.allowFormAuthenticationForClients();//здесь
затем опубликуйте это http://localhost:8081/sso/oauth/token?client_id=unity-client&client_secret=unity&grant_type=authorization_code&code=Yk4Sum&redirect_uri=http://localhost:8082/sso-demo/passport/login
его работы для меня, попробуйте
@Configuration
@EnableAuthorizationServer
public class Oauth2Config extends AuthorizationServerConfigurerAdapter {
private static final Logger log = LoggerFactory.getLogger(Oauth2Config.class);
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients(); // here
}
@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off
clients.inMemory()
.withClient("unity-client")
.secret("unity")
.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
.scopes("foo", "read", "write")
.accessTokenValiditySeconds(3600) // 1 hour
.refreshTokenValiditySeconds(2592000) // 30 days
;
} // @formatter:on
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
}
}
Ответ 4
Одной из проблем следующей ошибки может быть то, что аутентификация не была выполнена. Я столкнулся с этой проблемой в более старой реализации Spring.
подтвердите это:
TokenEndpoint → метод postAccessToken. Проверьте, не является ли Принципал нулевым. Если он нулевой, это означает, что базовая аутентификация не была выполнена.
Одним из решений для добавления фильтра было использование:
@Configuration
public class FilterChainInitializer extends AbstractSecurityWebApplicationInitializer {
}
Более подробную информацию о AbstractSecurityWebApplicationInitializer можно найти в документах Spring.