[java-idp-plugin-oidc-op-oidfed] branch dev/CACHE-REFACTOR updated: Include the use of jwks_uri into the automatic registration tests
Codeberg
noreply at shibboleth.net
Fri Mar 20 11:22:38 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch dev/CACHE-REFACTOR
in repository java-idp-plugin-oidc-op-oidfed.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-oidc-op-oidfed/commit/92123fc7168b473d8b846e96dad85bac267e7ebd
The following commit(s) were added to refs/heads/dev/CACHE-REFACTOR by this push:
new 92123fc Include the use of jwks_uri into the automatic registration tests
92123fc is described below
commit 92123fc7168b473d8b846e96dad85bac267e7ebd
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Mar 20 13:21:51 2026 +0200
Include the use of jwks_uri into the automatic registration tests
---
.../flow/oidfed/AbstractFederationFlowTest.java | 27 ++++++++++++-
.../AuthorizeFlowAutomaticRegistrationTest.java | 46 ++++++++++++++++++++++
...shedAuthorizeFlowAutomaticRegistrationTest.java | 29 ++++++++++++++
.../oidfed/TokenFlowAutomaticRegistrationTest.java | 46 ++++++++++++++++++++++
.../net/shibboleth/idp/module/conf/global.xml | 6 +++
5 files changed, 153 insertions(+), 1 deletion(-)
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java
index 9b26b9f..b31d518 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AbstractFederationFlowTest.java
@@ -116,7 +116,11 @@ public class AbstractFederationFlowTest extends AbstractOidcFlowTest {
@Autowired
@Qualifier("shibboleth.oidfed.HttpClient")
protected HttpClient federationHttpClient;
-
+
+ @Autowired
+ @Qualifier("shibboleth.oidc.NonBrowser.HttpClient")
+ protected HttpClient vanillaOidcHttpClient;
+
protected AbstractFederationFlowTest(final String flowId) {
super(flowId);
}
@@ -215,6 +219,12 @@ public class AbstractFederationFlowTest extends AbstractOidcFlowTest {
.thenReturn(classicResponse);
}
+ protected void mapVanillaOidcResponse(final String requestUri, final ClassicHttpResponse classicResponse)
+ throws IOException {
+ when(vanillaOidcHttpClient.executeOpen(any(), argThat(new RequestUriMatcher(requestUri)), any()))
+ .thenReturn(classicResponse);
+ }
+
protected ClassicHttpResponse mockResponse(final String contents)
throws UnsupportedOperationException, IOException {
return mockResponse(200, "application/entity-statement+jwt", contents);
@@ -502,6 +512,21 @@ public class AbstractFederationFlowTest extends AbstractOidcFlowTest {
}
}
+ protected void rpConfigureMockHttpClient(final String clientId, final URI jwksUri) {
+ final OIDCClientMetadata metadata = new OIDCClientMetadata();
+ try {
+ metadata.setRedirectionURI(new URI(redirectUri));
+ metadata.setJWKSetURI(jwksUri);
+ mapResponse(entityConfigurationUrl(clientId), mockResponse(rpEntityConfiguration(clientId, metadata)));
+ mapResponse(entityConfigurationUrl(anchorId), mockResponse(trustedAnchorConfiguration()));
+ mapResponse(subordinateStatementUrl(anchorFetchEndpoint, clientId),
+ mockResponse(subordinateStatement(clientId, Map.of("openid_relying_party",
+ new OIDCClientMetadata().toJSONObject()))));
+ } catch (UnsupportedOperationException | IOException | URISyntaxException e) {
+ Assert.fail("Could not initialize mock HTTP client", e);
+ }
+ }
+
protected void rpConfigureMockHttpClient(final String clientId, final JWK leafKey) {
try {
mapResponse(entityConfigurationUrl(clientId),
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
index 762f251..9d9469b 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/AuthorizeFlowAutomaticRegistrationTest.java
@@ -121,6 +121,52 @@ public class AuthorizeFlowAutomaticRegistrationTest extends AbstractFederationFl
Assert.assertEquals(unwrapTrustChainFromAuthorizeCode(successResponse), List.of(clientId, anchorId));
}
+ @Test
+ public void testWithValidTrustChain_signedRequestObject_jwksUri()
+ throws IOException, UnsupportedOperationException, URISyntaxException {
+ final String clientId = uniqueClientId();
+ final String jwksUri = clientId + "/jwks";
+ rpConfigureMockHttpClient(clientId, URI.create(jwksUri));
+ mapVanillaOidcResponse(jwksUri, mockResponse(200, "application/json",
+ new JWKSet(rpKey.toPublicJWK()).toString()));
+ final FlowExecutionResult result =
+ launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
+ "iss", clientId,
+ "client_id", clientId,
+ "aud", issuer,
+ "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+ "jti", UUID.randomUUID(),
+ "response_type", "code",
+ "scope", "openid profile",
+ "redirect_uri", redirectUri)));
+ final AuthenticationResponse responseMessage = parseSuccessResponse(result, AuthenticationResponse.class);
+ final AuthenticationSuccessResponse successResponse = responseMessage.toSuccessResponse();
+ Assert.assertEquals(successResponse.getRedirectionURI().toString(), redirectUri);
+ Assert.assertNull(successResponse.getIDToken());
+ Assert.assertNull(successResponse.getAccessToken());
+ Assert.assertNotNull(successResponse.getAuthorizationCode());
+ Assert.assertEquals(unwrapTrustChainFromAuthorizeCode(successResponse), List.of(clientId, anchorId));
+ }
+
+ @Test
+ public void testWithValidTrustChain_signedRequestObject_invalidJwksUri()
+ throws IOException, UnsupportedOperationException, URISyntaxException {
+ final String clientId = uniqueClientId();
+ final String jwksUri = clientId + "/jwks";
+ rpConfigureMockHttpClient(clientId, URI.create(jwksUri));
+ final FlowExecutionResult result =
+ launchAuthenticationRequest(clientId, "openid profile", signedRequestObject(Map.of(
+ "iss", clientId,
+ "client_id", clientId,
+ "aud", issuer,
+ "exp", Instant.now().plus(Duration.ofMinutes(5)).toEpochMilli(),
+ "jti", UUID.randomUUID(),
+ "response_type", "code",
+ "scope", "openid profile",
+ "redirect_uri", redirectUri)));
+ Assert.assertEquals(result.getOutcome().getId(), "ErrorView");
+ }
+
@Test
public void testWithValidTrustChain_signedRequestObject_emptyMetadataPolicyCrit()
throws IOException, UnsupportedOperationException, URISyntaxException {
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/PushedAuthorizeFlowAutomaticRegistrationTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/PushedAuthorizeFlowAutomaticRegistrationTest.java
index 206f314..2ffdd13 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/PushedAuthorizeFlowAutomaticRegistrationTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/PushedAuthorizeFlowAutomaticRegistrationTest.java
@@ -103,6 +103,35 @@ public class PushedAuthorizeFlowAutomaticRegistrationTest extends AbstractFedera
verifyAuthorizeEndpoint(clientId, response.getRequestURI().toString());
}
+ @Test
+ public void testSuccess_jwksUri() throws Exception {
+ final String clientId = uniqueClientId();
+ final String jwksUri = clientId + "/jwks";
+ rpConfigureMockHttpClient(clientId, URI.create(jwksUri));
+ mapVanillaOidcResponse(jwksUri, mockResponse(200, "application/json",
+ new JWKSet(rpKey.toPublicJWK()).toString()));
+ final SignedJWT jwt = createPrivateKeyJWT(validJwtAuthenticationClaimsSet(clientId, issuer),
+ rpKey.toRSAKey().toRSAPrivateKey(), JWSAlgorithm.RS512);
+ final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+ ClientAuthenticationMethod.PRIVATE_KEY_JWT, rpKey.toRSAKey().toPublicKey());
+ assertSuccessResponse(result, clientId);
+ final PushedAuthorizationSuccessResponse response =
+ parseSuccessResponse(result, PushedAuthorizationSuccessResponse.class);
+ verifyAuthorizeEndpoint(clientId, response.getRequestURI().toString());
+ }
+
+ @Test
+ public void testFails_invalidJwksUri() throws Exception {
+ final String clientId = uniqueClientId();
+ final String jwksUri = clientId + "/jwks";
+ rpConfigureMockHttpClient(clientId, URI.create(jwksUri));
+ final SignedJWT jwt = createPrivateKeyJWT(validJwtAuthenticationClaimsSet(clientId, issuer),
+ rpKey.toRSAKey().toRSAPrivateKey(), JWSAlgorithm.RS512);
+ final FlowExecutionResult result = launchWithJwtAuthentication(jwt, null,
+ ClientAuthenticationMethod.PRIVATE_KEY_JWT, rpKey.toRSAKey().toPublicKey());
+ assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
+ }
+
@Test
public void testUnmatchingRpConfigurationSignature() throws Exception {
final String clientId = uniqueClientId();
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/TokenFlowAutomaticRegistrationTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/TokenFlowAutomaticRegistrationTest.java
index ead63e7..6e6af99 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/TokenFlowAutomaticRegistrationTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/TokenFlowAutomaticRegistrationTest.java
@@ -29,6 +29,7 @@ import org.testng.Assert;
import org.testng.annotations.Test;
import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
@@ -80,6 +81,51 @@ public class TokenFlowAutomaticRegistrationTest extends AbstractFederationFlowTe
Assert.assertNotNull(response.getOIDCTokens().getIDToken().getJWTClaimsSet().getClaim("at_hash"));
}
+ @Test
+ public void testSuccess_jwksUri() throws Exception {
+ final String clientId = uniqueClientId();
+ final String jwksUri = clientId + "/jwks";
+ rpConfigureMockHttpClient(clientId, URI.create(jwksUri));
+ mapVanillaOidcResponse(jwksUri, mockResponse(200, "application/json",
+ new JWKSet(rpKey.toPublicJWK()).toString()));
+ final SignedJWT jwt = createPrivateKeyJWT(validJwtAuthenticationClaimsSet(clientId, issuer),
+ rpKey.toRSAKey().toRSAPrivateKey(), JWSAlgorithm.RS512);
+ final Map<String,String> requestParameters = new HashMap<>(Map.of(
+ "redirect_uri", redirectUri,
+ "grant_type", "authorization_code",
+ "code", buildAuthorizationCode(clientId, List.of(clientId, anchorId)),
+ "client_id", clientId));
+ final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS512,
+ ClientAuthenticationMethod.PRIVATE_KEY_JWT, null, requestParameters);
+ final OIDCTokenResponse response = parseSuccessResponse(result, OIDCTokenResponse.class);
+ Assert.assertNotNull(response.getTokens().getAccessToken());
+ final AccessTokenClaimsSet tokenClaims =
+ AccessTokenClaimsSet.parse(response.getTokens().getAccessToken().getValue(), getDataSealer());
+ final JWTClaimsSet claimsSet = tokenClaims.getClaimsSet();
+ assert claimsSet != null;
+ Assert.assertEquals(claimsSet.getStringListClaim(ClaimsSetExtensionSupport.KEY_AUTO_REGISTERED_TRUST_CHAIN),
+ List.of(clientId, anchorId));
+ Assert.assertNotNull(response.getOIDCTokens().getIDToken());
+ Assert.assertNotNull(response.getOIDCTokens().getIDToken().getJWTClaimsSet().getClaim("at_hash"));
+ }
+
+ @Test
+ public void testFails_invalidJwksUri() throws Exception {
+ final String clientId = uniqueClientId();
+ final String jwksUri = clientId + "/jwks";
+ rpConfigureMockHttpClient(clientId, URI.create(jwksUri));
+ final SignedJWT jwt = createPrivateKeyJWT(validJwtAuthenticationClaimsSet(clientId, issuer),
+ rpKey.toRSAKey().toRSAPrivateKey(), JWSAlgorithm.RS512);
+ final Map<String,String> requestParameters = new HashMap<>(Map.of(
+ "redirect_uri", redirectUri,
+ "grant_type", "authorization_code",
+ "code", buildAuthorizationCode(clientId, List.of(clientId, anchorId)),
+ "client_id", clientId));
+ final FlowExecutionResult result = launchWithJwtAuthentication(jwt, JWSAlgorithm.RS512,
+ ClientAuthenticationMethod.PRIVATE_KEY_JWT, null, requestParameters);
+ assertErrorCode(result, OAuth2Error.INVALID_CLIENT_CODE);
+ }
+
@Test
public void testSuccess_resolveApi() throws Exception {
final String clientId = uniqueClientId();
diff --git a/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/global.xml b/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/global.xml
index 07602b6..90f8968 100644
--- a/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/global.xml
+++ b/idp-oidfed-op-impl/src/test/resources/net/shibboleth/idp/module/conf/global.xml
@@ -89,6 +89,12 @@
<constructor-arg value="#{T(org.apache.hc.client5.http.classic.HttpClient)}" />
</bean>
+ <bean id="shibboleth.oidc.NonBrowser.HttpClient"
+ factory-bean="MockitoMockFactory"
+ factory-method="mock">
+ <constructor-arg value="#{T(org.apache.hc.client5.http.classic.HttpClient)}" />
+ </bean>
+
<bean id="HeaderUseResolveApiCondition" parent="shibboleth.Conditions.Expression"
p:customObject-ref="shibboleth.HttpServletRequestSupplier"
c:expression="'true'.equals(#custom.get().getHeader('useCustomResolverApi'))" />
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list