为什么 spring-security-oauth2 在令牌端点抛出未经授权的错误?如何开启对端点的访问?
Why is spring-security-oauth2 throwing unauthorized error at the token endpoint? How to open the access to the endpoint?
我正在尝试使用 spring 安全 oauth2 框架创建示例授权服务器。与任何其他 spring 相关示例相比,这些教程令人困惑。
更新: 如果您正在寻找可行的解决方案,请转到我的答案。忽略下面的代码。
当我调用令牌发布端点时,抛出以下错误
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
这是我的设置(使用 Groovy)。我正在使用 spring-security-oauth2:2.3.4.RELEASE、spring-cloud-security:2.0.1.RELEASE 和 boot:2.1.1.RELEASE.
@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()
}
}
邮递员设置
- 在两个地方添加了客户端凭据 - 授权 header 和正常 header.
- 使用 body 表单参数发送用户凭据
当我点击http://localhost:8080/auth/oauth/token时,运行进入以下错误
我查看了不同的教程,但没有弄明白。任何输入都会有所帮助。
根据规范,the token issue endpoint
必须受到保护。
您必须提供 client_id
和 client_secret
作为参数(表格)或作为 http-basic 授权 header
直接取自规范
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
我们为什么不暂时将客户端从您的等式中移除,而只关注您的令牌端点
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
并使用 http-basic
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 可以让我们从问题中消除它。
网上有几个教程,但其中一些没有提到他们正在使用 Boot 1.x。当我将这些指令与 Boot 2.x 组合在一起时,这就是我 运行 的目的。这些教程可能对 Boot 2.x 有效,但事情已经很混乱了,我无法找出一个工作模型。
这是启动 2.x 的有效解决方案。我从 https://github.com/spring-projects/spring-security-oauth2-boot/tree/master/samples/spring-boot-sample-secure-oauth2-provider 的代码示例重新开始。
导入 spring-security-oauth2-autoconfigure
依赖项。
将 @EnableAuthorizationServer
添加到您的主要 class。这就是最简单的工作模型所需的全部内容。无需添加 AuthorizationServerConfigurerAdapter 等,因为它是使用来自 application.yml 的数据自动配置的。看看上面的application.yml github link.
这是 Postman 配置
从 application.yml 复制示例客户端 ID 和密码并将它们作为 Auth headers.
提供
从启动日志中复制生成的密码并将其与其他属性一起放入Body表单数据中,如图所示。
就是这样。点击 http://localhost:8080/oauth/token,你应该会看到类似下面的内容
我正在尝试使用 spring 安全 oauth2 框架创建示例授权服务器。与任何其他 spring 相关示例相比,这些教程令人困惑。
更新: 如果您正在寻找可行的解决方案,请转到我的答案。忽略下面的代码。
当我调用令牌发布端点时,抛出以下错误
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
这是我的设置(使用 Groovy)。我正在使用 spring-security-oauth2:2.3.4.RELEASE、spring-cloud-security:2.0.1.RELEASE 和 boot:2.1.1.RELEASE.
@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()
}
}
邮递员设置
- 在两个地方添加了客户端凭据 - 授权 header 和正常 header.
- 使用 body 表单参数发送用户凭据
当我点击http://localhost:8080/auth/oauth/token时,
运行进入以下错误
我查看了不同的教程,但没有弄明白。任何输入都会有所帮助。
根据规范,the token issue endpoint
必须受到保护。
您必须提供 client_id
和 client_secret
作为参数(表格)或作为 http-basic 授权 header
直接取自规范
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
我们为什么不暂时将客户端从您的等式中移除,而只关注您的令牌端点
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
并使用 http-basic
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 可以让我们从问题中消除它。
网上有几个教程,但其中一些没有提到他们正在使用 Boot 1.x。当我将这些指令与 Boot 2.x 组合在一起时,这就是我 运行 的目的。这些教程可能对 Boot 2.x 有效,但事情已经很混乱了,我无法找出一个工作模型。
这是启动 2.x 的有效解决方案。我从 https://github.com/spring-projects/spring-security-oauth2-boot/tree/master/samples/spring-boot-sample-secure-oauth2-provider 的代码示例重新开始。
导入 spring-security-oauth2-autoconfigure
依赖项。
将 @EnableAuthorizationServer
添加到您的主要 class。这就是最简单的工作模型所需的全部内容。无需添加 AuthorizationServerConfigurerAdapter 等,因为它是使用来自 application.yml 的数据自动配置的。看看上面的application.yml github link.
这是 Postman 配置
从 application.yml 复制示例客户端 ID 和密码并将它们作为 Auth headers.
提供从启动日志中复制生成的密码并将其与其他属性一起放入Body表单数据中,如图所示。
就是这样。点击 http://localhost:8080/oauth/token,你应该会看到类似下面的内容