[java-idp-plugin-oidc-rp] branch main updated: Improve max_age handling, and set a timestamp onto the authentication request

Phil Smart philip.smart at jisc.ac.uk
Fri Apr 21 11:24:50 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=63aa8696aea94113ff31efd1d4320b05151b22aa

The following commit(s) were added to refs/heads/main by this push:
     new 63aa869  Improve max_age handling, and set a timestamp onto the authentication request
63aa869 is described below

commit 63aa8696aea94113ff31efd1d4320b05151b22aa
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Apr 21 12:24:48 2023 +0100

    Improve max_age handling, and set a timestamp onto the authentication
    request
---
 ...okupFunction.java => MaxAgeLookupFunction.java} | 49 ++++++++++++--
 .../AuthenticationRequestTimeLookupFunction.java   | 79 ++++++++++++++++++++++
 .../impl/SetAuthenticationRequestTimeHandler.java  | 41 +++++++++++
 .../oidc-relying-party-authn-beans.xml             | 12 +++-
 4 files changed, 173 insertions(+), 8 deletions(-)

diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/MaxAgeFromProfileLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/MaxAgeLookupFunction.java
similarity index 54%
rename from idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/MaxAgeFromProfileLookupFunction.java
rename to idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/MaxAgeLookupFunction.java
index 2631ef1..99795b1 100644
--- a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/MaxAgeFromProfileLookupFunction.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/navigate/MaxAgeLookupFunction.java
@@ -18,10 +18,10 @@
 package net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate;
 
 import java.time.Duration;
+import java.util.function.Function;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import javax.annotation.concurrent.ThreadSafe;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 
@@ -29,29 +29,68 @@ import net.shibboleth.idp.profile.config.ProfileConfiguration;
 import net.shibboleth.idp.profile.context.RelyingPartyContext;
 import net.shibboleth.idp.profile.context.navigate.AbstractRelyingPartyLookupFunction;
 import net.shibboleth.oidc.profile.config.OIDCAuthenticationProfileConfiguration;
+import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
 import net.shibboleth.utilities.java.support.annotation.ParameterName;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 
