You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 11:25:24