[java-idp-plugin-oidc-rp] branch main updated: JOIDCRP-14, JOIDCRP-13 - Client Authentication/Identifier Resolver
Phil Smart
philip.smart at jisc.ac.uk
Mon Mar 28 13:57:09 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=21f3a4fcb303a15d3d8b47100b32e1095ed2f896
The following commit(s) were added to refs/heads/main by this push:
new 21f3a4f JOIDCRP-14, JOIDCRP-13 - Client Authentication/Identifier Resolver
21f3a4f is described below
commit 21f3a4fcb303a15d3d8b47100b32e1095ed2f896
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Mon Mar 28 14:57:01 2022 +0100
JOIDCRP-14, JOIDCRP-13 - Client Authentication/Identifier Resolver
- Simplified the default strategies to use a simple Map over a further
strategy which used a storage service.
https://shibboleth.atlassian.net/browse/JOIDCRP-13
https://shibboleth.atlassian.net/browse/JOIDCRP-14
---
.../DefaultClientAuthenticationLookupStrategy.java | 171 +++++++++---
.../DefaultClientIdentifierLookupStrategy.java | 49 +++-
...ceBackedClientAuthenticationLookupStrategy.java | 291 ---------------------
...erviceBackedClientIdentifierLookupStrategy.java | 122 ---------
.../idp/service/relying-party/postconfig.xml | 36 +--
...aultClientAuthenticationLookupStrategyTest.java | 117 ++++++++-
pom.xml | 2 +-
7 files changed, 287 insertions(+), 501 deletions(-)
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientAuthenticationLookupStrategy.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientAuthenticationLookupStrategy.java
index 189b5f7..cefdee5 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientAuthenticationLookupStrategy.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientAuthenticationLookupStrategy.java
@@ -19,76 +19,157 @@ package net.shibboleth.idp.plugin.authn.oidc.rp.config;
import java.time.Duration;
import java.time.Instant;
+import java.util.Collections;
import java.util.Date;
+import java.util.Map;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import javax.annotation.concurrent.ThreadSafe;
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
import com.nimbusds.oauth2.sdk.auth.Secret;
-import net.shibboleth.utilities.java.support.annotation.ParameterName;
+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.storage.ClientAuthenticationDetails;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
+import net.shibboleth.utilities.java.support.annotation.constraint.ThreadSafeAfterInit;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
/**
* A strategy that produces a client authentication method either directly from the information supplied,
* or derived from a lookup strategy.
*/
- at ThreadSafe
+ at ThreadSafeAfterInit
public class DefaultClientAuthenticationLookupStrategy extends AbstractClientAuthenticationLookupStrategy {
/** A fixed client_id to use.*/
- @Nullable private final String clientId;
+ @Nullable private String clientId;
/** A fixed client_secret to use over any injected strategy to locate one .*/
- @Nullable private final String clientSecret;
+ @Nullable private char[] clientSecret;
/** A fixed client authentication method to use.*/
- @Nullable private final String clientAuthenticationMethod;
+ @Nullable private String clientAuthenticationMethod;
/** A fixed client secret expiry in seconds since UNIX EPOCH to use.*/
- @Nullable private final Duration clientSecretExpiresAt;
+ @Nullable private Duration clientSecretExpiresAt;
- /** The strategy used to locate the client authentication method if a fixed one is not already supplied.*/
- @Nullable private final Function<ProfileRequestContext, ClientAuthentication> clientAuthenticationLookupStrategy;
+ /** Map of client_id to client authentication details used to construct a {@link ClientAuthentication}.*/
+ @Nullable @NotLive private Map<String, ClientAuthenticationDetails> clientIdToClientAuthenticationMap;
+
+ /** The strategy used to lookup or create the {@link OAuth2ClientContext}.*/
+ @Nonnull private Function<ProfileRequestContext, OAuth2ClientContext> oauth2ClientContextLookupStrategy;
/**
- *
* Constructor.
- *
- * @param id the client_id
- * @param secret the client_secret
- * @param authenticationMethod the client authentication method
- * @param secretExpiresAt when the client secret expires, or 0 for no expiry
- * @param strategy the strategy to lookup the client authentication
- * @throws ComponentInitializationException
*/
- public DefaultClientAuthenticationLookupStrategy(
- @ParameterName(name="clientId") @Nullable final String id,
- @ParameterName(name="clientSecret") @Nullable final String secret,
- @ParameterName(name="clientAuthenticationMethod") @Nullable final String authenticationMethod,
- @ParameterName(name="clientSecretExpiresAt") @Nullable final Duration secretExpiresAt,
- @ParameterName(name="clientIdLookupStrategy")
- @Nullable final Function<ProfileRequestContext, ClientAuthentication> strategy)
- throws ComponentInitializationException {
+ public DefaultClientAuthenticationLookupStrategy() {
+ oauth2ClientContextLookupStrategy = new ChildContextLookup<>(OAuth2ClientContext.class).compose(
+ new ChildContextLookup<>(OIDCPeerEntityContext.class).compose(
+ new OutboundMessageContextLookup()));
+ }
+
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
-
- if (strategy == null && secret == null && authenticationMethod == null && secretExpiresAt == null) {
+ if (clientIdToClientAuthenticationMap == null && clientSecret == null &&
+ clientAuthenticationMethod == null && clientSecretExpiresAt == null) {
throw new ComponentInitializationException("Must supply a client_secret, client_authentication_method,"
- + " and client_secret_expires_at if a client authentication lookup strategy is not supplied");
+ + " and client_secret_expires_at if a client authentication map is not supplied");
}
+
+ }
+
+ /**
+ * Set the client_id.
+ *
+ * @param id the client_id
+ */
+ public void setClientId(@Nullable final String id) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
clientId = StringSupport.trimOrNull(id);
- clientSecret = StringSupport.trimOrNull(secret);
- clientAuthenticationMethod = StringSupport.trimOrNull(authenticationMethod);
- clientSecretExpiresAt = secretExpiresAt;
- clientAuthenticationLookupStrategy = strategy;
+ }
+
+ /**
+ * Set the client authentication method.
+ *
+ * @param authMethod the client authentication method
+ */
+ public void setClientAuthenticationMethod(@Nullable final String authMethod) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ clientAuthenticationMethod = StringSupport.trimOrNull(authMethod);
+ }
+
+ /**
+ * Set the client_secret.
+ *
+ * @param secret the client_secret
+ */
+ public void setClientSecret(@Nullable final char[] secret) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ clientSecret = secret;
+ }
+
+ /**
+ * Set when the client_secret expires. A duration of 0 means the secret does not expire.
+ *
+ * @param expiresAt when the client secret expires, or 0 for no expiry.
+ */
+ public void setClientSecretExpiresAt(@Nullable final Duration expiresAt) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ clientSecretExpiresAt = expiresAt;
+ }
+
+ /**
+ * Set the client_id to client authentication details map.
+ *
+ * @param map the map of client_id to client authentication details
+ */
+ public void setClientIdToClientAuthenticationMap(
+ @Nullable final Map<String, ClientAuthenticationDetails> map) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ if (map == null) {
+ clientIdToClientAuthenticationMap = Collections.emptyMap();
+ } else {
+ clientIdToClientAuthenticationMap = Collections.unmodifiableMap(map);
+ }
+ }
+
+ /**
+ * Set the strategy to lookup the {@link OAuth2ClientContext}
+ * from the {@link ProfileRequestContext}.
+ *
+ * @param strgy the strategy.
+ */
+ public void setOAuth2ClientContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext, OAuth2ClientContext> strgy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ oauth2ClientContextLookupStrategy = Constraint.isNotNull(strgy,
+ "OAuth2 client context lookup strategy cannot be null");
}
@Override
@@ -99,13 +180,33 @@ public class DefaultClientAuthenticationLookupStrategy extends AbstractClientAut
&& clientId != null) {
if (clientSecretExpiresAt.toSeconds() == 0) {
// No expiry if 0, so do not set.
- return constructClientAuthentication(clientId, clientAuthenticationMethod, new Secret(clientSecret));
+ return constructClientAuthentication(clientId, clientAuthenticationMethod,
+ new Secret(new String(clientSecret)));
}
- return constructClientAuthentication(clientId, clientAuthenticationMethod, new Secret(clientSecret,
+ return constructClientAuthentication(clientId, clientAuthenticationMethod,
+ new Secret(new String(clientSecret),
Date.from(Instant.ofEpochSecond(clientSecretExpiresAt.toSeconds()))));
}
- return clientAuthenticationLookupStrategy.apply(profileRequestContext);
+
+ // Else pull it from the map
+ final OAuth2ClientContext clientCtx = oauth2ClientContextLookupStrategy.apply(profileRequestContext);
+ if (clientCtx == null || StringSupport.trimOrNull(clientCtx.getClientId()) == null) {
+ return null;
+ }
+ final ClientAuthenticationDetails details =
+ clientIdToClientAuthenticationMap.get(clientCtx.getClientId());
+
+ if (details.getClientSecretExpiresAt() == 0) {
+ return constructClientAuthentication(
+ clientCtx.getClientId(), details.getTokenEndpointAuthMethod(),
+ new Secret(new String(details.getClientSecret())));
+ } else {
+ final Instant secretExpiration = Instant.ofEpochSecond(details.getClientSecretExpiresAt());
+ return constructClientAuthentication(
+ clientCtx.getClientId(), details.getTokenEndpointAuthMethod(),
+ new Secret(new String(details.getClientSecret()), Date.from(secretExpiration)));
+ }
}
}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientIdentifierLookupStrategy.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientIdentifierLookupStrategy.java
index 784e674..34e513b 100644
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientIdentifierLookupStrategy.java
+++ b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientIdentifierLookupStrategy.java
@@ -17,6 +17,8 @@
package net.shibboleth.idp.plugin.authn.oidc.rp.config;
+import java.util.Collections;
+import java.util.Map;
import java.util.function.Function;
import javax.annotation.Nonnull;
@@ -25,8 +27,12 @@ import javax.annotation.concurrent.ThreadSafe;
import org.opensaml.profile.context.ProfileRequestContext;
+import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.logic.Constraint;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
/**
@@ -39,29 +45,41 @@ public class DefaultClientIdentifierLookupStrategy implements Function<ProfileRe
/** A fixed client_id to use over any injected strategy to locate one.*/
@Nullable private final String clientId;
- /** The strategy used to locate the client_id if a fixed one is not already supplied.*/
- @Nullable private final Function<ProfileRequestContext, String> clientIdLookupStrategy;
+ /** Map of issuer to client_id. Can be {@literal null} if a fixed client_id is used.*/
+ @Nullable @NotLive private final Map<String, String> issuerToClientIdMap;
+
+ /** Lookup strategy to locate the provider metadata to use.*/
+ @NonnullAfterInit
+ private final Function<ProfileRequestContext, OIDCProviderMetadataContext> providerMetadataLookupStrategy;
/**
*
* Constructor.
*
* @param id a client_id that takes precedence over one derived from the lookup strategy.
- * @param strategy the strategy used to derive a client_id for the input profile request context.
+ * @param map the map used to derive a client_id for the input profile request context.
+ * @param strategy the strategy used to locate the provider metadata to find the issuer id.
*
* @throws ComponentInitializationException if both id and strategy are null, one is required.
*/
public DefaultClientIdentifierLookupStrategy(@ParameterName(name="clientId") @Nullable final String id,
- @ParameterName(name="clientIdLookupStrategy")
- @Nullable final Function<ProfileRequestContext, String> strategy)
+ @ParameterName(name="issuerToClientIdMap") @Nullable final Map<String, String> map,
+ @Nonnull @ParameterName(name="providerMetadataLookupStrategy")
+ final Function<ProfileRequestContext, OIDCProviderMetadataContext> strategy)
throws ComponentInitializationException {
- if (id == null && strategy == null) {
- throw new ComponentInitializationException("Must supply either a fixed client_id value or a "
- + "client_id lookup strategy");
+ if (id == null && map == null) {
+ throw new ComponentInitializationException("Must supply either a fixed client_id value or an "
+ + "issuer to client_id map");
+ }
+ if (map != null) {
+ issuerToClientIdMap = Collections.unmodifiableMap(map);
+ } else {
+ issuerToClientIdMap = Collections.emptyMap();
}
clientId = StringSupport.trimOrNull(id);
- clientIdLookupStrategy = strategy;
+ providerMetadataLookupStrategy =
+ Constraint.isNotNull(strategy, "The provider metadata lookup strategy can not be null");
}
@Override
@@ -70,8 +88,19 @@ public class DefaultClientIdentifierLookupStrategy implements Function<ProfileRe
// Use supplied client_id first
if (clientId != null) {
return clientId;
+ } else {
+ final OIDCProviderMetadataContext providerMetadataContext =
+ providerMetadataLookupStrategy.apply(profileRequestContext);
+ if (providerMetadataContext == null || providerMetadataContext.getProviderInformation() == null) {
+ return null;
+ }
+
+ if (issuerToClientIdMap != null) {
+ //Should not be if we get here.
+ return issuerToClientIdMap.get(providerMetadataContext.getProviderInformation().getIssuer().getValue());
+ }
}
- return clientIdLookupStrategy.apply(profileRequestContext);
+ return null;
}
}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/StorageServiceBackedClientAuthenticationLookupStrategy.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/StorageServiceBackedClientAuthenticationLookupStrategy.java
deleted file mode 100644
index eaa81d2..0000000
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/StorageServiceBackedClientAuthenticationLookupStrategy.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * 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.config;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.time.Instant;
-import java.util.Date;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import javax.json.Json;
-import javax.json.JsonException;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-import javax.json.JsonStructure;
-import javax.json.stream.JsonGenerator;
-
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.OutboundMessageContextLookup;
-import org.opensaml.storage.StorageRecord;
-import org.opensaml.storage.StorageSerializer;
-import org.opensaml.storage.StorageService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
-import com.nimbusds.oauth2.sdk.auth.Secret;
-
-import net.shibboleth.idp.plugin.authn.oidc.rp.context.OAuth2ClientContext;
-import net.shibboleth.idp.plugin.authn.oidc.rp.context.OIDCPeerEntityContext;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-/**
- * Default strategy for locating a configured client authentication method appropriate for the client_id
- * stashed in the {@link OAuth2ClientContext}.
- */
-public class StorageServiceBackedClientAuthenticationLookupStrategy
- extends AbstractClientAuthenticationLookupStrategy {
-
- /** The context name in the {@link StorageService}. */
- @Nonnull @NotEmpty public static final String CONTEXT_NAME = "oauth2ClientAuthentication";
-
- /** Class logger. */
- private final Logger log = LoggerFactory.getLogger(StorageServiceBackedClientAuthenticationLookupStrategy.class);
-
- /** The strategy used to lookup or create the {@link OAuth2ClientContext}.*/
- @NonnullAfterInit
- private Function<ProfileRequestContext, OAuth2ClientContext> oauth2ClientContextLookupStrategy;
-
- /** The {@link StorageService} used to store a client identifier for a given Issuer. */
- @NonnullAfterInit private StorageService storageService;
-
- /**
- * A storage service serializer for serializing and deserializing ClientAuthenticationRecords out of
- * storage records.
- */
- @Nonnull private StorageSerializer<ClientAuthenticationRecord> storageSerializer;
-
- /** Constructor. */
- public StorageServiceBackedClientAuthenticationLookupStrategy() {
- oauth2ClientContextLookupStrategy = new ChildContextLookup<>(OAuth2ClientContext.class).compose(
- new ChildContextLookup<>(OIDCPeerEntityContext.class).compose(
- new OutboundMessageContextLookup()));
-
- storageSerializer = new ClientAuthenticationStorageRecordSerializer();
- }
-
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
-
- if (oauth2ClientContextLookupStrategy == null) {
- throw new ComponentInitializationException("OAuth2ClientContextLookupStrategy cannot be null");
- }
- if (storageService == null) {
- throw new ComponentInitializationException("StorageService cannot be null");
- }
- }
-
- /**
- * Set the storage serializer to use with the storage service.
- *
- * @param serializer the storage serializer
- */
- public void setStorageSerializer(final StorageSerializer<ClientAuthenticationRecord> serializer) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
-
- storageSerializer = Constraint.isNotNull(serializer, "Storage serializer can not be null");
- }
-
- /**
- * Set the strategy to lookup the {@link OAuth2ClientContext}
- * from the {@link ProfileRequestContext}.
- *
- * @param strgy the strategy.
- */
- public void setOAuth2ClientContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext, OAuth2ClientContext> strgy) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
-
- oauth2ClientContextLookupStrategy = Constraint.isNotNull(strgy,
- "OAuth2 client context lookup strategy cannot be null");
- }
-
- /**
- * Set the {@link StorageService} back-end to use.
- *
- * @param storage the back-end to use
- */
- public void setStorageService(@Nonnull final StorageService storage) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
-
- storageService = Constraint.isNotNull(storage, "StorageService cannot be null");
- }
-
- @Override
- @Nullable public ClientAuthentication apply(@Nonnull final ProfileRequestContext profileRequestContext) {
- final OAuth2ClientContext clientCtx = oauth2ClientContextLookupStrategy.apply(profileRequestContext);
- if (clientCtx == null || StringSupport.trimOrNull(clientCtx.getClientId()) == null) {
- return null;
- }
- try {
- final StorageRecord<ClientAuthenticationRecord> record =
- storageService.read(CONTEXT_NAME, clientCtx.getClientId());
- if (record != null) {
- final ClientAuthenticationRecord clientAuthRecord =
- record.getValue(storageSerializer, CONTEXT_NAME, clientCtx.getClientId());
- return constructClientAuthentication(clientCtx.getClientId(),
- clientAuthRecord.getTokenEndpointAuthMethod(),
- clientAuthRecord.getClientSecret());
- }
- } catch (final IOException e) {
- log.debug("{}: Error retrieving client_authentication record from the storage service", getId(), e);
- return null;
- }
- return null;
- }
-
-
-
- /** A Storage service serializer for converting between ClientAuthenticationRecords and JSON.*/
- private static class ClientAuthenticationStorageRecordSerializer
- implements StorageSerializer<ClientAuthenticationRecord> {
-
- /** Class logger. */
- private final Logger log = LoggerFactory.getLogger(ClientAuthenticationStorageRecordSerializer.class);
-
- @Override
- public boolean isInitialized() {
- // Is initialized once created
- return true;
- }
-
- @Override
- public void initialize() throws ComponentInitializationException {
- //no-op here, does not need to be called.
- }
-
- @Override
- public String serialize(final ClientAuthenticationRecord instance) throws IOException {
-
- final StringWriter sink = new StringWriter(128);
-
- try (final JsonGenerator gen = Json.createGenerator(sink)) {
-
- final String secretExpiryTimeSinceEpochUTC = Long.toString(
- instance.getClientSecret().getExpirationDate().toInstant().getEpochSecond());
- gen.writeStartObject()
- .write("token_endpoint_auth_method", instance.getTokenEndpointAuthMethod())
- .write("client_secret", instance.getClientSecret().getValue())
- .write("client_secret_expires_at", secretExpiryTimeSinceEpochUTC);
-
- gen.writeEnd().close();
-
- return sink.toString();
- } catch (final JsonException e) {
- log.error("Exception while serializing ClientAuthenticationRecord: {}", e.getMessage());
- throw new IOException("Exception while serializing ClientAuthenticationRecord", e);
- }
- }
-
- @Override
- public ClientAuthenticationRecord deserialize(
- final long version, final String context, final String key, final String value,
- final Long expiration) throws IOException {
-
- try (final JsonReader reader = Json.createReader(new StringReader(value))) {
-
- final JsonStructure st = reader.read();
- if (!(st instanceof JsonObject)) {
- throw new IOException("Found invalid data structure while parsing ClientAuthenticationRecord");
- }
- final JsonObject obj = (JsonObject) st;
-
- final String tokenEndpointAuthMethod = obj.getString("token_endpoint_auth_method");
- final String secret = obj.getString("client_secret");
- final long expiryInSeconds = obj.getJsonNumber("client_secret_expires_at").longValueExact();
-
- if (expiryInSeconds == 0) {
- // Then no expiry
- return new ClientAuthenticationRecord(tokenEndpointAuthMethod, new Secret(secret));
- } else {
- final Instant secretExpiration = Instant.ofEpochSecond(expiryInSeconds);
- return new ClientAuthenticationRecord(
- tokenEndpointAuthMethod, new Secret(secret, Date.from(secretExpiration)));
- }
-
-
-
-
- } catch (final NullPointerException | ClassCastException | ArithmeticException | JsonException e) {
- log.error("Exception while parsing ClientAuthenticationRecord: {}", e.getMessage());
- throw new IOException("Found invalid data structure while parsing ClientAuthenticationRecord", e);
- }
- }
-
- }
-
- /**
- * A client authentication record that is serialized in and out of a storage service.
- */
- @Immutable
- private static class ClientAuthenticationRecord {
-
- /** The client authentication method for the token endpoint.*/
- @Nonnull private final String tokenEndpointAuthMethod;
-
- /** the client secret.*/
- @Nonnull private final Secret clientSecret;
-
- /**
- * Constructor.
- *
- * @param authMethod the client authentication method
- * @param secret the client secret
- */
- public ClientAuthenticationRecord(@Nonnull final String authMethod, @Nonnull final Secret secret) {
- tokenEndpointAuthMethod =
- Constraint.isNotEmpty(authMethod, "Authentication method type can not be null or empty");
- clientSecret = Constraint.isNotNull(secret, "Client Secrete can not be null");
- }
-
- /**
- * Get the token_endpoint_auth_method.
- *
- * @return Returns the tokenEndpointAuthMethod.
- */
- public final String getTokenEndpointAuthMethod() {
- return tokenEndpointAuthMethod;
- }
-
- /**
- * Get the client_sercret.
- *
- * @return Returns the clientSecret.
- */
- public final Secret getClientSecret() {
- return clientSecret;
- }
-
- }
-
-}
diff --git a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/StorageServiceBackedClientIdentifierLookupStrategy.java b/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/StorageServiceBackedClientIdentifierLookupStrategy.java
deleted file mode 100644
index 8270037..0000000
--- a/idp-oidc-rp-impl/src/main/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/StorageServiceBackedClientIdentifierLookupStrategy.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.config;
-
-import java.io.IOException;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.storage.StorageRecord;
-import org.opensaml.storage.StorageService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import net.shibboleth.oidc.metadata.context.OIDCProviderMetadataContext;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-
-/**
- * Default strategy for locating a client_id in the storage service based on the issuer_id found
- * in the provider metadata.
- */
-public class StorageServiceBackedClientIdentifierLookupStrategy extends AbstractIdentifiableInitializableComponent
- implements Function<ProfileRequestContext, String> {
-
- /** The context name in the {@link StorageService}. */
- @Nonnull @NotEmpty public static final String CONTEXT_NAME = "oauth2ClientIdentifier";
-
- /** Class logger. */
- private final Logger log = LoggerFactory.getLogger(StorageServiceBackedClientIdentifierLookupStrategy.class);
-
- /** Lookup strategy to locate the provider metadata to use.*/
- @NonnullAfterInit
- private Function<ProfileRequestContext, OIDCProviderMetadataContext> providerMetadataLookupStrategy;
-
- /** The {@link StorageService} used to store a client_id for a given issuer_id. */
- @NonnullAfterInit private StorageService storageService;
-
-
- /**
- * Set the lookup strategy to locate the OpenID providers metadata.
- *
- * @param strategy the strategy.
- */
- public void setProviderMetadataLookupStrategy(
- @Nonnull final Function<ProfileRequestContext, OIDCProviderMetadataContext> strategy) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
-
- providerMetadataLookupStrategy =
- Constraint.isNotNull(strategy,"Provider metadata lookup strategy can not be null");
- }
-
- @Override
- public void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
- if (storageService == null) {
- throw new ComponentInitializationException(getId() + ": StorageService cannot be null");
- }
- if (providerMetadataLookupStrategy == null) {
- throw new ComponentInitializationException(
- getId() + ": OIDC Provider metadata lookup strategy cannot be null");
- }
- }
-
- /**
- * Set the {@link StorageService} back-end to use.
- *
- * @param storage the back-end to use
- */
- public void setStorageService(@Nonnull final StorageService storage) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
-
- storageService = Constraint.isNotNull(storage, "StorageService cannot be null");
- }
-
- @Override
- @Nullable public String apply(@Nonnull final ProfileRequestContext profileRequestContext) {
-
- final OIDCProviderMetadataContext providerMetadataContext =
- providerMetadataLookupStrategy.apply(profileRequestContext);
- if (providerMetadataContext == null || providerMetadataContext.getProviderInformation() == null) {
- log.warn("{} No provider metadata found for peer, nothing to do", getId());
- return null;
- }
-
- try {
- final StorageRecord<?> record =
- storageService.read(CONTEXT_NAME,
- providerMetadataContext.getProviderInformation().getIssuer().getValue());
- if (record != null) {
- return record.getValue();
- }
- } catch (final IOException e) {
- log.warn(getId() + "{}: StorageService read failed, could not acquire client_id for issuer {}", getId(),
- providerMetadataContext.getProviderInformation().getIssuer(), e);
- }
- return null;
- }
-
-}
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 573f224..5feae96 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
@@ -32,43 +32,21 @@
p:deniedUserInfoAttributes="%{idp.authn.oidc.rp.deniedUserInfoAttributes:}"
p:clientIdLookupStrategy="#{getObject('shibboleth.authn.oidc.rp.ClientIdentifierLookupStrategy') ?: getObject('shibboleth.authn.oidc.rp.DefaultClientIdentifierLookupStrategy')}"
p:clientAuthenticationLookupStrategy="#{getObject('shibboleth.authn.oidc.rp.ClientAuthenticationLookupStrategy') ?: getObject('shibboleth.authn.oidc.rp.DefaultClientAuthenticationLookStrategy')}" />
-
<bean id="shibboleth.authn.oidc.rp.DefaultClientAuthenticationLookStrategy"
class="net.shibboleth.idp.plugin.authn.oidc.rp.config.DefaultClientAuthenticationLookupStrategy"
- c:clientId="%{idp.authn.oidc.rp.client.clientId:#{null}}"
- c:clientSecret="%{idp.authn.oidc.rp.client.clientSecret:#{null}}"
- c:clientAuthenticationMethod="%{idp.authn.oidc.rp.client.clientAuthenticationMethod:client_secret_basic}"
- c:clientSecretExpiresAt="%{idp.authn.oidc.rp.client.clientSecretExpiresAt:PT0S}"
- c:clientIdLookupStrategy="#{getObject('shibboleth.authn.oidc.rp.EmbeddedClientAuthenticationLookupStrategy') ?: getObject('shibboleth.authn.oidc.rp.StorageServiceBackedClientAuthenticationLookStrategy')}"/>
-
+ p:clientId="%{idp.authn.oidc.rp.client.clientId:#{null}}"
+ p:clientSecret="%{idp.authn.oidc.rp.client.clientSecret:#{null}}"
+ p:clientAuthenticationMethod="%{idp.authn.oidc.rp.client.clientAuthenticationMethod:client_secret_basic}"
+ p:clientSecretExpiresAt="%{idp.authn.oidc.rp.client.clientSecretExpiresAt:PT0S}"
+ p:clientIdToClientAuthenticationMap="#{getObject('shibboleth.authn.oidc.rp.ClientIdToClientAuthenticationMap')}"/>
<bean id="shibboleth.authn.oidc.rp.DefaultClientIdentifierLookupStrategy" lazy-init="true"
class="net.shibboleth.idp.plugin.authn.oidc.rp.config.DefaultClientIdentifierLookupStrategy"
c:clientId="%{idp.authn.oidc.rp.client.clientId:#{null}}"
- c:clientIdLookupStrategy="#{getObject('shibboleth.authn.oidc.rp.EmbeddedClientIdentifierLookupStrategy') ?: getObject('shibboleth.authn.oidc.rp.StorageServiceBackedClientIdentifierLookupStrategy')}"/>
-
- <bean id="shibboleth.authn.oidc.rp.StorageServiceBackedClientIdentifierLookupStrategy" lazy-init="true"
- class="net.shibboleth.idp.plugin.authn.oidc.rp.config.StorageServiceBackedClientIdentifierLookupStrategy"
- p:providerMetadataLookupStrategy-ref="shibboleth.ChildLookup.OIDCProviderMetadataContextFromOutbound"
- p:storageService="#{getObject('shibboleth.authn.oidc.rp.StorageService') ?: getObject('shibboleth.authn.oidc.rp.DefaultMapBackedClientIdStorageService')}" />
+ c:issuerToClientIdMap="#{getObject('shibboleth.authn.oidc.rp.IssuerToClientIdMap')}"
+ c:providerMetadataLookupStrategy-ref="shibboleth.ChildLookup.OIDCProviderMetadataContextFromOutbound"/>
- <bean id="shibboleth.authn.oidc.rp.DefaultMapBackedClientIdStorageService" scope="prototype"
- class="net.shibboleth.idp.plugin.authn.oidc.rp.config.MapBackedMemoryStorageServiceFactoryBean"
- c:context="#{T(net.shibboleth.idp.plugin.authn.oidc.rp.config.StorageServiceBackedClientIdentifierLookupStrategy).CONTEXT_NAME}"
- c:map="#{getObject('shibboleth.authn.oidc.rp.IssuerToClientIdMap')}"
- c:id="DefaultIssuerToClientIDMapStorageService" />
-
- <bean id="shibboleth.authn.oidc.rp.StorageServiceBackedClientAuthenticationLookStrategy" lazy-init="true"
- class="net.shibboleth.idp.plugin.authn.oidc.rp.config.StorageServiceBackedClientAuthenticationLookupStrategy"
- p:storageService="#{getObject('shibboleth.authn.oidc.rp.ClientAuthenticationStorageService') ?: getObject('shibboleth.authn.oidc.rp.DefaultMapBackedClientAuthenticationStorageService')}" />
-
- <bean id="shibboleth.authn.oidc.rp.DefaultMapBackedClientAuthenticationStorageService" lazy-init="true"
- class="net.shibboleth.idp.plugin.authn.oidc.rp.config.MapBackedMemoryStorageServiceFactoryBean"
- c:context="#{T(net.shibboleth.idp.plugin.authn.oidc.rp.config.StorageServiceBackedClientAuthenticationLookupStrategy).CONTEXT_NAME}"
- c:map="#{getObject('shibboleth.authn.oidc.rp.ClientIdToClientAuthenticationMap')}"
- c:id="DefaultClientIDToClientAuthenticationMapStorageService" />
-
<!-- Client Authentication parent bean which defaults secrets to not expire -->
<bean id="shibboleth.authn.oidc.rp.ClientAuthenticationDetails"
class="net.shibboleth.idp.plugin.authn.oidc.rp.storage.ClientAuthenticationDetails" abstract="true"
diff --git a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientAuthenticationLookupStrategyTest.java b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientAuthenticationLookupStrategyTest.java
index 60d257e..50359d5 100644
--- a/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientAuthenticationLookupStrategyTest.java
+++ b/idp-oidc-rp-impl/src/test/java/net/shibboleth/idp/plugin/authn/oidc/rp/config/DefaultClientAuthenticationLookupStrategyTest.java
@@ -23,16 +23,20 @@ import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.time.Duration;
+import java.time.Instant;
+import java.util.Map;
+import org.opensaml.messaging.context.MessageContext;
import org.opensaml.profile.context.ProfileRequestContext;
import org.testng.annotations.Test;
import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
import com.nimbusds.oauth2.sdk.auth.ClientSecretPost;
-import com.nimbusds.oauth2.sdk.auth.Secret;
-import com.nimbusds.oauth2.sdk.id.ClientID;
+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.storage.ClientAuthenticationDetails;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
/** Tests for the DefaultClientAuthenticationLookupStrategy.*/
@@ -43,8 +47,11 @@ public class DefaultClientAuthenticationLookupStrategyTest {
@Test
public void testBuildFromProperties() throws ComponentInitializationException {
- strategy = new DefaultClientAuthenticationLookupStrategy("client_id", "client_secret", "client_secret_basic",
- Duration.ofSeconds(0), s -> null);
+ strategy = new DefaultClientAuthenticationLookupStrategy();
+ strategy.setClientId("client_id");
+ strategy.setClientSecret("client_secret".toCharArray());
+ strategy.setClientSecretExpiresAt(Duration.ofSeconds(0));
+ strategy.setClientAuthenticationMethod("client_secret_basic");
strategy.setId("MockAuthenticationLookupStrategy");
strategy.initialize();
@@ -55,10 +62,20 @@ public class DefaultClientAuthenticationLookupStrategyTest {
assertFalse(((ClientSecretBasic)clientAuth).getClientSecret().expired());
}
+ @Test(expectedExceptions = ComponentInitializationException.class)
+ public void testInitialisationFailed() throws ComponentInitializationException {
+ strategy = new DefaultClientAuthenticationLookupStrategy();
+ strategy.setId("MockAuthenticationLookupStrategy");
+ strategy.initialize();
+ }
+
@Test
public void testBuildFromProperties_SecretExpired() throws ComponentInitializationException {
- strategy = new DefaultClientAuthenticationLookupStrategy("client_id", "client_secret", "client_secret_basic",
- Duration.ofSeconds(1), s -> null);
+ strategy = new DefaultClientAuthenticationLookupStrategy();
+ strategy.setClientId("client_id");
+ strategy.setClientSecret("client_secret".toCharArray());
+ strategy.setClientSecretExpiresAt(Duration.ofSeconds(1));
+ strategy.setClientAuthenticationMethod("client_secret_basic");
strategy.setId("MockAuthenticationLookupStrategy");
strategy.initialize();
@@ -67,13 +84,22 @@ public class DefaultClientAuthenticationLookupStrategyTest {
}
@Test
- public void testBuildFromStrategy() throws ComponentInitializationException {
- strategy = new DefaultClientAuthenticationLookupStrategy(null, null, null,
- null, s -> new ClientSecretPost(new ClientID("client_id"), new Secret("client_secret")));
+ public void testBuildFromMap() throws ComponentInitializationException {
+ strategy = new DefaultClientAuthenticationLookupStrategy();
+ strategy.setClientIdToClientAuthenticationMap(
+ Map.of("client_id",
+ new ClientAuthenticationDetails("client_secret".toCharArray(), 0, "client_secret_post")));
strategy.setId("MockAuthenticationLookupStrategy");
strategy.initialize();
- final ClientAuthentication clientAuth = strategy.apply(new ProfileRequestContext());
+ final var prc = new ProfileRequestContext();
+ final var outBnd = new MessageContext();
+ final var clientContext = outBnd.getSubcontext(OIDCPeerEntityContext.class, true)
+ .getSubcontext(OAuth2ClientContext.class,true);
+ clientContext.setClientId("client_id");
+ prc.setOutboundMessageContext(outBnd);
+
+ final ClientAuthentication clientAuth = strategy.apply(prc);
assertEquals(clientAuth.getClientID().getValue(), "client_id");
assertTrue(clientAuth instanceof ClientSecretPost);
assertEquals(((ClientSecretPost)clientAuth).getClientSecret().getValue(), "client_secret");
@@ -82,16 +108,81 @@ public class DefaultClientAuthenticationLookupStrategyTest {
@Test
public void testBuildFromStrategy_PartialClientProperties() throws ComponentInitializationException {
- strategy = new DefaultClientAuthenticationLookupStrategy("client_id", "client_secret", null,
- null, s -> new ClientSecretPost(new ClientID("client_id"), new Secret("client_secret")));
+ strategy = new DefaultClientAuthenticationLookupStrategy();
+ strategy.setClientId("client_id_static");
+ strategy.setClientSecret("client_secret_static".toCharArray());
+ strategy.setClientSecretExpiresAt(null);
+ strategy.setClientAuthenticationMethod(null);
+ strategy.setClientIdToClientAuthenticationMap(
+ Map.of("client_id",
+ new ClientAuthenticationDetails("client_secret".toCharArray(), 0, "client_secret_post")));
strategy.setId("MockAuthenticationLookupStrategy");
strategy.initialize();
- final ClientAuthentication clientAuth = strategy.apply(new ProfileRequestContext());
+ final var prc = new ProfileRequestContext();
+ final var outBnd = new MessageContext();
+ final var clientContext = outBnd.getSubcontext(OIDCPeerEntityContext.class, true)
+ .getSubcontext(OAuth2ClientContext.class,true);
+ clientContext.setClientId("client_id");
+ prc.setOutboundMessageContext(outBnd);
+
+ final ClientAuthentication clientAuth = strategy.apply(prc);
assertEquals(clientAuth.getClientID().getValue(), "client_id");
assertTrue(clientAuth instanceof ClientSecretPost);
assertEquals(((ClientSecretPost)clientAuth).getClientSecret().getValue(), "client_secret");
assertFalse(((ClientSecretPost)clientAuth).getClientSecret().expired());
}
+
+ @Test
+ public void testBuildFromStrategy_PartialClientProperties_ExpiredSecret() throws ComponentInitializationException {
+ strategy = new DefaultClientAuthenticationLookupStrategy();
+ strategy.setClientId("client_id_static");
+ strategy.setClientSecret("client_secret_static".toCharArray());
+ strategy.setClientSecretExpiresAt(null);
+ strategy.setClientAuthenticationMethod(null);
+ strategy.setClientIdToClientAuthenticationMap(
+ Map.of("client_id",
+ new ClientAuthenticationDetails("client_secret".toCharArray(), 1, "client_secret_post")));
+ strategy.setId("MockAuthenticationLookupStrategy");
+ strategy.initialize();
+
+ final var prc = new ProfileRequestContext();
+ final var outBnd = new MessageContext();
+ final var clientContext = outBnd.getSubcontext(OIDCPeerEntityContext.class, true)
+ .getSubcontext(OAuth2ClientContext.class,true);
+ clientContext.setClientId("client_id");
+ prc.setOutboundMessageContext(outBnd);
+ final ClientAuthentication clientAuth = strategy.apply(prc);
+ assertNull(clientAuth);
+ }
+
+ @Test
+ public void testBuildFromStrategy_PartialClientProperties_SecretNearlyExpired()
+ throws ComponentInitializationException {
+ strategy = new DefaultClientAuthenticationLookupStrategy();
+ strategy.setClientId("client_id_static");
+ strategy.setClientSecret("client_secret_static".toCharArray());
+ strategy.setClientSecretExpiresAt(null);
+ strategy.setClientAuthenticationMethod(null);
+ strategy.setClientIdToClientAuthenticationMap(
+ Map.of("client_id",
+ new ClientAuthenticationDetails("client_secret".toCharArray(),
+ Instant.now().plus(Duration.ofSeconds(10)).getEpochSecond(), "client_secret_post")));
+ strategy.setId("MockAuthenticationLookupStrategy");
+ strategy.initialize();
+
+ final var prc = new ProfileRequestContext();
+ final var outBnd = new MessageContext();
+ final var clientContext = outBnd.getSubcontext(OIDCPeerEntityContext.class, true)
+ .getSubcontext(OAuth2ClientContext.class,true);
+ clientContext.setClientId("client_id");
+ prc.setOutboundMessageContext(outBnd);
+
+ final ClientAuthentication clientAuth = strategy.apply(prc);
+ assertEquals(clientAuth.getClientID().getValue(), "client_id");
+ assertTrue(clientAuth instanceof ClientSecretPost);
+ assertEquals(((ClientSecretPost)clientAuth).getClientSecret().getValue(), "client_secret");
+ assertFalse(((ClientSecretPost)clientAuth).getClientSecret().expired());
+ }
}
diff --git a/pom.xml b/pom.xml
index 05904f9..a0bde1c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
<idp.version>4.2.0-SNAPSHOT</idp.version>
<opensaml.groupId>org.opensaml</opensaml.groupId>
<opensaml.version>4.2.0-SNAPSHOT</opensaml.version>
- <oidc.common.version>1.2.0-SNAPSHOT</oidc.common.version>
+ <oidc.common.version>2.0.0-SNAPSHOT</oidc.common.version>
<checkstyle.configLocation>${project.basedir}/checkstyle.xml</checkstyle.configLocation>
</properties>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list