提问者:小点点

为什么spring-security-oaut2在令牌endpoint抛出未经授权的错误?如何打开对endpoint的访问?


我正在尝试使用Spring Security oaut2框架创建一个示例授权服务器。与任何其他与Spring相关的示例相比,这些教程令人困惑。

更新:如果您正在寻找可行的解决方案,请转到我的答案。忽略下面的代码。

当我调用令牌问题endpoint时,引发了以下错误

{
    "error": "unauthorized",
    "error_description": "Full authentication is required to access this resource"
}

这是我的设置(使用Groovy)。我正在使用spring-security-oaut2:2.3.4。释放,spring-cloud d-security:2.0.1。释放和引导:2.1.1。释放。

@Configuration
@CompileStatic
class OAuth2ClientSpringConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    AuthenticationManager authenticationManager

    @Autowired
    UserDetailsService userDetailsService

    // register clients
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient('clientone')
                .secret('secret')
                .authorizedGrantTypes('password')
                .scopes('one', 'two')
    }

    //use default auth manager and user details service
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients()
        security.tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()")
                .allowFormAuthenticationForClients()  //<--- update
    }
}

静态用户凭据

@Configuration
@CompileStatic
class UserCredentialsSpringConfig extends WebSecurityConfigurerAdapter {

    @Bean
    AuthenticationManager authenticationManagerBean() {
        super.authenticationManagerBean()
    }

    @Bean
    UserDetailsService userDetailsServiceBean() {
        super.userDetailsServiceBean()
    }

    protected void configure(AuthenticationManagerBuilder auth) {
        auth.inMemoryAuthentication()
                .withUser('user1').password('pwd1').roles('USER')
                .and()
                .withUser('admin').password('pwd1').roles('ADMIN')
    }

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/oauth/token").permitAll()
                .anyRequest().authenticated()
    }
}

邮差设置

  • 在这两个地方添加了客户端凭据-授权标头和普通标头。

  • 使用主体表单参数发送用户凭据

当我点击http://localhost:8080/auth/oauth/token时,遇到以下错误

我研究了不同的教程,但没有弄清楚。任何输入都会有帮助。


共2个答案

匿名用户

网上有几个教程,但其中一些没有提到他们正在使用Boot 1. x。这就是我在将这些说明与Boot 2.x结合使用时遇到的。这些教程可能对Boot 2.x有效,但事情已经令人困惑,以至于我无法找出一个工作模型。

这是Boot 2. x的工作解决方案。我从https://github.com/spring-projects/spring-security-oauth2-boot/tree/master/samples/spring-boot-sample-secure-oauth2-provider的代码示例重新开始。

导入spring-security-oaut2-autoconfiure依赖项。将@EnableAuthorizationServer添加到您的主类中。这就是最简单的工作模型所需的全部。无需添加AuthorizationServerConfigrerAdapter等,因为它是使用application. yml中的数据自动配置的。看看上面github链接中的application.yml。

这是邮差的配置

从application. yml复制示例客户端ID和机密并将它们作为Auth标头提供。

从引导日志中复制生成的密码,并将其与其他属性一起放入Body表单数据中,如图所示。

就这样。打http://localhost:8080/oauth/token,你应该看到下面的东西

匿名用户

根据规范,令牌问题endpoint必须受到保护。

您必须提供client_idclient_secret作为参数(表单)或作为超文本传输协议-基本授权标头

直接取自规格

 POST /token HTTP/1.1
 Host: server.example.com
 Content-Type: application/x-www-form-urlencoded

 grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
 &client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw

请回顾

https://www.rfc-editor.org/rfc/rfc6749#section-2.3.1

我们为什么不把客户端从你的等式中移除一点,只关注你的令牌endpoint

curl是你的朋友,这是一个FORM示例(针对Cloud Foundry UAA本地验证的工作示例,其中客户端机密是一个空字符串)

curl -v \
    -H "Content-Type=application/x-www-form-urlencoded" \
    -H "Accept=application/json" \
    -d "grant_type=password" \
    -d "client_id=cf" \
    -d "response_type=token" \
    -d "username=marissa" \
    -d "password=koala" \
    -d "client_secret=" \
    http://localhost:8080/uaa/oauth/token

使用超文本传输协议

curl -v \
    -H "Content-Type=application/x-www-form-urlencoded" \
    -H "Accept=application/json" \
    -d "grant_type=password" \
    -d "client_id=cf" \
    -d "response_type=token" \
    -d "username=marissa" \
    -d "password=koala" \
    -u "cf:" \
    http://localhost:8080/uaa/oauth/token

你能不能用你的实际数据运行这些命令,让我们知道命令(也许更新你的问题),让我们知道结果。你看,我们不知道你的UI应用程序实际上在做什么,使用curl,可以让我们从问题中消除它。