[java-oidc-common] 02/03: Removed the deprecated AuthenticationTimeClaimsValidator class + references.
Henri Mikkonen
henri.mikkonen at iki.fi
Fri Sep 8 10:56:58 UTC 2023
This is an automated email from the git hooks/post-receive script.
hjmikkon pushed a commit to branch main
in repository java-oidc-common.
View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=088a7de402d76fbed8bebe6fd65a36bca13a843e
commit 088a7de402d76fbed8bebe6fd65a36bca13a843e
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Fri Sep 8 13:49:23 2023 +0300
Removed the deprecated AuthenticationTimeClaimsValidator class + references.
---
.../impl/AuthenticationTimeClaimsValidator.java | 244 ---------------------
.../AuthenticationTimeClaimsValidatorTest.java | 202 -----------------
.../impl/ChainingJWTClaimsValidatorTest.java | 27 ---
3 files changed, 473 deletions(-)
diff --git a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidator.java b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidator.java
deleted file mode 100644
index d78e843..0000000
--- a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidator.java
+++ /dev/null
@@ -1,244 +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.oidc.security.jwt.claims.impl;
-
-import java.text.ParseException;
-import java.time.Duration;
-import java.time.Instant;
-import java.util.Date;
-import java.util.function.Function;
-import java.util.function.Predicate;
-
-import javax.annotation.Nonnull;
-
-import org.opensaml.profile.context.ProfileRequestContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Predicates;
-import com.nimbusds.jwt.JWTClaimsSet;
-
-import net.shibboleth.oidc.jwt.claims.AbstractClaimsValidator;
-import net.shibboleth.oidc.jwt.claims.JWTValidationException;
-import net.shibboleth.shared.annotation.constraint.ThreadSafeAfterInit;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.logic.FunctionSupport;
-
-/**
- * Verifies the auth_time (when the End-User authentication took place):
- * <ol>
- * <li>If the authnLifetimeLookup returns 0 seconds (e.g. max_age=0), assume the 'forced authentication' semantic, and
- * check the auth_time is after the authentication request time.</li>
- * <li>Or, if the authnLifetimeLookup returns a value >0, check the authentication occurred within a valid expiration
- * window.</li>
- * </ol>
- *
- * <p>A predicate determines if the auth_time was requested e.g. was explicitly requested, or the max_age
- * claim was set. Defaults to true.</p>
- */
- at ThreadSafeAfterInit
-public class AuthenticationTimeClaimsValidator extends AbstractClaimsValidator {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(AuthenticationTimeClaimsValidator.class);
-
- /**
- * Lookup strategy to find the amount of time for which a token is valid
- * after if it was first issued. (Default value: 60 seconds)
- */
- @Nonnull private Function<ProfileRequestContext, Duration> authnLifetimeLookupStrategy;
-
- /**
- * Lookup strategy to find the time at which the authentication request was made.
- * Defaults to now minus the clockskew.
- */
- @Nonnull private Function<ProfileRequestContext, Instant> authnRequestTimeLookupStrategy;
-
- /**
- * Positive clock skew adjustment to consider when checking auth_time is not in the future
- * or has expired. (Default value: 60 seconds).
- */
- @Nonnull private Duration clockSkew;
-
- /**
- * Has the auth_time been requested, either explicitly or from the max_age parameter?
- * Defaults to true.
- */
- @Nonnull private Predicate<ProfileRequestContext> requested;
-
- /** Constructor.*/
- public AuthenticationTimeClaimsValidator() {
- authnLifetimeLookupStrategy = prc -> Duration.ofSeconds(60);
- clockSkew = Duration.ofSeconds(60);
- authnRequestTimeLookupStrategy = prc -> Instant.now().minus(clockSkew);
- requested = Predicates.alwaysTrue();
- }
-
- /**
- * Set the clock skew.
- *
- * @param skew clock skew to set
- */
- public void setClockSkew(@Nonnull final Duration skew) {
- ifInitializedThrowUnmodifiabledComponentException();
-
- clockSkew = Constraint.isNotNull(skew, "Clock skew cannot be null");
- }
-
- /**
- * Set the lookup strategy to find out when the authentication request (if any) was made.
- *
- * @param strategy the strategy
- *
- * @since 2.2.0
- */
- public void setAuthnRequestTimeLookupStrategy(
- final Function<ProfileRequestContext, Instant> strategy) {
- ifInitializedThrowUnmodifiabledComponentException();
- ifDestroyedThrowDestroyedComponentException();
-
- authnRequestTimeLookupStrategy = Constraint.isNotNull(strategy,
- "authnRequestTimeLookupStrategy can not be null");
- }
-
-
- /**
- * Has the auth_time been request e.g. explicitly, or by using the max_age parameter.
- * @deprecated use the activation condition in the base class instead.
- *
- * @param isRequested has auth_time been requested.
- */
- @Deprecated(forRemoval = true, since = "2.2.0")
- public void setRequested(final Predicate<ProfileRequestContext> isRequested) {
- ifInitializedThrowUnmodifiabledComponentException();
-
- requested = isRequested;
- }
-
- /**
- * Sets the amount of time for which a token is valid from when the original authentication took place.
- *
- * @param lifetime amount of time for which a token is valid
- */
- public void setAuthnLifetime(@Nonnull final Duration lifetime) {
- ifInitializedThrowUnmodifiabledComponentException();
-
- Constraint.isNotNull(lifetime, "Token authentication lifetime cannot be null");
- Constraint.isFalse(lifetime.isNegative(), "Token authentication lifetime cannot be negative");
-
- authnLifetimeLookupStrategy = FunctionSupport.constant(lifetime);
- }
-
- /**
- * Set the lookup strategy used to locate the amount of time for which a token is valid from when the original
- * authentication took place.
- *
- * @param strategy the strategy
- *
- * @since 2.2.0
- */
- public void setAuthnLifetimeLookupStrategy(@Nonnull final Function<ProfileRequestContext, Duration> strategy) {
- ifInitializedThrowUnmodifiabledComponentException();
- ifDestroyedThrowDestroyedComponentException();
-
- authnLifetimeLookupStrategy = Constraint.isNotNull(strategy,
- "AuthnLifetime Lookup Strategy can not be null");
- }
-
- // Checkstyle: CyclomaticComplexity|MethodLength OFF
- @Override
- public void doValidate(@Nonnull final JWTClaimsSet claimsSet, @Nonnull final ProfileRequestContext context)
- throws JWTValidationException {
-
- if (!requested.test(context)) {
- //not requested, so nothing to check.
- return;
- } else {
-
- try {
- final Duration authnLifetime = authnLifetimeLookupStrategy.apply(context);
- final Date authTimeDate = claimsSet.getDateClaim(IDTokenClaims.AUTHENTICATION_TIME.getClaimName());
-
- if (authTimeDate == null) {
- throw new JWTValidationException("No authentication time found in token");
- }
- if (authnLifetime == null) {
- throw new JWTValidationException("No authentication lifetime set");
- }
-
- if (authnLifetime.equals(Duration.ofSeconds(0))) {
- // Now assume forced authentication semantics, the authentication must have happened after the
- // authentication request was made to the OP
- if (authnRequestTimeLookupStrategy == null) {
- log.warn("Maximum authentication age of 0 seconds requested, but no "
- + "authentication request time lookup strategy set, can not check for a fresh "
- + "authentication");
- throw new JWTValidationException("Maximum authentication age of 0 seconds requested, but no "
- + "authentication request time lookup strategy set, can not check for a fresh "
- + "authentication");
- }
- final Instant authnRequestTime = authnRequestTimeLookupStrategy.apply(context);
-
- if (authnRequestTime == null) {
- log.warn("Maximum authentication age of 0 seconds requested, but no "
- + "authentication request time could be found, can not check for a fresh "
- + "authentication");
- throw new JWTValidationException("Maximum authentication age of 0 seconds requested, but no "
- + "authentication request time could be found, can not check for a fresh "
- + "authentication");
- }
-
- // Check authTime is after the time which the authentication request was made
- if (authTimeDate.toInstant().isBefore(authnRequestTime)) {
- log.warn("JWT token authentication time is not valid. Authentication is not fresh but max_age=0"
- + " was requested, re-authentication did not occur");
- throw new JWTValidationException("JWT token authentication time is not valid. Authentication "
- + "is not fresh but max_age=0 was requested, re-authentication did not occur");
- }
-
- } else {
- final Instant authTime = authTimeDate.toInstant();
- final Instant now = Instant.now();
- final Instant latestValid = now.plus(clockSkew);
- final Instant expiration = authTime.plus(clockSkew).plus(authnLifetime);
-
- // Check time of authentication wasn't in the future
- if (authTime.isAfter(latestValid)) {
- log.warn("Authentication is not yet valid: auth_time was {}, latest valid is: {}",
- authTime, latestValid);
- throw new JWTValidationException("JWT token authentication time is not yet valid");
- }
-
- // Check time of authentication has not expired
- if (expiration.isBefore(now)) {
- log.warn(
- "Authentication has expired: auth_time was '{}', "
- + "expired at: '{}', current time: '{}'",
- authTime, expiration, now);
- throw new JWTValidationException("JWT token authentication time has expired");
- }
- //is OK.
- }
-
- } catch (final ParseException e) {
- throw new JWTValidationException("Autentication forced, but no authentication time found in token",e);
- }
- }
-
- }
-
- // Checkstyle: CyclomaticComplexity|MethodLength ON
-}
diff --git a/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidatorTest.java b/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidatorTest.java
deleted file mode 100644
index 5dbe72a..0000000
--- a/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidatorTest.java
+++ /dev/null
@@ -1,202 +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.oidc.security.jwt.claims.impl;
-
-import java.time.Duration;
-import java.time.Instant;
-
-import javax.annotation.Nonnull;
-
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.nimbusds.jwt.JWTClaimsSet;
-
-import net.shibboleth.oidc.jwt.claims.JWTValidationException;
-import net.shibboleth.shared.component.ComponentInitializationException;
-
-/** Test for the {@link AuthenticationTimeClaimsValidator}. */
-public class AuthenticationTimeClaimsValidatorTest extends AbstractClaimsValidatorTest {
-
- /** The validator to test.*/
- @Nonnull private AuthenticationTimeClaimsValidator validator;
-
-
- @Override
- @BeforeMethod
- public void setup() throws ComponentInitializationException {
- super.setup();
- validator = new AuthenticationTimeClaimsValidator();
- }
-
- @Test
- public void doValidateTest() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
- IDTokenClaims.AUTHENTICATION_TIME.getClaimName(), Instant.now().getEpochSecond()).build();
- validator.setId("test-validator");
- validator.setAuthnLifetime(Duration.ofMinutes(1));
- validator.setClockSkew(Duration.ofSeconds(0));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- @Test
- public void doValidateTest_UseAuthnStrategy() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
- IDTokenClaims.AUTHENTICATION_TIME.getClaimName(), Instant.now().getEpochSecond()).build();
- validator.setId("test-validator");
- validator.setAuthnLifetimeLookupStrategy(prc -> Duration.ofMinutes(1));
- validator.setClockSkew(Duration.ofSeconds(0));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- @Test
- public void doValidateTest_DefaultAuthnTime() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
- IDTokenClaims.AUTHENTICATION_TIME.getClaimName(), Instant.now().getEpochSecond()).build();
- validator.setId("test-validator");
- validator.setClockSkew(Duration.ofSeconds(0));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- @Test
- public void doValidateTestWithinLifetime() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
- IDTokenClaims.AUTHENTICATION_TIME.getClaimName(),
- Instant.now().minus(Duration.ofSeconds(30)).getEpochSecond()).build();
- validator.setId("test-validator");
- validator.setAuthnLifetime(Duration.ofMinutes(1));
- validator.setClockSkew(Duration.ofSeconds(0));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- @Test
- public void doValidateNoClaimButNotActive() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().build();
- validator.setActivationCondition((prc,claims) -> false);
- validator.setId("test-validator");
- validator.setAuthnLifetime(Duration.ofMinutes(1));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- @Test(expectedExceptions = JWTValidationException.class)
- public void doRejectedTestCanNotParseDate() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
- IDTokenClaims.AUTHENTICATION_TIME.getClaimName(),"not-a-date").build();
- validator.setId("test-validator");
- validator.setAuthnLifetime(Duration.ofMinutes(1));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- @Test(expectedExceptions = JWTValidationException.class)
- public void doRejectedTest() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
- IDTokenClaims.AUTHENTICATION_TIME.getClaimName(),
- Instant.now().minus(Duration.ofMinutes(10)).getEpochSecond()).build();
- validator.setId("test-validator");
- validator.setAuthnLifetime(Duration.ofMinutes(1));
- validator.setClockSkew(Duration.ofMinutes(0));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- @Test(expectedExceptions = JWTValidationException.class)
- public void doRejectedInTheFuture() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
- IDTokenClaims.AUTHENTICATION_TIME.getClaimName(),
- Instant.now().plus(Duration.ofSeconds(30)).getEpochSecond()).build();
- validator.setId("test-validator");
- validator.setAuthnLifetime(Duration.ofMinutes(1));
- //set clockskew to 10 seconds, and JWT is 30 seconds in the future, so should throw
- validator.setClockSkew(Duration.ofSeconds(10));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- @Test
- public void doRejectedInTheFutureButInsideSkew() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
- IDTokenClaims.AUTHENTICATION_TIME.getClaimName(),
- Instant.now().plus(Duration.ofSeconds(30)).getEpochSecond()).build();
- validator.setId("test-validator");
- validator.setAuthnLifetime(Duration.ofMinutes(1));
- //set clockskew to 60 seconds, and JWT is 30 seconds in the future, so should be fine
- validator.setClockSkew(Duration.ofSeconds(60));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- @Test(expectedExceptions = JWTValidationException.class)
- public void doRejectedNoClaim() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().build();
- validator.setId("test-validator");
- validator.setAuthnLifetime(Duration.ofMinutes(1));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- @Test(expectedExceptions = JWTValidationException.class)
- public void doRejectedForceAuthenticationRequestButOldAuthnTime()
- throws JWTValidationException, ComponentInitializationException {
- // Authentication occurs 10 second before the authn request was sent
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
- IDTokenClaims.AUTHENTICATION_TIME.getClaimName(),
- Instant.now().minus(Duration.ofSeconds(10)).getEpochSecond()).build();
- validator.setId("test-validator");
- // returning 0 seconds 'signals' forced authentication
- validator.setAuthnLifetime(Duration.ofSeconds(0));
- validator.setAuthnRequestTimeLookupStrategy(prc -> Instant.now());
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
-
- @Test
- public void doValidForceAuthenticationRequest()
- throws JWTValidationException, ComponentInitializationException {
- // Authentication occurs 10 second after the authn request was sent
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
- IDTokenClaims.AUTHENTICATION_TIME.getClaimName(),
- Instant.now().plus(Duration.ofSeconds(10)).getEpochSecond()).build();
- validator.setId("test-validator");
- // returning 0 seconds 'signals' forced authentication
- validator.setAuthnLifetime(Duration.ofSeconds(0));
- validator.setAuthnRequestTimeLookupStrategy(prc -> Instant.now());
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
- /**
- * Would fail, but the claim was not requested, so it is not checked.
- *
- * @throws JWTValidationException on error.
- * @throws ComponentInitializationException on error.
- */
- @Test
- public void doValidateAuthTimeNotRequested() throws JWTValidationException, ComponentInitializationException {
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().build();
- validator.setId("test-validator");
- validator.setRequested(prc -> false);
- validator.setAuthnLifetime(Duration.ofMinutes(1));
- validator.initialize();
- validator.validate(claimsSet, prc);
- }
-
-}
diff --git a/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/ChainingJWTClaimsValidatorTest.java b/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/ChainingJWTClaimsValidatorTest.java
index 7e1f340..16b1690 100644
--- a/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/ChainingJWTClaimsValidatorTest.java
+++ b/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/ChainingJWTClaimsValidatorTest.java
@@ -86,14 +86,6 @@ public class ChainingJWTClaimsValidatorTest extends AbstractClaimsValidatorTest{
usernameExactV.initialize();
validators.add(usernameExactV);
- //auth time
- final AuthenticationTimeClaimsValidator authTimeV = new AuthenticationTimeClaimsValidator();
- authTimeV.setId("auth-time-validator");
- authTimeV.setAuthnLifetime(Duration.ofMinutes(1));
- authTimeV.setRequested(prc -> true);
- authTimeV.initialize();
- validators.add(authTimeV);
-
//nonce
final ExactMatchClaimsValidator nonceV = new ExactMatchClaimsValidator();
nonceV.setId("nonce-validator");
@@ -318,23 +310,4 @@ public class ChainingJWTClaimsValidatorTest extends AbstractClaimsValidatorTest{
validation.validate(claimsSet, prc);
}
- @Test(expectedExceptions = JWTValidationException.class)
- public void validationFailedAuthTimeTooFarInPast() throws ComponentInitializationException, JWTValidationException {
-
- final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
- .issuer("issuer")
- .subject("jdoe")
- .expirationTime(Date.from(Instant.now().plus(Duration.ofMinutes(10))))
- .audience("audience")
- .notBeforeTime(Date.from(Instant.now().minus(Duration.ofMinutes(1))))
- .issueTime(Date.from(Instant.now()))
- .claim(IDTokenClaims.AUTHENTICATION_TIME.getClaimName(),
- Instant.now().minus(Duration.ofSeconds(300)).getEpochSecond())
- .claim("username", "jdoe")
- .claim(IDTokenClaims.NONCE.getClaimName(), "nonce")
- .build();
-
- validation.validate(claimsSet, prc);
- }
-
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list