Spring OAuth2 - 没有客户端身份验证。尝试添加适当的身份验证过滤器

时间:2015-07-19 18:33:16

标签: spring-security access-token spring-security-oauth2

我们有一个使用spring-security-oauth2:1.0的应用程序。我试图将其更改为较新版本spring-security-oauth2:2.0.7.RELEASE。一些类被删除,一些包结构被更改,我设法整理所有这些东西,我能够没有任何问题启动服务器。但我在这里遇到一个奇怪的问题。

使用OAuth2 - 1.0 version,当用户登录时,我们曾在GET上发出/oauth/token请求,例如:

  

http://localhost:8080/echo/oauth/token?grant_type=password&client_id=ws&client_secret=secret&scope=read,write&username=john@abc.com&password=password123

它以前工作得很好。

当我尝试同样的事情时,首先由于TokenEndPoint.java

中的逻辑,我无法提出GET请求
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请求与上述网址相同,但我收到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令牌?

注意:我已经检查了以下问题:hereherehere。但我无法找到正确的解决方案。

5 个答案:

答案 0 :(得分:5)

我不知道以前的版本,但我对2.0.7有所了解。

我怀疑您的问题是您的TokenEndpoint安全性尝试针对您的用户服务验证您的客户端

TokenEndpoint受// Get a compilation error since null was passed var someInstance = new SomeObject(null); 保护。默认情况下,此过滤器将使用BasicAuthenticationFilter实例,该实例本身包含AuthenticationManager,它本身依赖于AuthenticationProvider的实例。 诀窍是UserDetailsService的这个特定实例必须基于客户端,而不是用户:这就是为什么有一个UserDetailsService,它适应{ {1}}至ClientDetailsUserDetailsService

通常,当您使用框架的配置类ClientDetailsServiceUserDetailsService等时,所有这些内容都已默认完成。

答案 1 :(得分:1)

我有同样的问题,我的application.yml有这一行:

servlet:
    path: /auth

因此令牌地址为:/auth/oauth/token

我从application.yml中删除了路径,因此令牌路径变为:

/oauth/token

一切正常。

我希望这个帮助

答案 2 :(得分:1)

以下错误的问题之一可能是未执行身份验证。我在较旧的Spring实施中遇到了这个问题。

验证:

TokenEndpoint-> postAccessToken方法。检查Principal是否不为null。如果为null,则表示未执行基本身份验证。

添加过滤器的一种方法是使用:

@Configuration
public class FilterChainInitializer extends AbstractSecurityWebApplicationInitializer {

}

有关AbstractSecurityWebApplicationInitializer的更多信息可以在Spring文档中找到

答案 3 :(得分:0)

就我而言,我找到了这个配置:

<强> 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 :(得分:0)

问题可能是因为打开了所有请求。您应该将其删除。

Lname