Skip to content

Commit

Permalink
Merge pull request #40883 from sberyozkin/oidc_valid_chain_but_invali…
Browse files Browse the repository at this point in the history
…d_claims

Confirm that expired or wrong aud JWT cause 401 even if the cert chain is valid
  • Loading branch information
sberyozkin committed May 29, 2024
2 parents ecdf3ea + aa9704c commit 7fb79c0
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ quarkus.oidc.bearer-certificate-full-chain.certificate-chain.trust-store-passwor

quarkus.oidc.bearer-chain-custom-validator.certificate-chain.trust-store-file=truststore.p12
quarkus.oidc.bearer-chain-custom-validator.certificate-chain.trust-store-password=storepassword
quarkus.oidc.bearer-chain-custom-validator.token.audience=https://service.example.com

quarkus.oidc.bearer-certificate-full-chain-root-only-wrongcname.certificate-chain.trust-store-file=truststore-rootcert.p12
quarkus.oidc.bearer-certificate-full-chain-root-only-wrongcname.certificate-chain.trust-store-password=storepassword
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,18 +199,37 @@ public void testCertChainWithCustomValidator() throws Exception {
// Send the token with the valid certificate chain and bind it to the token claim
String accessToken = getAccessTokenForCustomValidator(
List.of(subjectCert, intermediateCert, rootCert),
subjectPrivateKey, true);
subjectPrivateKey, "https://service.example.com", true, false);

RestAssured.given().auth().oauth2(accessToken)
.when().get("/api/admin/bearer-chain-custom-validator")
.then()
.statusCode(200)
.body(Matchers.containsString("admin"));

// Send the token with the valid certificate chain but do bind it to the token claim
// Send the token with the valid certificate chain but do not bind it to the token claim
accessToken = getAccessTokenForCustomValidator(
List.of(subjectCert, intermediateCert, rootCert),
subjectPrivateKey, false);
subjectPrivateKey, "https://service.example.com", false, false);

RestAssured.given().auth().oauth2(accessToken)
.when().get("/api/admin/bearer-chain-custom-validator")
.then()
.statusCode(401);

// Send the token with the valid certificate chain bound to the token claim, but expired
accessToken = getAccessTokenForCustomValidator(
List.of(subjectCert, intermediateCert, rootCert),
subjectPrivateKey, "https://service.example.com", true, true);
RestAssured.given().auth().oauth2(accessToken)
.when().get("/api/admin/bearer-chain-custom-validator")
.then()
.statusCode(401);

// Send the token with the valid certificate chain but with the wrong audience
accessToken = getAccessTokenForCustomValidator(
List.of(subjectCert, intermediateCert, rootCert),
subjectPrivateKey, "https://server.example.com", true, false);

RestAssured.given().auth().oauth2(accessToken)
.when().get("/api/admin/bearer-chain-custom-validator")
Expand Down Expand Up @@ -748,18 +767,25 @@ private String getAccessTokenWithCertChain(List<X509Certificate> chain,
}

private String getAccessTokenForCustomValidator(List<X509Certificate> chain,
PrivateKey privateKey, boolean setLeafCertThumbprint) throws Exception {
PrivateKey privateKey, String aud, boolean setLeafCertThumbprint, boolean expired) throws Exception {
JwtClaimsBuilder builder = Jwt.preferredUserName("alice")
.groups("admin")
.issuer("https://server.example.com")
.audience("https://service.example.com")
.audience(aud)
.claim("root-certificate-thumbprint", TrustStoreUtils.calculateThumprint(chain.get(chain.size() - 1)));
if (setLeafCertThumbprint) {
builder.claim("leaf-certificate-thumbprint", TrustStoreUtils.calculateThumprint(chain.get(0)));
}
return builder.jws()
if (expired) {
builder.expiresIn(1);
}
String jwt = builder.jws()
.chain(chain)
.sign(privateKey);
if (expired) {
Thread.sleep(2000);
}
return jwt;
}

private String getAccessTokenWithoutKidAndThumbprint(String userName, Set<String> groups) {
Expand Down

0 comments on commit 7fb79c0

Please sign in to comment.