-
Notifications
You must be signed in to change notification settings - Fork 926
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
feat: refresh support #361
Conversation
Co-authored-by: João Pedro Antunes Silva <[email protected]>
Some thoughts on auto refresh: |
@MathiasCiarlo If logging out the user when token expires what's the purpose of the refrash token? Can you please explain more? In current implementation |
@pi0 I don't mean the user should be logged out when the access token expires, but if no request/activity has been made before the refresh token expires, I think the user should be logged out. Lets say the access token expires after 5 minutes, and the refresh token expires after 30 minutes. If a user logs in, and leaves his or her computer for a really long coffee break, the session should expire after 30 minutes of inactivity. The user can keep the session alive by refreshing the token before the 30 minute mark. I have been using @robsontenorio's fork, where the token is only refreshed when the user performs a request, thus being active. I think this is a safer approach, since it only keeps active users logged in. So if I understand you correctly - the new refresh scheme is only temporary (and only works for local scheme), and will not be a scheme in the future? The goal is built in refresh functionality for both local and oauth2? |
Yes exactly Regarding auto-refresh timer, totally makes sense to be disabled by default. Does current error interceptor looks good/enough to you? |
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.
Some more questions 🙂
…e defaultExpirationTime to token.maxAge
I think it's because the token is refreshed when it has expired, not when invalidated. |
So, if I get 401 because of invalid token it won’t refresh, right? |
Right. We don't intercept 401 anymore. |
Got it. Thanks! Have a good day:) |
Thanks! You too! :) |
Hello @JoaoPedroAS51 , so to refresh token after a 401 we need to do it independently from auth module ? |
Hi @JSeifBY! Yes, if you want to refresh after a 401 you need to do it yourself. But if you have a 401 because of an expired token, means that our system is not working well. Then please let me know. :) We adopted the practice of refresh tokens based on the token expiration. We intercept requests and check for token expiration. If the token has expired then we refresh. The original request will await for refresh request. A 401 error means that you are unauthorized to access the target resource, but it doesn't mean that the token has expired. That's why we base the refresh on token expiration. |
Many thanks for those clarifications @JoaoPedroAS51 🙏 |
I can't wait to use V5.... |
Hello @JoaoPedroAS51 , My tokens are not being saved in the Local Storage / Cookie. In Local storage I see |
Hi @ismailonly! What version are you using? |
@ismailonly Can you also show me your auth config? :) |
version: 4.9.1 auth: { |
@ismailonly Thank you! :) So, refresh support wasn't released yet. It will be released in v5, but you can use the dev version in the meantime. We published a new package for dev version Please, check the updated docs for dev version, because we made a lot of changes https://dev.auth.nuxtjs.org/ |
Thanks for the quick resonse @JoaoPedroAS51 I will check it out. |
@JoaoPedroAS51 is the |
@ismailonly Yes, it was removed. Now you must set |
@JoaoPedroAS51 I believe that the
I humbly request you to reconsider and keep |
Hi @ismailonly! Thank you for your feedback! :) I fully agree with you! And that's why we decode JWT tokens to get the It will be used by other tokens that can't be decoded. The main reason we removed |
@JoaoPedroAS51 I am sorry. My bad. I didn't read the docs properly which clearly states that the Excellent. Thanks for the detailed responses. :) |
Hi @JoaoPedroAS51, one more question concerns refresh:) Error occurs on server and it seems the only way to catch it. |
Hi @iteamaster89! I think we can increment this plugin a little more :) NOT TESTED export default function ({ $axios, $auth }) {
$axios.onError(async ({ config, response: { status } }) => {
// Only intercept requests with status 401
// Don't intercept refresh token requests
// And check if user is logged in and tokens are available
if (status !== 401 || config.url === $auth.strategy.options.endpoints.refresh.url || !$auth.check()) {
return Promise.reject(error)
}
// Refresh tokens before retrying current request
await $auth.refreshTokens().catch((error) => {
// Tokens couldn't be refreshed. Force reset.
$auth.reset()
throw error
})
// Set `isRetryRequest` flag to true
config.__isRetryRequest = true
// Update Authorization header
config.headers[$auth.strategy.options.token.name] = $auth.token.get()
// Retry original request
return $axios.request(config)
})
} |
@iteamaster89 I still recommending the approach of refresh tokens based on the token expiration instead of on error.
|
Thanks man! |
@JoaoPedroAS51 Hi, is it possible to dynamically change login method depending, for example, on cookie info ('mode=dev' or 'mode=prod')? |
Hi @iteamaster89! If you want to change based on environment, I would suggest to use export default function ({ $auth }) {
// do something here
// you can access and change options using
// $auth.strategies['local'].options.endpoints.login
} |
Thanks a lot! It's what I really needed. |
Refresh strategy, based on token expiration time, is bit naive 😏. Even a small shift in time between the server and the client can lead to an unwanted 401 error. I think the refresh strategy should combine both the expiration time strategy and the interception of a 401 error.
This can be solved by checking an endpoint that is 100% available to the user, e.g. |
There seems to be some confusion between access tokens, refresh tokens (the objects), and token refresh (the process).
Not all refresh tokens can be decoded to obtain expiration. Nuxt-auth has a option to explicitly set expiration, but because time can be manipulated on the client, you still need to check for errors.
If you get a 401 when using a refresh token, you (i.e. nuxt-auth) must make sure the user is logged out and redirect to login page because refresh tokens are not renewable.
401 may not be the best response by the server for expired refresh tokens, but is reasonable. 403 might be better. However, this is not under nuxt-auth control.
In the case of access tokens, you can rely on expiration time in the JWT if it’s signed, but you also need to handle 401 because client time can be manipulated and the token can expire mid flight.
In this case, 401 is the correct response because the request can be retried when a new access token is obtained without user authentication using a valid refresh token.
Talking with the nuxt-auth maintainers, contributing my own fixes and features, and using the dev version on a daily basis, I can confirm that this is how the module behaves.
On Jul 3, 2020, at 1:04 AM, Asker Khakh <[email protected]> wrote:
@iteamaster89<https://github.com/iteamaster89> I still recommending the approach of refresh tokens based on the token expiration instead of on error.
We adopted the practice of refresh tokens based on the token expiration. We intercept requests and check for token expiration. If the token has expired then we refresh. The original request will await for refresh request.
Refresh strategy, based on token expiration time, is bit naive 😏. Even a small shift in time between the server and the client can lead to an unwanted 401 error. I think the refresh strategy should combine both the expiration time strategy and the interception of a 401 error.
A 401 error means that you are unauthorized to access the target resource, but it doesn't mean that the token has expired. That's why we base the refresh on token expiration.
This can be solved by checking an endpoint that is 100% available to the user, e.g. auth/me. If that endpoint returned 401 too, then we can say for sure that access token is expired.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub<#361 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/ACPNVXNDZQVVPMFWI67B3TDRZWGILANCNFSM4HPUDIRA>.
|
Fixed version of this axios interceptor, hope it'll help someone export default function ({$axios, $auth}) {
$axios.onError(async (error) => {
const config = error.config;
// Don't intercept retry request
// Only intercept requests with status 401
// Don't intercept refresh token requests
// And check if user is logged in and tokens are available
if (
config.__isRetryRequest ||
error.response.status !== 401 ||
config.url === $auth.strategy.options.endpoints.refresh.url ||
!$auth.check()
) {
return Promise.reject(error);
}
// Refresh tokens before retrying current request
await $auth.refreshTokens().catch((error) => {
// Tokens couldn't be refreshed. Force reset.
$auth.reset();
throw error;
});
// Set `isRetryRequest` flag to true
config.__isRetryRequest = true;
// Update Authorization header
config.headers[$auth.strategy.options.token.name] = $auth.token.get();
// Retry original request
return $axios.request(config);
});
} |
Based on #325 (@JoaoPedroAS51), #208 (@KonoMaxi) -- so main credits backs to authors. This PR is preparing to merge into upstream.
This closes #261, closes #398 and closes #67
Note
Refresh support will be released in v5. If you want to use it in the meantime, use the package
@nuxtjs/auth-next
. Please, check the updated docs for dev version https://dev.auth.nuxtjs.org/TODO
clientId
into refresh (and if possible generalize it more)