[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