OAuth2 Logout - `logoutRedirectUri` does not work correctly
Version
module: 5.0.0-1648802546.c9880dc nuxt: 2.15.8
Nuxt configuration
mode:
- [x] universal
Nuxt configuration
auth: {
cookie: {
options: {
expires: 365,
secure: process.env.APP_ENV !== 'local',
},
},
strategies: {
idp: {
scheme: 'oauth2',
endpoints: {
authorization: process.env.OAUTH_AUTHORIZE_URL,
token: process.env.OAUTH_TOKEN_URL,
userInfo: process.env.OAUTH_USER_URL,
logout: process.env.OAUTH_LOGOUT_URL,
},
clientId: process.env.OAUTH_CLIENT_ID,
token: {
property: 'access_token',
type: 'Bearer',
maxAge: 1800,
},
refreshToken: {
property: 'refresh_token',
maxAge: 60 * 60 * 24 * 30,
},
responseType: 'code',
grantType: 'authorization_code',
redirectUri: process.env.OAUTH_CALLBACK_URL,
logoutRedirectUri: process.env.OAUTH_REDIRECT_AFTER_LOGOUT_URL,
codeChallengeMethod: 'plain',
autoFetchUser: false,
autoLogout: true,
},
},
plugins: [
'~/plugins/updateLoggedInUser.js',
],
},
}
Reproduction
What is expected?
I expect logout to do 3 actions :
- GET request on my OAuth2
logoutendpoint which logs user out from my auth server and answers 302 tologoutRedirectUri:white_check_mark: - logout user from my front Nuxt app :white_check_mark:
- Redirect my user to
logoutRedirectUriafter logout :stop_sign:
The strange behaviour is that if I logout from homepage (/), redirection to logoutRedirectUr works. But not from any other pages.
What is actually happening?
The GET request on my logout auth server endpoint is sent but immediately cancelled on client side and ends in 499 on server side (Nginx). The logout is effective on the auth server. But Nuxt does not get any answer and does not redirect user to logoutRedirectUri.
Additional information
I'm not sure about what my OAuth2 logout endpoint should do according to Nuxt Auth. Does it need to answer 200 or 302 to logoutRedirectUri ?
What could cancel the GET request on Nuxt side ?
Thanks for your help
Checklist
- [x] I have tested with the latest Nuxt version and the issue still occurs
- [x] I have tested with the latest module version and the issue still occurs
- [x] I have searched the issue tracker and this issue hasn't been reported yet
Having the exact same problem here, anybody has an answer ?
I found the faulty code: https://github.com/nuxt-community/auth-module/blob/dev/src/schemes/oauth2.ts#L320
logout(): void {
if (this.options.endpoints.logout) {
const opts = {
client_id: this.options.clientId + '',
logout_uri: this.logoutRedirectURI
}
const url = this.options.endpoints.logout + '?' + encodeQuery(opts)
window.location.replace(url)
}
return this.$auth.reset() // <---- this seems to stop the upper "window.location.replace(url)"
}
As logout endpoint is optional and reset() function does not return anything, I'd rather go with something like that:
logout() {
this.$auth.reset();
if (this.options.endpoints.logout) {
const opts = {
client_id: this.options.clientId + "",
logout_uri: this.logoutRedirectURI
};
const url = this.options.endpoints.logout + "?" + encodeQuery(opts);
window.location.replace(url);
}
}
I'm also investigating around a resetInterceptor which seems to send Axios requests on reset.
More details on this problem.
In the reset() method, this.$auth.setUser(false); is faulty :
reset() {
this.$auth.setUser(false); // <---- this stops the upper "window.location.replace(url)"
this.token.reset();
this.refreshToken.reset();
this.requestHandler.reset();
}
this.$auth.setUser(false); sometimes redirects to /login before getting the response of window.location.replace(url);.
Ok, looks like we found a solution.
It's a "race condition" problem between 2 navigation instructions :
- logout on OAuth server (
window.location.replace(url);) - logout on Nuxt (
this.$auth.reset())
Disabling the option watchLoggedIn (https://auth.nuxtjs.org/api/options/#watchloggedin) solved the problem as it disabled auto-redirection to /login on this.$auth.setUser(false);.
Interesting topic about browsers behaviour : https://stackoverflow.com/questions/2536793/does-changing-window-location-stop-execution-of-javascript
However, I think Nuxt Auth logout functions should handle that point natively.