-/** Locate the maximum authentication age from the profile request context. Returning a default value if not found.*/
- at ThreadSafe
-public class MaxAgeFromProfileLookupFunction extends AbstractRelyingPartyLookupFunction<Duration> {
+/** 
+ * Locate the maximum authentication age from the authentication request (first) or profile configuration (second). 
+ * Returning a default value if neither are found.
+ */
+public class MaxAgeLookupFunction extends AbstractRelyingPartyLookupFunction<Duration> {
     
     /** Default max authentication age if none can be found on the profile context.*/
     private final Duration maxAgeDefault;
     
+    /** 
+     * Strategy used to locate the {@link OIDCAuthenticationRequest}. 
+     * Defaults to the outbound message context of the PRC. 
+     */
+    @Nonnull private Function<ProfileRequestContext, OIDCAuthenticationRequest> authenticationRequestLookupStrategy;
+    
     /**
      * Constructor.
      *
      * @param defaultAge the default value to use for maximum authentication age
      */
-    public MaxAgeFromProfileLookupFunction(@ParameterName(name = "maxAgeDefault") @Nonnull final Duration defaultAge) {
+    public MaxAgeLookupFunction(
+            @ParameterName(name = "maxAgeDefault") @Nonnull final Duration defaultAge) {
         maxAgeDefault = Constraint.isNotNull(defaultAge, "Max Age default can not be null");
+        
+        authenticationRequestLookupStrategy = prc -> {
+            if (prc.getOutboundMessageContext() != null && prc.getOutboundMessageContext().getMessage() != null &&
+                    prc.getOutboundMessageContext().getMessage() instanceof OIDCAuthenticationRequest) {
+                return (OIDCAuthenticationRequest)prc.getOutboundMessageContext().getMessage();
+            }
+            return null;
+        };
+    }
+    
+    /**
+     * Set the authentication request lookup strategy to use.
+     * 
+     * @param strategy the strategy
+     */
+    public void setAuthenticationRequestLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext, OIDCAuthenticationRequest> strategy) {
+        authenticationRequestLookupStrategy = Constraint.isNotNull(strategy,
+                "AuthenticationRequestLookupStrategy can not be null");
     }
 
     @Override
     @Nonnull
     public Duration apply(@Nullable final ProfileRequestContext input) {
         
+        // Max_age from authentication request is authoritative over that from the profile config. If it exists in the 
+        // profile config it should have already been set on the authentication request.
+        
+        final OIDCAuthenticationRequest authnRequest = authenticationRequestLookupStrategy.apply(input);
+        if (authnRequest != null && authnRequest.getMaxAge() != null) {
+            return authnRequest.getMaxAge();
+        }
+        
+        // Check one was not specified in the relying party context
+        
         final RelyingPartyContext rpc = getRelyingPartyContextLookupStrategy().apply(input);
         if (rpc != null) {
             final ProfileConfiguration pc = rpc.getProfileConfig();
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/navigate/AuthenticationRequestTimeLookupFunction.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/navigate/AuthenticationRequestTimeLookupFunction.java
new file mode 100644
index 0000000..13072d7
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/navigate/AuthenticationRequestTimeLookupFunction.java
@@ -0,0 +1,79 @@
+/*
+ * 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.navigate;
+
+import java.time.Instant;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/** 
+ * Lookup function that returns the time at which the RP sent the authentication request, as taken from the 
+ * authentication request object.
+ */
+public class AuthenticationRequestTimeLookupFunction  implements Function<ProfileRequestContext, Instant> {
+    
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(AuthenticationRequestTimeLookupFunction.class);
+    
+    /** 
+     * Strategy used to locate the {@link OIDCAuthenticationRequest}. 
+     * Defaults to the outbound message context of the PRC. 
+     */
+    @Nonnull private Function<ProfileRequestContext, OIDCAuthenticationRequest> authenticationRequestLookupStrategy;
+    
+    /** Constructor.*/
+    public AuthenticationRequestTimeLookupFunction() {
+        authenticationRequestLookupStrategy = prc -> {
+            if (prc.getOutboundMessageContext() != null && prc.getOutboundMessageContext().getMessage() != null &&
+                    prc.getOutboundMessageContext().getMessage() instanceof OIDCAuthenticationRequest) {
+                return (OIDCAuthenticationRequest)prc.getOutboundMessageContext().getMessage();
+            }
+            return null;
+        };   
+    }
+    
+    /**
+     * Set the strategy used to locate the {@link OIDCAuthenticationRequest} to use.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setAuthenticationRequestLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext, OIDCAuthenticationRequest> strategy) {
+        authenticationRequestLookupStrategy =
+                Constraint.isNotNull(strategy, "AuthenticationRequestLookupStrategy lookup strategy cannot be null");
+    }
+
+    @Override
+    @Nullable public Instant apply(@Nullable final ProfileRequestContext input) {
+        if (input == null) {
+            return null;
+        }
+        final OIDCAuthenticationRequest authnRequest = authenticationRequestLookupStrategy.apply(input);
+        return authnRequest == null ? null : authnRequest.getAuthnRequestTime();
+    }
+
+}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SetAuthenticationRequestTimeHandler.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SetAuthenticationRequestTimeHandler.java
new file mode 100644
index 0000000..d9e44bc
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/SetAuthenticationRequestTimeHandler.java
@@ -0,0 +1,41 @@
+/*
+ * 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.impl;
+
+import java.time.Instant;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.MessageContext;
+import org.opensaml.messaging.handler.MessageHandlerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Handler that adds the authentication request time to the authentication request.*/
+public class SetAuthenticationRequestTimeHandler extends AbstractOIDCAuthenticationRequestMessageHandler {
+    
+    /** Logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(SetAuthenticationRequestTimeHandler.class);
+    
+    /** {@inheritDoc} */
+    @Override
+    protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException {        
+        getAuthenticationRequest().setAuthnRequestTime(Instant.now());              
+    }
+
+}
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 7cb0046..eea844a 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
@@ -299,6 +299,8 @@
                             class="net.shibboleth.idp.plugin.authn.oidc.rp.context.navigate.RequestObjectTokenUpdateStrategy" />
                     </property>
                 </bean>
+                 <bean id="SetAuthenticationRequestTime"
+                    class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.impl.SetAuthenticationRequestTimeHandler" scope="prototype"/>
             </list>
         </property>
     </bean>
@@ -614,14 +616,18 @@
     
     <bean id="AuthenticationTimeClaimValidator" 
                 class="net.shibboleth.oidc.security.jwt.claims.impl.AuthenticationTimeClaimsValidator"
-                p:authnLifetimeLookupStrategy-ref="MaxAgeFromProfileLookupFunction"
+                p:authnLifetimeLookupStrategy-ref="MaxAgeLookupFunction"
+                p:authnRequestTimeLookupStrategy-ref="AuthenticationRequestTimeLookupFunction"
                 p:clockSkew="%{idp.authn.oidc.rp.client.idtoken.jwt.verifier.clockSkew:PT60S}"
                 p:activationCondition="#{getObject('shibboleth.authn.oidc.rp.jwt.AuthTimeActivationCondition') ?: 
                                 getObject('shibboleth.authn.oidc.rp.jwt.DefaultAuthTimeActivationCondition')}"/>
                                 
-    <bean id="MaxAgeFromProfileLookupFunction" 
-        class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.MaxAgeFromProfileLookupFunction"
+    <bean id="MaxAgeLookupFunction" 
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.MaxAgeLookupFunction"
         c:maxAgeDefault="%{idp.authn.oidc.rp.client.idtoken.jwt.verifier.authnLifetime:PT60S}"/>
+        
+    <bean id="AuthenticationRequestTimeLookupFunction" 
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.navigate.AuthenticationRequestTimeLookupFunction"/>  
 
     <bean id="shibboleth.authn.oidc.rp.jwt.DefaultAuthTimeActivationCondition" 
             class="net.shibboleth.oidc.security.jwt.claims.impl.AuthTimeRequestedActivationCondition"

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


More information about the commits mailing list