[java-idp-plugin-oidc-rp] branch main updated: Add tests, fix tests, and add inbuilt C14N flow

Phil Smart philip.smart at jisc.ac.uk
Wed Sep 14 15:25:20 UTC 2022


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=0325a2654de9d3d83a190edae4e0a30af716f336

The following commit(s) were added to refs/heads/main by this push:
     new 0325a26  Add tests, fix tests, and add inbuilt C14N flow
0325a26 is described below

commit 0325a2654de9d3d83a190edae4e0a30af716f336
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Wed Sep 14 16:25:13 2022 +0100

    Add tests, fix tests, and add inbuilt C14N flow
    
    Various other cleanups
---
 ...tObjectSupportedSignatureSigningAlgorithms.java |   3 +-
 .../principal/OIDCSubjectIdentifierPrincipal.java  |  90 ++++
 idp-oidc-rp-impl/pom.xml                           |  13 +
 ...impleOIDCSubjectIdentifierCanonicalization.java | 161 +++++++
 .../oidc/rp/impl/ValidateOIDCAuthentication.java   |  20 +-
 .../authn/oidc/rp/messaging/impl/EncryptJWT.java   |  32 +-
 .../META-INF/net.shibboleth.idp/postconfig.xml     |  10 +
 .../oidc-relying-party-authn-beans.xml             |  15 +-
 .../oidc-relying-party-authn-flow.xml              |   2 +-
 .../oidc-subject-identifier-c14n-beans.xml         |  28 ++
 .../oidc-subject-identifier-c14n-flow.xml          |  17 +
 .../idp/service/attribute/registry/postconfig.xml  | 411 ++++++++++++++++++
 .../idp/service/relying-party/postconfig.xml       |   6 +-
 .../authn/providermetadata-resolver-system.xml     |   3 -
 .../authn/oidc/rp/impl/AbstractOIDCTest.java       |  41 +-
 .../authn/oidc/rp/impl/AddRequestedClaimsTest.java |   5 +-
 .../oidc/rp/impl/AddResponseTypeAndModeTest.java   |   3 +-
 .../rp/impl/DefaultClaimMergingStrategyTest.java   |   3 +-
 .../oidc/rp/impl/ExchangeCodeForTokenTest.java     |   4 +-
 .../idp/plugin/authn/oidc/rp/impl/MockMatcher.java | 127 ++++++
 .../authn/oidc/rp/impl/MockReloadableService.java} |  41 +-
 .../oidc/rp/impl/MockSimpleStringTranscoder.java   |  77 ++++
 .../plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java  |  10 +-
 ...ingPartyProxySigningParametersResolverTest.java |   3 +-
 .../rp/impl/ValidateOIDCAuthenticationTest.java    | 168 +++++++
 .../authn/test/spring/MockApplicationContext.java  | 482 +++++++++++++++++++++
 .../attribute/filter/attribute-filter.xml          |   2 +-
 27 files changed, 1713 insertions(+), 64 deletions(-)

diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/RequestObjectSupportedSignatureSigningAlgorithms.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/RequestObjectSupportedSignatureSigningAlgorithms.java
similarity index 93%
copy from idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/RequestObjectSupportedSignatureSigningAlgorithms.java
copy to idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/RequestObjectSupportedSignatureSigningAlgorithms.java
index 533a024..df4675b 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/RequestObjectSupportedSignatureSigningAlgorithms.java
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/context/logic/RequestObjectSupportedSignatureSigningAlgorithms.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.authn.oidc.rp.config;
+package net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic;
 
 import java.util.List;
 import java.util.function.Function;
@@ -29,6 +29,7 @@ import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
 /**
  * Pull out the request object supported signature signing algorithms from the metadata.
  */
