Spring Security OAuth2 资源服务器总是返回无效的令牌 [英] Spring Security OAuth2 Resource Server Always Returning Invalid Token
问题描述
我正在尝试使用 Spring 库运行一个基本的内存中 OAuth2 服务器.我一直在关注 sparklr 示例.
I am trying to get a basic in-memory OAuth2 server running using the Spring Libraries. I have been following the sparklr example.
我目前已经配置了服务器并且几乎一切正常,但是我无法从资源服务器访问我的受限资源.
I currently have configured the Server and almost everything is working, however I cannot access my restricted resource from the resource server.
我的测试工作流程:
访问 oauth 授权 URI 以启动 OAuth2 流程:http://localhost:8080/server/oauth/authorize?response_type=code&client_id=client
重定向到登录页面:http://localhost:8080/server/login
处理批准并使用代码参数重定向到我配置的重定向页面:http://localhost:8080/client?code=HMJO4K
Handle the approval and redirect to my configured redirect page w/ a code parameter: http://localhost:8080/client?code=HMJO4K
使用客户端 ID 和密码以及授权类型和代码,使用基本身份验证构建 GET 请求:http://localhost:8080/server/oauth/token?grant_type=authorization_code&code=HMJO4K
Construct a GET request using Basic Auth using the client id and secret along with the grant type and code: http://localhost:8080/server/oauth/token?grant_type=authorization_code&code=HMJO4K
接收一个 access_token 并作为回报刷新令牌对象
Receive an access_token and refresh token object in return
{access_token:f853bcc5-7801-42d3-9cb8-303fc67b0453"token_type:承载"refresh_token:57100377-dea9-4df0-adab-62e33f2a1b49"expires_in: 299范围:读写"}
{ access_token: "f853bcc5-7801-42d3-9cb8-303fc67b0453" token_type: "bearer" refresh_token: "57100377-dea9-4df0-adab-62e33f2a1b49" expires_in: 299 scope: "read write" }
尝试使用 access_token 访问受限资源:http://localhost:8080/server/me?access_token=f853bcc5-7801-42d3-9cb8-303fc67b0453
Attempt to access a restricted resource using the access_token: http://localhost:8080/server/me?access_token=f853bcc5-7801-42d3-9cb8-303fc67b0453
收到无效的令牌回复
{错误:invalid_token"error_description:无效的访问令牌:f853bcc5-7801-42d3-9cb8-303fc67b0453"}
{ error: "invalid_token" error_description: "Invalid access token: f853bcc5-7801-42d3-9cb8-303fc67b0453" }
再次POST到令牌uri以刷新令牌:http://localhost:8080/server/oauth/token?grant_type=refresh_token&refresh_token=57100377-dea9-4df0-adab-62e33f2a1b49
POST to the token uri again to refresh token: http://localhost:8080/server/oauth/token?grant_type=refresh_token&refresh_token=57100377-dea9-4df0-adab-62e33f2a1b49
接收新令牌
{access_token: "ed104994-899c-4cd9-8860-43d5689a9420"token_type:承载"refresh_token:57100377-dea9-4df0-adab-62e33f2a1b49"expires_in: 300范围:读写"}
{ access_token: "ed104994-899c-4cd9-8860-43d5689a9420" token_type: "bearer" refresh_token: "57100377-dea9-4df0-adab-62e33f2a1b49" expires_in: 300 scope: "read write" }
我真的不确定我做错了什么,但似乎除了访问受限制的 uri 之外的一切都在工作.这是我的配置:
I am really not sure what I am doing wrong, but it appears that everything other than accessing the restricted uri is working. Here is my configuration:
@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;
}
}
}
是不是我遗漏了什么,或者我的处理方式有误?任何帮助将不胜感激.
Is there something I am missing or am I approaching this incorrectly? Any help would be greatly appreciated.
推荐答案
问题最终是资源服务器和授权服务器没有获得相同的令牌存储引用.不确定接线如何不正常工作,但在配置类中使用固定对象就像一个魅力.最终,我将转向持久性支持的令牌存储,它可能不会有任何问题.
The problem ended up being that the resource server and the authorization server were not getting the same token store reference. Not sure how the wiring was not working correctly, but using a fixed object in the configuration class worked like a charm. Ultimately, I'll move to a persistence backed token store, which probably would not have had any issues.
感谢@OhadR 的回答和帮助!
Thanks goes to @OhadR for the answer and the help!
最终,我简化了配置,通过了相同的工作流程,结果成功了
Ultimately, I simplified the configuration, went thru the same workflow, and it worked out
@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 示例,因为它有很多额外的配置,不一定需要开始.
Anyone that stumbles upon this post, I recommend looking more at the unit tests for example rather than the full blown sparklr/tonr example, as it has a lot of extra configuration that are not necessarily needed to get started.
这篇关于Spring Security OAuth2 资源服务器总是返回无效的令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!