Skip to content

Commit 86b5607

Browse files
committed
Fix DPoP jkt claim validation during refresh_token grant for public clients
Closes gh-2008
1 parent 07f9621 commit 86b5607

File tree

2 files changed

+5
-19
lines changed

2 files changed

+5
-19
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,12 @@
1515
*/
1616
package org.springframework.security.oauth2.server.authorization.authentication;
1717

18-
import java.security.MessageDigest;
1918
import java.security.Principal;
20-
import java.security.PublicKey;
21-
import java.util.Base64;
2219
import java.util.Collections;
2320
import java.util.HashMap;
2421
import java.util.Map;
2522
import java.util.Set;
2623

27-
import com.nimbusds.jose.jwk.AsymmetricJWK;
2824
import com.nimbusds.jose.jwk.JWK;
2925
import org.apache.commons.logging.Log;
3026
import org.apache.commons.logging.LogFactory;
@@ -292,26 +288,23 @@ public boolean supports(Class<?> authentication) {
292288
}
293289

294290
private static void verifyDPoPProofPublicKey(Jwt dPoPProof, ClaimAccessor accessTokenClaims) {
295-
PublicKey publicKey = null;
291+
JWK jwk = null;
296292
@SuppressWarnings("unchecked")
297293
Map<String, Object> jwkJson = (Map<String, Object>) dPoPProof.getHeaders().get("jwk");
298294
try {
299-
JWK jwk = JWK.parse(jwkJson);
300-
if (jwk instanceof AsymmetricJWK) {
301-
publicKey = ((AsymmetricJWK) jwk).toPublicKey();
302-
}
295+
jwk = JWK.parse(jwkJson);
303296
}
304297
catch (Exception ignored) {
305298
}
306-
if (publicKey == null) {
299+
if (jwk == null) {
307300
OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_DPOP_PROOF,
308301
"jwk header is missing or invalid.", null);
309302
throw new OAuth2AuthenticationException(error);
310303
}
311304

312305
String jwkThumbprint;
313306
try {
314-
jwkThumbprint = computeSHA256(publicKey);
307+
jwkThumbprint = jwk.computeThumbprint().toString();
315308
}
316309
catch (Exception ex) {
317310
OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_DPOP_PROOF,
@@ -335,10 +328,4 @@ private static void verifyDPoPProofPublicKey(Jwt dPoPProof, ClaimAccessor access
335328
}
336329
}
337330

338-
private static String computeSHA256(PublicKey publicKey) throws Exception {
339-
MessageDigest md = MessageDigest.getInstance("SHA-256");
340-
byte[] digest = md.digest(publicKey.getEncoded());
341-
return Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
342-
}
343-
344331
}

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2RefreshTokenGrantTests.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,8 @@ public void requestWhenRefreshTokenRequestWithPublicClientAndDPoPProofThenReturn
295295
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.DPOP,
296296
"dpop-bound-access-token", Instant.now(), Instant.now().plusSeconds(300));
297297
Map<String, Object> accessTokenClaims = new HashMap<>();
298-
PublicKey publicKey = TestJwks.DEFAULT_EC_JWK.toPublicKey();
299298
Map<String, Object> cnfClaim = new HashMap<>();
300-
cnfClaim.put("jkt", computeSHA256(publicKey));
299+
cnfClaim.put("jkt", TestJwks.DEFAULT_EC_JWK.toPublicJWK().computeThumbprint().toString());
301300
accessTokenClaims.put("cnf", cnfClaim);
302301
OAuth2Authorization authorization = TestOAuth2Authorizations
303302
.authorization(registeredClient, accessToken, accessTokenClaims)

0 commit comments

Comments
 (0)