-
Notifications
You must be signed in to change notification settings - Fork 6k
Add ClaimAccessor Support for ISO Date formatted timestamps #6189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ClaimAccessor Support for ISO Date formatted timestamps #6189
Conversation
…y Auth0 and OneLogin)
@greyfairer Please sign the Contributor License Agreement! Click here to manually synchronize the status of this Pull Request. See the FAQ for frequently asked questions. |
@greyfairer Thank you for signing the Contributor License Agreement! |
return Instant.parse((String) claimValue); | ||
} | ||
catch(DateTimeParseException e){ | ||
throw new IllegalArgumentException("Unable to convert claim '" + claim + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could return null, here. Or do a try-catch in the calling code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep the existing behaviour of throwing IllegalArgumentException
as mentioned in previous comment.
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR @greyfairer. I've provided some comments.
@@ -98,8 +99,18 @@ default Instant getClaimAsInstant(String claim) { | |||
if (Instant.class.isAssignableFrom(claimValue.getClass())) { | |||
return (Instant) claimValue; | |||
} | |||
if (String.class.isAssignableFrom(claimValue.getClass())) { | |||
try { | |||
return Instant.parse((String) claimValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of Instant.parse()
let's attempt both of these:
ZonedDateTime.parse(claimValue, DateTimeFormatter.ISO_INSTANT)
ZonedDateTime.parse(claimValue, DateTimeFormatter.ISO_ZONED_DATE_TIME)
If both of these do not parse along with the previous (existing) parse attempts than we'll keep with throwing IllegalArgumentException
as is the current behaviour. I know I said I agreed to not throw for getters, but this is a special case IMO. If the claim exists, which is the case if the parse attempt proceed than we cannot just return null
as we are basically silently ignoring the error and the existing claim. This will just cause bigger issues for the user as tracking the root issue will make things more difficult.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ZonedDateTime.parse(claimValue, DateTimeFormatter.ISO_INSTANT) doesn't work, but Instant.from(DateTimeFormatter.ISO_INSTANT.parse((String)claimValue)) does.
The second one: DateTimeFormatter.ISO_ZONED_DATE_TIME works for UTC timestamps too (i.e. ending with Z), so I'm not sure if doing the ISO_INSTANT first is necessary.
return Instant.parse((String) claimValue); | ||
} | ||
catch(DateTimeParseException e){ | ||
throw new IllegalArgumentException("Unable to convert claim '" + claim + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep the existing behaviour of throwing IllegalArgumentException
as mentioned in previous comment.
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java
Show resolved
Hide resolved
oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/ClaimAccessor.java
Show resolved
Hide resolved
// gh-6187 | ||
@Test | ||
public void getClaimAsInstantWhenISODateStringThenReturnInstant() { | ||
Instant expectedClaimValue = Instant.now(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's explicitly provide the String
value for the test, for example, 2011-12-03T10:15:30+01:00
@@ -98,8 +101,24 @@ default Instant getClaimAsInstant(String claim) { | |||
if (Instant.class.isAssignableFrom(claimValue.getClass())) { | |||
return (Instant) claimValue; | |||
} | |||
if (String.class.isAssignableFrom(claimValue.getClass())) { | |||
try { | |||
return Instant.from(DateTimeFormatter.ISO_INSTANT.parse((String)claimValue)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second one: DateTimeFormatter.ISO_ZONED_DATE_TIME works for UTC timestamps too (i.e. ending with Z), so I'm not sure if doing the ISO_INSTANT first is necessary, but I'll keep it as per your request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok let's remove DateTimeFormatter.ISO_INSTANT
and let DateTimeFormatter.ISO_ZONED_DATE_TIME
handle both cases. Can you ensure we have 2 tests for:
- 2011-12-03T10:15:30Z
- 2011-12-03T10:15:30+01:00
@@ -98,8 +101,24 @@ default Instant getClaimAsInstant(String claim) { | |||
if (Instant.class.isAssignableFrom(claimValue.getClass())) { | |||
return (Instant) claimValue; | |||
} | |||
if (String.class.isAssignableFrom(claimValue.getClass())) { | |||
try { | |||
return Instant.from(DateTimeFormatter.ISO_INSTANT.parse((String)claimValue)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok let's remove DateTimeFormatter.ISO_INSTANT
and let DateTimeFormatter.ISO_ZONED_DATE_TIME
handle both cases. Can you ensure we have 2 tests for:
- 2011-12-03T10:15:30Z
- 2011-12-03T10:15:30+01:00
return ZonedDateTime.from(DateTimeFormatter.ISO_ZONED_DATE_TIME.parse((String)claimValue)) | ||
.toInstant(); | ||
} | ||
catch(DateTimeParseException e2){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you ensure the code formatting is consistent with the class for try/catch - see getClaimAsURL
} | ||
|
||
// gh-6187 | ||
@Test(expected = IllegalArgumentException.class) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove expected = IllegalArgumentException.class
and use assertThat(this.claimAccessor...
to be consistent with other tests in this class. Also, assertThat(..)
is the preferred pattern for testing.
Closing this PR. Please see comment |
…y Auth0 and OneLogin)
#6187