+//TODO why is this in this package?
 public class RequestObjectSupportedSignatureSigningAlgorithms implements Function<OIDCProviderMetadata, List<String>>{
 
     @Override
diff --git a/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/principal/OIDCSubjectIdentifierPrincipal.java b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/principal/OIDCSubjectIdentifierPrincipal.java
new file mode 100644
index 0000000..a386341
--- /dev/null
+++ b/idp-oidc-rp-api/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/principal/OIDCSubjectIdentifierPrincipal.java
@@ -0,0 +1,90 @@
+/*
+ * 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.principal;
+
+import javax.annotation.Nonnull;
+
+import com.google.common.base.MoreObjects;
+
+import net.shibboleth.idp.authn.principal.CloneablePrincipal;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/** Principal based on an OIDC 'sub' (subject) identifier.*/
+public class OIDCSubjectIdentifierPrincipal implements CloneablePrincipal {
+    
+    /** The subject. */
+    @Nonnull @NotEmpty private String subject;
+    
+    /**
+     * Constructor.
+     * 
+     * @param sub the subject
+     */
+    public OIDCSubjectIdentifierPrincipal(@Nonnull @NotEmpty @ParameterName(name="name") final String sub) {
+        subject = Constraint.isNotNull(StringSupport.trimOrNull(sub), "Subject cannot be null or empty");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Nonnull @NotEmpty public String getName() {
+        return subject;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int hashCode() {
+        return subject.hashCode();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean equals(final Object other) {
+        if (other == null) {
+            return false;
+        }
+
+        if (this == other) {
+            return true;
+        }
+
+        if (other instanceof OIDCSubjectIdentifierPrincipal) {
+            return subject.equals(((OIDCSubjectIdentifierPrincipal) other).getName());
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this).add("subject", subject).toString();
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    public OIDCSubjectIdentifierPrincipal clone() throws CloneNotSupportedException {
+        final OIDCSubjectIdentifierPrincipal copy = (OIDCSubjectIdentifierPrincipal) super.clone();
+        copy.subject = subject;
+        return copy;
+    }
+    
+
+}
diff --git a/idp-oidc-rp-impl/pom.xml b/idp-oidc-rp-impl/pom.xml
index 2a000be..224b692 100644
--- a/idp-oidc-rp-impl/pom.xml
+++ b/idp-oidc-rp-impl/pom.xml
@@ -158,10 +158,23 @@
             <scope>test</scope>
             <type>test-jar</type>
         </dependency>
+        <!-- Spring webflow tests require Junit4, runs in TestNG bridge -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>com.squareup.okhttp3</groupId>
             <artifactId>mockwebserver</artifactId>
             <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>junit</groupId>
+                    <artifactId>junit</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>com.squareup.okhttp3</groupId>
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/SimpleOIDCSubjectIdentifierCanonicalization.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/SimpleOIDCSubjectIdentifierCanonicalization.java
new file mode 100644
index 0000000..7c951c5
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/SimpleOIDCSubjectIdentifierCanonicalization.java
@@ -0,0 +1,161 @@
+/*
+ * 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.impl;
+
+import java.util.Set;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.action.ActionSupport;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.authn.AbstractSubjectCanonicalizationAction;
+import net.shibboleth.idp.authn.AuthnEventIds;
+import net.shibboleth.idp.authn.SubjectCanonicalizationException;
+import net.shibboleth.idp.authn.context.SubjectCanonicalizationContext;
+import net.shibboleth.idp.plugin.authn.oidc.rp.principal.OIDCSubjectIdentifierPrincipal;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+
+/**
+ * An action that operates on a {@link SubjectCanonicalizationContext} child of the current
+ * {@link ProfileRequestContext}, and transforms the input {@link javax.security.auth.Subject}
+ * into a principal name by searching for one and only one {@link OIDCSubjectIdentifierPrincipal} custom principal.
+ * 
+ * @event {@link org.opensaml.profile.action.EventIds#PROCEED_EVENT_ID}
+ * @event {@link AuthnEventIds#INVALID_SUBJECT}
+ * @pre <pre>ProfileRequestContext.getSubcontext(SubjectCanonicalizationContext.class, false) != null</pre>
+ * @post <pre>SubjectCanonicalizationContext.getPrincipalName() != null
+ *  || SubjectCanonicalizationContext.getException() != null</pre>
+ */
+public class SimpleOIDCSubjectIdentifierCanonicalization extends AbstractSubjectCanonicalizationAction {
+
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(SimpleOIDCSubjectIdentifierCanonicalization.class);
+
+    /** Supplies logic for pre-execute test. */
+    @Nonnull private final ActivationCondition embeddedPredicate;
+    
+    /** The custom Principal to operate on. */
+    @Nullable private OIDCSubjectIdentifierPrincipal subjectIdentifierPrincipal;
+    
+    /** Constructor. */
+    public SimpleOIDCSubjectIdentifierCanonicalization() {
+        embeddedPredicate = new ActivationCondition(false);
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext, 
+            @Nonnull final SubjectCanonicalizationContext c14nContext) {
+
+        if (embeddedPredicate.apply(profileRequestContext, c14nContext, true)) {
+            subjectIdentifierPrincipal = 
+                    c14nContext.getSubject().getPrincipals(OIDCSubjectIdentifierPrincipal.class).iterator().next();
+            return super.doPreExecute(profileRequestContext, c14nContext);
+        }
+        
+        return false;
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext, 
+            @Nonnull final SubjectCanonicalizationContext c14nContext) {
+        
+        c14nContext.setPrincipalName(applyTransforms(subjectIdentifierPrincipal.getName()));
+    }
+     
+    /** A predicate that determines if this action can run or not. */
+    public static class ActivationCondition implements Predicate<ProfileRequestContext> {
+        
+        /** Disable this C14N no matter how appropriate the context?*/
+        private final boolean disabled;
+        
+        /**
+         * 
+         * Constructor.
+         *
+         * @param disable this C14N no matter how appropriate the context
+         */
+        public ActivationCondition(@ParameterName(name="disabled") final boolean disable) {
+            disabled = disable;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public boolean test(@Nullable final ProfileRequestContext input) {
+            if (disabled) {
+                return false;
+            }
+            if (input != null) {
+                final SubjectCanonicalizationContext c14nContext =
+                        input.getSubcontext(SubjectCanonicalizationContext.class, false);
+                if (c14nContext != null) {
+                    return apply(input, c14nContext, false);
+                }
+            }
+            
+            return false;
+        }
+
+        /**
+         * Helper method that runs either as part of the {@link Predicate} or directly from
+         * the {@link SimpleOIDCSubjectIdentifierCanonicalization#doPreExecute(ProfileRequestContext, 
+         * SubjectCanonicalizationContext)} method above.
+         * 
+         * @param profileRequestContext the current profile request context
+         * @param c14nContext   the current c14n context
+         * @param duringAction  true iff the method is run from the action above
+         * @return true iff the action can operate successfully on the candidate contexts
+         */
+        public boolean apply(@Nonnull final ProfileRequestContext profileRequestContext,
+                @Nonnull final SubjectCanonicalizationContext c14nContext, final boolean duringAction) {
+
+            final Set<OIDCSubjectIdentifierPrincipal> subjects;
+            if (c14nContext.getSubject() != null) {
+                subjects = c14nContext.getSubject().getPrincipals(OIDCSubjectIdentifierPrincipal.class);
+            } else {
+                subjects = null;
+            }
+            
+            if (subjects == null || subjects.isEmpty()) {
+                c14nContext.setException(
+                        new SubjectCanonicalizationException("No OIDCSubjectIdentifierPrincipals were found"));
+                if (duringAction) {
+                    ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_SUBJECT);
+                }
+                return false;
+            } else if (subjects.size() > 1) {
+                c14nContext.setException(
+                        new SubjectCanonicalizationException("Multiple OIDCSubjectIdentifierPrincipals were found"));
+                if (duringAction) {
+                    ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_SUBJECT);
+                }
+                return false;
+            }
+            
+            return true;
+        }
+        
+    }
+
+}
\ No newline at end of file
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ValidateOIDCAuthentication.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ValidateOIDCAuthentication.java
index 674957c..18b2243 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ValidateOIDCAuthentication.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ValidateOIDCAuthentication.java
@@ -34,19 +34,12 @@ import org.opensaml.profile.action.EventIds;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
 import org.opensaml.saml.metadata.resolver.MetadataResolver;
-import org.opensaml.saml.saml2.core.Assertion;
-import org.opensaml.saml.saml2.core.Audience;
-import org.opensaml.saml.saml2.core.AuthenticatingAuthority;
-import org.opensaml.saml.saml2.core.AuthnContext;
-import org.opensaml.saml.saml2.core.ProxyRestriction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Strings;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 import com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse;
-import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
 
 import net.minidev.json.JSONObject;
 import net.shibboleth.idp.attribute.AttributeDecodingException;
@@ -69,6 +62,7 @@ import net.shibboleth.idp.authn.principal.IdPAttributePrincipal;
 import net.shibboleth.idp.authn.principal.ProxyAuthenticationPrincipal;
 import net.shibboleth.idp.authn.principal.UsernamePrincipal;
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.EndUserClaimsContext;
+import net.shibboleth.idp.plugin.authn.oidc.rp.principal.OIDCSubjectIdentifierPrincipal;
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.idp.profile.context.RelyingPartyContext;
 import net.shibboleth.idp.saml.profile.context.navigate.SAMLMetadataContextLookupFunction;
@@ -124,7 +118,7 @@ public class ValidateOIDCAuthentication extends AbstractValidationAction {
     @Nullable private EndUserClaimsContext endUserContext;
         
     /** Strategy used to look up the {@link EndUserClaimsContext} to set the parameters for. */
-    @Nonnull private Function<ProfileRequestContext, EndUserClaimsContext> 
+    @Nonnull private final Function<ProfileRequestContext, EndUserClaimsContext> 
             endUserClaimsContextLookupStrategy;
     
     /** Context for externally supplied inbound attributes. */
@@ -249,7 +243,7 @@ public class ValidateOIDCAuthentication extends AbstractValidationAction {
             return false;
         }
         if (endUserContext.getUnprocessedIdTokenClaims() == null) {
-            log.error("{} Id_token not found in response", getLogPrefix());
+            log.error("{} id_token not found in response", getLogPrefix());
             ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
             return false;
         }
@@ -291,9 +285,11 @@ public class ValidateOIDCAuthentication extends AbstractValidationAction {
         
         //Add ACR from OIDC request/response
 
-         //What type of subject?  switch on subject_types_supported and subject_type.
-        //New principals?
-        subject.getPrincipals().add(new UsernamePrincipal(endUserContext.getUnprocessedIdTokenClaims().getSubject()));
+        // TODO What type of subject?  switch on subject_types_supported and subject_type.
+        if (endUserContext.getUnprocessedIdTokenClaims().getSubject() != null) {
+            subject.getPrincipals().add(
+                    new OIDCSubjectIdentifierPrincipal(endUserContext.getUnprocessedIdTokenClaims().getSubject()));
+        }
         subject.getPrincipals().add(buildProxyPrincipal());
         
         if (attributeContext != null && !attributeContext.getIdPAttributes().isEmpty()) {
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/EncryptJWT.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/EncryptJWT.java
index 1066b65..2bc0030 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/EncryptJWT.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/messaging/impl/EncryptJWT.java
@@ -82,7 +82,7 @@ public class EncryptJWT extends AbstractMessageHandler {
     /** The signature signing parameters. */
     @Nullable private JWTEncryptionParameters encryptionParameters;
     
-    /** A friendly name to log as the subject of encryption parameter resolution.*/
+    /** A friendly name to log as the subject of encryption.*/
     @Nonnull private String forFriendlyName;
     
     
@@ -221,17 +221,15 @@ public class EncryptJWT extends AbstractMessageHandler {
                 
                 jweObject = new JWEObject(new JWEHeader.Builder(encAlg, encEnc).contentType("JWT")
                                 .keyID(keyTransportKid).build(), payload);
-                log.debug("{} Encrypting '{}' with kid '{}' and params alg: {} enc: {}", 
-                        getLogPrefix(), forFriendlyName, keyTransportKid, encAlg.getName(), encEnc.getName());
+                logEncryption(forFriendlyName, keyTransportKid, encAlg.getName(), encEnc.getName());
                 jweObject.encrypt(new RSAEncrypter((RSAPublicKey) keyTransportCredential.getPublicKey()));
                 
             } else if (JWEAlgorithm.Family.ECDH_ES.contains(encAlg) && keyTransportCredential != null &&
                     keyTransportCredential.getPublicKey() != null) {
                 
                 jweObject = new JWEObject(new JWEHeader.Builder(encAlg, encEnc).contentType("JWT")
-                        .keyID(keyTransportKid).build(), payload);
-                log.debug("{} Encrypting '{}' with kid '{}' and params alg: {} enc: {}", 
-                        getLogPrefix(), forFriendlyName, keyTransportKid, encAlg.getName(), encEnc.getName());
+                        .keyID(keyTransportKid).build(), payload);                
+                logEncryption(forFriendlyName, keyTransportKid, encAlg.getName(), encEnc.getName());
                 jweObject.encrypt(new ECDHEncrypter((ECPublicKey) keyTransportCredential.getPublicKey()));
                 
             } else if ((JWEAlgorithm.Family.AES_KW.contains(encAlg) || JWEAlgorithm.Family.AES_GCM_KW.contains(encAlg)) 
@@ -239,9 +237,7 @@ public class EncryptJWT extends AbstractMessageHandler {
                 
                 jweObject = new JWEObject(new JWEHeader.Builder(encAlg, encEnc).contentType("JWT")
                         .keyID(keyTransportKid).build(), payload);
-                log.debug("{} Encrypting '{}' with kid '{}' and params alg: {} enc: {}", 
-                        getLogPrefix(), forFriendlyName, keyTransportKid, encAlg.getName(), 
-                        encEnc.getName());                
+                logEncryption(forFriendlyName, keyTransportKid, encAlg.getName(), encEnc.getName());              
                 jweObject.encrypt(new AESEncrypter(keyTransportCredential.getSecretKey()));
                 
             } else if (JWEAlgorithm.DIR.equals(encAlg) && dataEncryptionCredential != null &&
@@ -249,8 +245,7 @@ public class EncryptJWT extends AbstractMessageHandler {
                 
                 jweObject = new JWEObject(new JWEHeader.Builder(encAlg, encEnc).contentType("JWT")
                         .keyID(dataEncryptionKid).build(), payload);
-                log.debug("{} Encrypting '{}' with kid '{}' and params alg: {} enc: {}", 
-                        getLogPrefix(), forFriendlyName, dataEncryptionKid, encAlg.getName(), encEnc.getName());       
+                logEncryption(forFriendlyName, dataEncryptionKid, encAlg.getName(), encEnc.getName());      
                 jweObject.encrypt(new DirectEncrypter(dataEncryptionCredential.getSecretKey()));
                 
             } else {
@@ -274,5 +269,20 @@ public class EncryptJWT extends AbstractMessageHandler {
         }
         
     }
+    
+    /**
+     * A convince method to log encryption parameters. Avoids some of the clutter in the calling
+     * methods.
+     * 
+     * @param friendlyName the friendly name of the subject of encryption
+     * @param keyID the keyID
+     * @param enc the content encryption algorithm
+     * @param alg the key management algorithm
+     */
+    private void logEncryption(@Nullable final String friendlyName, @Nullable final String keyID, 
+            @Nullable final String enc, @Nullable final String alg) {
+        log.debug("{} Encrypting '{}' with kid '{}' and params alg: {} enc: {}", 
+                getLogPrefix(), friendlyName, keyID, alg, enc); 
+    }
 
 }
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index 18af883..6f964c0 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -153,6 +153,16 @@
                 c:_0="#{'%{idp.authn.oidc.rp.supportedPrincipals:}'.trim()}" />
         </property>
     </bean>
+    
+    <!-- Inbuilt C14N flow -->
+    
+    <bean id="c14n/OIDCSubjectIdentifier"
+        class="net.shibboleth.idp.authn.SubjectCanonicalizationFlowDescriptor" >
+        <property name="activationCondition">
+            <bean class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.SimpleOIDCSubjectIdentifierCanonicalization.ActivationCondition" 
+            c:disabled="%{idp.authn.oidc.rp.c14n.subjectidentifier.disabled:false}"/>
+        </property>
+    </bean>
 
     <!-- TODO check this -->
     <bean id="issuer" class="java.lang.String" c:_0="%{idp.authn.oidc.rp.issuer:%{idp.entityID}}" />
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 746efe1..8bb3e52 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
@@ -190,7 +190,7 @@
         p:providerMetadataAlgorithmLookupStrategy-ref="shibboleth.authn.oidc.rp.RequestObjectSupportedSignatureSigningAlgorithms" />
 
     <bean id="shibboleth.authn.oidc.rp.RequestObjectSupportedSignatureSigningAlgorithms" scope="prototype"
-        class="net.shibboleth.idp.plugin.authn.oidc.rp.config.RequestObjectSupportedSignatureSigningAlgorithms" />
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.messaging.context.logic.RequestObjectSupportedSignatureSigningAlgorithms" />
 
     <bean id="RequestObjectSignatureSigningConfigurationLookup" lazy-init="true"
         class="net.shibboleth.idp.plugin.authn.oidc.rp.config.navigate.RequestObjectSignatureSigningConfigurationLookupFunction"
@@ -694,7 +694,7 @@
     <!-- UserInfo decryption and signature check if JWT type -->
 
     <!-- FIXME: (might not be an issue) Will populate the same security params context as the id_token, but overwrite the 
-        decryption config -->
+        decryption config. The SAML one uses the same context for signature and decryption, so this seems OK?-->
     <bean id="PopulateUserInfoDecryptionParameters"
         class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.PopulateJWTDecryptionParameters" scope="prototype"
         p:profileContextLookupStrategy-ref="shibboleth.ChildLookup.ProxyProfileRequestContext"
@@ -861,7 +861,16 @@
         
    <bean id="PopulateSubjectCanonicalizationContext"
         class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
-        p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+        p:availableFlows-ref="shibboleth.authn.oidc.rp.c14n.PostLoginSubjectCanonicalizationFlows"/>
+    
+    <bean id="shibboleth.authn.oidc.rp.c14n.PostLoginSubjectCanonicalizationFlows"
+        class="net.shibboleth.ext.spring.factory.CombiningListFactoryBean"
+        p:firstList-ref="InbuiltPostLoginSubjectCanonicalizationFlows"
+        p:secondList-ref="shibboleth.PostLoginSubjectCanonicalizationFlows"/>
+        
+   <util:list id="InbuiltPostLoginSubjectCanonicalizationFlows">
+            <ref bean="c14n/OIDCSubjectIdentifier"/>
+    </util:list>
         
     <bean id="UnsupportedResponseTypeAction" class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.UnsupportedResponseTypeAction"/>
 
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
index fec0e96..34c802f 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OIDCRelyingParty/oidc-relying-party-authn-flow.xml
@@ -207,7 +207,7 @@
         <transition on="proceed" to="ReselectFlow" />
     </action-state>
     
-    <!-- Call flow specific c14n here, and allow an error to trigger a flow reselect. -->
+    <!-- Call the c14n subflow here, and allow an error to trigger a flow reselect. -->
     <subflow-state id="CallSubjectCanonicalization" subflow="c14n">
         <input name="calledAsSubflow" value="true" />
         <transition on="proceed" to="proceed" />
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/c14n/OIDCSubjectIdentifier/oidc-subject-identifier-c14n-beans.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/c14n/OIDCSubjectIdentifier/oidc-subject-identifier-c14n-beans.xml
new file mode 100644
index 0000000..df39c80
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/c14n/OIDCSubjectIdentifier/oidc-subject-identifier-c14n-beans.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xmlns:c="http://www.springframework.org/schema/c"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+                           
+       default-init-method="initialize"
+       default-destroy-method="destroy">
+
+    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"
+        p:placeholderPrefix="%{" p:placeholderSuffix="}" />
+
+    <bean class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
+    <bean class="net.shibboleth.idp.profile.impl.ProfileActionBeanPostProcessor" />
+    
+    <bean id="SimpleOIDCSubjectIdentifierCanonicalization"
+        class="net.shibboleth.idp.plugin.authn.oidc.rp.impl.SimpleOIDCSubjectIdentifierCanonicalization" scope="prototype"
+        p:lowercase="#{getObject('shibboleth.authn.oidc.rp.c14n.subjectidentifier.Lowercase') ?: %{idp.authn.oidc.rp.c14n.subjectidentifier.lowercase:false}}"
+        p:uppercase="#{getObject('shibboleth.authn.oidc.rp.c14n.subjectidentifier.Uppercase') ?: %{idp.authn.oidc.rp.c14n.subjectidentifier.uppercas:false}}"
+        p:trim="#{getObject('shibboleth.authn.oidc.rp.c14n.subjectidentifier.Trim') ?: %{idp.authn.oidc.rp.c14n.subjectidentifier.trim:true}}"
+        p:transforms="#{getObject('shibboleth.authn.oidc.rp.c14n.subjectidentifier.Transforms')}" />
+    
+</beans>
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/c14n/OIDCSubjectIdentifier/oidc-subject-identifier-c14n-flow.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/c14n/OIDCSubjectIdentifier/oidc-subject-identifier-c14n-flow.xml
new file mode 100644
index 0000000..1c22585
--- /dev/null
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/c14n/OIDCSubjectIdentifier/oidc-subject-identifier-c14n-flow.xml
@@ -0,0 +1,17 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
+      parent="c14n.abstract">
+
+    <!-- This is a one-step subflow that does OIDC based Subject Identifier Canonicalization. -->
+    
+    <action-state id="SimpleSubjectCanonicalization">
+        <evaluate expression="SimpleOIDCSubjectIdentifierCanonicalization" />
+        <evaluate expression="'proceed'" />
+        
+        <transition on="proceed" to="proceed" />
+    </action-state>
+
+    <bean-import resource="oidc-subject-identifier-c14n-beans.xml" />
+
+</flow>
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/attribute/registry/postconfig.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/attribute/registry/postconfig.xml
index 75ffe22..55000a8 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/attribute/registry/postconfig.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/attribute/registry/postconfig.xml
@@ -21,5 +21,416 @@
 
     <bean id="OIDCScopedStringTranscoder"
         class="net.shibboleth.oidc.attribute.transcoding.impl.OIDCScopedStringAttributeTranscoder" />
+        
+    <bean parent="shibboleth.TranscodingRuleLoader">
+    <constructor-arg>
+    <list>
+
+        <!-- Typical inetOrgPerson attributes that map to standard claims. -->
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">displayName</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">name</prop>
+                    <prop key="displayName.en">Display name</prop>
+                    <prop key="displayName.de">Anzeigename</prop>
+                    <prop key="displayName.fr">Nom</prop>
+                    <prop key="displayName.it">Nome</prop>
+                    <prop key="displayName.ja">表示名</prop>
+                    <prop key="description.en">The name that should appear in white-pages-like applications for this person.</prop>
+                    <prop key="description.de">Anzeigename</prop>
+                    <prop key="description.fr">Nom complet d'affichage</prop>
+                    <prop key="description.it">Nome</prop>
+                    <prop key="description.ja">アプリケーションでの表示に用いられる英字氏名</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">givenName</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">given_name</prop>
+                    <prop key="displayName.en">Given name</prop>
+                    <prop key="displayName.de">Vorname</prop>
+                    <prop key="displayName.fr">Prénom</prop>
+                    <prop key="displayName.it">Nome</prop>
+                    <prop key="displayName.ja">名</prop>
+                    <prop key="description.en">Given name of a person</prop>
+                    <prop key="description.de">Vorname</prop>
+                    <prop key="description.fr">Prénom de l'utilisateur</prop>
+                    <prop key="description.it">Nome</prop>
+                    <prop key="description.ja">氏名(名)の英語表記</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">homePhone</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">phone_number</prop>
+                    <prop key="displayName.en">Private phone number</prop>
+                    <prop key="displayName.de">Telefon Privat</prop>
+                    <prop key="displayName.fr">Teléphone personnel</prop>
+                    <prop key="displayName.it">Numero di telefono privato</prop>
+                    <prop key="displayName.ja">自宅電話番号</prop>
+                    <prop key="description.en">Private phone number</prop>
+                    <prop key="description.de">Private Telefonnummer</prop>
+                    <prop key="description.fr">Numéro de téléphone de domicile de la personne</prop>
+                    <prop key="description.it">Numero di telefono privato</prop>
+                    <prop key="description.ja">自宅の電話番号</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">mail</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">email</prop>
+                    <prop key="displayName.en">E-mail</prop>
+                    <prop key="displayName.de">E-Mail</prop>
+                    <prop key="displayName.fr">Email</prop>
+                    <prop key="displayName.it">E-mail</prop>
+                    <prop key="displayName.ja">メールアドレス</prop>
+                    <prop key="description.en">E-Mail: Preferred address for e-mail to be sent to this person</prop>
+                    <prop key="description.de">E-Mail-Adresse</prop>
+                    <prop key="description.de-ch">E-Mail Adresse</prop>
+                    <prop key="description.fr">Adresse de courrier électronique</prop>
+                    <prop key="description.it">E-Mail: l'indirizzo e-mail preferito dall'utente</prop>
+                    <prop key="description.ja">メールアドレス</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">preferredLanguage</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">locale</prop>
+                    <prop key="displayName.en">Preferred Language</prop>
+                    <prop key="displayName.de">Bevorzugte Sprache</prop>
+                    <prop key="displayName.fr">Langue préférée</prop>
+                    <prop key="displayName.it">Lingua preferita</prop>
+                    <prop key="displayName.ja">希望言語</prop>
+                    <prop key="description.en">Preferred language: Users preferred language (see RFC1766)</prop>
+                    <prop key="description.de">Bevorzugte Sprache (siehe RFC1766)</prop>
+                    <prop key="description.fr">Exemple: fr, de, it, en, ... (voir RFC1766)</prop>
+                    <prop key="description.it">Lingua preferita: la lingua preferita dall'utente (cfr. RFC1766)</prop>
+                    <prop key="description.ja">利用者が希望する言語(RFC1766 を参照)</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">sn</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">family_name</prop>
+                    <prop key="displayName.en">Surname</prop>
+                    <prop key="displayName.de">Nachname</prop>
+                    <prop key="displayName.fr">Nom de famille</prop>
+                    <prop key="displayName.it">Cognome</prop>
+                    <prop key="displayName.ja">姓</prop>
+                    <prop key="description.en">Surname or family name</prop>
+                    <prop key="description.de">Familienname</prop>
+                    <prop key="description.fr">Nom de famille de l'utilisateur.</prop>
+                    <prop key="description.it">Cognome dell'utilizzatore</prop>
+                    <prop key="description.ja">氏名(姓)の英語表記</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">telephoneNumber</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">phone_number</prop>
+                    <prop key="displayName.en">Business phone number</prop>
+                    <prop key="displayName.de">Telefon Geschäft</prop>
+                    <prop key="displayName.fr">Teléphone professionnel</prop>
+                    <prop key="displayName.it">Numero di telefono dell'ufficio</prop>
+                    <prop key="displayName.ja">所属機関内電話番号</prop>
+                    <prop key="description.en">Business phone number: Office or campus phone number</prop>
+                    <prop key="description.de">Telefonnummer am Arbeitsplatz</prop>
+                    <prop key="description.fr">Teléphone de l'institut, de l'université</prop>
+                    <prop key="description.it">Numero di telefono dell'ufficio</prop>
+                    <prop key="description.ja">所属機関での利用者の電話番号</prop>
+                </props>
+            </property>
+        </bean>
+        
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">uid</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">preferred_username</prop>
+                    <prop key="displayName.en">User ID</prop>
+                    <prop key="displayName.de">Benutzer-ID</prop>
+                    <prop key="displayName.fr">ID utilisateur</prop>
+                    <prop key="displayName.it">ID dell'utente</prop>
+                    <prop key="displayName.ja">ユーザID</prop>
+                    <prop key="description.en">A unique identifier for a person, mainly used for user identification within the user's home organization.</prop>
+                    <prop key="description.de">Eine eindeutige Nummer für eine Person, welche hauptsächlich zur Identifikation innerhalb der Organisation benutzt wird.</prop>
+                    <prop key="description.fr">Identifiant de connexion d'une personnes sur les systèmes informatiques.</prop>
+                    <prop key="description.it">Identificativo unico della persona, usato per l'identificazione dell'utente all'interno della organizzazione di appartenenza.</prop>
+                    <prop key="description.ja">所属機関内で一意の利用者識別子</prop>
+                </props>
+            </property>
+        </bean>
+
+        <!-- eduPerson attributes that map to standard claims. -->
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonNickname</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">nickname</prop>
+                    <prop key="displayName.en">Nickname</prop>
+                    <prop key="displayName.de">Kurzname</prop>
+                    <prop key="displayName.de-ch">Übername</prop>
+                    <prop key="displayName.fr">Surnom</prop>
+                    <prop key="displayName.it">Diminutivo</prop>
+                    <prop key="displayName.ja">ニックネーム</prop>
+                    <prop key="description.en">Person's nickname, or the informal name by which they are accustomed to be hailed.</prop>
+                    <prop key="description.de">Kurzname einer Person, oder üblicher Rufname zur Begrüßung.</prop>
+                    <prop key="description.de-ch">Übername einer Person, oder üblicher Rufname zur Begrüssung.</prop>
+                    <prop key="description.fr">Nom personnalisable pour un usage informel.</prop>
+                    <prop key="description.it">Diminutivo della persona, o  soprannome.</prop>
+                    <prop key="description.ja">利用者のニックネームもしくは通称</prop>
+                </props>
+            </property>
+        </bean>
+
+        <!-- A subset of the major eduPerson attributes that have no standard claim mapping. -->
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonAssurance</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">eduPersonAssurance</prop>
+                    <prop key="displayName.en">Assurance level</prop>
+                    <prop key="displayName.de">Vertrauensgrad</prop>
+                    <prop key="displayName.fr">Niveau de confiance</prop>
+                    <prop key="displayName.it">Livello di sicurezza</prop>
+                    <prop key="displayName.ja">保証レベル</prop>
+                    <prop key="description.en">Set of URIs that assert compliance with specific standards for identity assurance.</prop>
+                    <prop key="description.de">URIs die eine gewisse Zusicherung für spezifische Standards des Vertrauens beinhalten</prop>
+                    <prop key="description.fr">Un ensemble d'URI qui attestent la conformité selon un standard pour les niveaux d'assurance d'identités</prop>
+                    <prop key="description.it">Un insieme di URI che asseriscono l'osservanza dei livelli di sicurezza richiesti</prop>
+                    <prop key="description.ja">IDの保証レベルに関して特定の基準に準拠していることを示すURI</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonEntitlement</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">eduPersonEntitlement</prop>
+                    <prop key="displayName.en">Entitlement</prop>
+                    <prop key="displayName.de">Berechtigung</prop>
+                    <prop key="displayName.fr">Entitlement</prop>
+                    <prop key="displayName.it">Prerogativa</prop>
+                    <prop key="displayName.ja">資格情報</prop>
+                    <prop key="description.en">Member of: URI (either URL or URN) that indicates a set of rights to specific resources based on an agreement across the releavant community</prop>
+                    <prop key="description.de">Zeichenkette, die Rechte für spezifische Ressourcen beschreibt</prop>
+                    <prop key="description.fr">Membre de: URI (soit une URL ou une URN) décrivant un droit spécific d'accès.</prop>
+                    <prop key="description.it">Membro delle seguenti URI (sia URL o URN) che rappresentano diritti specifici d'accesso validi in tutta la communità</prop>
+                    <prop key="description.ja">特定のアプリケーションもしくはコミュニティ内の複数リソースへのアクセス権限を持つことを示すURI(URLもしくはURN)</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonPrincipalName</prop>
+                    <prop key="transcoder">OIDCScopedStringTranscoder</prop>
+                    <prop key="oidc.name">eduPersonPrincipalName</prop>
+                    <prop key="displayName.en">Principal name</prop>
+                    <prop key="displayName.de">Persönliche ID</prop>
+                    <prop key="displayName.fr">Principal Name</prop>
+                    <prop key="displayName.it">Principal Name</prop>
+                    <prop key="displayName.ja">プリンシパルID</prop>
+                    <prop key="description.en">A unique identifier for a person, mainly for inter-institutional user identification.</prop>
+                    <prop key="description.de">Eindeutige Benutzeridentifikation</prop>
+                    <prop key="description.de-ch">Eindeutige Benützeridentifikation</prop>
+                    <prop key="description.fr">L'identifiant unique de l'utilisateur</prop>
+                    <prop key="description.it">Un ID personale che identifica chiaramente l'utente in seno alla sua organizzazione</prop>
+                    <prop key="description.ja">フェデレーション内で一意かつ永続的な利用者識別子</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonScopedAffiliation</prop>
+                    <prop key="transcoder">OIDCScopedStringTranscoder</prop>
+                    <prop key="oidc.name">eduPersonScopedAffiliation</prop>
+                    <prop key="displayName.en">Scoped affiliation</prop>
+                    <prop key="displayName.de">Zugehörigkeit</prop>
+                    <prop key="displayName.fr">Affiliation</prop>
+                    <prop key="displayName.it">Tipo di membro</prop>
+                    <prop key="displayName.ja">スコープ付き職位</prop>
+                    <prop key="description.en">Specifies the person's affiliation within a particular security domain</prop>
+                    <prop key="description.de">Art der Zugehörigkeit zur Heimatorganisation</prop>
+                    <prop key="description.de-ch">Art der Zugehörigkeit zur Heimorganisation</prop>
+                    <prop key="description.fr">Type d'affiliation dans l'organisation</prop>
+                    <prop key="description.it">Tipo di membro: Tipo di lavoro svolto per l'organizzazione</prop>
+                    <prop key="description.ja">セキュリティドメインのスコープが付いた所属機関における職位</prop>
+                </props>
+            </property>
+        </bean>
+
+        <!-- The remainder are standard OIDC claims, which we map based on the actual claim name. -->
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">address</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.asObject">true</prop>
+                    <prop key="oidc.name">address</prop>
+                    <prop key="displayName.en">Postal address</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">birthdate</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">birthdate</prop>
+                    <prop key="displayName.en">Date of birth</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">email_verified</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">email_verified</prop>
+                    <prop key="oidc.asBoolean">true</prop>
+                    <prop key="displayName.en">E-mail verification status</prop>
+                    <prop key="description.en">Indicates whether e-mail address has been verified by the issuer</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">gender</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">gender</prop>
+                    <prop key="displayName.en">Gender</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">middle_name</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">middle_name</prop>
+                    <prop key="displayName.en">Middle name</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">phone_number_verified</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">phone_number_verified</prop>
+                    <prop key="oidc.asBoolean">true</prop>
+                    <prop key="displayName.en">Phone number verification status</prop>
+                    <prop key="description.en">Indicates whether phone number has been verified by the issuer</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">picture</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">picture</prop>
+                    <prop key="displayName.en">Picture</prop>
+                    <prop key="description.en">URL of personal photo</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">profile</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">profile</prop>
+                    <prop key="displayName.en">Profile page</prop>
+                    <prop key="description.en">URL of personal profile page</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">website</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">website</prop>
+                    <prop key="displayName.en">Web site</prop>
+                    <prop key="description.en">URL to personal web site</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">updated_at</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">updated_at</prop>
+                    <prop key="oidc.asInteger">true</prop>
+                    <prop key="displayName.en">Last update of information</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">zoneinfo</prop>
+                    <prop key="transcoder">OIDCStringTranscoder</prop>
+                    <prop key="oidc.name">zoneinfo</prop>
+                    <prop key="displayName.en">Time zone</prop>
+                </props>
+            </property>
+        </bean>
+
+    </list>
+    </constructor-arg>
+    </bean>
     
 </beans>
diff --git a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
index fc03ca7..61e45a3 100644
--- a/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
+++ b/idp-oidc-rp-impl/src/main/resources/META-INF/net/shibboleth/idp/service/relying-party/postconfig.xml
@@ -220,7 +220,8 @@
             <list>
                 <bean id="OIDCProviderMetadataCredentialResolver"
                     class="net.shibboleth.oidc.security.credential.impl.ProviderMetadataCredentialResolver"
-                    p:remoteJwkSetCache-ref="shibboleth.authn.oidc.rp.RemoteJwkSetCache" />
+                    p:remoteJwkSetCache-ref="shibboleth.authn.oidc.rp.RemoteJwkSetCache"
+                    p:keyFetchInterval="%{idp.authn.oidc.rp.provider.keyfetch.interval:PT30M}" />
                 <bean id="CriterionCredentialResolver"
                     class="net.shibboleth.oidc.security.credential.impl.CriterionCredentialResolver" />
             </list>
@@ -254,7 +255,8 @@
             <list>
                 <bean id="OIDCProviderMetadataCredentialResolver"
                     class="net.shibboleth.oidc.security.credential.impl.ProviderMetadataCredentialResolver"
-                    p:remoteJwkSetCache-ref="shibboleth.authn.oidc.rp.RemoteJwkSetCache" />
+                    p:remoteJwkSetCache-ref="shibboleth.authn.oidc.rp.RemoteJwkSetCache" 
+                    p:keyFetchInterval="%{idp.authn.oidc.rp.provider.keyfetch.interval:PT30M}"/>
                 <bean id="CriterionCredentialResolver"
                     class="net.shibboleth.oidc.security.credential.impl.CriterionCredentialResolver" />
             </list>
diff --git a/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/providermetadata-resolver-system.xml b/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/providermetadata-resolver-system.xml
index ae9274d..a811dff 100644
--- a/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/providermetadata-resolver-system.xml
+++ b/idp-oidc-rp-impl/src/main/resources/net/shibboleth/idp/plugin/authn/oidc/rp/conf/authn/providermetadata-resolver-system.xml
@@ -83,8 +83,5 @@
     <bean id="shibboleth.authn.oidc.rp.DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy" scope="prototype"
         class="net.shibboleth.oidc.metadata.cache.impl.DefaultOIDCProviderMetadataCriteriaToIdentifierStrategy" />
 
-    <!-- Wildcard import hook for plugins. -->
-    <!-- TODO: Not sure we need this -->
-    <!-- <import resource="classpath*:/META-INF/net/shibboleth/idp/plugin/oidc/op/service/clientinfo/postconfig.xml" /> -->
 
 </beans>
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCTest.java
index 44c8db9..ed3f9b6 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AbstractOIDCTest.java
@@ -18,6 +18,8 @@
 package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
 
 import java.net.URI;
+import java.time.Duration;
+import java.util.Set;
 
 import javax.annotation.Nonnull;
 
@@ -34,18 +36,32 @@ import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
 import net.minidev.json.JSONArray;
 import net.minidev.json.JSONObject;
 import net.minidev.json.parser.JSONParser;
+import net.shibboleth.idp.authn.AuthenticationFlowDescriptor;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.impl.DefaultAuthenticationResultSerializer;
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.OIDCPeerEntityContext;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
 import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
 import net.shibboleth.idp.profile.testing.RequestContextBuilder;
+import net.shibboleth.idp.relyingparty.RelyingPartyConfiguration;
 import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
 import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
+import net.shibboleth.oidc.profile.config.OIDCAuthorizationConfiguration;
 import net.shibboleth.oidc.profile.core.OIDCAuthenticationRequest;
 import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
 
 /** Abstract class for tests that require context setup appropriate for an OIDC request/response.*/
 public abstract class AbstractOIDCTest {
     
+    /** A redirect_uri override.*/
+    private static final String REDIRECT_URI_OVERRIDE = "https://localhost/callback";
+    
+    /** The client_id.*/
+    private static final String CLIENT_ID = "demo_rp";
+    
+    /** The client_secret.*/
+    private static final String CLIENT_SECRET = "Xp2s5v8y/B?E(H+MbQeThWmYq3t6w9z$";
+    
     protected final String GOOD_PROVIDER_CONFIGURATION_INFO = 
             "{\"issuer\":\"https://op.example.com/\","
             + "\"authorization_endpoint\":\"https://www.certification.openid.net/test/a/"
@@ -143,6 +159,9 @@ public abstract class AbstractOIDCTest {
     /** The authentication request.*/
     protected OIDCAuthenticationRequest authnRequest;
     
+    /** The authentication context (above the nested prc).*/
+    protected AuthenticationContext ac;
+    
     /** 
      * Setup the various contexts.
      * 
@@ -153,8 +172,16 @@ public abstract class AbstractOIDCTest {
         src = new RequestContextBuilder().buildRequestContext();
         rootPrc = new WebflowRequestContextProfileRequestContextLookup().apply(src);
         
-        final AuthenticationContext ac = new AuthenticationContext();
+        ac = new AuthenticationContext();
         ac.setAuthenticatingAuthority("https://op.example.com");
+        final AuthenticationFlowDescriptor desc = new AuthenticationFlowDescriptor();
+        desc.setId("foo");
+        desc.setResultSerializer(new DefaultAuthenticationResultSerializer());
+        desc.setLifetime(Duration.ofHours(1));
+        desc.initialize();
+        ac.getAvailableFlows().put(desc.getId(), desc);
+        ac.setAttemptedFlow(desc);
+       
         rootPrc.addSubcontext(ac);
         // Add a nested proxy PRC under the authentication context.
         prc = new ProfileRequestContext();
@@ -174,7 +201,17 @@ public abstract class AbstractOIDCTest {
                 OIDCClientInformation.parse((JSONObject)((JSONArray)parser.parse(CLIENT_METADATA)).get(0)));
         outMsgCtx.addSubcontext(metadataContext);
         
-        
+        final RelyingPartyContext partyContext = new RelyingPartyContext();
+        final OIDCAuthorizationConfiguration partyConfig = new OIDCAuthorizationConfiguration();  
+        partyContext.setProfileConfig(partyConfig);
+        partyConfig.setClientCredential(TestCredentialHelper.createClientSecretCredential(CLIENT_SECRET));
+        partyConfig.setTokenEndpointAuthMethods(Set.of("client_secret_basic"));
+        partyConfig.setClientId(CLIENT_ID);
+        partyConfig.setRedirectUriOverride(REDIRECT_URI_OVERRIDE);
+        final RelyingPartyConfiguration rPartyConfig = new RelyingPartyConfiguration();
+        rPartyConfig.setResponderId("http://idp.example.com/");
+        partyContext.setConfiguration(rPartyConfig);
+        prc.addSubcontext(partyContext);
         
         peerEntityCtx = outMsgCtx.getSubcontext(OIDCPeerEntityContext.class,true);
         final OIDCProviderMetadataContext providerCtx = new OIDCProviderMetadataContext();
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRequestedClaimsTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRequestedClaimsTest.java
index b0814c9..3f26247 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRequestedClaimsTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddRequestedClaimsTest.java
@@ -17,8 +17,9 @@
 
 package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
 
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
 
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.messaging.context.navigate.ParentContextLookup;
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddResponseTypeAndModeTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddResponseTypeAndModeTest.java
index e22887a..ca93722 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddResponseTypeAndModeTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/AddResponseTypeAndModeTest.java
@@ -1,6 +1,5 @@
 package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
-
-import static org.junit.Assert.assertEquals;
+import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DefaultClaimMergingStrategyTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DefaultClaimMergingStrategyTest.java
index 1b80a6a..cddca0f 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DefaultClaimMergingStrategyTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/DefaultClaimMergingStrategyTest.java
@@ -17,7 +17,8 @@
 
 package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
 
-import static org.junit.Assert.assertEquals;
+
+import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNull;
 
 import javax.annotation.Nonnull;
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ExchangeCodeForTokenTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ExchangeCodeForTokenTest.java
index 48ccf8b..b4750c6 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ExchangeCodeForTokenTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ExchangeCodeForTokenTest.java
@@ -17,7 +17,8 @@
 
 package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
 
-import static org.junit.Assert.assertEquals;
+
+import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 
@@ -61,6 +62,7 @@ public class ExchangeCodeForTokenTest extends AbstractOIDCTest {
     @Nonnull private ExchangeCodeForAccessToken exchangeAction;
     
     
+    @Override
     @BeforeMethod
     public void setup() throws Exception {    
         
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockMatcher.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockMatcher.java
new file mode 100644
index 0000000..507500b
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockMatcher.java
@@ -0,0 +1,127 @@
+/*
+ * 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.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.Set;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.filter.Matcher;
+import net.shibboleth.idp.attribute.filter.context.AttributeFilterContext;
+import net.shibboleth.utilities.java.support.component.AbstractIdentifiedInitializableComponent;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/** A simple, mock implementation of {@link Matcher}. */
+ at SuppressWarnings("javadoc")
+public class MockMatcher extends AbstractIdentifiedInitializableComponent implements Matcher { 
+
+    /** ID of the attribute to which this matcher applies. */
+    private String matchingAttribute;
+
+    /** Values, of the attribute, considered to match this matcher. */
+    private Collection<?> matchingValues;
+    
+    /** state variable */
+    private boolean initialized;
+
+   
+    /** do we fail when validate is called? do we fail when we are called?*/
+    private boolean fails;
+
+    /** what was passed to getMatchingValues(). */
+    private AttributeFilterContext contextUsed;
+
+    public MockMatcher() {
+        setId("Mock");
+    }
+
+    /**
+     * Sets the ID of the attribute to which this matcher applies.
+     * 
+     * @param id ID of the attribute to which this matcher applies
+     */
+    public void setMatchingAttribute(final String id) {
+        matchingAttribute = Constraint.isNotNull(StringSupport.trimOrNull(id), "attribute ID can not be null or empty");
+        if (!initialized) {
+            setId("Mock " + id);
+        }
+    }
+
+    /**
+     * Sets the values, of the attribute, considered to match this matcher. If null then all attribute values are
+     * considered to be matching.
+     * 
+     * @param values values, of the attribute, considered to match this matcher
+     */
+    public void setMatchingValues(final Collection<?> values) {
+        matchingValues = values;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Set<IdPAttributeValue> getMatchingValues(final IdPAttribute attribute, final AttributeFilterContext filterContext) {
+        if (fails) {
+            return null;
+        }
+        if (!Objects.equals(attribute.getId(), matchingAttribute)) {
+            return Collections.emptySet();
+        }
+
+        if (matchingValues == null) {
+            return Set.copyOf(attribute.getValues());
+        }
+
+        final LinkedHashSet<IdPAttributeValue> values = new LinkedHashSet<>();
+        for (final IdPAttributeValue value : attribute.getValues()) {
+            if (matchingValues.contains(value)) {
+                values.add(value);
+            }
+        }
+
+        return values;
+    }
+
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isInitialized() {
+        return initialized;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void doInitialize()  {
+        initialized = true;
+    }
+
+
+    public AttributeFilterContext getContextUsedAndReset() {
+        final AttributeFilterContext value = contextUsed;
+        contextUsed = null;
+        return value;
+    }
+
+    public void setFailValidate(final boolean doFail) {
+        fails = doFail;
+    }
+}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/RequestObjectSupportedSignatureSigningAlgorithms.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockReloadableService.java
similarity index 52%
rename from idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/RequestObjectSupportedSignatureSigningAlgorithms.java
rename to idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockReloadableService.java
index 533a024..be37c85 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/RequestObjectSupportedSignatureSigningAlgorithms.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockReloadableService.java
@@ -15,30 +15,41 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.plugin.authn.oidc.rp.config;
-
-import java.util.List;
-import java.util.function.Function;
-import java.util.stream.Collectors;
+package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
 
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import com.nimbusds.jose.JWSAlgorithm;
-import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+import net.shibboleth.utilities.java.support.service.AbstractReloadableService;
+import net.shibboleth.utilities.java.support.service.ServiceableComponent;
 
 /**
- * Pull out the request object supported signature signing algorithms from the metadata.
+ * Utility class for wrapping a serviceable component in a dummy reloadable service.
+ * 
+ * @param <T> type of component
  */
-public class RequestObjectSupportedSignatureSigningAlgorithms implements Function<OIDCProviderMetadata, List<String>>{
+public class MockReloadableService<T> extends AbstractReloadableService<T> {
+
+    @Nonnull private final ServiceableComponent<T> component;
+
+    public MockReloadableService(@Nullable final ServiceableComponent<T> what) {
+        component = what;
+    }
 
+    /** {@inheritDoc} */
     @Override
-    @Nullable public List<String> apply(@Nullable final OIDCProviderMetadata metadata) {
-        
-        if (metadata == null || metadata.getRequestObjectJWSAlgs() == null) {
+    @Nullable public ServiceableComponent<T> getServiceableComponent() {
+        if (null == component) {
             return null;
         }
-        return metadata.getRequestObjectJWSAlgs()
-                .stream().map(JWSAlgorithm::getName).collect(Collectors.toList());
+        component.pinComponent();
+        return component;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected boolean shouldReload() {
+        return false;
     }
 
-}
+}
\ No newline at end of file
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockSimpleStringTranscoder.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockSimpleStringTranscoder.java
new file mode 100644
index 0000000..304de39
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/MockSimpleStringTranscoder.java
@@ -0,0 +1,77 @@
+/*
+ * 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.impl;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.minidev.json.parser.JSONParser;
+import net.minidev.json.parser.ParseException;
+import net.shibboleth.idp.attribute.AttributeDecodingException;
+import net.shibboleth.idp.attribute.AttributeEncodingException;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.oidc.attribute.transcoding.AbstractOIDCAttributeTranscoder;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+
+/**
+ * Sample transcoder for tests which only supports simple strings.
+ */
+ at SuppressWarnings({"rawtypes"})
+public class MockSimpleStringTranscoder extends AbstractOIDCAttributeTranscoder {
+
+    @Override
+    protected Object encodeValues(final ProfileRequestContext profileRequestContext, final IdPAttribute attribute,
+            final TranscodingRule rule) throws AttributeEncodingException {
+        if (attribute.getValues().isEmpty()) {
+            return null;
+        }
+        
+        final StringBuilder attributeString = new StringBuilder();
+        for (final Object value : attribute.getValues()) {
+            attributeString.append(value.toString());
+        }
+        return toJSONObject(attributeString.toString());
+    }
+
+    @Override
+    protected List<IdPAttributeValue> decodeValues(final ProfileRequestContext profileRequestContext, final Object input,
+            final TranscodingRule rule) throws AttributeDecodingException {
+        if (input instanceof String) {            
+            return List.of(StringAttributeValue.valueOf((String)input));              
+        }
+        return Collections.emptyList();
+    }
+    
+    @Nonnull private Object toJSONObject(@Nonnull @NotEmpty final String value) throws AttributeEncodingException {
+        try {
+            return new JSONParser(JSONParser.MODE_PERMISSIVE).parse(value);
+        } catch (final ParseException e) {
+            throw new AttributeEncodingException("Unable to parse string into JSONObject", e);
+        }
+    }
+
+   
+    
+}
\ No newline at end of file
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
index b121ec2..41472d7 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/OIDCRPFlowTest.java
@@ -71,10 +71,10 @@ import net.shibboleth.idp.authn.context.ExternalAuthenticationContext;
 import net.shibboleth.idp.authn.context.RequestedPrincipalContext;
 import net.shibboleth.idp.authn.context.SubjectCanonicalizationContext;
 import net.shibboleth.idp.authn.impl.ExternalAuthenticationImpl;
-import net.shibboleth.idp.authn.principal.UsernamePrincipal;
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.EndUserClaimsContext;
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.OAuth2ClientContext;
 import net.shibboleth.idp.plugin.authn.oidc.rp.context.OIDCPeerEntityContext;
+import net.shibboleth.idp.plugin.authn.oidc.rp.principal.OIDCSubjectIdentifierPrincipal;
 import net.shibboleth.idp.plugin.authn.test.flow.AbstractAuthnXmlFlowExecutionTests;
 import net.shibboleth.idp.plugin.authn.test.flow.mock.MockFlowBuilder;
 import net.shibboleth.idp.profile.context.RelyingPartyContext;
@@ -443,11 +443,11 @@ public class OIDCRPFlowTest extends AbstractAuthnXmlFlowExecutionTests {
         assertNotNull(prc.getSubcontext(SubjectCanonicalizationContext.class));
         assertNotNull(prc.getSubcontext(SubjectCanonicalizationContext.class).getSubject().getPrincipals());
         //As SimpleSubjectCanonicalization has not been run, we pull out the subject
-        final UsernamePrincipal usernamePrincipal = 
+        final OIDCSubjectIdentifierPrincipal subjectIndentifierPrincipal = 
                 prc.getSubcontext(SubjectCanonicalizationContext.class).getSubject()
-                .getPrincipals(UsernamePrincipal.class).iterator().next();
-        assertNotNull(usernamePrincipal);
-        assertEquals(usernamePrincipal.getName(),"jdoe");
+                .getPrincipals(OIDCSubjectIdentifierPrincipal.class).iterator().next();
+        assertNotNull(subjectIndentifierPrincipal);
+        assertEquals(subjectIndentifierPrincipal.getName(),"jdoe");
     }
     
    
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolverTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolverTest.java
index 8cbea30..438d10b 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolverTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/RelyingPartyProxySigningParametersResolverTest.java
@@ -17,8 +17,7 @@
 
 package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
 
-
-import static org.junit.Assert.assertFalse;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ValidateOIDCAuthenticationTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ValidateOIDCAuthenticationTest.java
new file mode 100644
index 0000000..d2cdc8d
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/impl/ValidateOIDCAuthenticationTest.java
@@ -0,0 +1,168 @@
+package net.shibboleth.idp.plugin.authn.oidc.rp.impl;
+
+import org.testng.annotations.Test;
+import org.testng.AssertJUnit;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.time.Instant;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.messaging.context.navigate.ParentContextLookup;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.webflow.execution.Event;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.PlainJWT;
+import com.nimbusds.openid.connect.sdk.claims.ClaimsSet;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.filter.AttributeFilter;
+import net.shibboleth.idp.attribute.filter.AttributeFilterPolicy;
+import net.shibboleth.idp.attribute.filter.AttributeRule;
+import net.shibboleth.idp.attribute.filter.PolicyRequirementRule;
+import net.shibboleth.idp.attribute.filter.impl.AttributeFilterImpl;
+import net.shibboleth.idp.attribute.transcoding.AttributeTranscoderRegistry;
+import net.shibboleth.idp.attribute.transcoding.BasicNamingFunction;
+import net.shibboleth.idp.attribute.transcoding.TranscodingRule;
+import net.shibboleth.idp.attribute.transcoding.impl.AttributeTranscoderRegistryImpl;
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.principal.IdPAttributePrincipal;
+import net.shibboleth.idp.authn.principal.UsernamePrincipal;
+import net.shibboleth.idp.plugin.authn.oidc.rp.context.EndUserClaimsContext;
+import net.shibboleth.idp.plugin.authn.oidc.rp.principal.OIDCSubjectIdentifierPrincipal;
+import net.shibboleth.idp.plugin.authn.test.spring.MockApplicationContext;
+import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
+import net.shibboleth.oidc.attribute.transcoding.OIDCAttributeTranscoder;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+/** Tests for the ValidateOIDCAuthentication.*/
+public class ValidateOIDCAuthenticationTest  extends AbstractOIDCTest {
+    
+    private ValidateOIDCAuthentication action;
+    
+    private AttributeTranscoderRegistryImpl registry;
+    
+    /* Setup a transcoder to support the simple string trancoding of givenName.*/
+    private void setupTranscoderRegistry() throws ComponentInitializationException {
+        registry = new AttributeTranscoderRegistryImpl();
+        registry.setId("test");
+        
+        // This should be mocked, but this is harder to do 
+        final MockSimpleStringTranscoder transcoder = new MockSimpleStringTranscoder();
+        
+        registry.setNamingRegistry(Collections.singletonList(
+                new BasicNamingFunction<>(transcoder.getEncodedType(), ( input -> {
+                    if (input == null) {                
+                    return null;
+                }                
+                final Set<String> keys = input.keySet();
+                if (keys.size() != 1) {
+                    return null;
+                }                
+                return "OIDC:" + keys.iterator().next();}))));
+        
+        transcoder.initialize();
+        
+        final Map<String,Object> ruleset1 = new HashMap<>();
+        ruleset1.put(AttributeTranscoderRegistry.PROP_ID, "givenName");
+        ruleset1.put(AttributeTranscoderRegistry.PROP_TRANSCODER, transcoder);
+        ruleset1.put(AttributeTranscoderRegistry.PROP_DISPLAY_NAME, "givenName");
+        ruleset1.put(AttributeTranscoderRegistry.PROP_DESCRIPTION + '.' + Locale.ENGLISH.toLanguageTag(), "Given Name");
+        ruleset1.put(OIDCAttributeTranscoder.PROP_NAME,"name");
+        ruleset1.put("name", "bar");
+
+
+        registry.setTranscoderRegistry(List.of(
+                new TranscodingRule(ruleset1)));
+        registry.setApplicationContext(new MockApplicationContext());
+        registry.initialize();
+        
+        AssertJUnit.assertEquals(registry.getDisplayNames(new IdPAttribute("givenName")).size(), 1);
+        
+        action.setTranscoderRegistry(new MockReloadableService<AttributeTranscoderRegistry>(registry));
+    }
+    
+    /* Setup a simple filter policy for givenName.*/
+    public void setupAttributeFilter() throws ComponentInitializationException {
+        final MockMatcher givenNameMatcher = new MockMatcher();
+        givenNameMatcher.setMatchingAttribute("givenName");
+        givenNameMatcher.setMatchingValues(null);
+
+        final AttributeRule givenNameFilterPolicy = new AttributeRule();
+        givenNameFilterPolicy.setId("givenNameFilterPolicy");
+        givenNameFilterPolicy.setAttributeId("givenName");
+        givenNameFilterPolicy.setMatcher(givenNameMatcher);
+        givenNameFilterPolicy.setIsDenyRule(false);
+        givenNameFilterPolicy.initialize();
+        final AttributeFilterPolicy policy =
+                new AttributeFilterPolicy("attribute1Policy", PolicyRequirementRule.MATCHES_ALL,
+                        Collections.singletonList(givenNameFilterPolicy));
+        policy.initialize();
+        
+        final AttributeFilterImpl filter = new AttributeFilterImpl("engine", Collections.singletonList(policy));
+        filter.setApplicationContext(new MockApplicationContext());
+        filter.initialize();
+        action.setAttributeFilter(new MockReloadableService<AttributeFilter>(filter));
+    }
+    
+    @Override
+    @BeforeMethod
+    public void setup() throws Exception {
+        super.setup();
+        
+        action = new ValidateOIDCAuthentication();         
+        action.setProfileContextLookupStrategy(new ChildContextLookup<>(ProfileRequestContext.class).compose(
+                new ChildContextLookup<>(AuthenticationContext.class)
+                .compose(new WebflowRequestContextProfileRequestContextLookup())));    
+        action.setAuthenticationContextLookupStrategy(new ParentContextLookup<>(AuthenticationContext.class));
+        
+        final PlainJWT jwt = new PlainJWT(new JWTClaimsSet.Builder()
+                .issuer("https://op.example.com")
+                .audience(List.of("https://rp.example.com"))
+                .subject("jdoe")
+                .claim("nonce", "abadnonce")
+                .claim("azp", "https://rp.example.com")
+                .claim("name","jdoe")
+                .expirationTime(Date.from(Instant.now().plusSeconds(120)))
+                .build());
+        
+        final EndUserClaimsContext endClaimsContext = new EndUserClaimsContext();
+        final ClaimsSet endUserClaims = new ClaimsSet();
+        // We put all the claims in the JWT in here, not just the 'sanitized' ones
+        endUserClaims.putAll(jwt.getJWTClaimsSet().getClaims());
+        endClaimsContext.setUnprocessedIdTokenClaims(jwt.getJWTClaimsSet());
+        endClaimsContext.setEndUserClaims(endUserClaims);
+        
+        prc.getInboundMessageContext().addSubcontext(endClaimsContext);
+        
+        setupTranscoderRegistry();
+        setupAttributeFilter();
+              
+    }
+
+    @Test
+    public void testSuccess() throws ComponentInitializationException {
+        action.initialize();
+        final Event result = action.execute(src);
+        
+        AssertJUnit.assertNull(result);
+        AssertJUnit.assertNotNull(ac.getAuthenticationResult());
+        assertNotNull(ac.getAuthenticationResult().getSubject());
+        final var subject = ac.getAuthenticationResult().getSubject();
+        AssertJUnit.assertEquals(subject.getPrincipals(OIDCSubjectIdentifierPrincipal.class).size(), 1);
+        AssertJUnit.assertEquals(subject.getPrincipals(IdPAttributePrincipal.class).size(), 1);
+        AssertJUnit.assertEquals(subject.getPrincipals(IdPAttributePrincipal.class)
+                .iterator().next().getName(),"givenName");
+        
+    }
+}
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/spring/MockApplicationContext.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/spring/MockApplicationContext.java
new file mode 100644
index 0000000..476607e
--- /dev/null
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/test/spring/MockApplicationContext.java
@@ -0,0 +1,482 @@
+/*
+ * 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.test.spring;
+
+import static org.testng.Assert.fail;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.util.Locale;
+import java.util.Map;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.MessageSourceResolvable;
+import org.springframework.context.NoSuchMessageException;
+import org.springframework.core.ResolvableType;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.io.ProtocolResolver;
+import org.springframework.core.io.Resource;
+import org.springframework.core.metrics.ApplicationStartup;
+
+import net.shibboleth.ext.spring.service.AbstractServiceableComponent;
+
+/**
+ * Placeholder, which can be set on test {@link AbstractServiceableComponent}s to stop the
+ * "must be null" test firing.
+ */
+public class MockApplicationContext implements ConfigurableApplicationContext {
+
+    /** {@inheritDoc} */
+    @Override
+    public String getId() {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String getApplicationName() {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String getDisplayName() {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public long getStartupDate() {
+        fail();
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public ApplicationContext getParent() {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean containsBeanDefinition(final String beanName) {
+        fail();
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int getBeanDefinitionCount() {
+        fail();
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String[] getBeanDefinitionNames() {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String[] getBeanNamesForType(final ResolvableType type) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String[] getBeanNamesForType(final ResolvableType type, final boolean includeNonSingletons, final boolean allowEagerInit) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String[] getBeanNamesForType(final Class<?> type) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String[] getBeanNamesForType(final Class<?> type, final boolean includeNonSingletons, final boolean allowEagerInit) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <T> Map<String, T> getBeansOfType(final Class<T> type) throws BeansException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <T> Map<String, T> getBeansOfType(final Class<T> type, final boolean includeNonSingletons, final boolean allowEagerInit)
+            throws BeansException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String[] getBeanNamesForAnnotation(final Class<? extends Annotation> annotationType) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Map<String, Object> getBeansWithAnnotation(final Class<? extends Annotation> annotationType)
+            throws BeansException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <A extends Annotation> A findAnnotationOnBean(final String beanName, final Class<A> annotationType)
+            throws NoSuchBeanDefinitionException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object getBean(final String name) throws BeansException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <T> T getBean(final String name, final Class<T> requiredType) throws BeansException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Object getBean(final String name, final Object... args) throws BeansException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <T> T getBean(final Class<T> requiredType) throws BeansException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <T> T getBean(final Class<T> requiredType, final Object... args) throws BeansException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <T> ObjectProvider<T> getBeanProvider(final Class<T> requiredType) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <T> ObjectProvider<T> getBeanProvider(final ResolvableType requiredType) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean containsBean(final String name) {
+        fail();
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isSingleton(final String name) throws NoSuchBeanDefinitionException {
+        fail();
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isPrototype(final String name) throws NoSuchBeanDefinitionException {
+        fail();
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isTypeMatch(final String name, final ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
+        fail();
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isTypeMatch(final String name, final Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
+        fail();
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Class<?> getType(final String name) throws NoSuchBeanDefinitionException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Class<?> getType(final String name, final boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String[] getAliases(final String name) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public BeanFactory getParentBeanFactory() {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean containsLocalBean(final String name) {
+        fail();
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String getMessage(final String code, final Object[] args, final String defaultMessage, final Locale locale) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String getMessage(final String code, final Object[] args, final Locale locale) throws NoSuchMessageException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String getMessage(final MessageSourceResolvable resolvable, final Locale locale) throws NoSuchMessageException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void publishEvent(final Object event) {
+        fail();        
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Resource[] getResources(final String locationPattern) throws IOException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Resource getResource(final String location) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public ClassLoader getClassLoader() {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void start() {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void stop() {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isRunning() {
+        fail();
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setId(final String id) {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setParent(final ApplicationContext parent) {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setEnvironment(final ConfigurableEnvironment environment) {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public ConfigurableEnvironment getEnvironment() {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void addBeanFactoryPostProcessor(final BeanFactoryPostProcessor postProcessor) {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void addApplicationListener(final ApplicationListener<?> listener) {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void addProtocolResolver(final ProtocolResolver resolver) {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void refresh() throws BeansException, IllegalStateException {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void registerShutdownHook() {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void close() {
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isActive() {
+        fail();
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setClassLoader(final ClassLoader classLoader) {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <T> ObjectProvider<T> getBeanProvider(final Class<T> requiredType, final boolean allowEagerInit) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <T> ObjectProvider<T> getBeanProvider(final ResolvableType requiredType, final boolean allowEagerInit) {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setApplicationStartup(final ApplicationStartup applicationStartup) {
+        fail();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public ApplicationStartup getApplicationStartup() {
+        fail();
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public <A extends Annotation> A findAnnotationOnBean(final String beanName, final Class<A> annotationType,
+            final boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
+        fail();
+        return null;
+    }
+}
diff --git a/idp-oidc-rp-impl/src/test/resources/attribute/filter/attribute-filter.xml b/idp-oidc-rp-impl/src/test/resources/attribute/filter/attribute-filter.xml
index 7f77ede..dd41714 100644
--- a/idp-oidc-rp-impl/src/test/resources/attribute/filter/attribute-filter.xml
+++ b/idp-oidc-rp-impl/src/test/resources/attribute/filter/attribute-filter.xml
@@ -22,7 +22,7 @@
         <AttributeRule attributeID="displayName" permitAny="true" />
     </AttributeFilterPolicy>
 
-    <!-- Release an additional attribute if the issuer is the mock downstream OP. -->
+    <!-- Release an additional attribute if the issuer is the mock upstream OP. -->
     <AttributeFilterPolicy id="example1">
         <PolicyRequirementRule xsi:type="Issuer" value="https://localhost:9918" />
 

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


More information about the commits mailing list