Open tokidoki11 opened 2 years ago
Hi @tokidoki11, we face exactly the same issue. We decorated the RequestHandlers "requestInterceptor" and added a promise queue to let other requests wait on the one who initiated it:
async requestInterceptor(config) {
// eslint-disable-next-line no-underscore-dangle,no-console
console.log('this token', this)
// eslint-disable-next-line no-underscore-dangle
if (!this._needToken(config) || config.url === this.refreshEndpoint) {
return config
}
const {
valid,
tokenExpired,
refreshTokenExpired,
isRefreshable,
} = this.scheme.check(true)
let isValid = valid
if (refreshTokenExpired) {
this.scheme.reset()
throw new ExpiredAuthSessionError()
}
if (tokenExpired) {
if (!isRefreshable) {
this.scheme.reset()
throw new ExpiredAuthSessionError()
}
// eslint-disable-next-line no-console
console.log('token expired')
if (this.promiseQueue.working) {
// eslint-disable-next-line no-console
console.log('waiting on the refresh')
await this.promiseQueue.enqueue(() => new Promise((resolve) => {
resolve()
}))
return this.requestInterceptor(config)
}
isValid = await this.promiseQueue.enqueue(async () => {
// eslint-disable-next-line no-console
console.log('enqueue new refresh')
this.scheme.refreshTokens()
.then(() => true)
.catch(() => {
this.scheme.reset()
throw new ExpiredAuthSessionError()
})
})
}
const token = this.scheme.token.get()
if (!isValid) {
// eslint-disable-next-line no-underscore-dangle
if (!token && this._requestHasAuthorizationHeader(config)) {
throw new ExpiredAuthSessionError()
}
return config
}
// eslint-disable-next-line no-underscore-dangle
return this._getUpdatedRequestConfig(config, token)
}
initializeRequestInterceptor(refreshEndpoint) {
this.refreshEndpoint = refreshEndpoint
this.interceptor = this.axios.interceptors.request.use(this.requestInterceptor.bind(this))
}
What do people think about this solution?
Regards, Flo
That's fine @florianPat - could you post the implementation your promise queue? Maybe thats a fix that can be implemented directly in the RequestHandler.initializeRequestInterceptor()?
Or would it be an alternative to request a new token just every time before it gets expired and not when it is "too late". But, I know, requests during token updating would have to be queued, too.
What do people think about this solution?
Regards, Flo
Where should I put this function?
I opened a PR to fix this: https://github.com/nuxt-community/auth-module/pull/1796
This bug has been fixed in v5.0.0-1667386184.dfbbb54
.
Version
module: "5.0.0-1643791578.532b3d6" nuxt: ^2.15.7
Nuxt configuration
mode:
Nuxt configuration
Reproduction
What is expected?
What is actually happening?
Additional information
I have separate axios instance for calling API other than auth0
Calling refreshToken via $auth will call the refresh Token only once On further investigation calling refreshToken via $auth will trigger https://github.com/nuxt-community/auth-module/blob/c9880dc28fa13ba036f078d37ff76e1267c65d21/src/core/auth.ts#L266-L279
https://github.com/nuxt-community/auth-module/blob/c9880dc28fa13ba036f078d37ff76e1267c65d21/src/inc/refresh-controller.ts#L13-L20
But the interceptor will call this in which it doesnt check whether refresh Token is still ongoing or not https://github.com/nuxt-community/auth-module/blob/c9880dc28fa13ba036f078d37ff76e1267c65d21/src/inc/request-handler.ts#L61-L68
https://github.com/nuxt-community/auth-module/blob/c9880dc28fa13ba036f078d37ff76e1267c65d21/src/schemes/oauth2.ts#L433
Checklist