Spring Security:使用秘密 jwt 客户端身份验证从授权服务器获取 oauth2 令牌

问题描述 投票:0回答:1

我正在尝试通过 Spring Security 6 并设置 oauth2。为了获得令牌,我尝试使用客户端的

client_secret_jwt
身份验证机制。 但经过多次尝试,我还是无法做到。

这是我注册客户的代码:

@Bean
public RegisteredClientRepository registeredClientRepository() {
    RegisteredClient registeredClient =
            RegisteredClient
                    .withId(UUID.randomUUID().toString())
                    .clientId("client")
                    .clientSecret("secret_secret_secret_secret_secret")//.tokenSettings()
                    .clientAuthenticationMethod(
                            ClientAuthenticationMethod.CLIENT_SECRET_JWT)
                    .clientSettings(ClientSettings.builder()
                            .tokenEndpointAuthenticationSigningAlgorithm(SignatureAlgorithm.RS256)
                            .jwkSetUrl("http://localhost:8080/oauth2/jwks")
                            .build())
                    .authorizationGrantType(
                            AuthorizationGrantType.CLIENT_CREDENTIALS)
                    .redirectUri("https://www.manning.com/authorized")
                    //.clientSettings(ClientSettings.builder().build())
                    .scope("CUSTOM")
                    .build();

    return new InMemoryRegisteredClientRepository(registeredClient);
}

这是我的代码,用于生成使用上面定义的密钥签名的 jwt 令牌。

@Bean
    public JWKSource<SecurityContext> jwkSource()
            throws NoSuchAlgorithmException {

        /* A different method */

        JWKSet jwkSet = new JWKSet(rsaKey);
        try {
            //printing a token at startup
            String assertion = getJWTToken("client");
            logger.info("Created assertion: "+assertion);
        } catch (Exception e) {
            logger.info("Error creating assertion: "+e.getLocalizedMessage());
            e.printStackTrace();
        }

        return new ImmutableJWKSet<>(jwkSet);
    }

    private String getJWTToken(String username) {
        //using the secret key
        String secretKey = "secret_secret_secret_secret_secret";

        String token = Jwts.builder()
                .subject(username)
                .issuer(username)
                .id(UUID.randomUUID().toString())
                .audience().add("http://localhost:8080/oauth2/token").and()
                .issuedAt(new Date(System.currentTimeMillis()))
                .expiration(new Date(System.currentTimeMillis() + 600*1000))
                .signWith(Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8))).compact();

        return token;
    }



我正在使用开始时打印的断言来调用令牌 API,但在尝试了无数种变化后仍无法获取令牌。

这是我认为应该使用的curl 调用

curl -X POST -v\
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJjbGllbnQiLCJpc3MiOiJjbGllbnQiLCJqdGkiOiIxMjI0NmM4ZC0xZmIxLTRkM2UtODI2NC05OWRhNmYzNTA1NGIiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4MDgwL29hdXRoMi90b2tlbiJdLCJpYXQiOjE3MDc2MzM0ODcsImV4cCI6MTcwNzYzNDA4N30.eYk7T67ue4KrqZqf3Rk06HqwEPRRXpYGSzkbWXtv7zo" \
  http://localhost:8080/oauth2/token


这是我不断收到的回复

*   Trying [::1]:8080...
* Connected to localhost (::1) port 8080
> POST /oauth2/token HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.4.0
> Accept: */*
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 406
>
< HTTP/1.1 400
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 0
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 11 Feb 2024 06:39:31 GMT
< Connection: close
<
{"error":"invalid_request"}* Closing connection

我不确定我错过了什么或做错了什么。在互联网上找不到任何示例。

我已经能够使用基本方法和后秘密方法获得凭据。

编辑--- 进一步挖掘,发现客户端身份验证时出现异常

Caused by: com.nimbusds.jose.proc.BadJOSEException: Signed JWT rejected: Another algorithm expected, or no matching key(s) found
    at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:357) ~[nimbus-jose-jwt-9.37.3.jar:9.37.3]
    at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:303) ~[nimbus-jose-jwt-9.37.3.jar:9.37.3]
    at org.springframework.security.oauth2.jwt.NimbusJwtDecoder.createJwt(NimbusJwtDecoder.java:158) ~[spring-security-oauth2-jose-6.2.1.jar:6.2.1]
    ... 126 common frames omitted

我肯定缺少一些配置。

java spring spring-security oauth-2.0 oauth
1个回答
0
投票

所以在花了几乎一整天之后,我能够获得令牌。

2个变化:

  1. 提供与使用秘密签名密钥相同的算法。
.clientSettings(ClientSettings.builder()
                                .tokenEndpointAuthenticationSigningAlgorithm(MacAlgorithm.HS256)//not rs256
                                .jwkSetUrl("http://localhost:8080/oauth2/jwks")
                                .build())
  1. 确保在令牌请求中给出客户端 ID。尽管它是可选的,但 Spring 库需要它。
curl -X POST -v  -H \
"Content-Type: application/x-www-form-urlencoded"\
-d "client_id=client&grant_type=client_credentials&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJjbGllbnQiLCJpc3MiOiJjbGllbnQiLCJqdGkiOiIxNDdlMTU5YS05YjU3LTQ4NWMtYTM5Ni1hYzAxOGMyOThmZDkiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdDo4MDgwL29hdXRoMi90b2tlbiJdLCJpYXQiOjE3MDc2NDk2OTEsImV4cCI6MTcwNzY1NTY5MX0.J8G_luq7SMCbyaK_ykRtYdc9h-xEJhyi4RRTuH15w7I" \
http://localhost:8080/oauth2/token
© www.soinside.com 2019 - 2024. All rights reserved.