Skip to content
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

Update refresh strategy to use a separate refresh token #190

Merged
merged 6 commits into from
Mar 22, 2017

Conversation

evoactivity
Copy link
Contributor

As discussed in this issue #162 I've made the library use a separate token to refresh the JWT.

I've updated the tests and they all pass but someone should really check what I've done, testing is not my strong point.

I've ran this on my app and confirmed it refreshes the token as expected.

…esh the JWT

Made makeRefreshToken use the refresh token propert name to create it's object

updated tests to deal with new refresh token method
@eluciano11
Copy link
Contributor

@evoactivity thank you for your work!

I've looked at the test and the implementation and it looks good. I think that we should wait until @jpadilla can take a look at this before we merge the PR. This is a breaking change so we'll need to update the docs and demo too. We can do that after @jpadilla takes a look.

@evoactivity
Copy link
Contributor Author

@eluciano11 No problem :)

I was wondering about the docs/demos, but decided against updating them until this had been reviewed incase there are any changes needed.

@jpadilla jpadilla self-requested a review February 14, 2017 16:39
@@ -120,11 +122,11 @@ export default TokenAuthenticator.extend({

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (Ember.isEmpty(expiresAt)) {
         // Fetch the expire time from the token data since `expiresAt`
         // wasn't included in the data object that was passed in.
         const tokenData = this.getTokenData(token);
 
         expiresAt = tokenData[this.tokenExpireName];
         if (Ember.isEmpty(expiresAt)) {
           return resolve(data);
         }
       }
 
       if (expiresAt > now) {

Shouldn't we be checking if the refresh token expiresAt > now rather than the auth token expiresAt > now?

With the way it currently is, if the auth token expired but the refresh token has not expired, it would not attempt to refresh.
I think we would want to attempt to refresh if the refresh token is still valid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My API's refresh token library creates the token like so $this->refreshToken = bin2hex(openssl_random_pseudo_bytes(64));, so the refresh token is not just another JWT with an expires property to be decoded. Looking at the auth0 page on refresh tokens it looks like they're implementing them in a similar way https://auth0.com/learn/refresh-tokens/

If the auth token is expired that's exactly when this tries to refresh using the refresh token, so I'm not entirely sure what you mean by that?

Copy link
Contributor

@alechirsch alechirsch Feb 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I am seeing, if the auth token is expired when it enters the restore function then it will reject on line 132

 reject(new Error('token is expired'));

Copy link
Contributor Author

@evoactivity evoactivity Feb 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, I see what you mean now, my mistake.

I guess if the token is expired and we have refreshAccessTokens set to true it should also attempt to refresh the token there as well, and if the server rejects the refresh token then the user is unauthorised sending them back to the login form.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sorry for the confusion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evoactivity Do you have time to implement the fix for this? I am considering forking off, I will be trying to use this feature in an app for this week.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alechirsch I will be looking at this again maybe later today or tomorrow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alechirsch I've updated this to attempt a refresh if the JWT is expired. If the server rejects the request the session is invalidated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evoactivity Awesome, thanks for your work on this, it is perfect timing.

@jpadilla
Copy link
Contributor

@evoactivity At a first pass, this lgtm. Thanks for putting this together.
@eluciano11 is there anything we'd need after this, docs and dummy app?

I'm fine introducing this as a new major release, but would also love to sneak in updating everything else including to the latest ESA.

@evoactivity
Copy link
Contributor Author

evoactivity commented Feb 21, 2017

@jpadilla no worries :) I've just pushed a small update to address the expiry issue pointed out by @alechirsch

The docs will need updating to explain the new refreshTokenPropertyName option, if people want to use the current strategy they should be able to simply give that the same name as tokenPropertyName.

The demo app should probably be updated to show this being used, the demo server will need to return two tokens now, the JWT and a standard refresh token.

@eluciano11
Copy link
Contributor

@jpadilla @evoactivity yup, updated the docs and the demo app but it's not using the two tokens it's falling back to the old strategy.

@alechirsch
Copy link
Contributor

alechirsch commented Feb 21, 2017

I just did some testing in my own application, there seems to be an issue with old timeouts not being removed. I will do more testing to find out what is really going on.

@alechirsch
Copy link
Contributor

alechirsch commented Feb 21, 2017

@evoactivity From what I am finding if you log in then refresh the page to make it call restore, it will refresh the token, and then call restore again exponentially. Meaning it calls restore once, then twice, then 4 times, then 8. Something about resolve(this.refreshAccessToken(refreshToken)); is making it call restore twice for every time it is called.

Restore should be called only once, when the page is refresh or opened in a new tab. I am unsure why this is happening at the moment.

@evoactivity
Copy link
Contributor Author

evoactivity commented Feb 21, 2017

@alechirsch I've not seen that behaviour at all in my own app.

What sort of expiry time do you have on your JWT? Also, what leeway do you have set?

@alechirsch
Copy link
Contributor

alechirsch commented Feb 21, 2017

For testing purposes I set it to 60 seconds, with 55 second leeway. Maybe that is the problem?

@evoactivity
Copy link
Contributor Author

I've been testing with my JWT set to 1 minute and my refresh token set to 2 minutes and my leeway set to 0.

I'm not sure why a 5 second expiry would call exponential calls to refreshAccessToken though.

@alechirsch
Copy link
Contributor

alechirsch commented Feb 21, 2017

What's odd is that the restore function is being called more than once.

@alechirsch
Copy link
Contributor

alechirsch commented Feb 21, 2017

I blew away my node_modules and reinstalled, set my expire to 10 minutes and leeway to 60 seconds. I am running into the same problem, the restore function is being called in an infinite loop somehow. It works great if the restore function rejects the first time it is hit, however if it resolves, it calls itself again. It hogs up the CPU at 100% as well.

@alechirsch
Copy link
Contributor

alechirsch commented Feb 21, 2017

I have traced it back to this file ember-simple-auth/instance-initializers/setup-session-restoration.

The beforeModel hook is being called on an infinite loop, which is in turn calling restore. This might be a problem with my app, looking into it more.

@alechirsch
Copy link
Contributor

@evoactivity It was definitely a problem with my application, the feature works as expected now.

@jpadilla
Copy link
Contributor

This is the current server implementation that the dummy app uses https://github.com/jpadilla/ember-simple-auth-token-server

@alechirsch
Copy link
Contributor

alechirsch commented Mar 22, 2017

What is currently holding up this PR? I have been using this for the past few weeks in my apps and it works perfectly by the way.

@jpadilla
Copy link
Contributor

@alechirsch thanks for bumping this again, great to know you've been using it for a while now. Since this is a breaking change, it'll be released on v3, but before doing so I would love to make sure we update ember-cli, ESA, etc. Thanks to all!

PS If anyone else wants to help with that before I do, please feel free to do so. Thanks!

@jpadilla
Copy link
Contributor

@homu r+

@homu
Copy link
Contributor

homu commented Mar 22, 2017

📌 Commit 765e926 has been approved by jpadilla

@homu
Copy link
Contributor

homu commented Mar 22, 2017

⚡ Test exempted - status

@homu homu merged commit 765e926 into fenichelar:master Mar 22, 2017
homu added a commit that referenced this pull request Mar 22, 2017
Update refresh strategy to use a separate refresh token

As discussed in this issue #162 I've made the library use a separate token to refresh the JWT.

I've updated the tests and they all pass but someone should really check what I've done, testing is not my strong point.

I've ran this on my app and confirmed it refreshes the token as expected.
@jpadilla
Copy link
Contributor

@alechirsch @evoactivity I'm looking for help with maintenance, would any of you be up to it?

@alechirsch
Copy link
Contributor

@jpadilla I can help out with pull requests and issues

@jpadilla
Copy link
Contributor

jpadilla commented Apr 21, 2017

@alechirsch that's so great, just sent you an invite, thank you so much!

@evoactivity
Copy link
Contributor Author

@jpadilla I'm too busy to offer much help at the moment but I'd be interested in helping when things settle down a bit for me. That's probably a month or two away though.

@jpadilla
Copy link
Contributor

jpadilla commented May 6, 2017

@evoactivity understandable! Feel free to ping back whenever you have a few cycles free, thanks!

@knownasilya
Copy link
Contributor

knownasilya commented May 18, 2017

This is a breaking change, because if the refreshToken name isn't set it defaults to refresh_token, which used to be the token name. If the property isn't set, it should default to the token name.

@jpadilla
Copy link
Contributor

Thank you all again! Just released v3.0.0 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants