[java-oidc-common] branch main updated: JCOMOIDC-34 - Authentication request message encoder factory

Phil Smart philip.smart at jisc.ac.uk
Fri Jan 7 14:30:45 UTC 2022


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

philsmart pushed a commit to branch main
in repository java-oidc-common.

View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=9a24d04d16d316907922cf65fc55d9500b5cafdb

The following commit(s) were added to refs/heads/main by this push:
     new 9a24d04  JCOMOIDC-34 - Authentication request message encoder factory
9a24d04 is described below

commit 9a24d04d16d316907922cf65fc55d9500b5cafdb
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Fri Jan 7 14:30:39 2022 +0000

    JCOMOIDC-34 - Authentication request message encoder factory
    
    - Add a factory for returning a message encoder based on the request
    method in the profile configuration.
    
    https://shibboleth.atlassian.net/browse/JCOMOIDC-34
---
 ...AuthenticationRequestMessageEncoderFactory.java | 107 +++++++++++++
 .../shibboleth/oidc/profile/impl/package-info.java |  21 +++
 ...enticationRequestMessageEncoderFactoryTest.java | 173 +++++++++++++++++++++
 3 files changed, 301 insertions(+)

diff --git a/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/AuthenticationRequestMessageEncoderFactory.java b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/AuthenticationRequestMessageEncoderFactory.java
new file mode 100644
index 0000000..8fdd604
--- /dev/null
+++ b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/AuthenticationRequestMessageEncoderFactory.java
@@ -0,0 +1,107 @@
+/*
+ * 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.oidc.profile.impl;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opensaml.messaging.encoder.MessageEncoder;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
+import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration.OIDCHttpRequestMethod;
+import net.shibboleth.oidc.profile.encoder.OIDCMessageEncoder;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
+import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
+import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
+
+/**
+ * Message encoder factory function that returns the first encoder suitable for the given request method found in the
+ * profile configuration.
+ */
+ at ThreadSafe
+public class AuthenticationRequestMessageEncoderFactory extends AbstractInitializableComponent
+        implements Function<ProfileRequestContext, MessageEncoder> {
+
+    /** Class logger. */
+    @Nonnull
+    private final Logger log = LoggerFactory.getLogger(AuthenticationRequestMessageEncoderFactory.class);
+
+    /** The list of message encoders to choose from. */
+    @Nonnull @Unmodifiable @NotLive private final List<OIDCMessageEncoder> encoders;
+
+    /**
+     * 
+     * Constructor.
+     *
+     * @param encodersToUse the list of possible encoders to use.
+     */
+    public AuthenticationRequestMessageEncoderFactory(
+            @Nullable @ParameterName(name = "encoders") final List<OIDCMessageEncoder> encodersToUse) {
+        if (encodersToUse == null) {
+            encoders = Collections.emptyList();
+        } else {
+            encoders = Collections.unmodifiableList(encodersToUse);
+        }
+    }
+
+    @Override
+    @Nullable public MessageEncoder apply(@Nonnull final ProfileRequestContext profileRequestContext) {
+
+        final RelyingPartyContext rpCtx = profileRequestContext.getSubcontext(RelyingPartyContext.class);
+        OIDCAuthorizationConfiguration profileConfiguration = null;
+
+        if (rpCtx != null && rpCtx.getProfileConfig() instanceof OIDCAuthorizationConfiguration) {
+            profileConfiguration = (OIDCAuthorizationConfiguration) rpCtx.getProfileConfig();
+        }
+        if (profileConfiguration == null) {
+            log.warn("OIDCAuthorizationConfiguration not found, no encoders to lookup");
+            return null;
+        }
+
+        final OIDCHttpRequestMethod requestMethodFromConfig =
+                profileConfiguration.getHttpRequestMethod(profileRequestContext);
+
+        if (requestMethodFromConfig == null) {
+            log.warn("Authentication request method not found on profile, no encoders to lookup");
+            return null;
+        }
+
+        final Optional<OIDCMessageEncoder> encoder =
+                encoders.stream().filter(enc -> enc.test(requestMethodFromConfig)).findFirst();
+        if (encoder.isPresent()) {
+            log.trace("Returning OIDC message encoder of type '{}'", encoder.get().getClass());
+        } else {
+            log.warn("No message encoder was found for authentication request method type '{}'",
+                    requestMethodFromConfig);
+        }
+
+        return encoder.orElse(null);
+    }
+
+}
diff --git a/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/package-info.java b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/package-info.java
new file mode 100644
index 0000000..e1fd983
--- /dev/null
+++ b/oidc-common-profile-impl/src/main/java/net/shibboleth/oidc/profile/impl/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * OIDC profile implementation classes.
+ */
+package net.shibboleth.oidc.profile.impl;
\ No newline at end of file
diff --git a/oidc-common-profile-impl/src/test/java/net/shibboleth/oidc/profile/impl/AuthenticationRequestMessageEncoderFactoryTest.java b/oidc-common-profile-impl/src/test/java/net/shibboleth/oidc/profile/impl/AuthenticationRequestMessageEncoderFactoryTest.java
new file mode 100644
index 0000000..76485ac
--- /dev/null
+++ b/oidc-common-profile-impl/src/test/java/net/shibboleth/oidc/profile/impl/AuthenticationRequestMessageEncoderFactoryTest.java
@@ -0,0 +1,173 @@
+package net.shibboleth.oidc.profile.impl;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+import org.opensaml.messaging.encoder.MessageEncoder;
+import org.opensaml.messaging.encoder.MessageEncodingException;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
+import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration.OIDCHttpRequestMethod;
+import net.shibboleth.oidc.profile.encoder.OIDCMessageEncoder;
+import net.shibboleth.oidc.profile.encoder.impl.AbstractOIDCMessageEncoder;
+
+/** Test of the AuthenticationRequestMessageEncoderFactory class.*/
+public class AuthenticationRequestMessageEncoderFactoryTest {
+    
+    /** The factory to test.*/
+    private AuthenticationRequestMessageEncoderFactory factory;
+    
+    
+    @Test
+    public void testNoEncoders() {
+        factory = new AuthenticationRequestMessageEncoderFactory(null);
+        final ProfileRequestContext prc = new ProfileRequestContext();
+        final MessageEncoder encoder = factory.apply(prc);
+        //should be null
+        assertNull(encoder);
+    }
+    
+    @Test
+    public void testPostEncoder() {
+        final OIDCMessageEncoder mockPostEncoder = new AbstractOIDCMessageEncoder() {
+            
+            @Override
+            public boolean test(final OIDCHttpRequestMethod method) {
+                if (method == OIDCHttpRequestMethod.POST) {
+                    return true;
+                }
+                return false;
+            }
+            
+            @Override
+            protected void doEncode() throws MessageEncodingException {
+               //no-op                
+            }
+        };
+        factory = new AuthenticationRequestMessageEncoderFactory(List.of(mockPostEncoder));
+        
+        final ProfileRequestContext prc = new ProfileRequestContext();
+        // mock a profile config to request form POST serialization
+        final OIDCAuthorizationConfiguration config = new OIDCAuthorizationConfiguration();
+        config.setHttpRequestMethodLookupStrategy(rc -> OIDCHttpRequestMethod.POST);
+        final RelyingPartyContext rpCtx = prc.getSubcontext(RelyingPartyContext.class, true);
+        rpCtx.setProfileConfig(config);
+        
+        final MessageEncoder encoder = factory.apply(prc);
+        assertNotNull(encoder);
+        assertTrue(encoder == mockPostEncoder);
+    }
+    
+    @Test
+    public void testGetEncoder() {
+        final OIDCMessageEncoder mockGetEncoder = new AbstractOIDCMessageEncoder() {
+            
+            @Override
+            public boolean test(final OIDCHttpRequestMethod method) {
+                if (method == OIDCHttpRequestMethod.GET) {
+                    return true;
+                }
+                return false;
+            }
+            
+            @Override
+            protected void doEncode() throws MessageEncodingException {
+               //no-op                
+            }
+        };
+        factory = new AuthenticationRequestMessageEncoderFactory(List.of(mockGetEncoder));
+        
+        final ProfileRequestContext prc = new ProfileRequestContext();
+        // mock a profile config to request form POST serialization
+        final OIDCAuthorizationConfiguration config = new OIDCAuthorizationConfiguration();
+        config.setHttpRequestMethodLookupStrategy(rc -> OIDCHttpRequestMethod.GET);
+        final RelyingPartyContext rpCtx = prc.getSubcontext(RelyingPartyContext.class, true);
+        rpCtx.setProfileConfig(config);
+        
+        final MessageEncoder encoder = factory.apply(prc);
+        assertNotNull(encoder);
+        assertTrue(encoder == mockGetEncoder);
+    }
+    
+    /* Ask for POST, but only GET type registered.*/
+    @Test
+    public void testNoAvailableEncoder() {
+        final OIDCMessageEncoder mockGetEncoder = new AbstractOIDCMessageEncoder() {
+            
+            @Override
+            public boolean test(final OIDCHttpRequestMethod method) {
+                if (method == OIDCHttpRequestMethod.GET) {
+                    return true;
+                }
+                return false;
+            }
+            
+            @Override
+            protected void doEncode() throws MessageEncodingException {
+               //no-op                
+            }
+        };
+        factory = new AuthenticationRequestMessageEncoderFactory(List.of(mockGetEncoder));
+        
+        final ProfileRequestContext prc = new ProfileRequestContext();
+        // mock a profile config to request form POST serialization
+        final OIDCAuthorizationConfiguration config = new OIDCAuthorizationConfiguration();
+        config.setHttpRequestMethodLookupStrategy(rc -> OIDCHttpRequestMethod.POST);
+        final RelyingPartyContext rpCtx = prc.getSubcontext(RelyingPartyContext.class, true);
+        rpCtx.setProfileConfig(config);
+        
+        final MessageEncoder encoder = factory.apply(prc);
+        //should be null
+        assertNull(encoder);
+
+    }
+    
+    @Test
+    public void testNullRequestMethod() {
+        factory = new AuthenticationRequestMessageEncoderFactory(null);
+        
+        final ProfileRequestContext prc = new ProfileRequestContext();
+        // mock a profile config to request form POST serialization
+        final OIDCAuthorizationConfiguration config = new OIDCAuthorizationConfiguration();
+        config.setHttpRequestMethodLookupStrategy(rc -> null);
+        final RelyingPartyContext rpCtx = prc.getSubcontext(RelyingPartyContext.class, true);
+        rpCtx.setProfileConfig(config);
+        
+        final MessageEncoder encoder = factory.apply(prc);
+        //should be null
+        assertNull(encoder);
+
+    }
+    
+    @Test
+    public void testNullProfileConfiguration() {
+        factory = new AuthenticationRequestMessageEncoderFactory(null);
+        
+        final ProfileRequestContext prc = new ProfileRequestContext();     
+        final RelyingPartyContext rpCtx = prc.getSubcontext(RelyingPartyContext.class, true);
+        rpCtx.setProfileConfig(null);
+        
+        final MessageEncoder encoder = factory.apply(prc);
+        //should be null
+        assertNull(encoder);
+
+    }
+    
+    @Test
+    public void testNullRelyingPartyContext() {
+        factory = new AuthenticationRequestMessageEncoderFactory(null);
+        
+        final ProfileRequestContext prc = new ProfileRequestContext();             
+        final MessageEncoder encoder = factory.apply(prc);
+        //should be null
+        assertNull(encoder);
+
+    }
+
+}

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


More information about the commits mailing list