[java-idp-plugin-oidc-rp] branch main updated: Further flow test cleanups
Phil Smart
philip.smart at jisc.ac.uk
Wed Feb 15 11:29:52 UTC 2023
This is an automated email from the git hooks/post-receive script.
philsmart pushed a commit to branch main
in repository java-idp-plugin-oidc-rp.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-oidc-rp.git;a=commit;h=f9bca3dc44deceef450020387c69beccc1bc2015
The following commit(s) were added to refs/heads/main by this push:
new f9bca3d Further flow test cleanups
f9bca3d is described below
commit f9bca3dc44deceef450020387c69beccc1bc2015
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Wed Feb 15 11:29:50 2023 +0000
Further flow test cleanups
---
...MockAsymmetricJOSEObjectCredentialResolver.java | 60 +++
.../OIDCRPFlowFromAuthenticationResponseTest.java | 535 ++++++---------------
.../oidc/rp/impl/OIDCRPFlowPreRedirectTest.java | 2 +-
.../plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java | 98 +++-
.../plugin/authn/oidc/rp/impl/TestTokenHelper.java | 2 +-
5 files changed, 308 insertions(+), 389 deletions(-)
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockAsymmetricJOSEObjectCredentialResolver.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockAsymmetricJOSEObjectCredentialResolver.java
new file mode 100644
index 0000000..d81e93c
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockAsymmetricJOSEObjectCredentialResolver.java
@@ -0,0 +1,60 @@
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
+
+import static org.testng.Assert.fail;
+
+import java.util.List;
+
+import org.opensaml.security.credential.Credential;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWEAlgorithm;
+import com.nimbusds.jose.jwk.AsymmetricJWK;
+
+import net.shibboleth.oidc.security.credential.BasicJWKCredential;
+import net.shibboleth.oidc.security.credential.JOSEObjectCredentialResolver;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+/** Mock credential resolvers which builds a credential from the given key.*/
+public class MockAsymmetricJOSEObjectCredentialResolver implements JOSEObjectCredentialResolver {
+
+ private final AsymmetricJWK key;
+
+ private final String kid;
+
+ private final JWEAlgorithm alg;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param keyIn the key rto create a credential for.
+ */
+ public MockAsymmetricJOSEObjectCredentialResolver(final AsymmetricJWK keyIn, final String kidIn,
+ final JWEAlgorithm algIn) {
+ key = keyIn;
+ kid = kidIn;
+ alg = algIn;
+ }
+
+ @Override
+ public Credential resolveSingle(final CriteriaSet criteria) throws ResolverException {
+ final BasicJWKCredential jwkCredential = new BasicJWKCredential();
+ jwkCredential.setAlgorithm(alg);
+ jwkCredential.setKid(kid);
+ try {
+ jwkCredential.setPrivateKey(key.toPrivateKey());
+ jwkCredential.setPublicKey(key.toPublicKey());
+ } catch (final JOSEException e) {
+ fail();
+ }
+ return jwkCredential;
+ }
+
+ @Override
+ public Iterable<Credential> resolve(final CriteriaSet criteria) throws ResolverException {
+ return List.of(resolveSingle(criteria));
+ }
+
+}
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowFromAuthenticationResponseTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowFromAuthenticationResponseTest.java
index 7bf0135..0a1a43c 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowFromAuthenticationResponseTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowFromAuthenticationResponseTest.java
@@ -9,20 +9,16 @@ import org.junit.Test;
import org.opensaml.messaging.context.MessageContext;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.security.credential.BasicCredential;
-import org.opensaml.security.credential.Credential;
import org.springframework.webflow.engine.impl.FlowExecutionImpl;
import com.nimbusds.jose.EncryptionMethod;
-import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWSAlgorithm;
-import com.nimbusds.jose.JWSObject.State;
import com.nimbusds.jose.jwk.Curve;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.gen.ECKeyGenerator;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
-import com.nimbusds.jwt.SignedJWT;
import com.nimbusds.oauth2.sdk.ResponseType;
import com.nimbusds.oauth2.sdk.id.ClientID;
import com.nimbusds.openid.connect.sdk.AuthenticationResponseParser;
@@ -31,28 +27,18 @@ import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.authn.context.ExternalAuthenticationContext;
import net.shibboleth.idp.authn.context.SubjectCanonicalizationContext;
import net.shibboleth.idp.authn.impl.ExternalAuthenticationImpl;
-import net.shibboleth.idp.plugin.authn.oidc.rp.context.AccessTokenResponseContext;
-import net.shibboleth.idp.plugin.authn.oidc.rp.context.EndUserClaimsContext;
-import net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext;
-import net.shibboleth.idp.plugin.authn.oidc.rp.messaging.JWTUserInfoResponse;
-import net.shibboleth.idp.plugin.authn.oidc.rp.messaging.PlainUserInfoResponse;
-import net.shibboleth.idp.profile.context.RelyingPartyContext;
import net.shibboleth.idp.saml.authn.principal.AuthenticationMethodPrincipal;
import net.shibboleth.oidc.authn.principal.AuthenticationContextClassReferencePrincipal;
import net.shibboleth.oidc.profile.config.JSONSecurityConfiguration;
import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
-import net.shibboleth.oidc.security.credential.BasicJWKCredential;
import net.shibboleth.oidc.security.credential.DefaultClientSecretCredential;
-import net.shibboleth.oidc.security.credential.JOSEObjectCredentialResolver;
import net.shibboleth.oidc.security.credential.impl.BasicJOSEObjectCredentialResolver;
import net.shibboleth.oidc.security.credential.impl.ChainingJOSEObjectCredentialResolver;
import net.shibboleth.oidc.security.credential.impl.ClientSecretCriterionCredentialResolver;
import net.shibboleth.oidc.security.impl.ExplicitKeySignedJWTTrustEngine;
import net.shibboleth.oidc.security.jose.impl.BasicDecryptionConfiguration;
import net.shibboleth.oidc.security.jose.impl.BasicSignatureValidationConfiguration;
-import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
-import net.shibboleth.utilities.java.support.resolver.ResolverException;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
@@ -62,14 +48,8 @@ import okhttp3.mockwebserver.MockWebServer;
*/
public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
- /**
- * Test the flow from the external authorization request to the end of the flow.
- * Using a MAC-signed id_token and plain UserInfo JSON Response.
- *
- * @throws Exception on error.
- */
- @Test
- public void test_IDTokenHS256_PlainUserInfo() throws Exception {
+ /** Basic setup suitable for all tests.*/
+ private void basicSetup() {
setFlowPath(FLOW);
setFlowModelResources(flowResources);
@@ -80,55 +60,71 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
"idp.authn.oidc.rp.provider.proxyIssuer",OP_ISSUER_ID);
setMockProperties(mockProperties);
+ }
+
+ /** Resume a flow using a default prc construction.*/
+ private ProfileRequestContext resumeBasicFlow() throws Exception {
- final MockWebServer mockOPServer = createSimpleServer();
- // First is token exchange
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/json")
- .setBody(TestTokenHelper.createAccessTokenResponseJSON(
- OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null)));
- // Second is plain userInfo
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/json")
- .setBody(TestTokenHelper.createPlainUserInfoResponseString(OP_ISSUER_ID, List.of(CLIENT_ID),"jdoe")));
- mockOPServer.start(9918);
-
-
final var flowExecution = (FlowExecutionImpl)getFlowExecutionFactory()
.createFlowExecution(getFlowDefinition());
- final ProfileRequestContext prc = populateBasicContextTreeFromAuthnResponse(flowExecution);
-
-
- updateFlowExecution(flowExecution);
+ final ProfileRequestContext prc = populateBasicContextTreeFromAuthnResponse(flowExecution);
+ updateFlowExecution(flowExecution);
//set start view and ending event to transition on.
externalContext.setEventId("proceed");
setCurrentState("AuthnRequest");
resumeFlow(externalContext);
+ return prc;
+ }
+
+ /**
+ * Queue a mock response. Simulating a response from the OP.
+ *
+ * @param mockOPServer the mock server
+ * @param code the response HTTP code
+ * @param body the response body
+ * @param contentType the content type header
+ */
+ private void queueMockServerResponse(final MockWebServer mockOPServer, final int code,
+ final String body, final String contentType) {
+ mockOPServer.enqueue(new MockResponse().setResponseCode(code)
+ .setHeader("content-type", contentType)
+ .setBody(body));
+ }
+
+ /**
+ * Test the flow from the external authorization request to the end of the flow.
+ * Using a MAC-signed id_token and plain UserInfo JSON Response.
+ *
+ * @throws Exception on error.
+ */
+ @Test
+ public void test_IDTokenHS256_PlainUserInfo() throws Exception {
- mockOPServer.shutdown();
+ basicSetup();
- final var nestedPrc = assertStandardEndFlowSuccessConditions(prc);
+ final MockWebServer mockOPServer = createSimpleServer();
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
+ OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ final var userInfoResp =
+ TestTokenHelper.createPlainUserInfoResponseString(OP_ISSUER_ID, List.of(CLIENT_ID),"jdoe");
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/json");
+ mockOPServer.start(9918);
- final var accessTokenResponse =
- nestedPrc.getInboundMessageContext().getSubcontext(AccessTokenResponseContext.class);
- final var userInfoResponse =
- nestedPrc.getInboundMessageContext().getSubcontext(UserInfoResponseContext.class);
- final var endUserClaims =
- nestedPrc.getInboundMessageContext().getSubcontext(EndUserClaimsContext.class);
+ final var prc = resumeBasicFlow();
+ mockOPServer.shutdown();
- assertNotNull(accessTokenResponse.getIdToken());
- assertNotNull(userInfoResponse.getUserInfo());
- assertTrue(userInfoResponse.getUserInfo() instanceof PlainUserInfoResponse);
- assertTrue(accessTokenResponse.getIdToken() instanceof SignedJWT);
- final var signedJwt = (SignedJWT) accessTokenResponse.getIdToken();
- assertEquals(signedJwt.getState(), State.VERIFIED);
+ // Assert test conditions
- assertStandardIdTokenClaimsSuccessCondition(signedJwt.getJWTClaimsSet());
- assertStandardEndUserClaimsSuccessCondition(endUserClaims.getEndUserClaims());
-
-
+ final var nestedPrc = assertStandardEndFlowSuccessConditions(prc);
+
+ assertIdTokenSignatureAndClaimsVerified(nestedPrc);
+ assertPlainJSONObjectUserInfoToken(nestedPrc);
+ assertEndUserClaimsVerified(nestedPrc);
}
/**
@@ -140,56 +136,31 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
@Test
public void test_IDTokenHS256_InvalidPlainUserInfo() throws Exception {
- setFlowPath(FLOW);
- setFlowModelResources(flowResources);
- setSubflows(subflows);
-
- final Map<String,String> mockProperties = Map.of(
- "idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.provider.proxyIssuer",OP_ISSUER_ID);
-
- setMockProperties(mockProperties);
+ basicSetup();
final MockWebServer mockOPServer = createSimpleServer();
- // First is token exchange
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/json")
- .setBody(TestTokenHelper.createAccessTokenResponseJSON(
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null)));
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ final var userInfoResp =
+ TestTokenHelper.createPlainUserInfoResponseString(OP_ISSUER_ID, List.of(CLIENT_ID), null);
+
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
// Second is plain userInfo
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/json")
- .setBody(TestTokenHelper.createPlainUserInfoResponseString(OP_ISSUER_ID, List.of(CLIENT_ID), null)));
- mockOPServer.start(9918);
+ queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/json");
+ mockOPServer.start(9918);
- final var flowExecution = (FlowExecutionImpl)getFlowExecutionFactory()
- .createFlowExecution(getFlowDefinition());
- final ProfileRequestContext prc = populateBasicContextTreeFromAuthnResponse(flowExecution);
-
-
- updateFlowExecution(flowExecution);
-
- //set start view and ending event to transition on.
- externalContext.setEventId("proceed");
- setCurrentState("AuthnRequest");
- resumeFlow(externalContext);
+ final var prc = resumeBasicFlow();
mockOPServer.shutdown();
- assertFlowExecutionEnded();
-
- final var nestedPrc = prc.getSubcontext(AuthenticationContext.class).getSubcontext(ProfileRequestContext.class);
- final var accessTokenResponse =
- nestedPrc.getInboundMessageContext().getSubcontext(AccessTokenResponseContext.class);
-
- assertNotNull(accessTokenResponse.getIdToken());
- assertTrue(accessTokenResponse.getIdToken() instanceof SignedJWT);
- final var signedJwt = (SignedJWT) accessTokenResponse.getIdToken();
- assertEquals(signedJwt.getState(), State.VERIFIED);
- assertStandardIdTokenClaimsSuccessCondition(signedJwt.getJWTClaimsSet());
+ // Assert test conditions
+ assertFlowExecutionEnded();
+ assertIdTokenSignatureAndClaimsVerified(
+ prc.getSubcontext(AuthenticationContext.class).getSubcontext(ProfileRequestContext.class));
// Should have failed to produce a result
assertFlowEndedInErrorConditions(prc, "InvalidUserInfoClaims");
}
@@ -197,129 +168,74 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
@Test
public void test_IDTokenHS256_UserInfoHS256() throws Exception {
- setFlowPath(FLOW);
- setFlowModelResources(flowResources);
- setSubflows(subflows);
-
- final Map<String,String> mockProperties = Map.of(
- "idp.service.clientinfo.failFast","false",
- "idp.entityID", "http://idp.example.com/");
-
- setMockProperties(mockProperties);
+ basicSetup();
final MockWebServer mockOPServer = createSimpleServer();
- // First is token exchange
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/json")
- .setBody(TestTokenHelper.createAccessTokenResponseJSON(
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null)));
- // Second is userInfo
- final var userInfoToken = TestTokenHelper.createJWTUserInfoResponse(
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ final var userInfoResp = TestTokenHelper.createJWTUserInfoResponse(
OP_ISSUER_ID, List.of(CLIENT_ID), "jdoe", JWSAlgorithm.HS256, null, null,
new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/jwt")
- .setBody(userInfoToken.serialize()));
- mockOPServer.start(9918);
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp.serialize(), "application/jwt");
+ mockOPServer.start(9918);
- final var flowExecution = (FlowExecutionImpl)getFlowExecutionFactory()
- .createFlowExecution(getFlowDefinition());
- final ProfileRequestContext prc = populateBasicContextTreeFromAuthnResponse(flowExecution);
-
-
- updateFlowExecution(flowExecution);
-
- //set start view and ending event to transition on.
- externalContext.setEventId("proceed");
- setCurrentState("AuthnRequest");
- resumeFlow(externalContext);
+ final var prc = resumeBasicFlow();
mockOPServer.shutdown();
- final var nestedPrc = assertStandardEndFlowSuccessConditions(prc);
-
- final var accessTokenResponse =
- nestedPrc.getInboundMessageContext().getSubcontext(AccessTokenResponseContext.class);
- final var userInfoResponse =
- nestedPrc.getInboundMessageContext().getSubcontext(UserInfoResponseContext.class);
- final var endUserClaims =
- nestedPrc.getInboundMessageContext().getSubcontext(EndUserClaimsContext.class);
-
- assertNotNull(accessTokenResponse.getIdToken());
- assertNotNull(userInfoResponse.getUserInfo());
- assertTrue(accessTokenResponse.getIdToken() instanceof SignedJWT);
- final var signedJwt = (SignedJWT) accessTokenResponse.getIdToken();
- assertEquals(signedJwt.getState(), State.VERIFIED);
-
- assertTrue(userInfoResponse.getUserInfo() instanceof JWTUserInfoResponse);
- final var jwtUserInfoResponse = (JWTUserInfoResponse)(userInfoResponse.getUserInfo());
- assertTrue(jwtUserInfoResponse.getResponseJwt() instanceof SignedJWT);
- assertEquals(State.VERIFIED, ((SignedJWT)jwtUserInfoResponse.getResponseJwt()).getState());
-
- assertStandardIdTokenClaimsSuccessCondition(signedJwt.getJWTClaimsSet());
- assertStandardEndUserClaimsSuccessCondition(endUserClaims.getEndUserClaims());
+ // Assert test conditions
+ final var nestedPrc = assertStandardEndFlowSuccessConditions(prc);
+ assertIdTokenSignatureAndClaimsVerified(nestedPrc);
+ assertUserInfoTokenSignatureVerified(nestedPrc);
+ assertEndUserClaimsVerified(nestedPrc);
}
@Test
public void test_IDTokenHS256_DirA128CBC_HS256_UserInfoES256_RSA_OAEP_256A256GCM()
throws Exception {
- setFlowPath(FLOW);
- setFlowModelResources(flowResources);
- setSubflows(subflows);
-
- final Map<String,String> mockProperties = Map.of(
- "idp.service.clientinfo.failFast","false",
- "idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.provider.proxyIssuer",OP_ISSUER_ID);
-
- setMockProperties(mockProperties);
+ basicSetup();
final MockWebServer mockOPServer = createSimpleServer();
- // First is token exchange
-
- final var accessTokenResponseJson = TestTokenHelper.createAccessTokenResponseJSON(
+
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, JWEAlgorithm.DIR,
EncryptionMethod.A128CBC_HS256,
new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(),
new DefaultClientSecretCredential(CLIENT_SECRET).toEncryptionCredential(
JWEAlgorithm.DIR, EncryptionMethod.A128CBC_HS256));
-
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/json")
- .setBody(accessTokenResponseJson));
- // Second is userInfo
+
final var sigKey = new ECKeyGenerator(Curve.P_256).keyID("123").generate();
final RSAKey encKey = new RSAKeyGenerator(2048)
.keyID("1")
.keyUse(KeyUse.ENCRYPTION)
.generate();
- final var userInfoToken = TestTokenHelper.createJWTUserInfoResponse(
+ final var userInfoResp = TestTokenHelper.createJWTUserInfoResponse(
OP_ISSUER_ID, List.of(CLIENT_ID), "jdoe", JWSAlgorithm.ES256, JWEAlgorithm.RSA_OAEP_256,
EncryptionMethod.A256GCM,
new BasicCredential(sigKey.toPublicKey(), sigKey.toPrivateKey()),
new BasicCredential(encKey.toPublicKey(), encKey.toPrivateKey()));
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/jwt")
- .setBody(userInfoToken.serialize()));
- mockOPServer.start(9918);
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp.serialize(), "application/jwt");
+ mockOPServer.start(9918);
final FlowExecutionImpl flowExecution = (FlowExecutionImpl)getFlowExecutionFactory()
.createFlowExecution(getFlowDefinition());
final ProfileRequestContext prc = populateBasicContextTreeFromAuthnResponse(flowExecution);
- final OIDCAuthorizationConfiguration partyConfig =
- (OIDCAuthorizationConfiguration) prc.getSubcontext(AuthenticationContext.class)
- .getSubcontext(ProfileRequestContext.class)
- .getSubcontext(RelyingPartyContext.class)
- .getProfileConfig();
+ final OIDCAuthorizationConfiguration partyConfig = getRelyingPartyProfileConfig(prc);
partyConfig.setClientCredential(
TestCredentialHelper.createClientSecretCredential(CLIENT_SECRET));
@@ -333,27 +249,10 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
final var decryptConfig = new BasicDecryptionConfiguration();
decryptConfig.setContentEncryptionKeyCredentialResolver(
new ClientSecretCriterionCredentialResolver());
-
- decryptConfig.setKEKCredentialResolver(new JOSEObjectCredentialResolver() {
-
- @Override
- public Credential resolveSingle(final CriteriaSet criteria) throws ResolverException {
- final BasicJWKCredential jwkCredential = new BasicJWKCredential();
- jwkCredential.setAlgorithm(JWEAlgorithm.RSA_OAEP_256);
- jwkCredential.setKid(encKey.getKeyID());
- try {
- jwkCredential.setPrivateKey(encKey.toPrivateKey());
- jwkCredential.setPublicKey(encKey.toPublicKey());
- } catch (final JOSEException e) {
- fail();
- }
- return jwkCredential;
- }
- @Override
- public Iterable<Credential> resolve(final CriteriaSet criteria) throws ResolverException {
- return List.of(resolveSingle(criteria));
- }
- });
+
+ decryptConfig.setKEKCredentialResolver(
+ new MockAsymmetricJOSEObjectCredentialResolver(encKey, encKey.getKeyID(), JWEAlgorithm.RSA_OAEP_256));
+
secConfig.setJwtDecryptionConfiguration(decryptConfig);
//Signature config for userinfo token
@@ -363,26 +262,9 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
new ExplicitKeySignedJWTTrustEngine(
new ChainingJOSEObjectCredentialResolver(List.of(
new ClientSecretCriterionCredentialResolver(),
- new JOSEObjectCredentialResolver() {
-
- @Override
- public Credential resolveSingle(final CriteriaSet criteria) throws ResolverException {
- final BasicJWKCredential jwkCredential = new BasicJWKCredential();
- jwkCredential.setAlgorithm(JWEAlgorithm.RSA_OAEP_256);
- jwkCredential.setKid(sigKey.getKeyID());
- try {
- jwkCredential.setPrivateKey(sigKey.toPrivateKey());
- jwkCredential.setPublicKey(sigKey.toPublicKey());
- } catch (final JOSEException e) {
- fail();
- }
- return jwkCredential;
- }
- @Override
- public Iterable<Credential> resolve(final CriteriaSet criteria) throws ResolverException {
- return List.of(resolveSingle(criteria));
- }
- })), new BasicJOSEObjectCredentialResolver()));
+ new MockAsymmetricJOSEObjectCredentialResolver(
+ sigKey,sigKey.getKeyID(), JWEAlgorithm.RSA_OAEP_256)))
+ , new BasicJOSEObjectCredentialResolver()));
secConfig.setJwtSignatureValidationConfiguration(sigValidation);
@@ -397,29 +279,13 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
mockOPServer.shutdown();
- final var nestedPrc = assertStandardEndFlowSuccessConditions(prc);
-
- final var accessTokenResponse =
- nestedPrc.getInboundMessageContext().getSubcontext(AccessTokenResponseContext.class);
- final var userInfoResponse =
- nestedPrc.getInboundMessageContext().getSubcontext(UserInfoResponseContext.class);
- final var endUserClaims =
- nestedPrc.getInboundMessageContext().getSubcontext(EndUserClaimsContext.class);
-
- assertNotNull(accessTokenResponse.getIdToken());
- assertNotNull(userInfoResponse.getUserInfo());
- assertTrue(accessTokenResponse.getIdToken() instanceof SignedJWT);
- final var signedJwt = (SignedJWT) accessTokenResponse.getIdToken();
- assertEquals(signedJwt.getState(), State.VERIFIED);
-
- assertTrue(userInfoResponse.getUserInfo() instanceof JWTUserInfoResponse);
- final var jwtUserInfoResponse = (JWTUserInfoResponse)(userInfoResponse.getUserInfo());
- assertTrue(jwtUserInfoResponse.getResponseJwt() instanceof SignedJWT);
- assertEquals(State.VERIFIED, ((SignedJWT)jwtUserInfoResponse.getResponseJwt()).getState());
-
- assertStandardIdTokenClaimsSuccessCondition(signedJwt.getJWTClaimsSet());
- assertStandardEndUserClaimsSuccessCondition(endUserClaims.getEndUserClaims());
-
+ // Assert test conditions
+
+ final var nestedPrc = assertStandardEndFlowSuccessConditions(prc);
+
+ assertIdTokenSignatureAndClaimsVerified(nestedPrc);
+ assertUserInfoTokenSignatureVerified(nestedPrc);
+ assertEndUserClaimsVerified(nestedPrc);
}
/**
@@ -431,37 +297,27 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
public void test_IDTokenHS256_RSA_OAEP_256_A256GCM_PlainUserInfo()
throws Exception {
- setFlowPath(FLOW);
- setFlowModelResources(flowResources);
- setSubflows(subflows);
-
- final Map<String,String> mockProperties = Map.of(
- "idp.service.clientinfo.failFast","false",
- "idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.provider.proxyIssuer",OP_ISSUER_ID);
+ basicSetup();
- setMockProperties(mockProperties);
+ final MockWebServer mockOPServer = createSimpleServer();
final RSAKey encKey = new RSAKeyGenerator(2048)
.keyID("1")
.keyUse(KeyUse.ENCRYPTION)
.generate();
- final var accessTokenResponseJson = TestTokenHelper.createAccessTokenResponseJSON(
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, JWEAlgorithm.RSA_OAEP_256,
EncryptionMethod.A256GCM,
new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(),
new BasicCredential(encKey.toPublicKey(), encKey.toPrivateKey()));
+
+ final var userInfoResp =
+ TestTokenHelper.createPlainUserInfoResponseString(OP_ISSUER_ID, List.of(CLIENT_ID), "jdoe");
-
- final MockWebServer mockOPServer = createSimpleServer();
// First is token exchange
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/json")
- .setBody(accessTokenResponseJson));
- // Second is userInfo
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/json")
- .setBody(TestTokenHelper.createPlainUserInfoResponseString(OP_ISSUER_ID, List.of(CLIENT_ID), "jdoe")));
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/json");
mockOPServer.start(9918);
@@ -470,11 +326,7 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
final ProfileRequestContext prc = populateBasicContextTreeFromAuthnResponse(flowExecution);
- final OIDCAuthorizationConfiguration partyConfig =
- (OIDCAuthorizationConfiguration) prc.getSubcontext(AuthenticationContext.class)
- .getSubcontext(ProfileRequestContext.class)
- .getSubcontext(RelyingPartyContext.class)
- .getProfileConfig();
+ final OIDCAuthorizationConfiguration partyConfig = getRelyingPartyProfileConfig(prc);
final JSONSecurityConfiguration secConfig = new JSONSecurityConfiguration();
@@ -487,30 +339,11 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
secConfig.setJwtSignatureValidationConfiguration(sigValidation);
final var decryptConfig = new BasicDecryptionConfiguration();
- decryptConfig.setKEKCredentialResolver(new JOSEObjectCredentialResolver() {
-
- @Override
- public Credential resolveSingle(final CriteriaSet criteria) throws ResolverException {
- final BasicJWKCredential jwkCredential = new BasicJWKCredential();
- jwkCredential.setAlgorithm(JWEAlgorithm.RSA_OAEP_256);
- jwkCredential.setKid(encKey.getKeyID());
- try {
- jwkCredential.setPrivateKey(encKey.toPrivateKey());
- jwkCredential.setPublicKey(encKey.toPublicKey());
- } catch (final JOSEException e) {
- fail();
- }
- return jwkCredential;
- }
- @Override
- public Iterable<Credential> resolve(final CriteriaSet criteria) throws ResolverException {
- return List.of(resolveSingle(criteria));
- }
- });
+ decryptConfig.setKEKCredentialResolver(
+ new MockAsymmetricJOSEObjectCredentialResolver(encKey,encKey.getKeyID(), JWEAlgorithm.RSA_OAEP_256));
secConfig.setJwtDecryptionConfiguration(decryptConfig);
partyConfig.setSecurityConfiguration(secConfig);
-
updateFlowExecution(flowExecution);
@@ -521,31 +354,17 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
mockOPServer.shutdown();
- final var nestedPrc = assertStandardEndFlowSuccessConditions(prc);
-
- final var accessTokenResponse =
- nestedPrc.getInboundMessageContext().getSubcontext(AccessTokenResponseContext.class);
- final var userInfoResponse =
- nestedPrc.getInboundMessageContext().getSubcontext(UserInfoResponseContext.class);
- final var endUserClaims =
- nestedPrc.getInboundMessageContext().getSubcontext(EndUserClaimsContext.class);
+ // Assert test conditions
- assertNotNull(accessTokenResponse.getIdToken());
- assertNotNull(userInfoResponse.getUserInfo());
- assertTrue(accessTokenResponse.getIdToken() instanceof SignedJWT);
- final var signedJwt = (SignedJWT) accessTokenResponse.getIdToken();
- assertEquals(signedJwt.getState(), State.VERIFIED);
-
- assertTrue(userInfoResponse.getUserInfo() instanceof PlainUserInfoResponse);
-
- assertStandardIdTokenClaimsSuccessCondition(signedJwt.getJWTClaimsSet());
- assertStandardEndUserClaimsSuccessCondition(endUserClaims.getEndUserClaims());
-
+ final var nestedPrc = assertStandardEndFlowSuccessConditions(prc);
+ assertIdTokenSignatureAndClaimsVerified(nestedPrc);
+ assertPlainJSONObjectUserInfoToken(nestedPrc);
+ assertEndUserClaimsVerified(nestedPrc);
}
/**
- * Test a plain UserInfo JWT type. This can not happen, and should trigger an error.
+ * Test a plain UserInfo JWT type. This can not happen, and should trigger an error on signature validation.
*
* @throws Exception on error.
*/
@@ -553,45 +372,26 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
public void test_IDTokenHS256_PlainJWTUserInfoResponse()
throws Exception {
- setFlowPath(FLOW);
- setFlowModelResources(flowResources);
- setSubflows(subflows);
-
- final Map<String,String> mockProperties = Map.of(
- "idp.service.clientinfo.failFast","false",
- "idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.provider.proxyIssuer",OP_ISSUER_ID);
-
- setMockProperties(mockProperties);
+ basicSetup();
final MockWebServer mockOPServer = createSimpleServer();
- // First is token exchange
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/json")
- .setBody(TestTokenHelper.createAccessTokenResponseJSON(
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null)));
- // Second is userInfo
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/jwt")
- .setBody(TestTokenHelper.createPlainUserInfoResponseJSON(OP_ISSUER_ID,CLIENT_ID)
- .serialize()));
- mockOPServer.start(9918);
-
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ final var userInfoResp =
+ TestTokenHelper.createPlainJWTUserInfoResponseJSON(OP_ISSUER_ID,CLIENT_ID)
+ .serialize();
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo (tell it is a JWT type when it is not)
+ queueMockServerResponse(mockOPServer, 200, userInfoResp, "application/jwt");
+ mockOPServer.start(9918);
- final var flowExecution = (FlowExecutionImpl)getFlowExecutionFactory()
- .createFlowExecution(getFlowDefinition());
- final ProfileRequestContext prc = populateBasicContextTreeFromAuthnResponse(flowExecution);
-
- updateFlowExecution(flowExecution);
-
- //set start view and ending event to transition on.
- externalContext.setEventId("proceed");
- setCurrentState("AuthnRequest");
- resumeFlow(externalContext);
+ final var prc = resumeBasicFlow();
mockOPServer.shutdown();
+ // Assert test conditions
assertFlowEndedInErrorConditions(prc, "InvalidMessage");
}
@@ -600,30 +400,20 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
public void test_IDTokenHS256_UserInfoHS256_WithACRAMRTranslation()
throws Exception {
- setFlowPath(FLOW);
- setFlowModelResources(flowResources);
- setSubflows(subflows);
-
- final Map<String,String> mockProperties = Map.of(
- "idp.service.clientinfo.failFast","false",
- "idp.entityID", "http://idp.example.com/");
-
- setMockProperties(mockProperties);
+ basicSetup();
final MockWebServer mockOPServer = createSimpleServer();
- // First is token exchange
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/json")
- .setBody(TestTokenHelper.createAccessTokenResponseJSON(
+ final var accessTokenResp = TestTokenHelper.createAccessTokenResponseJSON(
OP_ISSUER_ID, CLIENT_ID, List.of(CLIENT_ID), JWSAlgorithm.HS256, null, null,
- new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null)));
- // Second is userInfo
- final var userInfoToken = TestTokenHelper.createJWTUserInfoResponse(
+ new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
+ final var userInfoResp = TestTokenHelper.createJWTUserInfoResponse(
OP_ISSUER_ID, List.of(CLIENT_ID), "jdoe", JWSAlgorithm.HS256, null, null,
new DefaultClientSecretCredential(CLIENT_SECRET).toSigningCredential(), null);
- mockOPServer.enqueue(new MockResponse().setResponseCode(200)
- .setHeader("content-type", "application/jwt")
- .setBody(userInfoToken.serialize()));
+
+ // First is token exchange
+ queueMockServerResponse(mockOPServer, 200, accessTokenResp, "application/json");
+ // Second is plain userInfo
+ queueMockServerResponse(mockOPServer, 200, userInfoResp.serialize(), "application/jwt");
mockOPServer.start(9918);
@@ -643,6 +433,8 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
mockOPServer.shutdown();
+ // Assert test conditions
+
assertStandardEndFlowSuccessConditions(prc);
// Add checks for added ACRs and AMRs
assertNotNull(prc.getSubcontext(SubjectCanonicalizationContext.class).getSubject()
@@ -662,15 +454,7 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
public void testUnsupportedOIDCFlow()
throws Exception {
- setFlowPath(FLOW);
- setFlowModelResources(flowResources);
- setSubflows(subflows);
-
- final Map<String,String> mockProperties = Map.of(
- "idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.provider.proxyIssuer",OP_ISSUER_ID);
-
- setMockProperties(mockProperties);
+ basicSetup();
final var flowExecution = (FlowExecutionImpl)getFlowExecutionFactory()
.createFlowExecution(getFlowDefinition());
@@ -693,10 +477,6 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
resumeFlow(externalContext);
assertFlowEndedInErrorConditions(prc);
- // Ensure flow did not produce an end-user message context
- assertNull(prc.getSubcontext(AuthenticationContext.class).getSubcontext(ProfileRequestContext.class)
- .getInboundMessageContext().getSubcontext(EndUserClaimsContext.class));
-
}
/**
@@ -709,16 +489,7 @@ public class OIDCRPFlowFromAuthenticationResponseTest extends OIDCRPFlowTest {
public void testErrorAuthenticationResponse()
throws Exception {
- setFlowPath(FLOW);
- setFlowModelResources(flowResources);
- setSubflows(subflows);
-
- final Map<String,String> mockProperties = Map.of(
- "idp.service.clientinfo.failFast","false",
- "idp.entityID", "http://idp.example.com/",
- "idp.authn.oidc.rp.provider.proxyIssuer",OP_ISSUER_ID);
-
- setMockProperties(mockProperties);
+ basicSetup();
final FlowExecutionImpl flowExecution = (FlowExecutionImpl)getFlowExecutionFactory()
.createFlowExecution(getFlowDefinition());
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowPreRedirectTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowPreRedirectTest.java
index 763b084..3a8f6ab 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowPreRedirectTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowPreRedirectTest.java
@@ -25,7 +25,7 @@ import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
/**
- * RP Flow tests for flows actions that built the authentication request before being redirected to the OP. Uses
+ * RP Flow tests for flows actions that build the authentication request before being redirected to the OP. Uses
* configuration from the loaded XML configuration files — unlike {@link OIDCRPFlowFromAuthenticationResponseTest}
* which needs to build the configuration programatically because the initial seeding of the configuration only happens
* pre-authn redirect.
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
index 8a71389..16e79ed 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
@@ -49,6 +49,7 @@ import org.springframework.webflow.engine.impl.FlowExecutionImpl;
import org.springframework.webflow.test.MockFlowBuilderContext;
import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.SignedJWT;
import com.nimbusds.oauth2.sdk.ParseException;
import com.nimbusds.oauth2.sdk.ResponseMode;
import com.nimbusds.oauth2.sdk.ResponseType;
@@ -71,6 +72,8 @@ import net.shibboleth.idp.plugin.authn.oidc.rp.context.EndUserClaimsContext;
import net.shibboleth.idp.plugin.authn.oidc.rp.context.OAuth2ClientContext;
import net.shibboleth.idp.plugin.authn.oidc.rp.context.OIDCPeerEntityContext;
import net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext;
+import net.shibboleth.idp.plugin.authn.oidc.rp.messaging.JWTUserInfoResponse;
+import net.shibboleth.idp.plugin.authn.oidc.rp.messaging.PlainUserInfoResponse;
import net.shibboleth.idp.plugin.authn.oidc.rp.principal.OIDCSubjectIdentifierPrincipal;
import net.shibboleth.idp.plugin.authn.test.flow.AbstractAuthnXmlFlowExecutionTests;
import net.shibboleth.idp.plugin.authn.test.flow.mock.MockFlowBuilder;
@@ -484,6 +487,19 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
});
}
+ /**
+ * Return the Profile configuration from the relying party context.
+ *
+ * @param prc the prc
+ * @return the relying party configuration
+ */
+ protected OIDCAuthorizationConfiguration getRelyingPartyProfileConfig(final ProfileRequestContext prc) {
+ return (OIDCAuthorizationConfiguration) prc.getSubcontext(AuthenticationContext.class)
+ .getSubcontext(ProfileRequestContext.class)
+ .getSubcontext(RelyingPartyContext.class)
+ .getProfileConfig();
+ }
+
/**
* Assert the basic set of conditions expected at the end of the entire authentication flow.
*
@@ -555,10 +571,13 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
@Nonnull final String error) {
assertFlowExecutionEnded();
- // No result
+ // No subject result
assertNull(rootPrc.getSubcontext(SubjectCanonicalizationContext.class));
- // Is there an authn result?
+ // No an authn result
assertNull(rootPrc.getSubcontext(AuthenticationContext.class).getAuthenticationResult());
+ // Ensure flow did not produce an end-user message context
+ assertNull(rootPrc.getSubcontext(AuthenticationContext.class).getSubcontext(ProfileRequestContext.class)
+ .getInboundMessageContext().getSubcontext(EndUserClaimsContext.class));
assertPreviousEventContextError(rootPrc, error);
}
@@ -571,10 +590,13 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
protected void assertFlowEndedInErrorConditions(@Nonnull final ProfileRequestContext rootPrc) {
assertFlowExecutionEnded();
- // No result
+ // No subject result
assertNull(rootPrc.getSubcontext(SubjectCanonicalizationContext.class));
- // Is there an authn result?
+ // No an authn result
assertNull(rootPrc.getSubcontext(AuthenticationContext.class).getAuthenticationResult());
+ // Ensure flow did not produce an end-user message context
+ assertNull(rootPrc.getSubcontext(AuthenticationContext.class).getSubcontext(ProfileRequestContext.class)
+ .getInboundMessageContext().getSubcontext(EndUserClaimsContext.class));
}
/**
@@ -642,6 +664,72 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
}
-
+ /**
+ * Assert the id_token exists, has had its signature verified, and the claims contained in the token are accurate.
+ *
+ * @param nestedPrc the nested profile request context
+ *
+ * @throws java.text.ParseException on error
+ */
+ protected void assertIdTokenSignatureAndClaimsVerified(final ProfileRequestContext nestedPrc)
+ throws java.text.ParseException {
+ final var accessTokenResponse =
+ nestedPrc.getInboundMessageContext().getSubcontext(AccessTokenResponseContext.class);
+ assertNotNull(accessTokenResponse.getIdToken());
+ assertTrue(accessTokenResponse.getIdToken() instanceof SignedJWT);
+ final var signedJwt = (SignedJWT) accessTokenResponse.getIdToken();
+ assertEquals(signedJwt.getState(), com.nimbusds.jose.JWSObject.State.VERIFIED);
+ assertStandardIdTokenClaimsSuccessCondition(signedJwt.getJWTClaimsSet());
+ }
+
+ /**
+ * Assert the user info response JWT exists, and has had its signature verified.
+ *
+ * @param nestedPrc the nested profile request context
+ *
+ * @throws java.text.ParseException on error
+ */
+ protected void assertUserInfoTokenSignatureVerified(final ProfileRequestContext nestedPrc)
+ throws java.text.ParseException {
+ final var userInfoResponse =
+ nestedPrc.getInboundMessageContext().getSubcontext(UserInfoResponseContext.class);
+ assertNotNull(userInfoResponse.getUserInfo());
+ assertTrue(userInfoResponse.getUserInfo() instanceof JWTUserInfoResponse);
+ final var jwtResponse = (JWTUserInfoResponse) userInfoResponse.getUserInfo();
+ final var signedJwt = (SignedJWT) jwtResponse.getResponseJwt();
+ assertEquals(signedJwt.getState(), com.nimbusds.jose.JWSObject.State.VERIFIED);
+
+ }
+
+ /**
+ * Assert a plain JSON object user info response.
+ *
+ * @param nestedPrc the nested profile request context
+ *
+ * @throws java.text.ParseException on error
+ */
+ protected void assertPlainJSONObjectUserInfoToken(final ProfileRequestContext nestedPrc)
+ throws java.text.ParseException {
+ final var userInfoResponse =
+ nestedPrc.getInboundMessageContext().getSubcontext(UserInfoResponseContext.class);
+ assertNotNull(userInfoResponse.getUserInfo());
+ assertTrue(userInfoResponse.getUserInfo() instanceof PlainUserInfoResponse);
+
+ }
+
+ /**
+ * Assert end-user claims exist, and the claims are accurate.
+ *
+ * @param nestedPrc the nested profile request context
+ *
+ * @throws java.text.ParseException on error
+ */
+ protected void assertEndUserClaimsVerified(final ProfileRequestContext nestedPrc)
+ throws java.text.ParseException {
+ final var endUserClaims =
+ nestedPrc.getInboundMessageContext().getSubcontext(EndUserClaimsContext.class);
+ assertStandardEndUserClaimsSuccessCondition(endUserClaims.getEndUserClaims());
+ }
+
}
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestTokenHelper.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestTokenHelper.java
index 7271d6c..59995ab 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestTokenHelper.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/TestTokenHelper.java
@@ -268,7 +268,7 @@ public final class TestTokenHelper {
* @return the signed JWT
* @throws JOSEException on error
*/
- public static PlainJWT createPlainUserInfoResponseJSON(final String issuer, final String audience)
+ public static PlainJWT createPlainJWTUserInfoResponseJSON(final String issuer, final String audience)
throws JOSEException {
final var payload = createBasicUserInfoClaims(issuer, List.of(audience), "jdoe");
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list