7 客户端认证方式 之 client_secret_jwt

本文详细介绍了OAuth2中client_secret_jwt的认证方式,包括原理、步骤和代码实现。首先,客户端使用HMAC算法和client_secret生成JWT,然后在授权请求中携带JWT。授权服务器通过相同算法和secret验证JWT,从而认证客户端。文中还展示了Postman测试和curl命令示例,完整呈现了整个认证流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章来讲讲 client_secret_jwt 方式。

client_secret_jwt

client_secret_jwt方式就是利用 JWT 进行认证。请求方和授权服务器,两者都知道客户端的 client_secret,通过相同的 HMAC 算法(对称签名算法)去加签和验签 JWT ,可以达到客户端认证的目的。
请求方 通过 HMAC算法,以 client_secret 作为密钥,将客户端信息加签生成 JWT
授权服务器 使用相同的 HMAC算法和client_secret,对请求方的 JWT 进行验签以认证客户端。

了解 JWT 的签名算法

示例

请求方传参:

  • client_id
  • client_assertion_type:固定值 urn:ietf:params:oauth:client-assertion-type:jwt-bearer
  • client_assertion:client生成的jwt

环境准备

授权服务器

同样的,基于 快速搭建一个授权服务器 文章中的示例,修改 SecurityConfigurationregisteredClientRepository() 方法,如下:

    @Bean
    public RegisteredClientRepository registeredClientRepository() {
        RegisteredClient registeredClient3 = RegisteredClient.withId(UUID.randomUUID().toString())
                .clientId("client3")
                // jwt方式验证,密码作为签名算法的密钥,不能配前缀!
                .clientSecret("01234567890123456789012345678912")
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT)
                .clientSettings(ClientSettings.builder()
                        // JWT 方式必须配置,确定jwt的签名算法(CLIENT_SECRET_JWT 方式使用 MacAlgorithm(对称加密算法),密钥为client_secret)
                        .tokenEndpointAuthenticationSigningAlgorithm(MacAlgorithm.HS256)
                        .build())
                .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
                .build();

        return new InMemoryRegisteredClientRepository(registeredClient3 );
    }

测试

  1. 生成 JWT
public class ClientJwtTest {
    public static void main(String[] args) throws JOSEException {
        String clientId = "client3";
        String clientSecret = "01234567890123456789012345678912";

        // 至少以下四项信息
        JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                // 主体:固定clientId
                .subject(clientId)
                // 发行者:固定clientId
                .issuer(clientId)
                // 授权中心的地址
                .audience("http://localhost:9000")
                // 过期时间
                .expirationTime(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24))
                .build();

        String jwt = hmacSign(claimsSet, clientSecret);
        System.out.println(jwt);
        // eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJjbGllbnQxIiwic3ViIjoiY2xpZW50MSIsImF1ZCI6Imh0dHA6XC9cL2xvY2FsaG9zdDo5MDAwIiwiZXhwIjoxNjYxNjk5ODAzfQ.xpv_8w_R8LTZFID3uoQPn3CyQK_Bli3G-WTmrSrwayE
    }

    /**
     * 使用 HMAC 算法加签生成jwt
     */
    private static String hmacSign(JWTClaimsSet claimsSet, String secret) throws JOSEException {
        SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        JWSSigner signer = new MACSigner(secretKeySpec);

        SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
        signedJWT.sign(signer);
        String token = signedJWT.serialize();
        return token;
    }

}
  1. 使用Postman测试,在 Body栏,填入’client_idclient_assertion_typeclient_assertiongrant_type’,发送请求。
    在这里插入图片描述
    可以看到,使用此方式能成功获取到 access_token,说明授权服务器确实支持此认证方式。
  • 相应的curl命令如下:
curl --location --request POST 'localhost:9000/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=client3' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode 'client_assertion=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJjbGllbnQzIiwic3ViIjoiY2xpZW50MyIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6OTAwMCIsImV4cCI6MTY3Mjk5OTgwM30.Cu0JobiFyhyn0mS4rc8pMogI5eOE8uM84v8w5011Gkg'

源码分析

JwtClientAssertionAuthenticationConverter

从请求中解析出 client_idclient_assertion_typeclient_assertion 参数。

JwtClientAssertionAuthenticationProvider

JwtClientAssertionAuthenticationProvider 的核心就是对JWT进行解析和验证。
核心流程如下:

  1. 使用请求携带的 clientId 查询客户端信息,若不存在则直接抛出异常。
  2. 创建解析 JWT 的核心类 JwtDecoder
  3. 解析 JWT,并验签
    在这里插入图片描述

解析:
我们在文章开头就说到 授权服务器 需要使用相同的 HMAC算法和client_secret,对请求方的 JWT 进行验签以认证客户端。事实也确实如此,一路跟踪创建 JwtDecoder 的代码就会发现,JwtDecoder 的创建过程就会用到客户端的配置(签名算法、密钥)
在这里插入图片描述
创建完 JwtDecoder 之后,就要执行解析和验签了:jwtDecoder.decode(clientAuthentication.getCredentials().toString());
从上面可以看出,jwtDecoder 的实际类型为 NimbusJwtDecoder,其解析JWT和验签逻辑如下:
在这里插入图片描述
到这,已经梳理完整个主干流程。另外像比如一些规范性的校验逻辑,读者就可以自行去扩展了解。

下集预告:客户端认证方式 之 private_key_jwt,敬请期待。


end

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值