Spring Authorization Server 1.0.0请求/oauth2/token时出现invalid_client及invalid_grant错误
问题描述
我基于Spring Authorization Server仓库中的示例搭建了一个简单的授权服务器,使用OIDC Debugger进行测试。能正常获取表单登录页,输入用户ID和密码后可成功获取授权码,但在调用/oauth2/token端点交换访问令牌时遇到问题:
- 以表单参数传递
client_id和client_secret时,返回401 Unauthorized,错误为invalid_client; - 改用Basic Auth头传递客户端凭证后,返回400 Bad Request,错误为
invalid_grant。
请求示例1(表单参数传凭证)
curl --location --request POST 'http://localhost:8080/oauth2/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=authorization_code' \ --data-urlencode 'client_id=messaging-client' \ --data-urlencode 'client_secret=secret' \ --data-urlencode 'code=ARfoO0m_srZSzi0RJgryvAyxOEmcoOHAZbFVYJlmng71x1CTv7qdCGD3I-DwG8EuBYBdyUGhmZwo5LBmoXyoxxuEuSZwJ7tPjYvQED7OBriRc4uFky5NbtNKuctz1PGt' \ --data-urlencode 'redirct_uri=https%3A%2F%2Foidcdebugger.com%2Fdebug'
请求示例2(Basic Auth头传凭证)
curl --location --request POST 'http://localhost:8080/oauth2/token' \ --header 'Authorization: Basic bWVzc2FnaW5nLWNsaWVudDpzZWNyZXQ=' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=authorization_code' \ --data-urlencode 'code=ARfoO0m_srZSzi0RJgryvAyxOEmcoOHAZbFVYJlmng71x1CTv7qdCGD3I-DwG8EuBYBdyUGhmZwo5LBmoXyoxxuEuSZwJ7tPjYvQED7OBriRc4uFky5NbtNKuctz1PGt' \ --data-urlencode 'redirct_uri=https%3A%2F%2Foidcdebugger.com%2Fdebug'
安全配置(客户端部分)
@Bean public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) { RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()) .clientId("messaging-client") .clientSecret("{noop}secret") .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) .redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc") .redirectUri("http://127.0.0.1:8080/authorized") .redirectUri("https://oidcdebugger.com/debug") .scope(OidcScopes.OPENID) .scope(OidcScopes.PROFILE) .scope("message.read") .scope("message.write") .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build()) .build(); JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate); registeredClientRepository.save(registeredClient); return registeredClientRepository; }
使用的依赖版本
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-authorization-server</artifactId> <version>1.0.0</version> </dependency>
问题排查与解决
1. 表单参数传凭证失败的原因
你的客户端配置仅指定了CLIENT_SECRET_BASIC认证方式,而表单参数传递凭证属于CLIENT_SECRET_POST认证方式,Spring Authorization Server会严格校验客户端配置的认证方式,未配置的方式会直接返回invalid_client错误。
需要在客户端配置中添加CLIENT_SECRET_POST认证方式:
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST) // 新增该行
2. Basic Auth头传凭证时invalid_grant的原因
请求中的回调地址参数名拼写错误:redirct_uri应为redirect_uri(少了一个字母'e')。授权码交换时,Spring Authorization Server会校验请求中的回调地址与授权码生成时使用的地址完全一致,参数名错误会导致地址不匹配,触发invalid_grant错误。
修正请求中的参数名即可:
--data-urlencode 'redirect_uri=https%3A%2F%2Foidcdebugger.com%2Fdebug'
额外优化建议
- 你的代码每次启动都会创建新的
RegisteredClient并保存到数据库,长期运行会导致客户端数据重复。建议在保存前先查询数据库,仅当客户端不存在时再执行保存操作,或者将初始化逻辑移到单独的数据库脚本中。 - 授权码是一次性有效凭证,若重复使用同一授权码也会触发
invalid_grant错误,确保每次交换都使用最新获取的授权码。
内容的提问来源于stack exchange,提问作者Sriram Sridharan
相关产品推荐
相关产品推荐

