[java-idp-oidc] branch main updated: JOIDC-172 - Generic condition bean for matching metadata values
Henri Mikkonen
henri.mikkonen at iki.fi
Tue Sep 5 16:35:27 UTC 2023
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=785f66f761ada03f7bd235c3fffba8fe3a59ebeb
The following commit(s) were added to refs/heads/main by this push:
new 785f66f7 JOIDC-172 - Generic condition bean for matching metadata values
785f66f7 is described below
commit 785f66f761ada03f7bd235c3fffba8fe3a59ebeb
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Tue Sep 5 19:33:25 2023 +0300
JOIDC-172 - Generic condition bean for matching metadata values
https://shibboleth.atlassian.net/browse/JOIDC-172
A new bean "shibboleth.oidc.Conditions.MetadataValueEquals" can be used for matching values from metadata.
For instance the following configuration returns true if application_type in metadata has value "native":
<bean parent="OIDC.SSO.MDDriven">
<property name="forcePKCEPredicate">
<bean parent="shibboleth.oidc.Conditions.MetadataValueEquals" p:key="application_type" p:value="native" />
</property>
</bean>
---
.../logic/MetadataValueEqualsCondition.java | 122 +++++++++++++++++++++
.../META-INF/net.shibboleth.idp/postconfig.xml | 3 +
.../logic/MetadataValueEqualsConditionTest.java | 87 +++++++++++++++
3 files changed, 212 insertions(+)
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/MetadataValueEqualsCondition.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/MetadataValueEqualsCondition.java
new file mode 100644
index 00000000..9be09626
--- /dev/null
+++ b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/MetadataValueEqualsCondition.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed 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.oidc.op.profile.logic;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.idp.plugin.oidc.op.profile.context.navigate.DefaultOIDCMetadataContextLookupFunction;
+import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.StringSupport;
+
+/**
+ * A predicate for matching if the OIDC metadata value with a configurable key is equal to a configurable value.
+ */
+public class MetadataValueEqualsCondition extends AbstractIdentifiableInitializableComponent
+ implements Predicate<ProfileRequestContext> {
+
+ /** The lookup strategy for OIDCMetadataContext. */
+ @Nonnull private Function<ProfileRequestContext, OIDCMetadataContext> oidcMetadataContextLookupStrategy;
+
+ /** The metadata key whose value is used for matching. */
+ @NonnullAfterInit private String metadataKey;
+
+ /** The metadata value to be matched. */
+ @NonnullAfterInit private Object metadataValue;
+
+ /** The value used for matching if metadata value was null. */
+ @Nullable private Object defaultValue;
+
+ /**
+ * Constructor.
+ */
+ public MetadataValueEqualsCondition() {
+ oidcMetadataContextLookupStrategy = new DefaultOIDCMetadataContextLookupFunction();
+ }
+
+ /**
+ * Set the lookup strategy for OIDCMetadataContext.
+ *
+ * @param strategy What to set.
+ */
+ public void setOidcMetadataContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext, OIDCMetadataContext> strategy) {
+ checkSetterPreconditions();
+ oidcMetadataContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+ }
+
+ /**
+ * Set the metadata key whose value is used for matching.
+ *
+ * @param function What to set.
+ */
+ public void setKey(@Nonnull final String key) {
+ checkSetterPreconditions();
+ metadataKey = Constraint.isNotEmpty(key, "Key value cannot be empty");
+ }
+
+ /**
+ * Set the metadata value to be matched.
+ *
+ * @param function What to set.
+ */
+ public void setValue(@Nonnull final Object value) {
+ checkSetterPreconditions();
+ metadataValue = Constraint.isNotNull(value, "Value cannot be empty");
+ }
+
+ /**
+ * Set the value used for matching if metadata value was null.
+ *
+ * @param value What to set.
+ */
+ public void setDefaultValue(@Nullable final Object value) {
+ checkSetterPreconditions();
+ defaultValue = value;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (StringSupport.trimOrNull(metadataKey) == null) {
+ throw new ComponentInitializationException("Key value cannot be empty");
+ }
+ if (metadataValue == null) {
+ throw new ComponentInitializationException("Value cannot be empty");
+ }
+ }
+
+ @Override
+ public boolean test(@Nullable final ProfileRequestContext input) {
+ final OIDCMetadataContext oidcMetadataCtx = oidcMetadataContextLookupStrategy.apply(input);
+ if (oidcMetadataCtx == null || oidcMetadataCtx.getClientInformation() == null) {
+ return false;
+ }
+ final Object value = oidcMetadataCtx.getClientInformation().getOIDCMetadata().toJSONObject().get(metadataKey);
+ return metadataValue.equals(value != null ? value : defaultValue);
+ }
+
+}
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index ff84ee14..5bbf1a48 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -738,4 +738,7 @@
<!-- PRC given to the apply-method can be null as the default function doesn't exploit that -->
</bean>
+ <bean id="shibboleth.oidc.Conditions.MetadataValueEquals"
+ class="net.shibboleth.idp.plugin.oidc.op.profile.logic.MetadataValueEqualsCondition" abstract="true" />
+
</beans>
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/MetadataValueEqualsConditionTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/MetadataValueEqualsConditionTest.java
new file mode 100644
index 00000000..59fde8c1
--- /dev/null
+++ b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/logic/MetadataValueEqualsConditionTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed 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.oidc.op.profile.logic;
+
+import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
+import net.shibboleth.shared.component.ComponentInitializationException;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.nimbusds.oauth2.sdk.id.ClientID;
+import com.nimbusds.openid.connect.sdk.rp.ApplicationType;
+import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
+import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
+
+/** {@link MetadataValueEqualsCondition} unit test. */
+public class MetadataValueEqualsConditionTest {
+
+ MetadataValueEqualsCondition predicate;
+
+ public void setup(final OIDCClientMetadata metadata, final String key, final Object value, final Object defValue)
+ throws ComponentInitializationException {
+ predicate = new MetadataValueEqualsCondition();
+ predicate.setKey(key);
+ predicate.setValue(value);
+ predicate.setDefaultValue(defValue);
+ final OIDCMetadataContext oidcMetadataCtx = new OIDCMetadataContext();
+ final OIDCClientInformation clientInformation = new OIDCClientInformation(new ClientID("mockId"), metadata);
+ oidcMetadataCtx.setClientInformation(clientInformation);
+ predicate.setOidcMetadataContextLookupStrategy(prc -> oidcMetadataCtx);
+ predicate.setId("mockId");
+ predicate.initialize();
+ }
+
+ @Test
+ public void testApplicationTypeMatch() throws ComponentInitializationException {
+ final OIDCClientMetadata metadata = new OIDCClientMetadata();
+ metadata.setApplicationType(ApplicationType.NATIVE);
+ setup(metadata, "application_type", "native", null);
+ Assert.assertTrue(predicate.test(new ProfileRequestContext()));
+ }
+
+ @Test
+ public void testApplicationTypeNoMatch() throws ComponentInitializationException {
+ final OIDCClientMetadata metadata = new OIDCClientMetadata();
+ metadata.setApplicationType(ApplicationType.WEB);
+ setup(metadata, "application_type", "native", null);
+ Assert.assertFalse(predicate.test(new ProfileRequestContext()));
+ }
+
+ @Test
+ public void testClientNameMatch() throws ComponentInitializationException {
+ final OIDCClientMetadata metadata = new OIDCClientMetadata();
+ metadata.setName("TestApp");
+ setup(metadata, "client_name", "TestApp", null);
+ Assert.assertTrue(predicate.test(new ProfileRequestContext()));
+ }
+
+ @Test
+ public void testClientNameNoMatch() throws ComponentInitializationException {
+ final OIDCClientMetadata metadata = new OIDCClientMetadata();
+ metadata.setName("TestApp");
+ setup(metadata, "client_name", "NotMatching", null);
+ Assert.assertFalse(predicate.test(new ProfileRequestContext()));
+ }
+
+ @Test
+ public void testClientNameDefaultMatch() throws ComponentInitializationException {
+ final OIDCClientMetadata metadata = new OIDCClientMetadata();
+ setup(metadata, "client_name", "DefaultApp", "DefaultApp");
+ Assert.assertTrue(predicate.test(new ProfileRequestContext()));
+ }
+
+}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list