[java-idp-oidc] branch main updated: JCOMOIDC-184 - Move OAuth2Client authentication flow from OP to oidc-common
Codeberg
noreply at shibboleth.net
Fri Sep 18 14:19:36 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch main
in repository java-idp-oidc.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-oidc/commit/ea45363371deea56745854d00fd39dbc39b28a4b
The following commit(s) were added to refs/heads/main by this push:
new ea453633 JCOMOIDC-184 - Move OAuth2Client authentication flow from OP to oidc-common
ea453633 is described below
commit ea45363371deea56745854d00fd39dbc39b28a4b
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Sep 18 16:35:29 2026 +0300
JCOMOIDC-184 - Move OAuth2Client authentication flow from OP to oidc-common
https://shibboleth.atlassian.net/browse/JCOMOIDC-184
Deleted content that was moved to java-oidc-common and java-idp-plugin-oidc-config modules.
---
...thenticationJWTPayloadClaimsAuditExtractor.java | 99 -----
...tAuthenticationJWTTypeHeaderAuditExtractor.java | 75 ----
.../oidc/op/authn/audit/impl/package-info.java | 16 -
.../ExtractClientAuthenticationFromRequest.java | 176 --------
.../oidc/op/authn/impl/JWTCredentialValidator.java | 302 --------------
.../impl/OIDCClientInfoCredentialValidator.java | 177 --------
.../impl/ValidateClientAuthenticationType.java | 208 ----------
.../plugin/oidc/op/authn/impl/package-info.java | 19 -
.../META-INF/net.shibboleth.idp/postconfig.xml | 20 -
.../authn/OAuth2Client/OAuth2Client-beans.xml | 295 --------------
.../flows/authn/OAuth2Client/OAuth2Client-flow.xml | 43 --
...ExtractClientAuthenticationFromRequestTest.java | 206 ----------
.../op/authn/impl/JWTCredentialValidatorTest.java | 446 ---------------------
.../OIDCClientInfoCredentialValidatorTest.java | 159 --------
.../impl/ValidateClientAuthenticationTypeTest.java | 159 --------
15 files changed, 2400 deletions(-)
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/audit/impl/ClientAuthenticationJWTPayloadClaimsAuditExtractor.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/audit/impl/ClientAuthenticationJWTPayloadClaimsAuditExtractor.java
deleted file mode 100644
index cfa7a0b1..00000000
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/audit/impl/ClientAuthenticationJWTPayloadClaimsAuditExtractor.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.idp.plugin.oidc.op.authn.audit.impl;
-
-import java.text.ParseException;
-import java.util.Date;
-import java.util.Optional;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.opensaml.profile.context.ProfileRequestContext;
-
-import com.nimbusds.jwt.SignedJWT;
-import com.nimbusds.oauth2.sdk.auth.JWTAuthentication;
-
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext;
-import net.shibboleth.shared.annotation.ParameterName;
-import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.logic.Constraint;
-
-/** {@link Function} that returns the desired claim from the client authentication JWT payload. */
-public class ClientAuthenticationJWTPayloadClaimsAuditExtractor implements Function<ProfileRequestContext, String> {
-
- /** Strategy that will return {@link OAuth2ClientAuthenticationContext}. */
- @Nonnull private Function<ProfileRequestContext,OAuth2ClientAuthenticationContext> clientAuthContextLookupStrategy;
-
- /** The claim whose value is to be extracted. */
- @Nonnull @NotEmpty private final String key;
-
- /**
- * Constructor.
- *
- * @param claim Claim whose value is to be extracted
- */
- public ClientAuthenticationJWTPayloadClaimsAuditExtractor(
- @Nonnull @NotEmpty @ParameterName(name = "key") final String claim) {
- key = Constraint.isNotEmpty(claim, "The claim cannot be empty");
- // PRC -> AuthenticationContext -> OAuth2ClientAuthenticationContext
- final Function<ProfileRequestContext,OAuth2ClientAuthenticationContext> cacls =
- new ChildContextLookup<>(OAuth2ClientAuthenticationContext.class).compose(
- new ChildContextLookup<>(AuthenticationContext.class));
- assert cacls != null;
- clientAuthContextLookupStrategy = cacls;
- }
-
- /**
- * Constructor.
- *
- * @param claim Claim whose value is to be extracted
- * @param lookupStrategy Strategy that will return {@link OAuth2ClientAuthenticationContext}.
- */
- public ClientAuthenticationJWTPayloadClaimsAuditExtractor(
- @Nonnull @NotEmpty @ParameterName(name = "key") final String claim,
- @Nonnull @ParameterName(name = "clientAuthContextLookupStrategy")
- final Function<ProfileRequestContext,OAuth2ClientAuthenticationContext> lookupStrategy) {
- key = Constraint.isNotEmpty(claim, "key cannot be empty");
- clientAuthContextLookupStrategy =
- Constraint.isNotNull(lookupStrategy, "clientAuthContextLookupStrategy lookup strategy cannot be null");
- }
-
- /** {@inheritDoc} */
- @Nullable public String apply(@Nullable final ProfileRequestContext input) {
- final SignedJWT jwt = Optional.ofNullable(clientAuthContextLookupStrategy.apply(input))
- .map(ctx -> ctx.getClientAuthentication())
- .filter(JWTAuthentication.class::isInstance)
- .map(JWTAuthentication.class::cast)
- .map(jwtAuthentication -> jwtAuthentication.getClientAssertion())
- .orElse(null);
- try {
- final Object claim = jwt == null ? null : jwt.getJWTClaimsSet().getClaim(key);
- if (claim instanceof Date date) {
- return date.toInstant().toString();
- } else if (claim != null) {
- return claim.toString();
- } else {
- return null;
- }
- } catch (final ParseException e) {
- return null;
- }
- }
-
-}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/audit/impl/ClientAuthenticationJWTTypeHeaderAuditExtractor.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/audit/impl/ClientAuthenticationJWTTypeHeaderAuditExtractor.java
deleted file mode 100644
index 11436813..00000000
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/audit/impl/ClientAuthenticationJWTTypeHeaderAuditExtractor.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.idp.plugin.oidc.op.authn.audit.impl;
-
-import java.util.Optional;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.opensaml.profile.context.ProfileRequestContext;
-
-import com.nimbusds.oauth2.sdk.auth.JWTAuthentication;
-
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext;
-import net.shibboleth.shared.annotation.ParameterName;
-import net.shibboleth.shared.logic.Constraint;
-
-/** {@link Function} that returns the type header from the client authentication JWT payload. */
-public class ClientAuthenticationJWTTypeHeaderAuditExtractor implements Function<ProfileRequestContext, String> {
-
- /** Strategy that will return {@link OAuth2ClientAuthenticationContext}. */
- @Nonnull private Function<ProfileRequestContext,OAuth2ClientAuthenticationContext> clientAuthContextLookupStrategy;
-
- /**
- * Constructor.
- */
- public ClientAuthenticationJWTTypeHeaderAuditExtractor() {
- // PRC -> AuthenticationContext -> OAuth2ClientAuthenticationContext
- final Function<ProfileRequestContext,OAuth2ClientAuthenticationContext> cacls =
- new ChildContextLookup<>(OAuth2ClientAuthenticationContext.class).compose(
- new ChildContextLookup<>(AuthenticationContext.class));
- assert cacls != null;
- clientAuthContextLookupStrategy = cacls;
- }
-
- /**
- * Constructor.
- *
- * @param lookupStrategy Strategy that will return {@link OAuth2ClientAuthenticationContext}.
- */
- public ClientAuthenticationJWTTypeHeaderAuditExtractor(
- @Nonnull @ParameterName(name = "clientAuthContextLookupStrategy")
- final Function<ProfileRequestContext,OAuth2ClientAuthenticationContext> lookupStrategy) {
- clientAuthContextLookupStrategy =
- Constraint.isNotNull(lookupStrategy, "clientAuthContextLookupStrategy lookup strategy cannot be null");
- }
-
- /** {@inheritDoc} */
- @Nullable public String apply(@Nullable final ProfileRequestContext input) {
- return Optional.ofNullable(clientAuthContextLookupStrategy.apply(input))
- .map(ctx -> ctx.getClientAuthentication())
- .filter(JWTAuthentication.class::isInstance)
- .map(JWTAuthentication.class::cast)
- .map(jwtAuthentication -> jwtAuthentication.getClientAssertion())
- .map(jwt -> jwt.getHeader().getType())
- .map(joseType -> joseType.getType())
- .orElse(null);
- }
-
-}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/audit/impl/package-info.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/audit/impl/package-info.java
deleted file mode 100644
index 65ee5e57..00000000
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/audit/impl/package-info.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/** Package for audit extractors related to client authentication. */
-package net.shibboleth.idp.plugin.oidc.op.authn.audit.impl;
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ExtractClientAuthenticationFromRequest.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ExtractClientAuthenticationFromRequest.java
deleted file mode 100644
index ef0a65a5..00000000
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ExtractClientAuthenticationFromRequest.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.idp.plugin.oidc.op.authn.impl;
-
-import java.util.Set;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.profile.action.ActionSupport;
-import org.opensaml.profile.action.EventIds;
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.slf4j.Logger;
-
-import com.nimbusds.oauth2.sdk.AbstractOptionallyAuthenticatedRequest;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
-import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
-import com.nimbusds.oauth2.sdk.auth.ClientSecretPost;
-import com.nimbusds.oauth2.sdk.auth.TLSClientAuthentication;
-
-import net.shibboleth.idp.authn.AbstractExtractionAction;
-import net.shibboleth.idp.authn.AuthnEventIds;
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.idp.authn.context.CertificateContext;
-import net.shibboleth.idp.authn.context.UsernamePasswordContext;
-import net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext;
-import net.shibboleth.oidc.profile.config.navigate.TokenEndpointAuthMethodLookupFunction;
-import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-
-/**
- * Extracts OAuth 2 client authentication details from a request and stores them in an
- * {@link OAuth2ClientAuthenticationContext} beneath the {@link AuthenticationContext} for subsequent
- * validation.
- *
- * <p>Depending on the form of authentication, additional child contexts may be created to store
- * extracted credentials, and they may undergo configured transformations. For example, password-based
- * methods will result in a {@link UsernamePasswordContext}, certificate-based in an {@link CertificateContext},
- * etc.</p>
- *
- * @pre ProfileRequestContext.getSubcontext(AuthenticationContext.class) != null
- * @post AuthenticationContext.getSubcontext(OAuth2ClientAuthenticationContext.class) ! null
- * along with other contexts as appropriate
- * @event {@link EventIds#PROCEED_EVENT_ID}
- * @event {@link EventIds#INVALID_MSG_CTX}
- * @event {@link AuthnEventIds#NO_CREDENTIALS}
- */
-public class ExtractClientAuthenticationFromRequest extends AbstractExtractionAction {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(ExtractClientAuthenticationFromRequest.class);
-
- /** Lookup strategy for enabled client authentication methods. */
- @NonnullAfterInit private Function<ProfileRequestContext, Set<ClientAuthenticationMethod>>
- clientAuthMethodsLookupStrategy;
-
- /** Message to extract credentials from. */
- @Nullable private AbstractOptionallyAuthenticatedRequest request;
-
- /**
- * Constructor.
- */
- public ExtractClientAuthenticationFromRequest() {
- clientAuthMethodsLookupStrategy = new TokenEndpointAuthMethodLookupFunction();
- }
-
- /**
- * Set the lookup strategy for enabled client authentication methods.
- *
- * @param strategy What to set.
- */
- public void setClientAuthMethodsLookupStrategy(
- @Nonnull final Function<ProfileRequestContext, Set<ClientAuthenticationMethod>> strategy) {
- ifInitializedThrowUnmodifiabledComponentException();
-
- clientAuthMethodsLookupStrategy = Constraint.isNotNull(strategy,
- "Client authentication methods lookup strategy cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override
- protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext,
- @Nonnull final AuthenticationContext authenticationContext) {
- if (!super.doPreExecute(profileRequestContext, authenticationContext)) {
- return false;
- }
-
- if (profileRequestContext.getInboundMessageContext() != null) {
- final Object msg = profileRequestContext.ensureInboundMessageContext().getMessage();
- if (msg instanceof AbstractOptionallyAuthenticatedRequest aoar) {
- request = aoar;
- return true;
- }
- }
-
- log.warn("{} Inbound message missing or of incorrect type", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
- return false;
- }
-
-// Checkstyle: CyclomaticComplexity OFF
- /** {@inheritDoc} */
- @Override
- protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
- @Nonnull final AuthenticationContext authenticationContext) {
-
- assert request != null;
- final ClientAuthentication clientAuthentication = request.getClientAuthentication();
-
- final OAuth2ClientAuthenticationContext ctx =
- authenticationContext.ensureSubcontext(OAuth2ClientAuthenticationContext.class);
- ctx.setClientAuthentication(clientAuthentication);
-
- if (clientAuthentication == null) {
- log.debug("{} No OAuth client credentials in request", getLogPrefix());
- final Set<ClientAuthenticationMethod> methods =
- clientAuthMethodsLookupStrategy.apply(profileRequestContext);
- // Build event only if 'none' is not enabled in the profile configuration
- if (methods == null || !methods.contains(ClientAuthenticationMethod.NONE)) {
- ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
- }
- return;
- }
-
- // Note the Nimbus APIs appear to prevent the client ID or secret from being null.
-
- if (ClientAuthenticationMethod.CLIENT_SECRET_BASIC.equals(clientAuthentication.getMethod())) {
- final ClientSecretBasic basic = (ClientSecretBasic) clientAuthentication;
- if (basic.getClientID() != null && basic.getClientSecret() != null) {
- final UsernamePasswordContext upContext = new UsernamePasswordContext();
- upContext.setUsername(applyTransforms(basic.getClientID().getValue()))
- .setPassword(basic.getClientSecret().getValue());
- authenticationContext.addSubcontext(upContext, true);
- } else {
- log.warn("{} No OAuth client credentials in basic-auth request?", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
- }
- } else if (ClientAuthenticationMethod.CLIENT_SECRET_POST.equals(clientAuthentication.getMethod())) {
- final ClientSecretPost post = (ClientSecretPost) clientAuthentication;
- if (post.getClientID() != null && post.getClientSecret() != null) {
- final UsernamePasswordContext upContext = new UsernamePasswordContext();
- upContext.setUsername(applyTransforms(post.getClientID().getValue()))
- .setPassword(post.getClientSecret().getValue());
- authenticationContext.addSubcontext(upContext, true);
- } else {
- log.warn("{} No OAuth client credentials in POST request?", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
- }
- } else if (ClientAuthenticationMethod.TLS_CLIENT_AUTH.equals(clientAuthentication.getMethod()) ||
- ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH.equals(clientAuthentication.getMethod())) {
- final TLSClientAuthentication tls = (TLSClientAuthentication) clientAuthentication;
- if (tls.getClientX509Certificate() != null) {
- final CertificateContext certContext = new CertificateContext();
- certContext.setCertificate(tls.getClientX509Certificate());
- authenticationContext.addSubcontext(certContext, true);
- }
- }
- }
-// Checkstyle: CyclomaticComplexity ON
-
-}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java
deleted file mode 100644
index 67b545b5..00000000
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidator.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.idp.plugin.oidc.op.authn.impl;
-
-import java.text.ParseException;
-import java.util.Optional;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-import net.shibboleth.idp.authn.AbstractCredentialValidator;
-import net.shibboleth.idp.authn.AuthnEventIds;
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.idp.authn.principal.UsernamePrincipal;
-import net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext;
-import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
-import net.shibboleth.oidc.jwt.claims.JWTValidationException;
-import net.shibboleth.oidc.profile.config.navigate.ClaimsValidatorLookupFunction;
-import net.shibboleth.oidc.profile.config.navigate.ClientAuthenticationJWTTypeLookupFunction;
-import net.shibboleth.oidc.security.jose.context.SecurityParametersContext;
-import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.primitive.StringSupport;
-
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
-import org.slf4j.Logger;
-
-import com.nimbusds.jwt.JWTClaimsSet;
-import com.nimbusds.jwt.SignedJWT;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
-import com.nimbusds.oauth2.sdk.auth.JWTAuthentication;
-import com.nimbusds.oauth2.sdk.id.ClientID;
-
-/**
- * A validator that handles authentication via signed JWT.
- *
- * <p>For now, implemented via Nimbus APIs.</p>
- *
- * TODO: there will be additional validation checks added once implemented on the older branch
- */
- at ThreadSafeAfterInit
-public class JWTCredentialValidator extends AbstractCredentialValidator {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(JWTCredentialValidator.class);
-
- /** Strategy that will return {@link OAuth2ClientAuthenticationContext}. */
- @Nonnull private Function<ProfileRequestContext,OAuth2ClientAuthenticationContext> clientAuthContextLookupStrategy;
-
- /** Strategy used to locate the {@link SecurityParametersContext} to use for verification. */
- @Nonnull private Function<ProfileRequestContext,SecurityParametersContext> securityParametersLookupStrategy;
-
- /** Strategy used to obtain {@link ClaimsValidator}. */
- @Nonnull private Function<ProfileRequestContext,ClaimsValidator> claimsValidatorLookupStrategy;
-
- /** Strategy used to fetch required JWT type header value. */
- @Nonnull private Function<ProfileRequestContext,String> requiredJwtTypeHeaderLookupStrategy;
-
- /** Whether to save the JWT in the Java Subject's public credentials. */
- private boolean saveTokenToCredentialSet;
-
- /** Constructor. */
- public JWTCredentialValidator() {
- // PRC -> AuthenticationContext -> OAuth2ClientAuthenticationContext
- final Function<ProfileRequestContext,OAuth2ClientAuthenticationContext> cacls =
- new ChildContextLookup<>(OAuth2ClientAuthenticationContext.class).compose(
- new ChildContextLookup<>(AuthenticationContext.class));
- assert cacls != null;
- clientAuthContextLookupStrategy = cacls;
- // PRC -> INBOUND -> SPC
- final Function<ProfileRequestContext,SecurityParametersContext> spls =
- new ChildContextLookup<>(SecurityParametersContext.class).compose(
- new InboundMessageContextLookup());
- assert spls != null;
- securityParametersLookupStrategy = spls;
-
- claimsValidatorLookupStrategy = new ClaimsValidatorLookupFunction();
- requiredJwtTypeHeaderLookupStrategy = new ClientAuthenticationJWTTypeLookupFunction();
- }
-
- /**
- * Set the strategy used to return the {@link OAuth2ClientAuthenticationContext}.
- *
- * @param strategy lookup strategy
- */
- public void setOAuth2ClientAuthenticationLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,OAuth2ClientAuthenticationContext> strategy) {
- ifInitializedThrowUnmodifiabledComponentException();
-
- clientAuthContextLookupStrategy =
- Constraint.isNotNull(strategy, "OAuth2ClientAuthenticationContext lookup strategy cannot be null");
- }
-
- /**
- * Set the strategy used to locate the {@link SecurityParametersContext} to use.
- *
- * @param strategy lookup strategy
- */
- public void setSecurityParametersLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,SecurityParametersContext> strategy) {
- ifInitializedThrowUnmodifiabledComponentException();
-
- securityParametersLookupStrategy =
- Constraint.isNotNull(strategy, "SecurityParameterContext lookup strategy cannot be null");
- }
-
- /**
- * Set the strategy used to locate {@link ClaimsValidator} used.
- *
- * @param strategy lookup strategy
- */
- public void setClaimsValidatorLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,ClaimsValidator> strategy) {
- ifInitializedThrowUnmodifiabledComponentException();
-
- claimsValidatorLookupStrategy =
- Constraint.isNotNull(strategy, "ClaimsValidator lookup strategy cannot be null");
- }
-
- /**
- * Set whether to save the JWT in the Java Subject's public credentials.
- *
- * <p>Defaults to true</p>
- *
- * @param flag flag to set
- */
- public void setSaveTokenToCredentialSet(final boolean flag) {
- ifInitializedThrowUnmodifiabledComponentException();
-
- saveTokenToCredentialSet = flag;
- }
-
- /**
- * Set the strategy used to fetch required JWT type header value.
- *
- * @param strategy lookup strategy
- *
- * @since 4.3.0
- */
- public void setRequiredJwtTypeHeaderLookupStrategy(@Nonnull final Function<ProfileRequestContext,String> strategy) {
- checkSetterPreconditions();
-
- requiredJwtTypeHeaderLookupStrategy =
- Constraint.isNotNull(strategy, "RequiredJwtTypeHeaderLookupStrategy cannot be null");
- }
-
-// Checkstyle: CyclomaticComplexity OFF
- /** {@inheritDoc} */
- @Override
- @Nullable protected Subject doValidate(@Nonnull final ProfileRequestContext profileRequestContext,
- @Nonnull final AuthenticationContext authenticationContext,
- @Nullable final WarningHandler warningHandler,
- @Nullable final ErrorHandler errorHandler) throws Exception {
-
- final OAuth2ClientAuthenticationContext clientAuthContext =
- clientAuthContextLookupStrategy.apply(profileRequestContext);
- if (clientAuthContext == null) {
- log.debug("{} No OAuth 2.0 client authentication information found", getLogPrefix());
- return null;
- }
-
- final ClientAuthentication clientAuth = clientAuthContext.getClientAuthentication();
- if (clientAuth == null) {
- log.debug("{} No OAuth 2.0 client authentication information found", getLogPrefix());
- return null;
- }
- if (!ClientAuthenticationMethod.CLIENT_SECRET_JWT.equals(clientAuth.getMethod()) &&
- !ClientAuthenticationMethod.PRIVATE_KEY_JWT.equals(clientAuth.getMethod())) {
- log.debug("{} OAuth client authentication for '{}' of unsupported type: {}", getLogPrefix(),
- clientAuth.getClientID(), clientAuth.getMethod());
- return null;
- }
-
- if (!(clientAuth instanceof JWTAuthentication)) {
- log.warn("{} OAuth client authentication object of unexpected type: {}", getLogPrefix(),
- clientAuth.getClass().getSimpleName());
- log.info("{} Login by '{}' failed", getLogPrefix(), clientAuth.getClientID());
- final LoginException e = new LoginException(AuthnEventIds.INVALID_CREDENTIALS);
- if (errorHandler != null) {
- errorHandler.handleError(profileRequestContext, authenticationContext, e,
- AuthnEventIds.INVALID_CREDENTIALS);
- }
- throw e;
- }
-
- final JWTAuthentication jwtAuth = (JWTAuthentication) clientAuth;
- final SignedJWT clientAssertion = jwtAuth.getClientAssertion();
- final ClientID clientId = clientAuth.getClientID();
- assert clientAssertion != null;
- assert clientId != null;
- try {
- validateJWTClaims(profileRequestContext, clientAssertion, clientId);
- } catch (final Exception e) {
- log.info("{} Login by '{}' failed", getLogPrefix(), clientAuth.getClientID());
- if (errorHandler != null) {
- errorHandler.handleError(profileRequestContext, authenticationContext, e,
- AuthnEventIds.INVALID_CREDENTIALS);
- }
- throw e;
- }
-
- log.info("{} Login by '{}' succeeded", getLogPrefix(), clientAuth.getClientID());
-
- return populateSubject(clientId, clientAssertion);
- }
-// Checkstyle: CyclomaticComplexity ON
-
- /**
- * Validates the contents of the given JWT against the requirements set in the OIDC core specification section 9.
- *
- * @param jwt JWT to be validated
- * @param clientId client ID from which the JWT is coming from
- * @param profileRequestContext profile request context
- *
- * @throws ParseException if unable to parse the claim set
- * @throws JWTValidationException if the claims fail to validate
- */
- protected void validateJWTClaims(@Nonnull final ProfileRequestContext profileRequestContext,
- @Nonnull final SignedJWT jwt, @Nonnull final ClientID clientId)
- throws ParseException, JWTValidationException {
-
- final String requiredType = requiredJwtTypeHeaderLookupStrategy.apply(profileRequestContext);
- if (StringSupport.trimOrNull(requiredType) != null) {
- log.debug("{} Type header is required to be {}", getLogPrefix(), requiredType);
- final String type = Optional.ofNullable(jwt.getHeader().getType())
- .map(joseType -> joseType.getType())
- .orElse(null);
- if (!requiredType.equals(type)) {
- log.warn("{} JWT validation failed for client '{}': Invalid JWT type header {}",
- getLogPrefix(), clientId, type);
- throw new JWTValidationException("Invalid JWT type header " + type);
- }
- }
-
- final ClaimsValidator validator = claimsValidatorLookupStrategy.apply(profileRequestContext);
- if (validator == null) {
- log.warn("{} JWT validation failed for client '{}': No ClaimsValidator found in configuration",
- getLogPrefix(), clientId);
- throw new JWTValidationException("No ClaimsValidator found in configuration");
- }
-
- final JWTClaimsSet claimsSet;
- try {
- claimsSet = jwt.getJWTClaimsSet();
- } catch (final ParseException e) {
- log.warn("{} Could not parse the JWT from client '{}' into claims set", getLogPrefix(), clientId);
- throw e;
- }
-
- assert claimsSet != null;
- try {
- validator.validate(claimsSet, profileRequestContext);
- } catch (final JWTValidationException e) {
- log.warn("{} JWT validation failed for client '{}': {}", getLogPrefix(), clientId, e.getMessage());
- throw e;
- }
- }
-
- /**
- * Builds a subject with "standard" content from the validation.
- *
- * @param clientId client ID
- * @param token the token validated
- *
- * @return the decorated subject
- */
- @Nonnull protected Subject populateSubject(@Nonnull @NotEmpty final ClientID clientId,
- @Nonnull final SignedJWT token) {
-
- final Subject subject = new Subject();
- final String clientIdValue = clientId.getValue();
- if (clientIdValue != null) {
- subject.getPrincipals().add(new UsernamePrincipal(clientIdValue));
- if (saveTokenToCredentialSet) {
- subject.getPublicCredentials().add(token);
- }
- }
-
- return super.populateSubject(subject);
- }
-
-}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidator.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidator.java
deleted file mode 100644
index 6a46b6d0..00000000
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidator.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.idp.plugin.oidc.op.authn.impl;
-
-import java.security.NoSuchAlgorithmException;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-import net.shibboleth.idp.authn.AbstractUsernamePasswordCredentialValidator;
-import net.shibboleth.idp.authn.AuthnEventIds;
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.idp.authn.context.UsernamePasswordContext;
-import net.shibboleth.idp.authn.principal.UsernamePrincipal;
-import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
-import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.shared.codec.StringDigester;
-import net.shibboleth.shared.codec.StringDigester.OutputFormat;
-import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
-import org.slf4j.Logger;
-
-import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
-import com.nimbusds.oauth2.sdk.client.ClientMetadata;
-import com.nimbusds.oauth2.sdk.id.ClientID;
-import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
-
-/**
- * A password validator that authenticates against OIDC client metadata (which may itself be emulated
- * via SAML metadata).
- */
- at ThreadSafeAfterInit
-public class OIDCClientInfoCredentialValidator extends AbstractUsernamePasswordCredentialValidator {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(OIDCClientInfoCredentialValidator.class);
-
- /** Strategy that will return {@link OIDCMetadataContext}. */
- @Nonnull private Function<ProfileRequestContext,OIDCMetadataContext> oidcMetadataContextLookupStrategy;
-
- /** Digester for SHA-1. */
- @NonnullAfterInit private StringDigester digester;
-
- /** Constructor. */
- public OIDCClientInfoCredentialValidator() {
- final Function<ProfileRequestContext,OIDCMetadataContext> omcls =
- new ChildContextLookup<>(OIDCMetadataContext.class).compose(
- new InboundMessageContextLookup());
- assert omcls != null;
- oidcMetadataContextLookupStrategy = omcls;
- }
-
- /**
- * Set the strategy used to return the {@link OIDCMetadataContext}.
- *
- * @param strategy The lookup strategy.
- */
- public void setOidcMetadataContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext,OIDCMetadataContext> strategy) {
- ifInitializedThrowUnmodifiabledComponentException();
-
- oidcMetadataContextLookupStrategy =
- Constraint.isNotNull(strategy, "OIDCMetadataContext lookup strategy cannot be null");
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doInitialize() throws ComponentInitializationException {
- super.doInitialize();
-
- try {
- digester = new StringDigester("SHA-256", OutputFormat.BASE64);
- } catch (final NoSuchAlgorithmException e) {
- throw new ComponentInitializationException("Error creating digester", e);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected Subject doValidate(@Nonnull final ProfileRequestContext profileRequestContext,
- @Nonnull final AuthenticationContext authenticationContext,
- @Nullable final WarningHandler warningHandler,
- @Nullable final ErrorHandler errorHandler) throws Exception {
-
- final OIDCMetadataContext oidcMetadataContext = oidcMetadataContextLookupStrategy.apply(profileRequestContext);
-
- if (oidcMetadataContext == null || oidcMetadataContext.getClientInformation() == null ) {
- log.debug("{} OIDC client metadata is missing", getLogPrefix());
- return null;
- }
-
- final OIDCClientInformation clientInformation = oidcMetadataContext.getClientInformation();
- assert clientInformation != null;
- final ClientMetadata clientMetadata = clientInformation.getMetadata();
- assert clientMetadata != null;
- if (ClientAuthenticationMethod.NONE.equals(clientMetadata.getTokenEndpointAuthMethod())) {
- log.debug("{} OIDC client metadata contains 'none' type for endpoint authentication");
- final Subject subject = new Subject();
- final ClientID clientId = clientInformation.getID();
- assert clientId != null;
- final String clientIdValue = clientId.getValue();
- if (clientIdValue != null) {
- subject.getPrincipals().add(new UsernamePrincipal(applyTransforms(clientIdValue)));
- }
- return super.populateSubject(subject);
- } else if (clientInformation.getSecret() == null) {
- log.debug("{} OIDC client metadata for '{}' missing client secret", getLogPrefix(),
- clientInformation.getID());
- return null;
- }
-
- return super.doValidate(profileRequestContext, authenticationContext, warningHandler, errorHandler);
- }
-
- /** {@inheritDoc} */
- @Override
- @Nullable protected Subject doValidate(@Nonnull final ProfileRequestContext profileRequestContext,
- @Nonnull final AuthenticationContext authenticationContext,
- @Nonnull final UsernamePasswordContext usernamePasswordContext,
- @Nullable final WarningHandler warningHandler,
- @Nullable final ErrorHandler errorHandler) throws Exception {
-
- final OIDCMetadataContext oidcMetadataContext = oidcMetadataContextLookupStrategy.apply(profileRequestContext);
- if (oidcMetadataContext == null || oidcMetadataContext.getClientInformation() == null ) {
- log.debug("{} OIDC client metadata is missing", getLogPrefix());
- return null;
- }
-
- final OIDCClientInformation clientInformation = oidcMetadataContext.getClientInformation();
- assert clientInformation != null;
-
- final String username = usernamePasswordContext.getTransformedUsername();
- log.debug("{} Attempting to authenticate effective client ID '{}' ", getLogPrefix(), username);
-
- final String secret = clientInformation.getSecret().getValue();
- if (secret.startsWith("{SHA2}")) {
- if (secret.substring(6).equals(digester.apply(usernamePasswordContext.getPassword()))) {
- log.info("{} Login by '{}' succeeded", getLogPrefix(), username);
- return populateSubject(new Subject(), usernamePasswordContext);
- }
- } else if (secret.equals(usernamePasswordContext.getPassword())) {
- log.info("{} Login by '{}' succeeded", getLogPrefix(), username);
- return populateSubject(new Subject(), usernamePasswordContext);
- }
-
- log.info("{} Login by '{}' failed", getLogPrefix(), username);
-
- final LoginException e = new LoginException(AuthnEventIds.INVALID_CREDENTIALS);
- if (errorHandler != null) {
- errorHandler.handleError(profileRequestContext, authenticationContext, e,
- AuthnEventIds.INVALID_CREDENTIALS);
- }
- throw e;
- }
-
-}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ValidateClientAuthenticationType.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ValidateClientAuthenticationType.java
deleted file mode 100644
index b9539ffd..00000000
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ValidateClientAuthenticationType.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.idp.plugin.oidc.op.authn.impl;
-
-import java.util.Collections;
-import java.util.Set;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.opensaml.profile.action.ActionSupport;
-import org.opensaml.profile.action.EventIds;
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
-import org.slf4j.Logger;
-
-import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
-import com.nimbusds.oauth2.sdk.id.ClientID;
-import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
-import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
-
-import net.shibboleth.idp.authn.AbstractAuthenticationAction;
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext;
-import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
-import net.shibboleth.oidc.profile.config.navigate.TokenEndpointAuthMethodLookupFunction;
-import net.shibboleth.shared.annotation.constraint.NonnullElements;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.LoggerFactory;
-
-/**
- * Validates the client authentication type with the token_endpoint_auth_method stored in the client's metadata
- * and the profile configuration.
- *
- * <p>In the absence of metadata, the profile configuration is used alone.</p>
- *
- * @pre {@link OIDCMetadataContext} is available
- * @pre AuthenticationContext.getSubcontext(OAuth2ClientAuthenticationContext.class) != null
- * @event {@link EventIds#PROCEED_EVENT_ID}
- * @event {@link EventIds#ACCESS_DENIED}
- */
-public class ValidateClientAuthenticationType extends AbstractAuthenticationAction {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(ValidateClientAuthenticationType.class);
-
- /** Strategy that will return {@link OIDCMetadataContext}. */
- @Nonnull private Function<ProfileRequestContext,OIDCMetadataContext> oidcMetadataContextLookupStrategy;
-
- /** Strategy to obtain enabled token endpoint authentication methods. */
- @Nonnull private Function<ProfileRequestContext,Set<ClientAuthenticationMethod>>
- tokenEndpointAuthMethodsLookupStrategy;
-
- /** The attached OIDC metadata context. */
- @Nullable private OIDCMetadataContext oidcMetadataContext;
-
- /** The extracted client authentication information. */
- @Nullable private ClientAuthentication clientAuthentication;
-
- /** Enabled client authn methods. */
- @Nullable @NonnullElements private Set<ClientAuthenticationMethod> enabledMethods;
-
- /**
- * Constructor.
- */
- public ValidateClientAuthenticationType() {
- final Function<ProfileRequestContext,OIDCMetadataContext> omcls =
- new ChildContextLookup<>(OIDCMetadataContext.class).compose(
- new InboundMessageContextLookup());
- assert omcls != null;
- oidcMetadataContextLookupStrategy = omcls;
- tokenEndpointAuthMethodsLookupStrategy = new TokenEndpointAuthMethodLookupFunction();
- }
-
- /**
- * Set the strategy used to return the {@link OIDCMetadataContext}.
- *
- * @param strategy The lookup strategy.
- */
- public void setOIDCMetadataContextLookupStrategy(
- @Nonnull final Function<ProfileRequestContext, OIDCMetadataContext> strategy) {
- checkSetterPreconditions();
-
- oidcMetadataContextLookupStrategy =
- Constraint.isNotNull(strategy, "OIDCMetadataContext lookup strategy cannot be null");
- }
-
- /**
- * Set strategy to obtain enabled token endpoint authentication methods.
- * @param strategy What to set.
- */
- public void setTokenEndpointAuthMethodsLookupStrategy(@Nonnull final Function<ProfileRequestContext,
- Set<ClientAuthenticationMethod>> strategy) {
- checkSetterPreconditions();
-
- tokenEndpointAuthMethodsLookupStrategy = Constraint.isNotNull(strategy,
- "Strategy to obtain enabled token endpoint authentication methods cannot be null");
-
- }
-
- /** {@inheritDoc} */
- @Override
- protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext,
- @Nonnull final AuthenticationContext authenticationContext) {
- if (!super.doPreExecute(profileRequestContext, authenticationContext)) {
- return false;
- }
-
- final OAuth2ClientAuthenticationContext oauth2Ctx =
- authenticationContext.getSubcontext(OAuth2ClientAuthenticationContext.class);
- if (oauth2Ctx != null) {
- clientAuthentication = oauth2Ctx.getClientAuthentication();
- }
-
- oidcMetadataContext = oidcMetadataContextLookupStrategy.apply(profileRequestContext);
-
- enabledMethods = tokenEndpointAuthMethodsLookupStrategy.apply(profileRequestContext);
- if (enabledMethods == null) {
- enabledMethods = Collections.emptySet();
- }
-
- return true;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
- @Nonnull final AuthenticationContext authenticationContext) {
-
- final ClientAuthenticationMethod registeredMethod;
-
- // Pull the client's registered authn method, or default to client_secret_basic.
- // If no metadata exists, leave null.
- if (oidcMetadataContext != null) {
- final OIDCClientInformation clientInformation = oidcMetadataContext.getClientInformation();
- if (clientInformation != null) {
- final OIDCClientMetadata clientMetadata = clientInformation.getOIDCMetadata();
- registeredMethod = clientMetadata.getTokenEndpointAuthMethod() != null ?
- clientMetadata.getTokenEndpointAuthMethod() : ClientAuthenticationMethod.CLIENT_SECRET_BASIC;
- } else {
- registeredMethod = null;
- }
- } else {
- registeredMethod = null;
- }
-
- // Did the client use what it registered and is that still allowed?
- // The enabledMethods member contains the methods authorized in the configuration as a whole.
-
- final ClientAuthenticationMethod used =
- clientAuthentication != null ? clientAuthentication.getMethod() : ClientAuthenticationMethod.NONE;
-
- if (registeredMethod != null && !registeredMethod.equals(used)) {
- log.warn("{} Client '{}' registered {} but attempted {}", getLogPrefix(), getClientID(),
- registeredMethod, used);
- ActionSupport.buildEvent(profileRequestContext, EventIds.ACCESS_DENIED);
- return;
- }
- assert enabledMethods != null;
- if (!enabledMethods.contains(used)) {
- log.warn("{} Requested method {} not enabled in profile configuration", getLogPrefix(), used);
- ActionSupport.buildEvent(profileRequestContext, EventIds.ACCESS_DENIED);
- }
- }
-
- /**
- * Parses the client ID from OIDC metadata or client authentication, if exists.
- *
- * @return client ID, or null it it couldn't be found.
- */
- @Nullable private String getClientID() {
- if (oidcMetadataContext != null) {
- final OIDCClientInformation clientInformation = oidcMetadataContext.getClientInformation();
- if (clientInformation != null) {
- return getClientIDValue(clientInformation.getID());
- }
- }
- if (clientAuthentication != null) {
- return getClientIDValue(clientAuthentication.getClientID());
- }
- return null;
- }
-
- /**
- * Get the client ID value as string if the object is non-null.
- *
- * @param clientId client ID, may be null.
- * @return the client ID value.
- */
- @Nullable private String getClientIDValue(@Nullable final ClientID clientId) {
- return clientId == null ? null : clientId.getValue();
- }
-}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/package-info.java b/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/package-info.java
deleted file mode 100644
index 20ad6130..00000000
--- a/idp-oidc-extension-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/package-info.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-/**
- * Implementation classes supporting OIDC/OAuth client authentication.
- */
-package net.shibboleth.idp.plugin.oidc.op.authn.impl;
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index cd6daefd..d5d350e0 100644
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidc-extension-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -42,26 +42,6 @@
<bean parent="shibboleth.AuthnComparisonRegistration"
c:key-ref="shibboleth.OIDCAuthnMethodExact" c:value-ref="shibboleth.ExactMatchFactory" />
- <!-- OAuth2 login flow -->
- <bean p:id="authn/OAuth2Client" parent="shibboleth.AuthenticationFlow"
- p:order="%{idp.authn.OAuth2Client.order:1000}"
- p:nonBrowserSupported="true"
- p:passiveAuthenticationSupported="true"
- p:forcedAuthenticationSupported="true"
- p:proxyRestrictionsEnforced="true"
- p:proxyScopingEnforced="false"
- p:discoveryRequired="false"
- p:lifetime="PT60S"
- p:inactivityTimeout="PT60S"
- p:reuseCondition-ref="shibboleth.Conditions.FALSE"
- p:activationCondition-ref="#{'%{idp.authn.OAuth2Client.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
- p:subjectDecorator="#{getObject('%{idp.authn.OAuth2Client.subjectDecorator:}'.trim())}">
- <property name="supportedPrincipalsByString">
- <bean parent="shibboleth.CommaDelimStringArray"
- c:_0="#{'%{idp.authn.OAuth2Client.supportedPrincipals:}'.trim()}" />
- </property>
- </bean>
-
<!-- Property-based definition of login flows for OAuth endpoints. -->
<bean id="shibboleth.oidc.PotentialFlows" class="org.springframework.beans.factory.config.ListFactoryBean"
p:sourceList="#{getObject('shibboleth.AuthenticationFlowDescriptorManager').getComponents().?[id matches 'authn/(' + '%{idp.oauth2.authn.flows:OAuth2Client}'.trim() + ')']}" />
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-beans.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-beans.xml
deleted file mode 100644
index 797fcb55..00000000
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-beans.xml
+++ /dev/null
@@ -1,295 +0,0 @@
-<?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">
-
- <!-- Default message map. -->
- <util:map id="shibboleth.authn.OAuth2Client.ClassifiedMessageMap">
- <entry key="RequestUnsupported">
- <list>
- <value>RequestUnsupported</value>
- </list>
- </entry>
- </util:map>
-
- <import resource="conditional:%{idp.home}/conf/authn/oauth2client-authn-config.xml" />
-
- <bean id="ExtractClientAuthenticationFromRequest"
- class="net.shibboleth.idp.plugin.oidc.op.authn.impl.ExtractClientAuthenticationFromRequest" scope="prototype"
- p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier" />
-
- <bean id="PopulateTokenEndpointJwtSignatureValidationParameters"
- class="net.shibboleth.oidc.profile.impl.PopulateJWTSignatureValidationParameters"
- scope="prototype"
- c:strategy-ref="shibboleth.MessageContextLookup.Inbound">
- <property name="configurationLookupStrategy">
- <bean class="net.shibboleth.oidc.profile.config.navigate.JWTSignatureValidationConfigurationLookupFunction" />
- </property>
- <property name="signatureValidationParametersResolver">
- <bean class="net.shibboleth.oidc.security.jose.impl.BasicSignatureValidationParametersResolver" />
- </property>
-<!-- <property name="securityParametersContextLookupStrategy">
- <bean parent="shibboleth.Functions.Compose"
- c:g-ref="shibboleth.ChildLookupOrCreate.SecurityParameters"
- c:f-ref="shibboleth.ChildLookup.RelyingParty" />
- </property>
- <property name="existingParametersContextLookupStrategy">
- <bean parent="shibboleth.Functions.Compose"
- c:g-ref="shibboleth.ChildLookup.SecurityParameters"
- c:f-ref="shibboleth.MessageContextLookup.Outbound" />
- </property>-->
- </bean>
-
- <bean id="JWTAuthenticationCondition" parent="shibboleth.Conditions.Expression"
- c:expression="#input.ensureSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).ensureSubcontext(T(net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext)).getClientAuthentication() instanceof T(com.nimbusds.oauth2.sdk.auth.JWTAuthentication)" />
-
- <bean id="ValidateJWTSignature" class="net.shibboleth.idp.profile.impl.WebFlowMessageHandlerAdaptor"
- scope="prototype" c:executionDirection="INBOUND" p:activationCondition-ref="JWTAuthenticationCondition"
- p:errorEvent="#{T(net.shibboleth.idp.authn.AuthnEventIds).AUTHN_EXCEPTION}">
- <constructor-arg>
- <bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
- <property name="handlers">
- <list>
- <bean class="net.shibboleth.oidc.security.impl.CheckClientJWTSignatureAlgorithmHandler"
- scope="prototype" p:defaultAlgorithmValue="">
- <property name="jwtTokenLookupStrategy">
- <bean
- class="net.shibboleth.profile.context.navigate.SpringExpressionContextLookupFunction"
- c:_0="#{ T(org.opensaml.messaging.context.MessageContext) }"
- c:outputType="#{T(com.nimbusds.jwt.SignedJWT)}"
- c:expression="#input.getParent().ensureSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).ensureSubcontext(T(net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext)).getClientAuthentication().getClientAssertion()" />
- </property>
- <property name="clientInformationLookupStrategy">
- <bean
- class="net.shibboleth.profile.context.navigate.SpringExpressionContextLookupFunction"
- c:_0="#{ T(org.opensaml.messaging.context.MessageContext) }"
- c:expression="#input.ensureSubcontext(T(net.shibboleth.oidc.metadata.context.OIDCMetadataContext)).getClientInformation()" />
- </property>
- <property name="signatureAlgorithmLookupStrategy">
- <bean
- class="net.shibboleth.oidc.profile.config.navigate.ClientInformationStringValueLookupFunction"
- c:keyName="token_endpoint_auth_signing_alg" />
- </property>
- </bean>
- <bean class="net.shibboleth.oidc.security.impl.JWTMessageSignatureSecurityHandler"
- scope="prototype">
- <property name="jwtTokenLookupStrategy">
- <bean
- class="net.shibboleth.profile.context.navigate.SpringExpressionContextLookupFunction"
- c:_0="#{ T(org.opensaml.messaging.context.MessageContext) }"
- c:outputType="#{T(com.nimbusds.jwt.SignedJWT)}"
- c:expression="#input.getParent().ensureSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).ensureSubcontext(T(net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext)).getClientAuthentication().getClientAssertion()" />
- </property>
- <property name="clientInformationLookupStrategy">
- <bean
- class="net.shibboleth.profile.context.navigate.SpringExpressionContextLookupFunction"
- c:_0="#{ T(org.opensaml.messaging.context.MessageContext) }"
- c:expression="#input.ensureSubcontext(T(net.shibboleth.oidc.metadata.context.OIDCMetadataContext)).getClientInformation()" />
- </property>
- </bean>
- </list>
- </property>
- </bean>
- </constructor-arg>
- </bean>
-
-
- <bean id="ValidateClientAuthenticationType"
- class="net.shibboleth.idp.plugin.oidc.op.authn.impl.ValidateClientAuthenticationType" scope="prototype" />
-
- <bean id="DefaultCleanupHook"
- class="net.shibboleth.idp.authn.impl.ValidateCredentials.UsernamePasswordCleanupHook" />
-
- <bean id="ValidateCredentials"
- class="net.shibboleth.idp.authn.impl.ValidateCredentials" scope="prototype"
- p:requireAll="%{idp.authn.OAuth2Client.requireAll:false}"
- p:validators="#{getObject('shibboleth.authn.OAuth2Client.Validators') ?: getObject('DefaultOAuth2ClientValidators')}"
- p:addDefaultPrincipals="%{idp.authn.OAuth2Client.addDefaultPrincipals:true}"
- p:supportedPrincipals="#{getObject('shibboleth.authn.OAuth2Client.PrincipalOverride')}"
- p:classifiedMessages="#{getObject('shibboleth.authn.OAuth2Client.ClassifiedMessageMap')}"
- p:cleanupHook="#{T(java.lang.Boolean).valueOf('%{idp.authn.OAuth2Client.removeAfterValidation:true}') ? getObject('DefaultCleanupHook') : null}"
- p:lockoutManager="#{getObject('shibboleth.authn.OAuth2Client.AccountLockoutManager')}"
- p:populateAuditContextAction="#{%{idp.authn.OAuth2Client.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.OAuth2Client.PopulateAuditContext') : null}"
- p:writeAuditLogAction="#{%{idp.authn.OAuth2Client.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuthnAuditLog') : null}" />
-
- <bean id="PopulateSubjectCanonicalizationContext"
- class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="%{idp.authn.OAuth2Client.c14n.postLoginFlows:shibboleth.PostLoginSubjectCanonicalizationFlows}" />
-
- <!-- Default validators equivalent to previous versions. -->
-
- <util:list id="DefaultOAuth2ClientValidators">
- <ref bean="shibboleth.OIDCClientInfoValidator" />
- <ref bean="shibboleth.JWTValidator" />
- </util:list>
-
- <!-- Validator parent beans -->
-
- <bean id="shibboleth.CredentialValidator" abstract="true"
- p:savePasswordToCredentialSet="%{idp.authn.OAuth2Client.retainAsPrivateCredential:false}" />
-
- <bean id="shibboleth.OIDCClientInfoValidator" parent="shibboleth.CredentialValidator"
- class="net.shibboleth.idp.plugin.oidc.op.authn.impl.OIDCClientInfoCredentialValidator"
- p:id="oauth2-clientinfo" />
-
- <bean id="shibboleth.JWTValidator" class="net.shibboleth.idp.plugin.oidc.op.authn.impl.JWTCredentialValidator"
- p:id="oauth2-jwt" />
-
- <bean id="shibboleth.JAASValidator" parent="shibboleth.CredentialValidator"
- class="net.shibboleth.idp.authn.impl.JAASCredentialValidator" abstract="true"
- p:id="oauth2-jaas" />
-
- <bean id="shibboleth.KerberosValidator" parent="shibboleth.CredentialValidator"
- class="net.shibboleth.idp.authn.impl.KerberosCredentialValidator" abstract="true"
- p:id="oauth2-krb5" />
-
- <bean id="shibboleth.LDAPValidator" parent="shibboleth.CredentialValidator" lazy-init="true"
- class="net.shibboleth.idp.authn.impl.LDAPCredentialValidator"
- p:id="oauth2-ldap"
- p:authenticator-ref="shibboleth.authn.OAuth2Client.LDAP.authenticator" />
-
- <bean id="shibboleth.HTPasswdValidator" abstract="true"
- class="net.shibboleth.idp.authn.impl.HTPasswdCredentialValidator"
- p:id="oauth2-htpasswd" />
-
- <bean id="shibboleth.X509Validator" abstract="true"
- class="net.shibboleth.idp.authn.impl.X509CertificateCredentialValidator"
- p:id="oauth2-x509" />
-
- <!-- Parent beans for custom ldaptive types. -->
-
- <bean id="shibboleth.authn.OAuth2Client.LDAP.authenticator" parent="shibboleth.LDAPAuthenticationFactory"
- lazy-init="true" />
-
- <bean id="shibboleth.X509ResourceCredentialConfig"
- class="net.shibboleth.idp.authn.impl.X509ResourceCredentialConfig" abstract="true" />
- <bean id="shibboleth.KeystoreResourceCredentialConfig"
- class="net.shibboleth.idp.authn.impl.KeystoreResourceCredentialConfig" abstract="true" />
-
- <bean id="shibboleth.authn.OAuth2Client.LDAP.trustCertificates" parent="shibboleth.X509ResourceCredentialConfig"
- p:trustCertificates="%{idp.authn.OAuth2Client.LDAP.trustCertificates:undefined}" />
- <bean id="shibboleth.authn.OAuth2Client.LDAP.truststore" parent="shibboleth.KeystoreResourceCredentialConfig"
- p:truststore="%{idp.authn.OAuth2Client.LDAP.trustStore:undefined}" />
-
- <bean id="shibboleth.LDAPAuthenticationFactory" abstract="true"
- class="net.shibboleth.idp.authn.config.LDAPAuthenticationFactoryBean"
- p:authenticatorType="#{'%{idp.authn.OAuth2Client.LDAP.authenticator:anonSearchAuthenticator}'.trim()}"
- p:trustType="#{'%{idp.authn.OAuth2Client.LDAP.sslConfig:certificateTrust}'.trim()}"
- p:connectionStrategyType="#{'%{idp.authn.OAuth2Client.LDAP.connectionStrategy:ACTIVE_PASSIVE}'.trim()}"
- p:ldapUrl="%{idp.authn.OAuth2Client.LDAP.ldapURL:ldap://localhost:10389}"
- p:useStartTLS="%{idp.authn.OAuth2Client.LDAP.useStartTLS:true}"
- p:startTLSTimeout="%{idp.authn.OAuth2Client.LDAP.startTLSTimeout:PT3S}"
- p:connectTimeout="%{idp.authn.OAuth2Client.LDAP.connectTimeout:PT3S}"
- p:responseTimeout="%{idp.authn.OAuth2Client.LDAP.responseTimeout:PT3S}"
- p:autoReconnect="%{idp.authn.OAuth2Client.LDAP.autoReconnect:true}"
- p:reconnectTimeout="%{idp.authn.OAuth2Client.LDAP.reconnectTimeout:PT10S}"
- p:trustCertificatesCredentialConfig-ref="shibboleth.authn.OAuth2Client.LDAP.trustCertificates"
- p:truststoreCredentialConfig-ref="shibboleth.authn.OAuth2Client.LDAP.truststore"
- p:disablePooling="%{idp.authn.OAuth2Client.LDAP.disablePooling:false}"
- p:blockWaitTime="%{idp.pool.LDAP.blockWaitTime:PT3S}"
- p:minPoolSize="%{idp.pool.LDAP.minSize:3}"
- p:maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
- p:validateOnCheckout="%{idp.pool.LDAP.validateOnCheckout:false}"
- p:validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
- p:validatePeriod="%{idp.pool.LDAP.validatePeriod:PT5M}"
- p:validateDn="#{'%{idp.pool.LDAP.validateDN:}'.trim()}"
- p:validateFilter="#{'%{idp.pool.LDAP.validateFilter:(objectClass=*)}'.trim()}"
- p:bindPoolPassivatorType="#{'%{idp.authn.OAuth2Client.LDAP.bindPoolPassivator:none}'.trim()}"
- p:prunePeriod="%{idp.pool.LDAP.prunePeriod:PT5M}"
- p:idleTime="%{idp.pool.LDAP.idleTime:PT10M}"
- p:dnFormat="%{idp.authn.OAuth2Client.LDAP.dnFormat:undefined}"
- p:baseDn="#{'%{idp.authn.OAuth2Client.LDAP.baseDN:undefined}'.trim()}"
- p:userFilter="#{'%{idp.authn.OAuth2Client.LDAP.userFilter:undefined}'.trim()}"
- p:subtreeSearch="%{idp.authn.OAuth2Client.LDAP.subtreeSearch:false}"
- p:resolveEntryOnFailure="%{idp.authn.OAuth2Client.LDAP.resolveEntryOnFailure:false}"
- p:resolveEntryWithBindDn="%{idp.authn.OAuth2Client.LDAP.resolveEntryWithBindDN:false}"
- p:velocityEngine-ref="shibboleth.VelocityEngine"
- p:bindDn="#{'%{idp.authn.OAuth2Client.LDAP.bindDN:undefined}'.trim()}"
- p:bindDnCredential="%{idp.authn.OAuth2Client.LDAP.bindDNCredential:undefined}"
- p:usePasswordPolicy="%{idp.authn.OAuth2Client.LDAP.usePasswordPolicy:false}"
- p:usePasswordExpiration="%{idp.authn.OAuth2Client.LDAP.usePasswordExpiration:false}"
- p:activeDirectory="%{idp.authn.OAuth2Client.LDAP.activeDirectory:false}"
- p:freeIPA="%{idp.authn.OAuth2Client.LDAP.freeIPADirectory:false}"
- p:EDirectory="%{idp.authn.OAuth2Client.LDAP.eDirectory:false}"
- p:accountStateExpirationPeriod="%{idp.authn.OAuth2Client.LDAP.accountStateExpirationPeriod:#{null}}"
- p:accountStateWarningPeriod="%{idp.authn.OAuth2Client.LDAP.accountStateWarningPeriod:#{null}}"
- p:accountStateLoginFailures="%{idp.authn.OAuth2Client.LDAP.accountStateLoginFailures:0}" />
-
- <util:map id="shibboleth.authn.AuditFormattingMap">
- <entry key="#{'%{idp.authn.OAuth2Client.audit.category:Shibboleth-Audit.OAuth2Client}'.trim()}"
- value="#{'%{idp.authn.OAuth2Client.audit.format:%a|%T|%SP|%I|%s|%AF|%CV|%u|%tu|%AR|%UA}'.trim()}" />
- </util:map>
-
- <bean id="shibboleth.authn.OAuth2Client.PopulateAuditContext" parent="shibboleth.authn.AbstractPopulateAuditContext" lazy-init="true"
- p:fieldExtractors="#{getObject('shibboleth.authn.OAuth2Client.AuditExtractors') ?: getObject('shibboleth.authn.OAuth2Client.DefaultAuditExtractors')}"/>
-
- <bean id="shibboleth.authn.OAuth2Client.DefaultAuditExtractors" parent="shibboleth.authn.DefaultAuditExtractors" lazy-init="true"
- class="org.springframework.beans.factory.config.MapFactoryBean">
- <property name="sourceMap">
- <map merge="true">
- <entry>
- <key>
- <util:constant static-field="net.shibboleth.idp.profile.IdPAuditFields.USERNAME"/>
- </key>
- <bean class="net.shibboleth.idp.authn.audit.impl.AttemptedUsernameAuditExtractor" />
- </entry>
- <entry>
- <key>
- <util:constant static-field="net.shibboleth.idp.authn.AuthnAuditFields.TRANSFORMED_USERNAME"/>
- </key>
- <bean class="net.shibboleth.idp.authn.audit.impl.TransformedUsernameAuditExtractor" />
- </entry>
- <entry>
- <key>
- <util:constant static-field="net.shibboleth.idp.saml.profile.SAMLAuditFields.REQUEST_ID"/>
- </key>
- <bean class="net.shibboleth.idp.plugin.oidc.op.authn.audit.impl.ClientAuthenticationJWTPayloadClaimsAuditExtractor"
- c:key="jti" />
- </entry>
- <entry>
- <key>
- <util:constant static-field="net.shibboleth.idp.saml.profile.SAMLAuditFields.REQUEST_ISSUE_INSTANT"/>
- </key>
- <bean class="net.shibboleth.idp.plugin.oidc.op.authn.audit.impl.ClientAuthenticationJWTPayloadClaimsAuditExtractor"
- c:key="iat" />
- </entry>
- <entry>
- <key>
- <util:constant static-field="net.shibboleth.idp.plugin.oidc.op.audit.AuditFields.AUDIENCE"/>
- </key>
- <bean class="net.shibboleth.idp.plugin.oidc.op.authn.audit.impl.ClientAuthenticationJWTPayloadClaimsAuditExtractor"
- c:key="aud" />
- </entry>
- <entry key="iss">
- <bean class="net.shibboleth.idp.plugin.oidc.op.authn.audit.impl.ClientAuthenticationJWTPayloadClaimsAuditExtractor"
- c:key="iss" />
- </entry>
- <entry key="sub">
- <bean class="net.shibboleth.idp.plugin.oidc.op.authn.audit.impl.ClientAuthenticationJWTPayloadClaimsAuditExtractor"
- c:key="sub" />
- </entry>
- <entry key="exp">
- <bean class="net.shibboleth.idp.plugin.oidc.op.authn.audit.impl.ClientAuthenticationJWTPayloadClaimsAuditExtractor"
- c:key="exp" />
- </entry>
- <entry key="iat">
- <bean class="net.shibboleth.idp.plugin.oidc.op.authn.audit.impl.ClientAuthenticationJWTPayloadClaimsAuditExtractor"
- c:key="iat" />
- </entry>
- <entry key="typ">
- <bean class="net.shibboleth.idp.plugin.oidc.op.authn.audit.impl.ClientAuthenticationJWTTypeHeaderAuditExtractor" />
- </entry>
- </map>
- </property>
- </bean>
-
-</beans>
diff --git a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-flow.xml b/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-flow.xml
deleted file mode 100644
index a75eb608..00000000
--- a/idp-oidc-extension-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/OAuth2Client/OAuth2Client-flow.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<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="authn.abstract">
-
- <!--
- This is a login flow for handling OAuth2-defined client authentication mechanisms.
- The current implementation relies on Nimbus APIs but could be replaced in the future if necessary.
- -->
-
- <action-state id="OAuth2Client">
- <evaluate expression="PopulateTokenEndpointJwtSignatureValidationParameters"/>
- <evaluate expression="ExtractClientAuthenticationFromRequest" />
- <evaluate expression="ValidateClientAuthenticationType" />
- <evaluate expression="ValidateJWTSignature"/>
- <evaluate expression="ValidateCredentials" />
- <evaluate expression="PopulateSubjectCanonicalizationContext" />
- <evaluate expression="'proceed'" />
-
- <transition on="proceed" to="CallSubjectCanonicalization" />
- </action-state>
-
- <!-- This runs a c14n step on the result of the authentication. -->
- <subflow-state id="CallSubjectCanonicalization" subflow="c14n">
- <input name="calledAsSubflow" value="true" />
- <transition on="proceed" to="proceed" />
-
- <!-- This shouldn't generally happen, but if c14n fails, it's allowable to fall through. -->
- <transition on="SubjectCanonicalizationError" to="ReselectFlow" />
- </subflow-state>
-
- <!-- As a "fall-through" method, remap selected events to select a different flow. -->
- <global-transitions>
- <transition on="NoCredentials" to="ReselectFlow" />
- <transition on="InvalidCredentials" to="ReselectFlow" />
- <transition on="RequestUnsupported" to="ReselectFlow" />
- <transition on="UnknownUsername" to="ReselectFlow" />
- <transition on="AccessDenied" to="ReselectFlow" />
- </global-transitions>
-
- <bean-import resource="OAuth2Client-beans.xml" />
-
-</flow>
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ExtractClientAuthenticationFromRequestTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ExtractClientAuthenticationFromRequestTest.java
deleted file mode 100644
index 3f0c7492..00000000
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ExtractClientAuthenticationFromRequestTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.idp.plugin.oidc.op.authn.impl;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.interfaces.RSAPrivateKey;
-
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.springframework.webflow.execution.Event;
-import org.springframework.webflow.execution.RequestContext;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.nimbusds.jose.JOSEException;
-import com.nimbusds.jose.JWSAlgorithm;
-import com.nimbusds.oauth2.sdk.AuthorizationCode;
-import com.nimbusds.oauth2.sdk.AuthorizationCodeGrant;
-import com.nimbusds.oauth2.sdk.AuthorizationGrant;
-import com.nimbusds.oauth2.sdk.TokenRequest;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
-import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
-import com.nimbusds.oauth2.sdk.auth.ClientSecretJWT;
-import com.nimbusds.oauth2.sdk.auth.ClientSecretPost;
-import com.nimbusds.oauth2.sdk.auth.PrivateKeyJWT;
-import com.nimbusds.oauth2.sdk.auth.Secret;
-import com.nimbusds.oauth2.sdk.id.ClientID;
-
-import net.shibboleth.idp.authn.AuthnEventIds;
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.idp.authn.context.UsernamePasswordContext;
-import net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext;
-import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
-import net.shibboleth.idp.profile.testing.ActionTestingSupport;
-import net.shibboleth.idp.profile.testing.RequestContextBuilder;
-
-/**
- * Unit tests for {@link ExtractClientAuthenticationFromRequest}.
- */
-public class ExtractClientAuthenticationFromRequestTest {
-
- private ClientID clientId;
- private Secret clientSecret;
-
- private URI endpointUri;
-
- private RSAPrivateKey rsaPrivateKey;
-
- private ExtractClientAuthenticationFromRequest action;
-
- private RequestContext rc;
- private ProfileRequestContext prc;
-
- @BeforeClass
- public void initKeys() throws NoSuchAlgorithmException {
- final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
- keyGen.initialize(2048);
- final KeyPair keyPair = keyGen.genKeyPair();
- rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
- }
-
- @BeforeMethod
- public void init() throws URISyntaxException, ComponentInitializationException {
- clientId = new ClientID("mockId");
- clientSecret = new Secret("secret1234567890secret1234567890secret1234567890");
- endpointUri = new URI("https://mock.example.org/");
-
- action = new ExtractClientAuthenticationFromRequest();
- action.initialize();
- }
-
- protected void initializeRequestCtx(final ClientAuthenticationMethod method)
- throws JOSEException, ComponentInitializationException {
- final ClientAuthentication clientAuth;
- if (method.equals(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)) {
- clientAuth = new ClientSecretBasic(clientId, clientSecret);
- } else if (method.equals(ClientAuthenticationMethod.CLIENT_SECRET_POST)) {
- clientAuth = new ClientSecretPost(clientId, clientSecret);
- } else if (method.equals(ClientAuthenticationMethod.CLIENT_SECRET_JWT)) {
- clientAuth = new ClientSecretJWT(clientId, endpointUri, JWSAlgorithm.HS256, clientSecret);
- } else if (method.equals(ClientAuthenticationMethod.PRIVATE_KEY_JWT)) {
- clientAuth = new PrivateKeyJWT(clientId, endpointUri, JWSAlgorithm.RS256, (PrivateKey) rsaPrivateKey, null,
- null);
- } else {
- clientAuth = null;
- }
- final AuthorizationGrant authzGrant = new AuthorizationCodeGrant(new AuthorizationCode(), null);
-
- rc = new RequestContextBuilder()
- .setInboundMessage(new TokenRequest(null, clientAuth, authzGrant, null))
- .buildRequestContext();
- prc = new WebflowRequestContextProfileRequestContextLookup().apply(rc);
- prc.addSubcontext(new AuthenticationContext());
- }
-
- @Test
- public void testNoAuthnContext() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
- prc.removeSubcontext(AuthenticationContext.class);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertEvent(e, AuthnEventIds.INVALID_AUTHN_CTX);
- }
-
- @Test
- public void testBasic() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertProceedEvent(e);
-
- final OAuth2ClientAuthenticationContext oauth =
- prc.ensureSubcontext(AuthenticationContext.class).getSubcontext(OAuth2ClientAuthenticationContext.class);
- Assert.assertNotNull(oauth);
- assert oauth != null;
- final ClientAuthentication clientAuthentication = oauth.getClientAuthentication();
- assert clientAuthentication != null;
- Assert.assertEquals(clientAuthentication.getClientID(), clientId);
- Assert.assertEquals(clientAuthentication.getMethod(), ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
- final UsernamePasswordContext up = prc.ensureSubcontext(AuthenticationContext.class)
- .getSubcontext(UsernamePasswordContext.class);
- Assert.assertNotNull(up);
- assert up != null;
- Assert.assertEquals(up.getUsername(), clientId.getValue());
- Assert.assertEquals(up.getPassword(), clientSecret.getValue());
- }
-
- @Test
- public void testPost() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.CLIENT_SECRET_POST);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertProceedEvent(e);
-
- final OAuth2ClientAuthenticationContext oauth =
- prc.ensureSubcontext(AuthenticationContext.class).getSubcontext(OAuth2ClientAuthenticationContext.class);
- Assert.assertNotNull(oauth);
- assert oauth != null;
- final ClientAuthentication clientAuthentication = oauth.getClientAuthentication();
- assert clientAuthentication != null;
- Assert.assertEquals(clientAuthentication.getClientID(), clientId);
- Assert.assertEquals(clientAuthentication.getMethod(), ClientAuthenticationMethod.CLIENT_SECRET_POST);
- final UsernamePasswordContext up = prc.ensureSubcontext(AuthenticationContext.class)
- .getSubcontext(UsernamePasswordContext.class);
- Assert.assertNotNull(up);
- assert up != null;
- Assert.assertEquals(up.getUsername(), clientId.getValue());
- Assert.assertEquals(up.getPassword(), clientSecret.getValue());
- }
-
- @Test
- public void testSecretJwt() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.CLIENT_SECRET_JWT);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertProceedEvent(e);
-
- final OAuth2ClientAuthenticationContext oauth =
- prc.ensureSubcontext(AuthenticationContext.class).getSubcontext(OAuth2ClientAuthenticationContext.class);
- Assert.assertNotNull(oauth);
- assert oauth != null;
- final ClientAuthentication clientAuthentication = oauth.getClientAuthentication();
- assert clientAuthentication != null;
- Assert.assertEquals(clientAuthentication.getClientID(), clientId);
- Assert.assertEquals(clientAuthentication.getMethod(), ClientAuthenticationMethod.CLIENT_SECRET_JWT);
- final UsernamePasswordContext up = prc.ensureSubcontext(AuthenticationContext.class)
- .getSubcontext(UsernamePasswordContext.class);
- Assert.assertNull(up);
- }
-
- @Test
- public void testPrivateKeyJwt() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.PRIVATE_KEY_JWT);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertProceedEvent(e);
-
- final OAuth2ClientAuthenticationContext oauth =
- prc.ensureSubcontext(AuthenticationContext.class).getSubcontext(OAuth2ClientAuthenticationContext.class);
- Assert.assertNotNull(oauth);
- assert oauth != null;
- final ClientAuthentication clientAuthentication = oauth.getClientAuthentication();
- assert clientAuthentication != null;
- Assert.assertEquals(clientAuthentication.getClientID(), clientId);
- Assert.assertEquals(clientAuthentication.getMethod(), ClientAuthenticationMethod.PRIVATE_KEY_JWT);
- final UsernamePasswordContext up = prc.ensureSubcontext(AuthenticationContext.class)
- .getSubcontext(UsernamePasswordContext.class);
- Assert.assertNull(up);
- }
-
-}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidatorTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidatorTest.java
deleted file mode 100644
index abe32f7f..00000000
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/JWTCredentialValidatorTest.java
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.idp.plugin.oidc.op.authn.impl;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.time.Instant;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.function.Function;
-
-import org.mockito.Mockito;
-import org.opensaml.messaging.context.navigate.ChildContextLookup;
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.storage.ReplayCache;
-import org.opensaml.storage.impl.MemoryStorageService;
-import org.opensaml.storage.impl.StorageServiceReplayCache;
-import org.springframework.webflow.execution.Event;
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.nimbusds.jose.JOSEException;
-import com.nimbusds.jose.JOSEObjectType;
-import com.nimbusds.jose.JWSAlgorithm;
-import com.nimbusds.jose.JWSHeader;
-import com.nimbusds.jose.crypto.MACSigner;
-import com.nimbusds.jose.crypto.RSASSASigner;
-import com.nimbusds.jwt.JWTClaimsSet;
-import com.nimbusds.jwt.SignedJWT;
-import com.nimbusds.oauth2.sdk.AuthorizationCode;
-import com.nimbusds.oauth2.sdk.AuthorizationCodeGrant;
-import com.nimbusds.oauth2.sdk.AuthorizationGrant;
-import com.nimbusds.oauth2.sdk.TokenRequest;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
-import com.nimbusds.oauth2.sdk.auth.ClientSecretJWT;
-import com.nimbusds.oauth2.sdk.auth.PrivateKeyJWT;
-import com.nimbusds.oauth2.sdk.auth.Secret;
-import com.nimbusds.oauth2.sdk.id.ClientID;
-import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
-import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
-
-import jakarta.servlet.http.HttpServletRequest;
-import net.shibboleth.idp.authn.AuthenticationResult;
-import net.shibboleth.idp.authn.AuthnEventIds;
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.idp.authn.impl.ValidateCredentials;
-import net.shibboleth.idp.authn.impl.testing.BaseAuthenticationContextTest;
-import net.shibboleth.idp.authn.principal.UsernamePrincipal;
-import net.shibboleth.idp.profile.testing.ActionTestingSupport;
-import net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext;
-import net.shibboleth.oidc.jwt.claims.ClaimsValidator;
-import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
-import net.shibboleth.oidc.profile.oauth2.config.impl.AbstractOAuth2ClientAuthenticableProfileConfiguration;
-import net.shibboleth.oidc.profile.oauth2.config.impl.DefaultOAuth2TokenConfiguration;
-import net.shibboleth.oidc.security.jose.context.SecurityParametersContext;
-import net.shibboleth.oidc.security.jwt.claims.impl.AudienceClaimsValidator;
-import net.shibboleth.oidc.security.jwt.claims.impl.ChainingJWTClaimsValidator;
-import net.shibboleth.oidc.security.jwt.claims.impl.ExactMatchClaimsValidator;
-import net.shibboleth.oidc.security.jwt.claims.impl.ExpiryClaimsValidator;
-import net.shibboleth.oidc.security.jwt.claims.impl.IssuedAtClaimsValidator;
-import net.shibboleth.oidc.security.jwt.claims.impl.JWTIdentifierClaimsValidator;
-import net.shibboleth.profile.context.RelyingPartyContext;
-import net.shibboleth.profile.context.navigate.RelyingPartyIdLookupFunction;
-import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.shared.logic.BiFunctionSupport;
-
-/**
- * Unit tests for {@link JWTCredentialValidator}.
- */
-public class JWTCredentialValidatorTest extends BaseAuthenticationContextTest {
-
- ClientID clientId;
- Secret clientSecret;
-
- URI endpointUri;
-
- RSAPrivateKey rsaPrivateKey;
- RSAPublicKey rsaPublicKey;
-
- private ClaimsValidator claimsValidator;
- private JWTCredentialValidator validator;
- private ValidateCredentials action;
-
- @SuppressWarnings("unchecked")
- private Function<ProfileRequestContext, String> typeHeaderLookup = Mockito.mock(Function.class);
-
- @BeforeClass
- public void initKeys() throws NoSuchAlgorithmException {
- final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
- keyGen.initialize(2048);
- final KeyPair keyPair = keyGen.genKeyPair();
- rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
- rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
- }
-
- @Override
- @BeforeMethod
- public void setUp() throws ComponentInitializationException {
- super.setUp();
-
- clientId = new ClientID("mockId");
- clientSecret = new Secret("secret1234567890secret1234567890secret1234567890");
- try {
- endpointUri = new URI("http://localhost");
- } catch (final URISyntaxException e) {
- throw new ComponentInitializationException(e);
- }
-
- final StorageServiceReplayCache replayCache = new StorageServiceReplayCache();
- final MemoryStorageService storageService = new MemoryStorageService();
- storageService.setId("mockId");
- storageService.initialize();
- replayCache.setStorage(storageService);
-
- claimsValidator =
- constructClaimsValidator((HttpServletRequest) src.getExternalContext().getNativeRequest(), replayCache);
- final DefaultOAuth2TokenConfiguration profile = new DefaultOAuth2TokenConfiguration();
- profile.setClaimsValidator(claimsValidator);
- prc.ensureSubcontext(RelyingPartyContext.class).setProfileConfig(profile);
-
- validator = new JWTCredentialValidator();
- validator.setId("test");
- validator.setSecurityParametersLookupStrategy(new ChildContextLookup<>(SecurityParametersContext.class));
- validator.setRequiredJwtTypeHeaderLookupStrategy(typeHeaderLookup);
- validator.initialize();
-
- action = new ValidateCredentials();
- action.setValidators(Collections.singletonList(validator));
- action.initialize();
- }
-
- protected void completeSetup(final TokenRequest request, final ClientAuthenticationMethod storedMethod,
- final boolean sameSecret) throws NoSuchAlgorithmException, JOSEException {
-
- final OIDCMetadataContext oidcContext = new OIDCMetadataContext();
- final OIDCClientMetadata metadata = new OIDCClientMetadata();
- metadata.setTokenEndpointAuthMethod(storedMethod);
-
- final OIDCClientInformation clientInformation =
- new OIDCClientInformation(clientId, new Date(), metadata, clientSecret);
- oidcContext.setClientInformation(clientInformation);
- prc.ensureInboundMessageContext().addSubcontext(oidcContext);
- }
-
- protected void initializeTokenRequest(final ClientAuthenticationMethod method, final SignedJWT jwt,
- final boolean sameSecret) throws JOSEException, NoSuchAlgorithmException {
-
- final ClientAuthentication clientAuth;
- if (method.equals(ClientAuthenticationMethod.CLIENT_SECRET_JWT)) {
- clientAuth = new ClientSecretJWT(jwt);
- } else if (method.equals(ClientAuthenticationMethod.PRIVATE_KEY_JWT)) {
- clientAuth = new PrivateKeyJWT(jwt);
- } else {
- clientAuth = null;
- }
-
- final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
- ac.setAttemptedFlow(authenticationFlows.get(0));
- ac.ensureSubcontext(OAuth2ClientAuthenticationContext.class).setClientAuthentication(clientAuth);
-
- prc.ensureSubcontext(RelyingPartyContext.class).setRelyingPartyId(clientId.getValue());
-
- final AuthorizationGrant authzGrant = new AuthorizationCodeGrant(new AuthorizationCode(), null);
- completeSetup(new TokenRequest(null, clientAuth, authzGrant, null), method, sameSecret);
- }
-
- protected ClaimsValidator constructClaimsValidator(final HttpServletRequest httpRequest,
- final ReplayCache replayCache) {
- final ChainingJWTClaimsValidator claimsValidation = new ChainingJWTClaimsValidator();
- final ExpiryClaimsValidator expValidator = new ExpiryClaimsValidator();
- final IssuedAtClaimsValidator iatValidator = new IssuedAtClaimsValidator();
- iatValidator.setRequiredRule(false);
- final ExactMatchClaimsValidator issValidator = new ExactMatchClaimsValidator();
- issValidator.setClaimName("iss");
- issValidator.setValueToMatchLookupStrategy(
- BiFunctionSupport.forFunctionOfFirstArg(new RelyingPartyIdLookupFunction()));
- final ExactMatchClaimsValidator subValidator = new ExactMatchClaimsValidator();
- subValidator.setClaimName("sub");
- subValidator.setValueToMatchLookupStrategy(
- BiFunctionSupport.forFunctionOfFirstArg(new RelyingPartyIdLookupFunction()));
- final AudienceClaimsValidator audValidator = new AudienceClaimsValidator();
- audValidator.setAudienceLookupStrategy((prc, claims) -> httpRequest.getRequestURL().toString());
- final JWTIdentifierClaimsValidator jitValidator = new JWTIdentifierClaimsValidator();
- assert replayCache != null;
- jitValidator.setReplayCache(replayCache);
- claimsValidation.setClaimValidators(List.of(expValidator, iatValidator, issValidator, subValidator,
- audValidator, jitValidator));
- return claimsValidation;
- }
-
- protected void testFailingJwtAuth(final ClientAuthenticationMethod method, final SignedJWT jwt,
- final boolean replay, final boolean sameSecret) throws Exception {
- initializeTokenRequest(method, jwt, sameSecret);
-
- Event event = action.execute(src);
- if (replay) {
- ActionTestingSupport.assertProceedEvent(event);
- event = action.execute(src);
- }
- ActionTestingSupport.assertEvent(event, AuthnEventIds.INVALID_CREDENTIALS);
- }
-
- protected JWTClaimsSet claimsSetWithIatInTheFuture() {
- return new JWTClaimsSet.Builder()
- .subject(clientId.toString())
- .issuer(clientId.toString())
- .audience(endpointUri.toString())
- .expirationTime(Date.from(Instant.now().plusSeconds(600)))
- .issueTime(Date.from(Instant.now().plusSeconds(600)))
- .jwtID("mockId")
- .build();
- }
-
- protected JWTClaimsSet claimsSetWithExpInThePast() {
- return new JWTClaimsSet.Builder()
- .subject(clientId.toString())
- .issuer(clientId.toString())
- .audience(endpointUri.toString())
- .expirationTime(Date.from(Instant.now().minusSeconds(600)))
- .issueTime(Date.from(Instant.now()))
- .jwtID("mockId")
- .build();
- }
-
- protected JWTClaimsSet claimsSetWithoutJit() {
- return new JWTClaimsSet.Builder()
- .subject(clientId.toString())
- .issuer(clientId.toString())
- .audience(endpointUri.toString())
- .expirationTime(Date.from(Instant.now().plusSeconds(600)))
- .issueTime(Date.from(Instant.now()))
- .build();
- }
-
- protected JWTClaimsSet validClaimsSet() {
- return new JWTClaimsSet.Builder()
- .subject(clientId.toString())
- .issuer(clientId.toString())
- .audience(endpointUri.toString())
- .expirationTime(Date.from(Instant.now().plusSeconds(600)))
- .issueTime(Date.from(Instant.now()))
- .jwtID("mockId")
- .build();
- }
-
- protected SignedJWT createSecretJWT(final JWTClaimsSet claimsSet) throws JOSEException {
- return createSecretJWT(claimsSet, clientSecret.getValue());
- }
-
- protected SignedJWT createSecretJWT(final JWTClaimsSet claimsSet, final String clientSecret)
- throws JOSEException {
- return createSecretJWT(claimsSet, clientSecret, null);
- }
-
- protected SignedJWT createSecretJWT(final JWTClaimsSet claimsSet, final String clientSecret,
- final String typeHeader) throws JOSEException {
- final SignedJWT jwt;
- if (typeHeader == null) {
- jwt = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
- } else {
- jwt = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.HS256)
- .type(new JOSEObjectType(typeHeader)).build(), claimsSet);
- }
- final MACSigner signer = new MACSigner(clientSecret);
- jwt.sign(signer);
- return jwt;
- }
-
- protected SignedJWT createPrivateKeyJWT(final JWTClaimsSet claimsSet) throws JOSEException {
- final SignedJWT jwt = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), claimsSet);
- final RSASSASigner signer = new RSASSASigner(rsaPrivateKey);
- jwt.sign(signer);
- return jwt;
- }
-
- protected SignedJWT createPrivateKeyJWT(final JWTClaimsSet claimsSet, final String header) throws JOSEException {
- final SignedJWT jwt = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.RS256)
- .type(new JOSEObjectType(header)).build(), claimsSet);
- final RSASSASigner signer = new RSASSASigner(rsaPrivateKey);
- jwt.sign(signer);
- return jwt;
- }
-
- @Test
- public void testNoClaimsValidator() throws Exception {
- ((AbstractOAuth2ClientAuthenticableProfileConfiguration) prc.ensureSubcontext(
- RelyingPartyContext.class).ensureProfileConfig()).setClaimsValidator(null);
- testFailingJwtAuth(ClientAuthenticationMethod.CLIENT_SECRET_JWT,
- createSecretJWT(validClaimsSet()), false, true);
- }
-
- @Test
- public void testSecretJwt() throws JOSEException, NoSuchAlgorithmException {
- initializeTokenRequest(ClientAuthenticationMethod.CLIENT_SECRET_JWT, createSecretJWT(validClaimsSet()), true);
-
- Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(null);
- final Event event = action.execute(src);
- ActionTestingSupport.assertProceedEvent(event);
-
- final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
- final AuthenticationResult ar = ac.getAuthenticationResult();
- Assert.assertNotNull(ar);
- assert ar != null;
- Assert.assertEquals(ar.getSubject().getPrincipals(UsernamePrincipal.class).iterator()
- .next().getName(), clientId.getValue());
- }
-
- @Test
- public void testSecretJwt_enforcedHeader() throws JOSEException, NoSuchAlgorithmException {
- final String header = "enforcedTypeHeader";
- initializeTokenRequest(ClientAuthenticationMethod.CLIENT_SECRET_JWT, createSecretJWT(validClaimsSet(),
- clientSecret.toString(), header), true);
- Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(header);
-
- final Event event = action.execute(src);
- ActionTestingSupport.assertProceedEvent(event);
-
- final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
- final AuthenticationResult ar = ac.getAuthenticationResult();
- Assert.assertNotNull(ar);
- assert ar != null;
- Assert.assertEquals(ar.getSubject().getPrincipals(UsernamePrincipal.class).iterator()
- .next().getName(), clientId.getValue());
- }
-
-
- @Test
- public void testSecretJwt_missingMandatoryHeader() throws Exception {
- final String header = "enforcedTypeHeader";
- Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(header);
- testFailingJwtAuth(ClientAuthenticationMethod.CLIENT_SECRET_JWT,
- createSecretJWT(validClaimsSet()), false, true);
- }
-
- @Test
- public void testPrivateKeyJwt() throws JOSEException, NoSuchAlgorithmException {
- initializeTokenRequest(ClientAuthenticationMethod.PRIVATE_KEY_JWT, createPrivateKeyJWT(validClaimsSet()), true);
-
- Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(null);
- final Event event = action.execute(src);
- ActionTestingSupport.assertProceedEvent(event);
-
- final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
- final AuthenticationResult ar = ac.getAuthenticationResult();
- Assert.assertNotNull(ar);
- assert ar != null;
- Assert.assertEquals(ar.getSubject().getPrincipals(UsernamePrincipal.class).iterator()
- .next().getName(), clientId.getValue());
- }
-
- @Test
- public void testPrivateKeyJwt_enforcedHeader() throws JOSEException, NoSuchAlgorithmException {
- final String header = "enforcedTypeHeader";
- initializeTokenRequest(ClientAuthenticationMethod.PRIVATE_KEY_JWT,
- createPrivateKeyJWT(validClaimsSet(), header), true);
- Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(header);
-
- final Event event = action.execute(src);
- ActionTestingSupport.assertProceedEvent(event);
-
- final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
- final AuthenticationResult ar = ac.getAuthenticationResult();
- Assert.assertNotNull(ar);
- assert ar != null;
- Assert.assertEquals(ar.getSubject().getPrincipals(UsernamePrincipal.class).iterator()
- .next().getName(), clientId.getValue());
- }
-
- @Test
- public void testPrivateKeyJwt_missingMandatoryHeader() throws Exception {
- final String header = "enforcedTypeHeader";
- Mockito.when(typeHeaderLookup.apply(Mockito.any())).thenReturn(header);
- testFailingJwtAuth(ClientAuthenticationMethod.PRIVATE_KEY_JWT,
- createPrivateKeyJWT(validClaimsSet()), false, true);
- }
-
- @Test
- public void testInvalidSecretJwt_iatInTheFuture() throws Exception {
- testFailingJwtAuth(ClientAuthenticationMethod.CLIENT_SECRET_JWT,
- createSecretJWT(claimsSetWithIatInTheFuture()), false, true);
- }
-
- @Test
- public void testInvalidSecretJwt_expInThePast() throws Exception {
- testFailingJwtAuth(ClientAuthenticationMethod.CLIENT_SECRET_JWT,
- createSecretJWT(claimsSetWithExpInThePast()), false, true);
- }
-
- @Test
- public void testInvalidSecretJwt_withoutJit() throws Exception {
- testFailingJwtAuth(ClientAuthenticationMethod.CLIENT_SECRET_JWT,
- createSecretJWT(claimsSetWithoutJit()), false, true);
- }
-
- @Test
- public void testInvalidSecretJwt_jitReplayDetected() throws Exception {
- testFailingJwtAuth(ClientAuthenticationMethod.CLIENT_SECRET_JWT,
- createSecretJWT(validClaimsSet()), true, true);
- }
-
- @Test
- public void testInvalidPrivateKeyJwt_iatInTheFuture() throws Exception {
- testFailingJwtAuth(ClientAuthenticationMethod.PRIVATE_KEY_JWT,
- createPrivateKeyJWT(claimsSetWithIatInTheFuture()), false, true);
- }
-
- @Test
- public void testInvalidPrivateKeyJwt_expInThePast() throws Exception {
- testFailingJwtAuth(ClientAuthenticationMethod.PRIVATE_KEY_JWT,
- createPrivateKeyJWT(claimsSetWithExpInThePast()), false, true);
- }
-
- @Test
- public void testInvalidPrivateKeyJwt_withoutJit() throws Exception {
- testFailingJwtAuth(ClientAuthenticationMethod.PRIVATE_KEY_JWT,
- createPrivateKeyJWT(claimsSetWithoutJit()), false, true);
- }
-
- @Test
- public void testInvalidPrivateKeyJwt_jitReplayDetected() throws Exception {
- testFailingJwtAuth(ClientAuthenticationMethod.PRIVATE_KEY_JWT,
- createPrivateKeyJWT(validClaimsSet()), true, true);
- }
-
-}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidatorTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidatorTest.java
deleted file mode 100644
index 62d60f89..00000000
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/OIDCClientInfoCredentialValidatorTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.idp.plugin.oidc.op.authn.impl;
-
-import java.security.NoSuchAlgorithmException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.security.auth.login.LoginException;
-
-import net.shibboleth.idp.authn.AuthenticationResult;
-import net.shibboleth.idp.authn.AuthnEventIds;
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.idp.authn.context.AuthenticationErrorContext;
-import net.shibboleth.idp.authn.context.UsernamePasswordContext;
-import net.shibboleth.idp.authn.impl.ValidateCredentials;
-import net.shibboleth.idp.authn.impl.testing.BaseAuthenticationContextTest;
-import net.shibboleth.idp.authn.principal.UsernamePrincipal;
-import net.shibboleth.idp.profile.testing.ActionTestingSupport;
-import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
-import net.shibboleth.shared.codec.StringDigester;
-import net.shibboleth.shared.codec.StringDigester.OutputFormat;
-import net.shibboleth.shared.component.ComponentInitializationException;
-
-import org.springframework.webflow.execution.Event;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.nimbusds.oauth2.sdk.auth.Secret;
-import com.nimbusds.oauth2.sdk.id.ClientID;
-import com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
-import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
-
-/** Unit test for {@link OIDCClientInfoCredentialValidator}. */
-public class OIDCClientInfoCredentialValidatorTest extends BaseAuthenticationContextTest {
-
- private ClientID clientId;
- private Secret clientSecret;
-
- private OIDCClientInfoCredentialValidator validator;
-
- private ValidateCredentials action;
-
- @BeforeMethod public void setUp() throws ComponentInitializationException {
- super.setUp();
-
- clientId = new ClientID("mockId");
- clientSecret = new Secret("secret1234567890secret1234567890secret1234567890");
-
- validator = new OIDCClientInfoCredentialValidator();
- validator.setId("test");
- validator.initialize();
-
- action = new ValidateCredentials();
- action.setValidators(Collections.singletonList(validator));
-
- final Map<String,Collection<String>> mappings = new HashMap<>();
- mappings.put("InvalidPassword", Collections.singleton(AuthnEventIds.INVALID_CREDENTIALS));
- mappings.put(AuthnEventIds.UNKNOWN_USERNAME, Collections.singleton(AuthnEventIds.UNKNOWN_USERNAME));
- action.setClassifiedMessages(mappings);
-
- action.initialize();
-
- final OIDCMetadataContext oidcContext = new OIDCMetadataContext();
- final OIDCClientMetadata metadata = new OIDCClientMetadata();
- final Secret secret = new Secret("secret1234567890secret1234567890secret1234567890");
- final OIDCClientInformation clientInformation =
- new OIDCClientInformation(clientId, new Date(), metadata, secret);
- oidcContext.setClientInformation(clientInformation);
- prc.ensureInboundMessageContext().addSubcontext(oidcContext);
- }
-
- @Test public void testMissingFlow() {
- final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, AuthnEventIds.INVALID_AUTHN_CTX);
- }
-
- @Test public void testMissingUser() {
- prc.ensureSubcontext(AuthenticationContext.class).setAttemptedFlow(authenticationFlows.get(0));
-
- final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, AuthnEventIds.NO_CREDENTIALS);
- }
-
- @Test public void testMissingUser2() {
- final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
- ac.setAttemptedFlow(authenticationFlows.get(0));
- ac.ensureSubcontext(UsernamePasswordContext.class);
-
- final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, AuthnEventIds.NO_CREDENTIALS);
- }
-
- @Test public void testBadPassword() {
- final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
- ac.setAttemptedFlow(authenticationFlows.get(0));
- ac.ensureSubcontext(UsernamePasswordContext.class).setUsername(clientId.getValue()).setPassword("foo");
-
- final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, "InvalidPassword");
- final AuthenticationErrorContext errorCtx = ac.ensureSubcontext(AuthenticationErrorContext.class);
- Assert.assertTrue(errorCtx.getExceptions().get(0) instanceof LoginException);
- Assert.assertFalse(errorCtx.isClassifiedError("UnknownUsername"));
- Assert.assertTrue(errorCtx.isClassifiedError("InvalidPassword"));
- }
-
- @Test public void testAuthorized() {
- final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
- ac.setAttemptedFlow(authenticationFlows.get(0));
- ac.ensureSubcontext(UsernamePasswordContext.class).setUsername(clientId.getValue()).setPassword(clientSecret.getValue());
-
- final Event event = action.execute(src);
- ActionTestingSupport.assertProceedEvent(event);
-
- final AuthenticationResult ar = ac.getAuthenticationResult();
- Assert.assertNotNull(ar);
- assert ar != null;
- Assert.assertEquals(ar.getSubject().getPrincipals(UsernamePrincipal.class).iterator()
- .next().getName(), clientId.getValue());
- }
-
- @Test public void testAuthorizedSHA2() throws NoSuchAlgorithmException {
- final AuthenticationContext ac = prc.ensureSubcontext(AuthenticationContext.class);
- ac.setAttemptedFlow(authenticationFlows.get(0));
- ac.ensureSubcontext(UsernamePasswordContext.class).setUsername(clientId.getValue()).setPassword(clientSecret.getValue());
-
- final OIDCClientMetadata metadata = new OIDCClientMetadata();
- final Secret secret = new Secret("{SHA2}" + new StringDigester("SHA-256", OutputFormat.BASE64).apply(clientSecret.getValue()));
- final OIDCClientInformation clientInformation =
- new OIDCClientInformation(clientId, new Date(), metadata, secret);
- prc.ensureInboundMessageContext().ensureSubcontext(OIDCMetadataContext.class).setClientInformation(clientInformation);
-
- final Event event = action.execute(src);
- ActionTestingSupport.assertProceedEvent(event);
-
- final AuthenticationResult ar = ac.getAuthenticationResult();
- Assert.assertNotNull(ar);
- assert ar != null;
- Assert.assertEquals(ar.getSubject().getPrincipals(UsernamePrincipal.class).iterator()
- .next().getName(), clientId.getValue());
- }
-
-}
\ No newline at end of file
diff --git a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ValidateClientAuthenticationTypeTest.java b/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ValidateClientAuthenticationTypeTest.java
deleted file mode 100644
index e2c3c91c..00000000
--- a/idp-oidc-extension-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/authn/impl/ValidateClientAuthenticationTypeTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package net.shibboleth.idp.plugin.oidc.op.authn.impl;
-
-import java.util.Collections;
-import java.util.Date;
-import java.util.Set;
-
-import org.opensaml.profile.action.EventIds;
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.springframework.webflow.execution.Event;
-import org.springframework.webflow.execution.RequestContext;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.nimbusds.jose.JOSEException;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
-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 com.nimbusds.openid.connect.sdk.rp.OIDCClientInformation;
-import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
-
-import net.shibboleth.idp.authn.AuthnEventIds;
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.oidc.authn.context.OAuth2ClientAuthenticationContext;
-import net.shibboleth.oidc.metadata.context.OIDCMetadataContext;
-import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
-import net.shibboleth.idp.profile.testing.ActionTestingSupport;
-import net.shibboleth.idp.profile.testing.RequestContextBuilder;
-
-/**
- * Unit tests for {@link ValidateClientAuthenticationType}.
- */
-public class ValidateClientAuthenticationTypeTest {
-
- private ClientID clientId;
- private Secret clientSecret;
-
- private ValidateClientAuthenticationType action;
-
- private RequestContext rc;
- private ProfileRequestContext prc;
-
- private Set<ClientAuthenticationMethod> enabledMethods;
-
- @BeforeMethod
- public void init() throws ComponentInitializationException {
- clientId = new ClientID("mockId");
- clientSecret = new Secret("secret1234567890secret1234567890secret1234567890");
- enabledMethods = Collections.emptySet();
-
- action = new ValidateClientAuthenticationType();
- action.setTokenEndpointAuthMethodsLookupStrategy(p -> {
- return enabledMethods;
- }
- );
- action.initialize();
- }
-
- protected void initializeRequestCtx(final ClientAuthenticationMethod method,
- final ClientAuthenticationMethod storedMethod) throws JOSEException, ComponentInitializationException {
- final ClientAuthentication clientAuth;
- if (method.equals(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)) {
- clientAuth = new ClientSecretBasic(clientId, clientSecret);
- } else if (method.equals(ClientAuthenticationMethod.CLIENT_SECRET_POST)) {
- clientAuth = new ClientSecretPost(clientId, clientSecret);
- } else {
- clientAuth = null;
- }
- rc = new RequestContextBuilder().setInboundMessage(null).buildRequestContext();
- prc = new WebflowRequestContextProfileRequestContextLookup().apply(rc);
- prc.addSubcontext(new AuthenticationContext()).addSubcontext(
- new OAuth2ClientAuthenticationContext().setClientAuthentication(clientAuth));
-
- final OIDCMetadataContext oidcContext = new OIDCMetadataContext();
- final OIDCClientMetadata metadata = new OIDCClientMetadata();
- metadata.setTokenEndpointAuthMethod(storedMethod);
- // we're not actually validating the secret so it doesn't matter
- final Secret secret = new Secret("WRONG1234567890secret1234567890secret1234567890");
- final OIDCClientInformation clientInformation =
- new OIDCClientInformation(clientId, new Date(), metadata, secret);
- oidcContext.setClientInformation(clientInformation);
- prc.ensureInboundMessageContext().addSubcontext(oidcContext);
- }
-
- @Test
- public void testNoAuthnContext() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.CLIENT_SECRET_BASIC,
- ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
- prc.removeSubcontext(AuthenticationContext.class);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertEvent(e, AuthnEventIds.INVALID_AUTHN_CTX);
- }
-
- @Test
- public void testNoneDisabled() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.NONE,
- ClientAuthenticationMethod.NONE);
- prc.ensureSubcontext(AuthenticationContext.class).removeSubcontext(OAuth2ClientAuthenticationContext.class);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertEvent(e, EventIds.ACCESS_DENIED);
- }
-
- @Test
- public void testNoneEnabled() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.NONE,
- ClientAuthenticationMethod.NONE);
- enabledMethods = Collections.singleton(ClientAuthenticationMethod.NONE);
- prc.ensureSubcontext(AuthenticationContext.class).removeSubcontext(OAuth2ClientAuthenticationContext.class);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertProceedEvent(e);
- }
-
- @Test
- public void testBasicDisabled() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.NONE,
- ClientAuthenticationMethod.NONE);
- enabledMethods = Collections.singleton(ClientAuthenticationMethod.CLIENT_SECRET_POST);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertEvent(e, EventIds.ACCESS_DENIED);
- }
-
- @Test
- public void testBasicEnabled() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.CLIENT_SECRET_BASIC,
- ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
- enabledMethods = Collections.singleton(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertProceedEvent(e);
- }
-
- @Test
- public void testNoMetadata() throws Exception {
- initializeRequestCtx(ClientAuthenticationMethod.CLIENT_SECRET_BASIC,
- ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
- prc.ensureInboundMessageContext().removeSubcontext(
- prc.ensureInboundMessageContext().ensureSubcontext(OIDCMetadataContext.class));
- enabledMethods = Collections.singleton(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
- final Event e = action.execute(rc);
- ActionTestingSupport.assertProceedEvent(e);
- }
-
-}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list