From 2bd31c96eddae1082c370f6cfca20e7ac052a2f3 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Tue, 3 Apr 2018 20:52:00 -0400 Subject: [PATCH] ClaimAccessor.getClaimAsInstant() converts Long or Date Fixes gh-5191, Fixes gh-5192 --- .../security/oauth2/core/ClaimAccessor.java | 16 +++- .../oauth2/core/ClaimAccessorTests.java | 73 +++++++++++++++++++ .../oauth2/core/oidc/OidcIdTokenTests.java | 2 +- .../oauth2/core/oidc/OidcUserInfoTests.java | 2 +- .../security/oauth2/jwt/JwtTests.java | 2 +- 5 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClaimAccessorTests.java diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java index 80cad10d63..9cf2dc8deb 100644 --- a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java +++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java @@ -21,6 +21,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.time.Instant; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -81,11 +82,18 @@ public interface ClaimAccessor { if (!this.containsClaim(claim)) { return null; } - try { - return Instant.ofEpochMilli(Long.valueOf(this.getClaimAsString(claim))); - } catch (NumberFormatException ex) { - throw new IllegalArgumentException("Unable to convert claim '" + claim + "' to Instant: " + ex.getMessage(), ex); + Object claimValue = this.getClaims().get(claim); + if (Long.class.isAssignableFrom(claimValue.getClass())) { + return Instant.ofEpochSecond((Long) claimValue); } + if (Date.class.isAssignableFrom(claimValue.getClass())) { + return ((Date) claimValue).toInstant(); + } + if (Instant.class.isAssignableFrom(claimValue.getClass())) { + return (Instant) claimValue; + } + throw new IllegalArgumentException("Unable to convert claim '" + claim + + "' of type '" + claimValue.getClass() + "' to Instant."); } /** diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClaimAccessorTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClaimAccessorTests.java new file mode 100644 index 0000000000..2c35a87578 --- /dev/null +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/ClaimAccessorTests.java @@ -0,0 +1,73 @@ +/* + * Copyright 2002-2018 the original author or authors. + * + * 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 org.springframework.security.oauth2.core; + +import org.junit.Before; +import org.junit.Test; + +import java.time.Instant; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ClaimAccessor}. + * + * @author Joe Grandja + */ +public class ClaimAccessorTests { + private Map claims = new HashMap<>(); + private ClaimAccessor claimAccessor = (() -> this.claims); + + @Before + public void setup() { + this.claims.clear(); + } + + // gh-5192 + @Test + public void getClaimAsInstantWhenDateTypeThenReturnInstant() { + Instant expectedClaimValue = Instant.now(); + String claimName = "date"; + this.claims.put(claimName, Date.from(expectedClaimValue)); + + assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( + expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); + } + + // gh-5191 + @Test + public void getClaimAsInstantWhenLongTypeSecondsThenReturnInstant() { + Instant expectedClaimValue = Instant.now(); + String claimName = "longSeconds"; + this.claims.put(claimName, expectedClaimValue.getEpochSecond()); + + assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( + expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); + } + + @Test + public void getClaimAsInstantWhenInstantTypeThenReturnInstant() { + Instant expectedClaimValue = Instant.now(); + String claimName = "instant"; + this.claims.put(claimName, expectedClaimValue); + + assertThat(this.claimAccessor.getClaimAsInstant(claimName)).isBetween( + expectedClaimValue.minusSeconds(1), expectedClaimValue.plusSeconds(1)); + } +} diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenTests.java index 26965b1230..143e6790bb 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcIdTokenTests.java @@ -110,7 +110,7 @@ public class OidcIdTokenTests { assertThat(idToken.getAudience()).isEqualTo(AUD_VALUE); assertThat(idToken.getIssuedAt().toEpochMilli()).isEqualTo(IAT_VALUE); assertThat(idToken.getExpiresAt().toEpochMilli()).isEqualTo(EXP_VALUE); - assertThat(idToken.getAuthenticatedAt().toEpochMilli()).isEqualTo(AUTH_TIME_VALUE); + assertThat(idToken.getAuthenticatedAt().getEpochSecond()).isEqualTo(AUTH_TIME_VALUE); assertThat(idToken.getNonce()).isEqualTo(NONCE_VALUE); assertThat(idToken.getAuthenticationContextClass()).isEqualTo(ACR_VALUE); assertThat(idToken.getAuthenticationMethods()).isEqualTo(AMR_VALUE); diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoTests.java index df37a1b8b6..5b4e416cb6 100644 --- a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoTests.java +++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/oidc/OidcUserInfoTests.java @@ -137,6 +137,6 @@ public class OidcUserInfoTests { assertThat(userInfo.getPhoneNumber()).isEqualTo(PHONE_NUMBER_VALUE); assertThat(userInfo.getPhoneNumberVerified()).isEqualTo(PHONE_NUMBER_VERIFIED_VALUE); assertThat(userInfo.getAddress()).isEqualTo(new DefaultAddressStandardClaim.Builder(ADDRESS_VALUE).build()); - assertThat(userInfo.getUpdatedAt().toEpochMilli()).isEqualTo(UPDATED_AT_VALUE); + assertThat(userInfo.getUpdatedAt().getEpochSecond()).isEqualTo(UPDATED_AT_VALUE); } } diff --git a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTests.java b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTests.java index 650b9a3aad..14cb9e4ff4 100644 --- a/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTests.java +++ b/oauth2/oauth2-jose/src/test/java/org/springframework/security/oauth2/jwt/JwtTests.java @@ -106,7 +106,7 @@ public class JwtTests { assertThat(jwt.getSubject()).isEqualTo(SUB_VALUE); assertThat(jwt.getAudience()).isEqualTo(AUD_VALUE); assertThat(jwt.getExpiresAt().toEpochMilli()).isEqualTo(EXP_VALUE); - assertThat(jwt.getNotBefore().toEpochMilli()).isEqualTo(NBF_VALUE); + assertThat(jwt.getNotBefore().getEpochSecond()).isEqualTo(NBF_VALUE); assertThat(jwt.getIssuedAt().toEpochMilli()).isEqualTo(IAT_VALUE); assertThat(jwt.getId()).isEqualTo(JTI_VALUE); }