-
Notifications
You must be signed in to change notification settings - Fork 536
fix: Tune auth token refresh and valid windows. #2630
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
Conversation
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.
Most of this is absolutely fine - just a few questions that affect the public API. Probably worth chatting about in a meeting rather than back-and-forth here.
// it's expired now. | ||
long isHardExpiredSeconds = 60 * 15; | ||
// it's not valid and may not be used. | ||
long mayNotBeUsesSeconds = 60 * 15; |
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.
Uses => Used
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.
Done
|
||
/// <summary> | ||
/// Returns true if the token represented by this token response is valid, that is, it may be used | ||
/// for authentication and authorizations purposes. |
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.
authorizations => authorization
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.
Done
/// <list type="bullet"> | ||
/// <item>At least one of <see cref="AccessToken"/> and <see cref="IdToken"/> is not null.</item> | ||
/// <item><see cref="ExpiresInSeconds"/> is not null.</item> | ||
/// <item>The token has not expired and will not expire in the very near future. That is if |
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.
Hmm. This is where I have a problem with "valid" as the term. If a token hasn't expired, I would say it's valid. If I send it to a service and there isn't clock skew involved, it's still going to succeed.
Do we need to make this public immediately? Can we make it internal for now (or even remove it if we're using a clock elsewhere) and then make it public when we've got a better name?
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.
I'm removing this property entirely, we don't use it and we didn't have anything like this before.
internal bool MayBeUsed(IClock clock) => | ||
(AccessToken is not null || IdToken is not null) && | ||
ExpiresInSeconds.HasValue && | ||
IssuedUtc.AddSeconds(ExpiresInSeconds.Value - TokenInvalidWindowSeconds) > clock.UtcNow; |
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.
Just as a potential future refactor, I wonder whether we should have an EffectiveExpiryTimeUtc which is IssuedUtc.AddSeconds(ExpiresInSeconds.Value - TokenInvalidWindowSeconds)
(and make it nullable) so we could make this:
(AccessToken is not null || IdToken is not null) &&
EffectiveExpiryUtc is DateTime effectiveExpiry &&
clock.UtcNow < effectiveExpiry
Happy to bikeshed the "effective expiry" name - maybe "DoNotUseAfter" or something :)
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.
Yep, and I'm doing the same for the ShouldRefresh one. I'm adding: RefreshWindowStartUtc and ExpiryWindowStartUtc. Does that sound good?
@@ -135,7 +135,7 @@ public bool ShouldRequestAuthorizationCode(TokenResponse token) | |||
// If the flow includes a parameter that requires a new token, if the stored token is null or it doesn't | |||
// have a refresh token and the access token is expired we need to retrieve a new authorization code. | |||
return Flow.ShouldForceTokenRetrieval() || token == null || (token.RefreshToken == null | |||
&& token.IsExpired(flow.Clock)); | |||
&& token.ShouldBeRefreshed(flow.Clock)); |
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.
This is a semantic change, right? (Admittedly one that would only be hit very rarely.)
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've talked about this offline, but just to close the loop: this is just change in the method name that was not clear before. The semantics are exactly the same as before, it's just the new method name that matches those semantics better.
9d0af17
to
b7df1b7
Compare
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.
@jskeet I've addressed your comments and also increased the "invalid" window to 1 minute before expiry (from 30 seconds). Changes are in ordered commits named "Address comments..."
// it's expired now. | ||
long isHardExpiredSeconds = 60 * 15; | ||
// it's not valid and may not be used. | ||
long mayNotBeUsesSeconds = 60 * 15; |
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.
Done
|
||
/// <summary> | ||
/// Returns true if the token represented by this token response is valid, that is, it may be used | ||
/// for authentication and authorizations purposes. |
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.
Done
/// <list type="bullet"> | ||
/// <item>At least one of <see cref="AccessToken"/> and <see cref="IdToken"/> is not null.</item> | ||
/// <item><see cref="ExpiresInSeconds"/> is not null.</item> | ||
/// <item>The token has not expired and will not expire in the very near future. That is if |
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.
I'm removing this property entirely, we don't use it and we didn't have anything like this before.
@@ -135,7 +135,7 @@ public bool ShouldRequestAuthorizationCode(TokenResponse token) | |||
// If the flow includes a parameter that requires a new token, if the stored token is null or it doesn't | |||
// have a refresh token and the access token is expired we need to retrieve a new authorization code. | |||
return Flow.ShouldForceTokenRetrieval() || token == null || (token.RefreshToken == null | |||
&& token.IsExpired(flow.Clock)); | |||
&& token.ShouldBeRefreshed(flow.Clock)); |
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've talked about this offline, but just to close the loop: this is just change in the method name that was not clear before. The semantics are exactly the same as before, it's just the new method name that matches those semantics better.
internal bool MayBeUsed(IClock clock) => | ||
(AccessToken is not null || IdToken is not null) && | ||
ExpiresInSeconds.HasValue && | ||
IssuedUtc.AddSeconds(ExpiresInSeconds.Value - TokenInvalidWindowSeconds) > clock.UtcNow; |
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.
Yep, and I'm doing the same for the ShouldRefresh one. I'm adding: RefreshWindowStartUtc and ExpiryWindowStartUtc. Does that sound good?
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.
Great, thanks!
This is to account for Metadata Servers caching the tokens.
We are using a shared extension method instead.
b7df1b7
to
09e2199
Compare
Thanks! I've squashed the review commits and will merge on green. |
Fixes: - #2613 Default JSON serializer is not affected by gloabl JSON settings. - #2630 Tune authorization token staleness and validity windows so that it doesn't overlap with Metadata Server authorization token caching. Features: - #2616 Makes batch response handling more efficient, particularly benefiting large responses.
Fixes: - #2613 Default JSON serializer is not affected by gloabl JSON settings. - #2630 Tune authorization token staleness and validity windows so that it doesn't overlap with Metadata Server authorization token caching. Features: - #2616 Makes batch response handling more efficient, particularly benefiting large responses.
And some code cleanup and refactor.
@jskeet as always, one commit at a time.