Spring Безопасность Сервер ресурсов OAuth2 всегда возвращает недопустимый токен
Я пытаюсь получить базовый сервер OAuth2 с памятью, работающий с использованием библиотек Spring. Я следил за пример sparklr.
В настоящее время я настроил сервер, и почти все работает, однако я не могу получить доступ к моему ограниченному ресурсу с сервера ресурсов.
Мой тестовый рабочий процесс:
Я действительно не уверен, что я делаю неправильно, но похоже, что все, кроме доступа к ограниченному uri, работает. Вот моя конфигурация:
@Configuration
public class Oauth2ServerConfiguration {
private static final String SERVER_RESOURCE_ID = "oauth2-server";
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(SERVER_RESOURCE_ID);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and().requestMatchers()
.antMatchers("/me")
.and().authorizeRequests()
.antMatchers("/me").access("#oauth2.clientHasRole('ROLE_CLIENT')")
;
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthotizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.resourceIds(SERVER_RESOURCE_ID)
.secret("secret")
.authorizedGrantTypes("authorization_code", "refresh_token")
.authorities("ROLE_CLIENT")
.scopes("read","write")
.redirectUris("http://localhost:8080/client")
.accessTokenValiditySeconds(300)
.autoApprove(true)
;
}
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore())
.userApprovalHandler(userApprovalHandler())
.authenticationManager(authenticationManager)
;
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.realm("oauth");
}
@Bean
public ApprovalStore approvalStore() throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore());
return store;
}
@Bean
public UserApprovalHandler userApprovalHandler() throws Exception {
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
handler.setTokenStore(tokenStore());
return handler;
}
}
}
Есть ли что-то, что у меня пропало, или я приближаюсь к этому неправильно? Любая помощь будет принята с благодарностью.
Ответы
Ответ 1
Проблема заключалась в том, что сервер ресурсов и сервер авторизации не получали одну и ту же информацию о хранилище маркеров. Не знаете, как проводка работает некорректно, но использование фиксированного объекта в классе конфигурации работает как шарм. В конечном счете, я перейду к хранилищу токенов с сохранением сохранности, у которого, вероятно, не было бы проблем.
Спасибо за @OhadR за ответ и помощь!
В конечном счете, я упростил конфигурацию, прошел один и тот же рабочий процесс, и это сработало
@Configuration
public class Oauth2ServerConfiguration {
private static final String SERVER_RESOURCE_ID = "oauth2-server";
private static InMemoryTokenStore tokenStore = new InMemoryTokenStore();
@Configuration
@EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(tokenStore).resourceId(SERVER_RESOURCE_ID);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/me").and().authorizeRequests().antMatchers("/me").access("#oauth2.hasScope('read')");
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).approvalStoreDisabled();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.authorizedGrantTypes("authorization_code","refresh_token")
.authorities("ROLE_CLIENT")
.scopes("read")
.resourceIds(SERVER_RESOURCE_ID)
.secret("secret")
;
}
}
}
Любой, кто наткнулся на этот пост, я рекомендую больше смотреть на модульные тесты, а не на полный пример sparklr/tonr, поскольку он имеет много дополнительной конфигурации, которые не обязательно необходимы для начала работы.
Ответ 2
Ваш шаг №6 неверен - маркер доступа не должен быть отправлен в URL-адрес, поскольку он уязвим таким образом. rathen, чем GET, используйте POST.
Кроме того, я не понимаю ваш шаг № 1 - почему вы вызываете /oauth/authorize? это должно быть сделано неявно, когда вы пытаетесь получить защищенный ресурс. Я хочу сказать, что ваш поток должен начинаться с:
Попытка доступа к ограниченному ресурсу с помощью access_token: http://localhost:8080/server/me
Затем переговоры начнутся "за кадром": перенаправление на "/oauth/authorize" и т.д.
Кроме того, на шаге 8 обратите внимание, что вы не запрашиваете "другой токен доступа", но вместо этого это запрос "токен обновления". Как будто ваш токен доступа истек.
Примечание. Поставщик удостоверений и сервер ресурсов должны совместно использовать tokenStore! Читайте здесь: Spring Защищенный сервер ресурсов OAuth2
НТН
Ответ 3
Это работает для меня:
@Configuration
public class Oauth2ServerConfiguration {
private static final String SERVER_RESOURCE_ID = "oauth2-server";
@Autowired
private TokenStore tokenStore;
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Configuration
@EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(tokenStore).resourceId(SERVER_RESOURCE_ID);
}
@Override
public void configure(HttpSecurity http) throws Exception {
// ... Not important at this stage
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).approvalStoreDisabled();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//... Not important at this stage
}
}
}