[java-idp-plugin-oidc-rp] branch main updated: Add predicates to express conditions in the flow
Phil Smart
philip.smart at jisc.ac.uk
Thu Feb 17 17:02:32 UTC 2022
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=3f892d215e19feb016719242185d914ecdc89379
The following commit(s) were added to refs/heads/main by this push:
new 3f892d2 Add predicates to express conditions in the flow
3f892d2 is described below
commit 3f892d215e19feb016719242185d914ecdc89379
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Thu Feb 17 17:02:26 2022 +0000
Add predicates to express conditions in the flow
---
idp-oidc-rp-api/pom.xml | 5 +
.../AbstractUserInfoResponseTypeCondition.java | 87 +++++++++++++++++
.../UserInfoEncryptedJWTResponseTypeCondition.java | 38 ++++++++
.../context/logic}/UserInfoLookupCondition.java | 2 +-
.../UserInfoSignedJWTResponseTypeCondition.java | 38 ++++++++
.../plugin/authn/oidc/rp/impl/AddAuthzRequest.java | 9 +-
.../authn/oidc/rp/impl/ProcessEndUserClaims.java | 3 +-
.../oidc-relying-party-authn-beans.xml | 10 +-
.../oidc-relying-party-authn-flow.xml | 24 ++---
.../plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java | 104 +++++++++++++++++++++
10 files changed, 297 insertions(+), 23 deletions(-)
diff --git a/idp-oidc-rp-api/pom.xml b/idp-oidc-rp-api/pom.xml
index 67d9a6d..2a8126f 100644
--- a/idp-oidc-rp-api/pom.xml
+++ b/idp-oidc-rp-api/pom.xml
@@ -40,6 +40,11 @@
<groupId>${idp.groupId}</groupId>
<artifactId>idp-authn-api</artifactId>
<scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>net.shibboleth.oidc</groupId>
+ <artifactId>oidc-common-profile-api</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/AbstractUserInfoResponseTypeCondition.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/AbstractUserInfoResponseTypeCondition.java
new file mode 100644
index 0000000..51f0e15
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/AbstractUserInfoResponseTypeCondition.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
+
+import net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Abstract predicate for pulling out the {@link UserInfoResponseContext}. If either the
+ * profile request context or extracted UserInfo response context are null, false is returned
+ * immediately.
+ */
+public abstract class AbstractUserInfoResponseTypeCondition implements Predicate<ProfileRequestContext> {
+
+ /** Strategy used to look up the {@link UserInfoResponseContext}. */
+ @Nonnull private final Function<ProfileRequestContext, UserInfoResponseContext>
+ userInfoResponseContextLookupStrategy;
+
+ /** Constructor.*/
+ protected AbstractUserInfoResponseTypeCondition() {
+ userInfoResponseContextLookupStrategy =
+ new ChildContextLookup<>(UserInfoResponseContext.class).compose(
+ new InboundMessageContextLookup());
+ }
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param strategy the UserInfo response context lookup strategy to use.
+ */
+ protected AbstractUserInfoResponseTypeCondition(
+ @Nonnull final Function<ProfileRequestContext, UserInfoResponseContext> strategy) {
+ userInfoResponseContextLookupStrategy =
+ Constraint.isNotNull(strategy, "UserInfoResponseContext lookup strategy can not be null");
+ }
+
+ @Override
+ public boolean test(@Nullable final ProfileRequestContext prc) {
+ if (prc == null) {
+ return false;
+ }
+ final UserInfoResponseContext context = userInfoResponseContextLookupStrategy.apply(prc);
+ if (context == null) {
+ return false;
+ }
+ return doTest(prc, context);
+
+ }
+
+ /**
+ * Implementations should override this method to provide necessary logic.
+ *
+ * @param prc the profile request context
+ * @param context the UserInfo response context
+ *
+ * @return the result of this test
+ */
+ protected abstract boolean doTest(@Nonnull final ProfileRequestContext prc,
+ @Nonnull final UserInfoResponseContext context);
+
+}
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/UserInfoEncryptedJWTResponseTypeCondition.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/UserInfoEncryptedJWTResponseTypeCondition.java
new file mode 100644
index 0000000..04cfca2
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/UserInfoEncryptedJWTResponseTypeCondition.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext;
+
+/**
+ * Return true if the UserInfo response was an encrypted JWT type.
+ */
+public class UserInfoEncryptedJWTResponseTypeCondition extends AbstractUserInfoResponseTypeCondition {
+
+ @Override
+ protected boolean doTest(@Nonnull final ProfileRequestContext prc,
+ @Nonnull final UserInfoResponseContext context) {
+ if (context.getUserInfo() == null) {
+ return false;
+ }
+ return context.getUserInfo().isEncrypted();
+ }}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/UserInfoLookupCondition.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/UserInfoLookupCondition.java
similarity index 96%
rename from idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/UserInfoLookupCondition.java
rename to idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/UserInfoLookupCondition.java
index e2e0e24..3329b56 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/UserInfoLookupCondition.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/UserInfoLookupCondition.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
+package net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic;
import java.util.function.Predicate;
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/UserInfoSignedJWTResponseTypeCondition.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/UserInfoSignedJWTResponseTypeCondition.java
new file mode 100644
index 0000000..d1322b8
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/UserInfoSignedJWTResponseTypeCondition.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext;
+
+/**
+ * Return true if the UserInfo response was a signed JWT type.
+ */
+public class UserInfoSignedJWTResponseTypeCondition extends AbstractUserInfoResponseTypeCondition {
+
+ @Override
+ protected boolean doTest(@Nonnull final ProfileRequestContext prc,
+ @Nonnull final UserInfoResponseContext context) {
+ if (context.getUserInfo() == null) {
+ return false;
+ }
+ return context.getUserInfo().isSigned();
+ }}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthzRequest.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthzRequest.java
index 7cd1a66..0665f4b 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthzRequest.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddAuthzRequest.java
@@ -17,6 +17,7 @@
package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
+import java.util.List;
import java.util.function.Function;
import javax.annotation.Nonnull;
@@ -65,7 +66,7 @@ import net.shibboleth.utilities.java.support.logic.Constraint;
public class AddAuthzRequest extends AbstractAuthenticationAction {
/** Class logger. */
- @Nonnull private Logger log = LoggerFactory.getLogger(AddAuthzRequest.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AddAuthzRequest.class);
/** Overwrite an existing message? */
private boolean overwriteExisting;
@@ -230,7 +231,10 @@ public class AddAuthzRequest extends AbstractAuthenticationAction {
request.setEndpointURI(providerMetadata.getProviderInformation().getAuthorizationEndpointURI());
request.setRedirectURI(clientMetadata.getClientInformation().getMetadata().getRedirectionURI());
- request.getScope().add("profile");
+ // Add scopes
+ final List<String> scopes =
+ clientMetadata.getClientInformation().getMetadata().getScope().toStringList();
+ scopes.forEach(s -> request.getScope().add(s));
//TODO use strategy with injectable secure random implementation?
request.setNonce(new Nonce(OIDCProxySupport.generateNonce(16)));
@@ -248,4 +252,5 @@ public class AddAuthzRequest extends AbstractAuthenticationAction {
}
+
}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProcessEndUserClaims.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProcessEndUserClaims.java
index cd65321..51cabc8 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProcessEndUserClaims.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ProcessEndUserClaims.java
@@ -40,7 +40,6 @@ import net.shibboleth.idp.authn.context.AuthenticationContext;
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.oidc.profile.core.OidcEventIds;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
@@ -48,7 +47,7 @@ import net.shibboleth.utilities.java.support.logic.Constraint;
* Process the end-user claims from the id_token and possible UserInfo claims sets.
*
* <p>Sanitized both claims sets using a replaceable strategy. For example,
- * by default to remove 'validation claims' that should not be exposed further by the system.</p>
+ * by default to remove standard JWT 'validation' claims that should not be exposed further by the system.</p>
*
* <p>Merge the claims sets together to produce an aggregate claims set. The UserInfo claims can
* be empty i.e. claims from the UserInfo endpoint were not requested.</p>
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
index b6492b9..d49e603 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-beans.xml
@@ -400,8 +400,8 @@
<bean id="CheckUserInfoRequiredCondition"
- class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.UserInfoLookupCondition"/>
-
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic.UserInfoLookupCondition"/>
+
<!-- UserInfo endpoint beans -->
@@ -432,6 +432,12 @@
class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.ProcessEndUserClaims" scope="prototype"
p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
p:authenticationContextLookupStrategy-ref="ParentAuthenticiationContextLookup"/>
+
+ <bean id="CheckUserInfoSignedJWTResponseTypeCondition"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic.UserInfoSignedJWTResponseTypeCondition"/>
+
+ <bean id="CheckUserInfoEncryptedJWTResponseTypeCondition"
+ class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic.UserInfoEncryptedJWTResponseTypeCondition"/>
<!-- UserInfo response JWT validation -->
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
index 8b31a5d..44e1bd6 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
@@ -102,14 +102,12 @@
<!-- <evaluate expression="PopulateTokenEncryptionParameters" /> -->
<evaluate expression="ValidateIDTokenClaims" />
<evaluate expression="'proceed'" />
- <transition on="proceed" to="CheckUserInfoRequired" />
+ <transition on="proceed" to="CheckUserInfoClaimsRequired" />
</action-state>
- <!-- Should we request information from the UserInfo endpoint based on profile config -->
- <decision-state id="CheckUserInfoRequired">
+ <decision-state id="CheckUserInfoClaimsRequired">
<if test="CheckUserInfoRequiredCondition.test(opensamlProfileRequestContext.getSubcontext('net.shibboleth.idp.authn.context.AuthenticationContext').getSubcontext('org.opensaml.profile.context.ProfileRequestContext'))"
- then="UserInfoRequest"
- else="FinalizeResponse" />
+ then="UserInfoRequest" else="FinalizeResponse" />
<!-- if else here, we need to set id_token claims into EndUserClaimsContext -->
</decision-state>
@@ -120,18 +118,11 @@
<transition on="proceed" to="CheckUserInfoResponseType" />
</action-state>
- <!-- Make strategy for these conditions
- Also, what about a plain JWT? need to extract out the claims for those too -->
+ <!-- A plain JWT will skip token validation and go straight to claim validation -->
<decision-state id="CheckUserInfoResponseType">
- <if test="opensamlProfileRequestContext.getSubcontext('net.shibboleth.idp.authn.context.AuthenticationContext')
- .getSubcontext('org.opensaml.profile.context.ProfileRequestContext').getInboundMessageContext()
- .getSubcontext('net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext')
- .getUserInfo().isSigned()"
+ <if test="CheckUserInfoSignedJWTResponseTypeCondition.test(opensamlProfileRequestContext.getSubcontext('net.shibboleth.idp.authn.context.AuthenticationContext').getSubcontext('org.opensaml.profile.context.ProfileRequestContext'))"
then="ValidateSignedUserInfoJWT" />
- <if test="opensamlProfileRequestContext.getSubcontext('net.shibboleth.idp.authn.context.AuthenticationContext')
- .getSubcontext('org.opensaml.profile.context.ProfileRequestContext').getInboundMessageContext()
- .getSubcontext('net.shibboleth.idp.plugin.authn.oidc.rp.context.UserInfoResponseContext')
- .getUserInfo().isEncrypted()"
+ <if test="CheckUserInfoEncryptedJWTResponseTypeCondition.test(opensamlProfileRequestContext.getSubcontext('net.shibboleth.idp.authn.context.AuthenticationContext').getSubcontext('org.opensaml.profile.context.ProfileRequestContext'))"
then="DecryptUserInfoJWT"
else="ValidateUserInfoClaimsSet"/>
</decision-state>
@@ -143,6 +134,7 @@
<transition on="proceed" to="ValidateUserInfoClaimsSet" />
</action-state>
+ <!-- TODO decrypt then check signature if signed, then check claims if signed! see 5.3.2 -->
<action-state id="DecryptUserInfoJWT">
<!-- <evaluate expression="PopulateTokenEncryptionParameters" /> -->
<evaluate expression="ValidateUserInfoToken" /> <!-- Will die if not decrypted properly first -->
@@ -157,7 +149,7 @@
</action-state>
<action-state id="FinalizeResponse">
- <evaluate expression="ProcessEndUserClaims" /> <!-- check this works if no userInfo -->
+ <evaluate expression="ProcessEndUserClaims" />
<evaluate expression="ValidateOIDCAuthentication" />
<evaluate expression="'proceed'" />
<transition on="proceed" to="proceed" />
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 df03349..1f5537f 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
@@ -64,6 +64,7 @@ import com.nimbusds.jose.jwk.gen.ECKeyGenerator;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
import com.nimbusds.jwt.EncryptedJWT;
import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.PlainJWT;
import com.nimbusds.jwt.SignedJWT;
import com.nimbusds.oauth2.sdk.ParseException;
import com.nimbusds.oauth2.sdk.ResponseMode;
@@ -356,6 +357,29 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
return signedJWT;
}
+ /**
+ * Create a Plain UserInfo response JWT.
+ *
+ * @param issuer the issuer
+ * @param audience the audience
+ * @return the signed JWT
+ * @throws JOSEException on error
+ */
+ private PlainJWT createPlainUserInfoJWTResponseJSON(final String issuer, final String audience)
+ throws JOSEException {
+
+
+ final var payload = new JWTClaimsSet.Builder()
+ .issuer(issuer)
+ .audience(audience)
+ .subject("jdoe")
+ .claim("preferred_username", "jdoe")
+ .claim("name", "J Doe")
+ .build();
+
+ return new PlainJWT(payload);
+ }
+
/**
* Create a signed and encrypted UserInfo response JWT.
*
@@ -754,6 +778,86 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
assertEquals(prc.getSubcontext(SubjectCanonicalizationContext.class).getPrincipalName(),"jdoe");
+ }
+
+ @Test
+ public void testAuthnFlowFromAuthorizationCallback_UsingPlainJWTUserInfoResponse()
+ 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.proxyIssuer",OP_ISSUER_ID);
+
+ setMockProperties(mockProperties);
+
+ final MockWebServer mockOPServer = createSimpleServer();
+ // First is token exchange
+ mockOPServer.enqueue(new MockResponse().setResponseCode(200)
+ .setHeader("content-type", "application/json")
+ .setBody(createAccessTokenResponseJSON()));
+ // Second is userInfo
+ mockOPServer.enqueue(new MockResponse().setResponseCode(200)
+ .setHeader("content-type", "application/jwt")
+ .setBody(createPlainUserInfoJWTResponseJSON(OP_ISSUER_ID,"demo_rp")
+ .serialize()));
+ mockOPServer.start(9918);
+
+
+ final FlowExecutionImpl flowExecution = (FlowExecutionImpl)getFlowExecutionFactory()
+ .createFlowExecution(getFlowDefinition());
+ final ProfileRequestContext prc = buildProfileRequestContext("authn/OIDCRelyingParty", false,false);
+ prc.getSubcontext(AuthenticationContext.class).setAuthenticatingAuthority(OP_ISSUER_ID);
+
+ // create a nested PRC under the authentication context
+ final ProfileRequestContext nestPrc = (ProfileRequestContext)
+ prc.getSubcontext(AuthenticationContext.class).addSubcontext(new ProfileRequestContext(), true);
+
+ // Add under nest PRC
+ final RelyingPartyContext partyContext = new RelyingPartyContext();
+ final OIDCAuthorizationConfiguration partyConfig = new OIDCAuthorizationConfiguration();
+ partyContext.setProfileConfig(partyConfig);
+ nestPrc.addSubcontext(partyContext);
+
+ // Setup outbound context
+ final MessageContext outMsgCtx = new MessageContext();
+ outMsgCtx.setMessage(createAuthenticationRequest());
+ outMsgCtx.addSubcontext(createPeerContext());
+ outMsgCtx.addSubcontext(createResponseTypeAndModeContext());
+ outMsgCtx.addSubcontext(createClientMedataContext());
+ nestPrc.setOutboundMessageContext(outMsgCtx);
+
+ // Setup inbound context.
+ final MessageContext inMsgCtx = new MessageContext();
+ inMsgCtx.setMessage(createAuthenticationResponse());
+ nestPrc.setInboundMessageContext(inMsgCtx);
+
+ // Add prc to flow.
+ prc.getSubcontext(AuthenticationContext.class)
+ .addSubcontext(new ExternalAuthenticationContext(new ExternalAuthenticationImpl(false)));
+ flowExecution.getConversationScope().put("opensamlProfileRequestContext",prc);
+
+
+ updateFlowExecution(flowExecution);
+
+ //set start view and ending event to transition on.
+ externalContext.setEventId("proceed");
+ setCurrentState("AuthRequest");
+ resumeFlow(externalContext);
+
+ mockOPServer.shutdown();
+
+ //assert success conditions
+ assertFlowExecutionEnded();
+ assertNotNull(prc.getSubcontext(AuthenticationContext.class));
+ assertNotNull(prc.getSubcontext(SubjectCanonicalizationContext.class));
+ assertEquals(prc.getSubcontext(SubjectCanonicalizationContext.class).getPrincipalName(),"jdoe");
+
+
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list