[java-idp-oidc] 03/06: JOIDC-5 Initial version of a secret resolver based on Attribute Resolver.
Henri Mikkonen
henri.mikkonen at iki.fi
Fri Jun 26 13:31:02 UTC 2020
This is an automated email from the git hooks/post-receive script.
hjmikkon pushed a commit to branch dev/JOIDC-5
in repository java-idp-oidc.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-oidc.git;a=commit;h=a9ad6620575d038bc1cef59c7d2e24299bd2c3b7
commit a9ad6620575d038bc1cef59c7d2e24299bd2c3b7
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Jun 26 12:40:31 2020 +0300
JOIDC-5 Initial version of a secret resolver based on Attribute Resolver.
https://issues.shibboleth.net/jira/browse/JOIDC-5
A new AttributeResolutionContext is constructed, and its populated with
the client secret reference as principal and the related entity ID (RP
client_id) as attribute recipient ID.
---
.../ResolverServiceClientSecretValueResolver.java | 160 ++++++++++++
...solverServiceClientSecretValueResolverTest.java | 283 +++++++++++++++++++++
.../idpextension/oidc/metadata/impl/RdbmsData.sql | 7 +
.../idpextension/oidc/metadata/impl/RdbmsStore.sql | 5 +
.../impl/attribute-resolver-clientsecrets.xml | 53 ++++
.../oidc/metadata/impl/ldapDataConnectorTest.ldif | 26 ++
.../idpextension/oidc/metadata/impl/service.xml | 47 ++++
7 files changed, 581 insertions(+)
diff --git a/idp-oidc-extension-impl/src/main/java/org/geant/idpextension/oidc/metadata/impl/ResolverServiceClientSecretValueResolver.java b/idp-oidc-extension-impl/src/main/java/org/geant/idpextension/oidc/metadata/impl/ResolverServiceClientSecretValueResolver.java
new file mode 100644
index 00000000..fc136434
--- /dev/null
+++ b/idp-oidc-extension-impl/src/main/java/org/geant/idpextension/oidc/metadata/impl/ResolverServiceClientSecretValueResolver.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2017 - 2020, GÉANT
+ *
+ * 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 org.geant.idpextension.oidc.metadata.impl;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.geant.idpextension.oidc.criterion.ClientSecretReferenceCriterion;
+import org.opensaml.core.criterion.EntityIdCriterion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.resolver.AttributeResolver;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.collection.LazySet;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+import net.shibboleth.utilities.java.support.service.ReloadableService;
+
+/**
+ * A client secret value resolver that fetches the values from the given {@link AttributeResolver} service.
+ *
+ * This class builds a new {@link AttributeResolutionContext} and sets the client secret reference key value to
+ * {@link AttributeResolutionContext#setPrincipal(String)} and its related entity ID to
+ * {@link AttributeResolutionContext#setAttributeRecipientID(String)}. The resolution context does not have any
+ * parent contexts.
+ */
+public class ResolverServiceClientSecretValueResolver extends AbstractClientSecretValueResolver {
+
+ /** Class logger. */
+ private final Logger log = LoggerFactory.getLogger(ResolverServiceClientSecretValueResolver.class);
+
+ /** The attribute resolver service used for the client secret value resolution. */
+ @NonnullAfterInit private ReloadableService<AttributeResolver> service;
+
+ /** The list of attribute IDs that may contain the resolved client secret values. */
+ @Nonnull private List<String> attributeIds;
+
+ /**
+ * Constructor.
+ */
+ public ResolverServiceClientSecretValueResolver() {
+ attributeIds = Collections.emptyList();
+ }
+
+ /**
+ * Set the attribute resolver service used for the client secret value resolution.
+ *
+ * @param resolver The attribute resolver service used for the client secret value resolution.
+ */
+ public void setAttributeResolver(@Nonnull final ReloadableService<AttributeResolver> resolver) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ service = Constraint.isNotNull(resolver, "Attribute resolver service can not be null");
+ }
+
+ /**
+ * Get the attribute resolver service used for the client secret value resolution.
+ *
+ * @return The attribute resolver service used for the client secret value resolution.
+ */
+ public @NonnullAfterInit ReloadableService<AttributeResolver> getAttributeResolver() {
+ return service;
+ }
+
+ /**
+ * Set the list of attribute IDs that may contain the resolved client secret values.
+ *
+ * @param ids The list of attribute IDs that may contain the resolved client secret values.
+ */
+ public void setAttributeIds(@Nonnull final List<String> ids) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ attributeIds = (List<String>) Constraint.isNotEmpty(ids, "The list of attribute ids cannot be empty");
+ }
+
+ /**
+ * Get the list of attribute IDs that may contain the resolved client secret values.
+ *
+ * @return The list of attribute IDs that may contain the resolved client secret values.
+ */
+ public @Nonnull List<String> getAttributeIds() {
+ return attributeIds;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public @Nonnull Iterable<String> resolve(@Nonnull final CriteriaSet criteria) throws ResolverException {
+ ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ final ClientSecretReferenceCriterion referenceCriterion = criteria.get(ClientSecretReferenceCriterion.class);
+ Constraint.isNotNull(referenceCriterion,
+ "The client secret reference criterion must be included in the criteria.");
+
+ final AttributeResolutionContext resolutionContext = new AttributeResolutionContext();
+ resolutionContext.setPrincipal(referenceCriterion.getSecretReference());
+ if (criteria.contains(EntityIdCriterion.class)) {
+ resolutionContext.setAttributeRecipientID(criteria.get(EntityIdCriterion.class).getEntityId());
+ }
+ resolutionContext.resolveAttributes(service);
+ final Map<String, IdPAttribute> resolvedAttributes = resolutionContext.getResolvedIdPAttributes();
+ final LazySet<String> result = new LazySet<>();
+ for (final String attributeId : attributeIds) {
+ if (resolvedAttributes.containsKey(attributeId)) {
+ log.debug("Found a value for reference '{}' via attribute ID {}",
+ referenceCriterion.getSecretReference(), attributeId);
+ result.add((String) resolvedAttributes.get(attributeId).getValues().get(0).getNativeValue());
+ }
+ }
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public @Nullable String resolveSingle(@Nonnull final CriteriaSet criteria) throws ResolverException {
+ final Iterator<String> iterator = resolve(criteria).iterator();
+ return iterator.hasNext() ? iterator.next() : null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doDestroy() {
+ service = null;
+ attributeIds = null;
+ super.doDestroy();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (getAttributeResolver() == null) {
+ throw new ComponentInitializationException("Attribute resolver service can not be null");
+ }
+ }
+}
diff --git a/idp-oidc-extension-impl/src/test/java/org/geant/idpextension/oidc/metadata/impl/ResolverServiceClientSecretValueResolverTest.java b/idp-oidc-extension-impl/src/test/java/org/geant/idpextension/oidc/metadata/impl/ResolverServiceClientSecretValueResolverTest.java
new file mode 100644
index 00000000..1bc18e78
--- /dev/null
+++ b/idp-oidc-extension-impl/src/test/java/org/geant/idpextension/oidc/metadata/impl/ResolverServiceClientSecretValueResolverTest.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2017 - 2020, GÉANT
+ *
+ * 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 org.geant.idpextension.oidc.metadata.impl;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.opensaml.core.criterion.EntityIdCriterion;
+import org.springframework.context.support.ConversionServiceFactoryBean;
+import org.springframework.context.support.GenericApplicationContext;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.unboundid.ldap.listener.InMemoryDirectoryServer;
+import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
+import com.unboundid.ldap.listener.InMemoryListenerConfig;
+import com.unboundid.ldap.sdk.LDAPException;
+
+import net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor;
+import net.shibboleth.ext.spring.config.StringToDurationConverter;
+import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
+import net.shibboleth.idp.attribute.resolver.AttributeResolver;
+import net.shibboleth.idp.testing.DatabaseTestingSupport;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.UnmodifiableComponentException;
+import net.shibboleth.utilities.java.support.logic.ConstraintViolationException;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+import net.shibboleth.utilities.java.support.service.ReloadableService;
+
+/**
+ * Unit tests for {@link ResolverServiceClientSecretValueResolver}.
+ *
+ * Based on <pre>idp-attribute-resolver-spring</pre> /
+ * <pre>net.shibboleth.idp.attribute.resolver.spring.AttributeResolverTest</pre>.
+ */
+public class ResolverServiceClientSecretValueResolverTest
+ extends BaseClientSecretValueResolverTest<ResolverServiceClientSecretValueResolver> {
+
+ /** LDAP */
+ private InMemoryDirectoryServer directoryServer;
+
+ /** LDAP initialization. */
+ private static final String LDAP_INIT_FILE =
+ "src/test/resources/org/geant/idpextension/oidc/metadata/impl/ldapDataConnectorTest.ldif";
+
+ /** Database initialization. */
+ private static final String DB_INIT_FILE = "/org/geant/idpextension/oidc/metadata/impl/RdbmsStore.sql";
+
+ /** Database population. */
+ private static final String DB_DATA_FILE = "/org/geant/idpextension/oidc/metadata/impl/RdbmsData.sql";
+
+ /** The resolver service configuration. */
+ private static final String SERVICE_CONF_FILE = "/org/geant/idpextension/oidc/metadata/impl/service.xml";
+
+ private GenericApplicationContext pendingTeardownContext = null;
+
+ String entityId = "CLIENT_ID_ONE";
+ String entityId2 = "CLIENT_ID_TWO";
+
+ String clientSecretKeyReferenceBoth = "keyReferenceOne";
+ String clientSecretKeyReferenceOnlyLdap = "keyReferenceTwo";
+
+ String clientSecretValueRdbms = "thePlainTextSecretValue1234567890";
+ String clientSecretValueLdap = "thePlainTextSecretValue9876543210";
+
+
+ @AfterMethod public void tearDownTestContext() {
+ if (null == pendingTeardownContext ) {
+ return;
+ }
+ pendingTeardownContext.close();
+ pendingTeardownContext = null;
+ }
+
+ protected void setTestContext(final GenericApplicationContext context) {
+ tearDownTestContext();
+ pendingTeardownContext = context;
+ }
+
+ @BeforeTest public void setupDataConnectors() throws LDAPException {
+
+ System.setProperty("org.ldaptive.provider", "org.ldaptive.provider.unboundid.UnboundIDProvider");
+
+ // LDAP
+ final InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=shibboleth,dc=net");
+ config.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("default", 10391));
+ config.addAdditionalBindCredentials("cn=Directory Manager", "password");
+ directoryServer = new InMemoryDirectoryServer(config);
+ directoryServer.importFromLDIF(true, LDAP_INIT_FILE);
+ directoryServer.startListening();
+
+ // RDBMS
+ final DataSource datasource = DatabaseTestingSupport.GetMockDataSource(DB_INIT_FILE, "myTestDB");
+ DatabaseTestingSupport.InitializeDataSourceFromFile(DB_DATA_FILE, datasource);
+
+ }
+
+ /**
+ * Shutdown the in-memory directory server.
+ */
+ @AfterTest public void teardownDataConnectors() {
+ directoryServer.shutDown(true);
+
+ System.clearProperty("org.ldaptive.provider");
+ }
+
+ protected ReloadableService<AttributeResolver> getResolver() {
+ final GenericApplicationContext context = new GenericApplicationContext();
+ context.getBeanFactory().addBeanPostProcessor(new IdentifiableBeanPostProcessor());
+ setTestContext(context);
+ context.setDisplayName("ApplicationContext: " + ResolverServiceClientSecretValueResolverTest.class);
+
+ final ConversionServiceFactoryBean service = new ConversionServiceFactoryBean();
+ context.setDisplayName("ApplicationContext: ");
+ service.setConverters(new HashSet<>(Arrays.asList(new StringToDurationConverter())));
+ service.afterPropertiesSet();
+
+ context.getBeanFactory().setConversionService(service.getObject());
+
+ final SchemaTypeAwareXMLBeanDefinitionReader beanDefinitionReader =
+ new SchemaTypeAwareXMLBeanDefinitionReader(context);
+
+ beanDefinitionReader.loadBeanDefinitions(SERVICE_CONF_FILE);
+ context.refresh();
+
+ return context.getBean(ReloadableService.class);
+ }
+
+ @Test(expectedExceptions = ComponentInitializationException.class)
+ public void initialize_shouldThrowWhenAttributeResolverNotSet() throws ComponentInitializationException {
+ resolver = new ResolverServiceClientSecretValueResolver();
+ resolver.setId("mockId");
+ resolver.initialize();
+ }
+
+ @Test(expectedExceptions = ConstraintViolationException.class)
+ public void setAttributeResolver_shouldThrowIfAttributeResolverIsNull() {
+ resolver = new ResolverServiceClientSecretValueResolver();
+ resolver.setAttributeResolver(null);
+ }
+
+ @Test(expectedExceptions = UnmodifiableComponentException.class)
+ public void setAttributeResolver_shouldThrowAfterInit() throws ComponentInitializationException {
+ resolver = buildResolver(true);
+ resolver.setAttributeResolver(getResolver());
+ }
+
+ @Test(expectedExceptions = ConstraintViolationException.class)
+ public void setAttributeIds_shouldThrowIfAttributeIdsNull() throws ComponentInitializationException {
+ resolver = new ResolverServiceClientSecretValueResolver();
+ resolver.setAttributeIds(null);
+ }
+
+ @Test(expectedExceptions = ConstraintViolationException.class)
+ public void setAttributeIds_shouldThrowIfAttributeIdsEmpty() throws ComponentInitializationException {
+ resolver = new ResolverServiceClientSecretValueResolver();
+ resolver.setAttributeIds(Collections.emptyList());
+ }
+
+ @Test(expectedExceptions = UnmodifiableComponentException.class)
+ public void setAttributeIds_shouldThrowAfterInit() throws ComponentInitializationException {
+ resolver = buildResolver(true);
+ resolver.setAttributeIds(Arrays.asList("myDBClientSecret", "myLDAPClientSecret"));
+ }
+
+ @Test
+ public void resolveSingle_shouldReturnNullWhenValuesNotFound() throws ResolverException,
+ ComponentInitializationException {
+ resolver = buildResolver(true);
+ Assert.assertNull(resolver.resolveSingle(buildCriteriaSet("not_found")));
+ }
+
+ @Test
+ public void resolveSingle_shouldReturnRdbmsValueWhenFound() throws ResolverException,
+ ComponentInitializationException {
+ resolver = buildResolver(true, Arrays.asList("myDBClientSecret"));
+ Assert.assertEquals(resolver.resolveSingle(buildCriteriaSet(clientSecretKeyReferenceBoth, entityId)),
+ clientSecretValueRdbms);
+ }
+
+ @Test
+ public void resolveSingle_shouldReturnLdapValueWhenFound() throws ResolverException,
+ ComponentInitializationException {
+ resolver = buildResolver(true, Arrays.asList("myLDAPClientSecret"));
+ Assert.assertEquals(resolver.resolveSingle(buildCriteriaSet(clientSecretKeyReferenceBoth, entityId)),
+ clientSecretValueLdap);
+ }
+
+ @Test
+ public void resolveSingle_shouldReturnLdapValueWhenOnlyFoundFromLdap() throws ResolverException,
+ ComponentInitializationException {
+ resolver = buildResolver(true, Arrays.asList("myDBClientSecret", "myLDAPClientSecret"));
+ Assert.assertEquals(resolver.resolveSingle(buildCriteriaSet(clientSecretKeyReferenceOnlyLdap, entityId2)),
+ "thePlainTextSecretValue1111111111");
+ }
+
+ @Test
+ public void resolve_shouldReturnEmptyIteratorWhenValuesNotFound() throws ResolverException,
+ ComponentInitializationException {
+ resolver = buildResolver(true);
+ final Iterable<String> iterable = resolver.resolve(buildCriteriaSet("not_found"));
+ Assert.assertNotNull(iterable);
+ Assert.assertFalse(iterable.iterator().hasNext());
+ }
+
+ @Test
+ public void resolve_shouldReturnOneValueIteratorWhenSingleValueFound() throws ResolverException,
+ ComponentInitializationException {
+ resolver = buildResolver(true);
+ final Iterable<String> iterable
+ = resolver.resolve(buildCriteriaSet(clientSecretKeyReferenceOnlyLdap, entityId2));
+ Assert.assertNotNull(iterable);
+ final Iterator<String> iterator = iterable.iterator();
+ Assert.assertTrue(iterator.hasNext());
+ Assert.assertEquals(iterator.next(), "thePlainTextSecretValue1111111111");
+ Assert.assertFalse(iterator.hasNext());
+ }
+
+ @Test
+ public void resolve_shouldReturnTwoValueIteratorWhenFoundFromBoth() throws ResolverException,
+ ComponentInitializationException {
+ resolver = buildResolver(true);
+ final Iterable<String> iterable = resolver.resolve(buildCriteriaSet(clientSecretKeyReferenceBoth, entityId));
+ Assert.assertNotNull(iterable);
+ final Iterator<String> iterator = iterable.iterator();
+ Assert.assertTrue(iterator.hasNext());
+ final String firstValue = iterator.next();
+ Assert.assertTrue(firstValue.equals(clientSecretValueLdap) || firstValue.equals(clientSecretValueRdbms));
+ Assert.assertTrue(iterator.hasNext());
+ final String secondValue = iterator.next();
+ Assert.assertFalse(firstValue.equals(secondValue));
+ Assert.assertTrue(secondValue.equals(clientSecretValueLdap) || secondValue.equals(clientSecretValueRdbms));
+ Assert.assertFalse(iterator.hasNext());
+ }
+
+ @Override
+ protected ResolverServiceClientSecretValueResolver buildResolver(boolean init)
+ throws ComponentInitializationException {
+ return buildResolver(init, Arrays.asList("myDBClientSecret", "myLDAPClientSecret"));
+ }
+
+ protected ResolverServiceClientSecretValueResolver buildResolver(boolean init, List<String> attributeIds)
+ throws ComponentInitializationException {
+ ResolverServiceClientSecretValueResolver resolver = new ResolverServiceClientSecretValueResolver();
+ resolver.setAttributeResolver(getResolver());
+ resolver.setAttributeIds(attributeIds);
+ resolver.setId("resolver");
+ if (init) {
+ resolver.initialize();
+ }
+ return resolver;
+ }
+
+ protected CriteriaSet buildCriteriaSet(final String secretReference, final String clientId) {
+ final CriteriaSet criteria = super.buildCriteriaSet(secretReference);
+ criteria.add(new EntityIdCriterion(clientId));
+ return criteria;
+ }
+
+}
diff --git a/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/RdbmsData.sql b/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/RdbmsData.sql
new file mode 100644
index 00000000..483921be
--- /dev/null
+++ b/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/RdbmsData.sql
@@ -0,0 +1,7 @@
+INSERT INTO clientSecrets
+ (entityId, clientSecretKeyReference, clientSecretValue)
+ values (
+ 'CLIENT_ID_ONE',
+ 'keyReferenceOne',
+ 'thePlainTextSecretValue1234567890');
+
diff --git a/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/RdbmsStore.sql b/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/RdbmsStore.sql
new file mode 100644
index 00000000..b4980e4b
--- /dev/null
+++ b/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/RdbmsStore.sql
@@ -0,0 +1,5 @@
+CREATE TABLE clientSecrets (
+ entityId VARCHAR(250) NOT NULL,
+ clientSecretKeyReference VARCHAR(250) NOT NULL,
+ clientSecretValue VARCHAR(250) NOT NULL);
+
diff --git a/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/attribute-resolver-clientsecrets.xml b/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/attribute-resolver-clientsecrets.xml
new file mode 100644
index 00000000..69e60d11
--- /dev/null
+++ b/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/attribute-resolver-clientsecrets.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttributeResolver xmlns="urn:mace:shibboleth:2.0:resolver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+ <!-- ========================================== -->
+ <!-- Attribute Definitions -->
+ <!-- ========================================== -->
+
+ <AttributeDefinition xsi:type="Simple" id="myLDAPClientSecret">
+ <InputDataConnector ref="myLDAP" attributeNames="mobile"/>
+ </AttributeDefinition>
+
+
+ <AttributeDefinition xsi:type="Simple" id="myDBClientSecret">
+ <InputDataConnector ref="myDB" attributeNames="CLIENTSECRETVALUE"/>
+ </AttributeDefinition>
+
+ <!-- ========================================== -->
+ <!-- Data Connectors -->
+ <!-- ========================================== -->
+
+ <!-- Example Relational Database Connector -->
+
+ <DataConnector id="myDB" xsi:type="RelationalDatabase">
+ <SimpleManagedConnection
+ jdbcDriver="org.hsqldb.jdbc.JDBCDriver"
+ jdbcURL="jdbc:hsqldb:mem:myTestDB"
+ jdbcUserName="SA"
+ jdbcPassword="" />
+ <QueryTemplate>
+ <![CDATA[
+ SELECT * FROM clientSecrets WHERE clientSecretKeyReference = '$resolutionContext.principal' AND entityId = '$resolutionContext.attributeRecipientID'
+ ]]>
+ </QueryTemplate>
+ </DataConnector>
+
+
+ <!-- Example LDAP Connector -->
+ <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
+ ldapURL="ldap://localhost:10391"
+ baseDN="dc=shibboleth,dc=net"
+ connectTimeout="PT6S"
+ responseTimeout="PT6S"
+ principal="cn=Directory Manager"
+ principalCredential="password">
+ <FilterTemplate>
+ <![CDATA[
+ (uid=$resolutionContext.principal)
+ ]]>
+ </FilterTemplate>
+ </DataConnector>
+
+</AttributeResolver>
diff --git a/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/ldapDataConnectorTest.ldif b/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/ldapDataConnectorTest.ldif
new file mode 100644
index 00000000..30e88e48
--- /dev/null
+++ b/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/ldapDataConnectorTest.ldif
@@ -0,0 +1,26 @@
+dn: dc=shibboleth,dc=net
+dc: shibboleth
+objectClass: dcObject
+objectClass: organization
+o: Shibboleth, Inc.
+
+dn: ou=clientsecrets,dc=shibboleth,dc=net
+ou: clientsecrets
+description: Client secrets
+objectclass: organizationalunit
+
+dn: cn=CLIENT_ID_ONE,ou=clientsecrets,dc=shibboleth,dc=net
+objectclass: inetOrgPerson
+cn: CLIENT_ID_ONE
+sn: Ignored
+uid: keyReferenceOne
+mobile: thePlainTextSecretValue9876543210
+description: test principal
+
+dn: cn=CLIENT_ID_TWO,ou=clientsecrets,dc=shibboleth,dc=net
+objectclass: inetOrgPerson
+cn: CLIENT_ID_TWO
+sn: Ignored
+uid: keyReferenceTwo
+mobile: thePlainTextSecretValue1111111111
+description: test principal
diff --git a/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/service.xml b/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/service.xml
new file mode 100644
index 00000000..34d6966b
--- /dev/null
+++ b/idp-oidc-extension-impl/src/test/resources/org/geant/idpextension/oidc/metadata/impl/service.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:c="http://www.springframework.org/schema/c"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+ default-init-method="initialize"
+ default-destroy-method="destroy">
+
+ <!-- This BeanPostProcessor auto-sets identifiable beans with the bean name (if not already set). -->
+ <bean id="shibboleth.IdentifiableBeanPostProcessor"
+ class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
+
+ <bean id="shibboleth.VelocityEngine" class="net.shibboleth.ext.spring.velocity.VelocityEngineFactoryBean">
+ <property name="velocityProperties">
+ <props>
+ <prop key="resource.loader">classpath, string</prop>
+ <prop key="classpath.resource.loader.class">
+ org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
+ </prop>
+ <prop key="string.resource.loader.class">
+ org.apache.velocity.runtime.resource.loader.StringResourceLoader
+ </prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean id="shibboleth.ClientSecretValueResolverService" class="net.shibboleth.ext.spring.service.ReloadableSpringService"
+ depends-on="shibboleth.VelocityEngine"
+ p:beanPostProcessors-ref="shibboleth.IdentifiableBeanPostProcessor"
+ p:failFast="false" p:reloadCheckDelay="0">
+
+ <constructor-arg name="claz"
+ value="net.shibboleth.idp.attribute.resolver.AttributeResolver" />
+ <constructor-arg name="strategy">
+ <bean
+ class="net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverServiceStrategy"
+ p:id="Shibboleth.Resolver" />
+ </constructor-arg>
+ <property name="serviceConfigurations">
+ <util:list>
+ <value>org/geant/idpextension/oidc/metadata/impl/attribute-resolver-clientsecrets.xml</value>
+ </util:list>
+ </property>
+ </bean>
+</beans>
\ 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