-
-
Notifications
You must be signed in to change notification settings - Fork 621
Expire the token prematurely on client side #394
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
|
@klippx Interesting solution. What if instead of adding a constant that would globally apply for every use case, including some where it may be detrimental, we added the Current: Update: Then the handling of the expires_at can remain the same, from the perspective of all outside callers of this class, the expiry is just sooner than it otherwise would have been. Would that work for your use case? |
|
@pboling Sounds good! I updated with inspiration from your suggested code, and added some specs. |
lib/oauth2/access_token.rb
Outdated
| @expires_at &&= @expires_at.to_i | ||
| @expires_at ||= Time.now.to_i + @expires_in if @expires_in | ||
| @expires_latency &&= @expires_latency.to_i | ||
| @expires_at ||= Time.now.to_i + @expires_in - @expires_latency if @expires_in |
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 almost correct.
The instance variables initially get set to a value if provided, or nil.
instance_variable_set("@#{arg}", opts.delete(arg) || opts.delete(arg.to_s))
The &&= then ensures that the values stay nil, or if they are String/Integer, they are cast to integer.
@expires_in &&= @expires_in.to_i
@expires_at &&= @expires_at.to_i
This means that the values can be nil, and if nil, can't be used in math, unless cast to integer, or protected by a condition.
I see that you are defaulting expires_latency to 0, but would prefer it default to nil like the others. It is nonsensical to use &&= if it will always be a truthy value.
@expires_latency &&= @expires_latency.to_i
Additionally the code as you have it will not apply the expires_latency when the expires_at has been provided explicitly, as it is only applied after an ||=.
The following would fix that:
@expires_at ||= Time.now.to_i + @expires_in if @expires_in
@expires_at -= @expires_latency if @expires_latency
I think that this is in line with the underlying purpose of @expires_latency though.
lib/oauth2/access_token.rb
Outdated
| [:refresh_token, :expires_in, :expires_at, :expires_latency].each do |arg| | ||
| instance_variable_set("@#{arg}", opts.delete(arg) || opts.delete(arg.to_s)) | ||
| end | ||
| @expires_latency ||= 0 |
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 think I'd prefer having it be nil by default in keeping with the other options' nil defaults.
| hash = {:access_token => token, :expires_in => 100} | ||
| target = described_class.from_hash(client, hash) | ||
| expect(target.expires_latency).to eq 0 | ||
| end |
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.
Would prefer that it be nil by default.
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.
- make it nil by default
| hash = {:access_token => token, :expires_latency => 10, :expires_in => 100} | ||
| target = described_class.from_hash(client, hash) | ||
| expect(target.expires_at).to eq 1_530_000_090 | ||
| end |
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 code as you have it would fail a spec where expires_at and expires_latency are both provided explicitly, as expires_at would not be adjusted by the expires_latency. See my comment inline with the code for a suggestion at a small change to make expires_latency globally applicable when provided.
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.
- Added a spec for this scenario
|
@klippx I like the direction of this! |
|
Made the initialize code slightly more complex and had to add another rubocop exclusion I'm afraid. The initialize code is getting hairy, I have to admit. |
lib/oauth2/access_token.rb
Outdated
| @expires_latency &&= @expires_latency.to_i | ||
| if @expires_in | ||
| @expires_at ||= Time.now.to_i + @expires_in | ||
| @expires_at -= @expires_latency if @expires_latency |
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 would expect this setting to always apply if provided. I don't see a reason to have it be dependent on the @expires_in being set. Other methods of getting an @expires_at set are possible.
Was there a reason for structuring it this way?
I prefer to have features that work independent of other features, for less confusing, less complex logic. Something like:
@expires_at ||= Time.now.to_i + @expires_in if @expires_in
@expires_at -= @expires_latency if @expires_at && @expires_latency
| expect(target.expires_at).to eq(expires_at + expires_in - expires_latency) | ||
| end | ||
|
|
||
| it 'reduces expires_at by the given amount if expires_at is provided as option' do |
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.
Perhaps one more additional test - reduces expires_at by the given amount if expires_at is not provided as option?
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 think reduces expires_at by the given amount covers this case since expires_at is not provided by default and this test explicitly says that it is provided, and adds it to the hash.
|
I added further changes as per review. Unfortunately the rubocop complaints are still there, I cannot get rid of them without a bigger refactoring of the code. Perhaps this can be raised as separate issue. |
pboling
left a comment
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.
Looks good! Thanks for seeing it through 👍
|
Need to keep this branch open a while until a new version of the gem is released |
|
Progress is slow on the next release, but it is coming! |
Our assumption was that
expires_at?is inaccurate and needs to be offset by some fixed latency amount that we never expect to exceed has been tested and this change solves the described issue #393The Kred::HttpErrors (which are due to getting two 401 in a row and failing the request) have vanished competely after the deploy (second green marker from the right).
The 10 seconds are a bit arbitrary, and in worst case (where latency is zero) will simply expire the token 10seconds too early on the client side. Which I think most people can live with since expires_at often is 300s or even 1800s.