2014-12-23 41 views
5

我一直在過去的幾天中使用spring-security-oauth2來實現spring引導/ spring安全性和java配置。我已經設法解決了大部分的困難,但是現在出現了什麼問題,我很難過。Spring-Oauth2訪問令牌請求永遠不會成功,因爲缺少CSRF'保留狀態'

我成功地完成以下步驟:

  • 發送用戶的供應商授權以代表他們的應用
  • 提示用戶按安全
  • 用戶授權來登錄到供應商應用程序和重定向url將它們發送回原始url處的客戶端應用程序以及查詢字符串中的?code=asdfa&state=asdfasf

在此點,我相信任何使用AuthorizationCodeResourceDetails應該交換訪問令牌的授權代碼和客戶端應用程序憑證。這是下一個堆棧跟蹤過程失敗的地方。在客戶端的樣子

Caused by: org.springframework.security.oauth2.common.exceptions.InvalidRequestException: Possible CSRF detected - state parameter was present but no state could be found 
    at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.getParametersForTokenRequest(AuthorizationCodeAccessTokenProvider.java:246) 
    at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:198) 
    at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:142) 
    at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:118) 
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221) 
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173) 
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.createRequest(OAuth2RestTemplate.java:105) 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:564) 
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.doExecute(OAuth2RestTemplate.java:128) 
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:529) 
    at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:261) 
    at com.pvr.apps.admin.user.UserServiceImpl.getAllUsers(UserServiceImpl.java:51) 
    at com.pvr.apps.admin.web.IndexController.serveUserList(IndexController.java:35) 

事(我也有在主配置的@EnableOAuth2Client註釋)。

@Component 
public class UserServiceImpl implements UserService { 

    @Resource 
    @Qualifier("accessTokenRequest") 
    private AccessTokenRequest accessTokenRequest; 

    public OAuth2ProtectedResourceDetails createResource() { 
     AuthorizationCodeResourceDetails resourceDetails = new AuthorizationCodeResourceDetails(); 
     resourceDetails.setScope(Lists.newArrayList("read", "write")); 
     resourceDetails.setClientId("admin"); 
     resourceDetails.setClientSecret("password"); 
     resourceDetails.setAuthenticationScheme(AuthenticationScheme.query); 
     resourceDetails.setAccessTokenUri("http://provider.com:8080/oauth/token"); 
     resourceDetails.setUserAuthorizationUri("http://provider.com:8080/oauth/authorize"); 
     return resourceDetails; 
    } 

    @Override 
    public List<User> getAllUsers() { 

     RestTemplate template = new OAuth2RestTemplate(createResource(), new DefaultOAuth2ClientContext(accessTokenRequest)); 

     ResponseEntity<User[]> responseEntity = template.getForEntity("http://provider.com:8080/users/", User[].class); 
     return Lists.newArrayList(responseEntity.getBody()); 
    } 
} 

而且對事物的提供方:

授權服務器配置:

@Configuration 
@EnableAuthorizationServer 
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{ 

    @Autowired 
    private LoginUrlAuthenticationEntryPoint authenticationEntryPoint; 

    @Autowired 
    private AuthenticationManager authenticationManager; 


    @Override 
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
     oauthServer 
       .authenticationEntryPoint(authenticationEntryPoint) 
       .tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')") 
       .checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')"); 
    } 

    @Override 
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 

     JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); 

     endpoints 
       .authenticationManager(authenticationManager) 
       .accessTokenConverter(converter) 
       .tokenStore(new JwtTokenStore(converter)); 
    } 


    // TODO: this should read from a db 
    public void configure(ClientDetailsServiceConfigurer clientConfigurer) throws Exception { 
     clientConfigurer.inMemory() 
       .withClient("admin").secret("password") 
       .authorizedGrantTypes(
         GrantType.PASSWORD.type, 
         GrantType.AUTHORIZATION_CODE.type, 
         GrantType.IMPLICIT.type, 
         GrantType.REFRESH_TOKEN.type 
       ) 
       .authorities("ROLE_TRUSTED_CLIENT") 
       .scopes("read", "write", "trust") 
       .accessTokenValiditySeconds(60); 
    } 
} 

和資源服務器配置:

@Configuration 
@EnableWebMvcSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class MySecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    UserDetailsService userDetailService; 

    @Autowired 
    AuthenticationProvider authenticationProvider; 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.authenticationProvider(authenticationProvider); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.authorizeRequests() 
       .antMatchers("/login").permitAll() 
       .anyRequest().authenticated() 
      .and() 
       .formLogin() 
        .loginProcessingUrl("/login.do") 
        .usernameParameter("uid") 
        .passwordParameter("pwd") 
        .loginPage("/login") 
        .failureUrl("/login?error=true") 
      .and() 
       .userDetailsService(userDetailService); 
    } 

} 
+0

另外,我打算在我理解了所有這些之後再做一次寫作。目前的文檔和示例很稀疏,在較早的解決方法和較新的便利性之間有些混亂。 @Rob絞盤? – RutledgePaulV

+0

我也有同樣的錯誤,但我正在使用三個應用程序實現OAuth2 Authorize,資源和客戶端服務器都在不同的端口上運行,它將在您的同一個URL上結束。 –

+0

嗨@Paul_R你可以分享你寫的auth代碼嗎?你的代碼結構與我偶然發現的其他例子截然不同,它會非常有幫助。 –

回答

5

它正在尋找狀態將在OAuth2ClientContext中,但由於您剛剛創建了一個新的,所以在需要時它超出了範圍。如果你注入來自@EnableOAuth2Client的那個,它將在@Scope("session")中,所以它將能夠爲你解決問題。 GitHub中的所有示例都以這種方式工作。或者你可以自己管理持久性,我想。

+0

謝謝戴夫,這很有道理。不幸的是,服務器現在提供'OAuth2AccessDeniedException:客戶端的無效令牌'。當試圖獲取資源時。我已經確認發送標題中的訪問令牌IS。你能看到其他東西看起來或提供一些方向嗎? – RutledgePaulV

+0

刪除了jwt令牌配置,現在得到一個UserDeniedAuthorizationException ..這是否意味着提供者不記得授權? – RutledgePaulV

+0

您的「資源服務器」實際上並不是一個OAuth2資源服務器(不包括@ EnableResourceServer)。也許你粘貼了錯誤的代碼?在auth服務器上有'UserDeniedAuthorizationException'(看起來像是一個明顯的提示)。 –