[java-idp-oidc] branch main updated: JOIDC-88 Honoring semantics for forceAuthn flag in the same manner as SAML

Henri Mikkonen henri.mikkonen at iki.fi
Mon Apr 11 15:23:19 UTC 2022


This is an automated email from the git hooks/post-receive script.

hjmikkon pushed a commit to branch main
in repository java-idp-oidc.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-oidc.git;a=commit;h=4f799a8dc2726d0df6137502147b314e51cddffc

The following commit(s) were added to refs/heads/main by this push:
     new 4f799a8d JOIDC-88 Honoring semantics for forceAuthn flag in the same manner as SAML
4f799a8d is described below

commit 4f799a8dc2726d0df6137502147b314e51cddffc
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Mon Apr 11 18:22:29 2022 +0300

    JOIDC-88 Honoring semantics for forceAuthn flag in the same manner as SAML
    
    https://shibboleth.atlassian.net/browse/JOIDC-88
    
    Added configurable forceAuthnPredicate for the InitializeAuthenticationContext action.
    It’s set to ForceAuthnProfileConfigPredicate (protocol-independent) by default.
---
 .../impl/InitializeAuthenticationContext.java      | 24 ++++++++++++++++
 .../impl/InitializeAuthenticationContextTest.java  | 32 ++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/InitializeAuthenticationContext.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/InitializeAuthenticationContext.java
index 8c406b06..39fb9cb1 100644
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/InitializeAuthenticationContext.java
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/InitializeAuthenticationContext.java
@@ -19,9 +19,11 @@ package net.shibboleth.idp.plugin.oidc.op.profile.impl;
 
 import java.time.Duration;
 import java.util.function.Function;
+import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
 
+import net.shibboleth.idp.authn.config.navigate.ForceAuthnProfileConfigPredicate;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultRequestLoginHintLookupFunction;
 import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultRequestMaxAgeLookupFunction;
@@ -59,6 +61,9 @@ public class InitializeAuthenticationContext extends AbstractOIDCAuthenticationR
     /** Strategy used to obtain the request max_age value. */
     @Nonnull private Function<ProfileRequestContext, Duration> maxAgeLookupStrategy;
 
+    /** Extracts forceAuthn property from profile config. */
+    @Nonnull private Predicate<ProfileRequestContext> forceAuthnPredicate;
+
     /**
      * Constructor.
      */
@@ -66,6 +71,7 @@ public class InitializeAuthenticationContext extends AbstractOIDCAuthenticationR
         promptLookupStrategy = new DefaultRequestedPromptLookupFunction();
         loginHintLookupStrategy = new DefaultRequestLoginHintLookupFunction();
         maxAgeLookupStrategy = new DefaultRequestMaxAgeLookupFunction();
+        forceAuthnPredicate = new ForceAuthnProfileConfigPredicate();
     }
 
     /**
@@ -99,6 +105,19 @@ public class InitializeAuthenticationContext extends AbstractOIDCAuthenticationR
         maxAgeLookupStrategy = Constraint.isNotNull(strategy, "MaxAgeLookupStrategy lookup strategy cannot be null");
     }
 
+    /**
+     * Set the predicate to apply to derive the message-independent forced authn default. 
+     * 
+     * @param condition condition to set
+     * 
+     * @since 3.1.0
+     */
+    public void setForceAuthnPredicate(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        forceAuthnPredicate = Constraint.isNotNull(condition, "Forced authentication predicate cannot be null");
+    }
+
     /** {@inheritDoc} */
     @Override
     protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
@@ -118,6 +137,11 @@ public class InitializeAuthenticationContext extends AbstractOIDCAuthenticationR
             authnCtx.setIsPassive(prompt.contains(Prompt.Type.NONE));
             authnCtx.setForceAuthn(prompt.contains(Prompt.Type.LOGIN));
         }
+
+        if (!authnCtx.isForceAuthn()) {
+            authnCtx.setForceAuthn(forceAuthnPredicate.test(profileRequestContext));
+        }
+
         final String loginHint = loginHintLookupStrategy.apply(profileRequestContext);
         if (loginHint != null) {
             authnCtx.setHintedName(loginHint);
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/InitializeAuthenticationContextTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/InitializeAuthenticationContextTest.java
index 7c9b62b6..4cb3ed75 100644
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/InitializeAuthenticationContextTest.java
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/impl/InitializeAuthenticationContextTest.java
@@ -38,6 +38,7 @@ import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Predicates;
 import com.nimbusds.oauth2.sdk.ParseException;
 import com.nimbusds.oauth2.sdk.ResponseType;
 import com.nimbusds.oauth2.sdk.Scope;
@@ -103,6 +104,37 @@ public class InitializeAuthenticationContextTest {
         Assert.assertEquals(authnCtx.getMaxAge(), Duration.ofSeconds(5));
     }
 
+    @Test
+    public void testOIDCAuthnRequestWithoutPrompt() {
+        final AuthenticationRequest req = new AuthenticationRequest.Builder(new ResponseType("code"), new Scope("openid"),
+                new ClientID("000123"), URI.create("https://example.com/callback")).state(new State()).build();
+        prc.getInboundMessageContext().setMessage(req);
+        final Event event = action.execute(requestCtx);
+        ActionTestingSupport.assertProceedEvent(event);
+        final AuthenticationContext authnCtx = prc.getSubcontext(AuthenticationContext.class, false);
+        Assert.assertNotNull(authnCtx);
+        Assert.assertFalse(authnCtx.isForceAuthn());
+        Assert.assertFalse(authnCtx.isPassive());
+        Assert.assertNull(authnCtx.getMaxAge());
+    }
+
+    @Test
+    public void testOIDCAuthnRequestWithoutPromptForceAuthnViaPredicate() throws ComponentInitializationException {
+        action = new InitializeAuthenticationContext();
+        action.setForceAuthnPredicate(Predicates.alwaysTrue());
+        action.initialize();
+        final AuthenticationRequest req = new AuthenticationRequest.Builder(new ResponseType("code"), new Scope("openid"),
+                new ClientID("000123"), URI.create("https://example.com/callback")).state(new State()).build();
+        prc.getInboundMessageContext().setMessage(req);
+        final Event event = action.execute(requestCtx);
+        ActionTestingSupport.assertProceedEvent(event);
+        final AuthenticationContext authnCtx = prc.getSubcontext(AuthenticationContext.class, false);
+        Assert.assertNotNull(authnCtx);
+        Assert.assertTrue(authnCtx.isForceAuthn());
+        Assert.assertFalse(authnCtx.isPassive());
+        Assert.assertNull(authnCtx.getMaxAge());
+    }
+
     @Test(expectedExceptions = ConstraintViolationException.class)
     public void testSetNullLoginHintLookupStrategy() throws Exception {
         action = new InitializeAuthenticationContext();

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list