I have difficulty moving the page after logging in.
If you click the page link that requires authentication and the login page appears, save the path to the previous page in the redirect token and return to the previous page if you successfully log in. This works exactly.
However, if you enter a page URL that requires authentication in your browser, or if you refresh the login page, you will be taken to the home instead of the previous page. You'll also need to double-click the Sign In button.
Perhaps the redirect token does not seem to generate the path of the previous page.
This issue also appears to be the same on the demo page.
How can we solve this problem?
I'm running into this problem as well, don't know why the issue was closed.
So what happens is that the server sets the redirect url in the store, and then goes to the login page on the server.
Because of this, the server reloads on the login page and loses all previous data (including the store).
In other words; this will work perfectly fine in mode:spa. (because then the redirect is done on the client instead, and the store is preserved).
A way to fix this might be by sending a cookie with the auth state on the server, then when we reload, we can check if a cookie excists and reload the previous state.
For whoever wants to solve this;
I made a middleware based on the original version that will set the cookie.
Then i am using a custom login scheme where i am checking for this cookie in the login function on the client.
I am using this plugin to set the cookies: https://github.com/S64/vue-universal-cookies
Middleware:
import { routeOption, getMatchedComponents } from '@nuxtjs/auth/lib/core/utilities'
export default function (ctx) {
// Disable middleware if options: { auth: false } is set on the route
if (routeOption(ctx.route, 'auth', false)) {
return
}
// Disable middleware if no route was matched to allow 404/error page
const matches = []
const Components = getMatchedComponents(ctx.route, matches)
if (!Components.length) {
return
}
const { login, callback } = ctx.app.$auth.options.redirect
if (ctx.app.$auth.$state.loggedIn) {
// -- Authorized --
// Redirect to home page if inside login page (or login page disabled)
if (!login || ctx.route.path === login.split('?')[0]) {
ctx.app.$auth.redirect('home')
}
} else {
// -- Guest --
// Redirect to login page if not authorized and not inside callback page
// (Those passing `callback` at runtime need to mark their callback component
// with `auth: false` to avoid an unnecessary redirect from callback to login)
if (!callback || ctx.route.path !== callback.split('?')[0]) {
if(process.server){
//we are redirecting to the login page from the server!
//to make sure we afterwards can retrieve the page we came from, we set a cookie.
app.$cookies.set('auth-redirect', route.path, {
path: login
})
}
ctx.app.$auth.redirect('login')
}
}
}
Login scheme:
async login (endpoint) {
if (!this.options.endpoints.login) {
return
}
// Ditch any leftover local tokens before attempting to log in
await this._logoutLocally()
const result = await this.$auth.request(
endpoint,
this.options.endpoints.login
)
if (this.options.tokenRequired) {
const token = this.options.tokenType
? this.options.tokenType + ' ' + result
: result
this.$auth.setToken(this.name, token)
this._setToken(token)
}
//check if cookie excists containing a redirect url.
const cookie = this.$auth.ctx.app.$cookies.get('auth-redirect')
if(cookie){
//set the redirect url to ctx.from if there is none
if(!this.$auth.ctx.from){
this.$auth.ctx.from = cookie
}
//its now safe to remove the cookie
this.$auth.ctx.app.$cookies.remove('auth-redirect')
}
return this.fetchUser()
}
The other option is to use a query param, similar to how other frameworks have done it in the past. This is my current solution:
middleware/isLoggedIn.js:
// These helpers were copied from https://github.com/nuxt-community/auth-module/blob/dev/lib/core/utilities.js
// because it was easier than figuring out how to import them properly.
import { encodeQuery, routeOption, getMatchedComponents } from '../utils/nuxtjs-auth';
// NOTE: This is mostly a copy of the middleware from @nuxtjs/auth, however
// because we're using ctx.redirect and not $auth.redirect, this circumvents a
// number of features that library has to prevent infinite redirects and only
// redirect to known safe pages, so be very careful.
export default function isLoggedIn(ctx) {
// Disable middleware if options: { auth: false } is set on the route
if (routeOption(ctx.route, 'auth', false)) {
return;
}
// Disable middleware if no route was matched to allow 404/error page
const matches = [];
const Components = getMatchedComponents(ctx.route, matches);
if (!Components.length) {
return;
}
// If we're not logged in, redirect to /login with
if (!ctx.app.$auth.loggedIn) {
ctx.redirect(`/login?${encodeQuery({ next: ctx.route.fullPath })}`);
}
}
pages/login.vue:
<script>
import { isRelativeURL } from '../utils/nuxtjs-auth';
export default {
auth: false,
head: {
title: 'Login',
},
data() {
return {
username: '',
password: '',
errors: {},
};
},
mounted() {
// NOTE: This is meant to work around an issue with @nuxtjs/auth where
// redirecting doesn't work properly. This only fixes the issue client
// side, but that's good enough for now.
if (this.$auth.loggedIn) {
this.redirect();
}
},
methods: {
redirect() {
if (this.$route.query.next && isRelativeURL(this.$route.query.next)) {
this.$router.push(this.$route.query.next);
} else {
this.$router.push('/');
}
},
handleLogin() {
this.errors = [];
this.$auth.login({
data: {
username: this.username,
password: this.password,
},
}).then(() => {
this.redirect();
}).catch((error) => {
this.errors = [error.message];
});
},
},
};
</script>
Please, take a look at my workaround
Please could you post it the the original (proper) issue?
I agree with @mathieutu, this is a duplicate of #134 and should be closed.
As @belak said:
The query param solution is better,
However, for me his solution didn鈥檛 work as I have problems when trying to import the helpers from the library. Nevertheless, there is a most simple solution:
Create an auth-guard middleware that saves the requested url and redirects to the login with such url saved in the query params.
nuxt.config.js:
router: {
middleware: ['auth-guard'],
},
auth: {
vuex: { namespace: '_auth' },
redirect: {
login: false,
logout: '/login',
callback: false,
home: false,
},
localStorage: false,
},
strategies: {
local: {
endpoints: {
login: {
url: '/auth/login',
method: 'post',
propertyName: 'access_token',
},
logout: {
url: '/auth/logout',
method: 'post',
},
user: {
url: '/auth/me',
method: 'get',
propertyName: false,
},
},
},
}
middleware/auth-guard.js
export default function({ $auth, route, redirect }) {
if (route.path !== '/login') {
const REDIRECT_URL = '/login?redirect=' + route.path
if (!$auth.loggedIn) {
redirect(REDIRECT_URL)
}
}
}
Use the query params for redirect after a successful login to the saved path if exists.
pages/login.vue
const handleSubmit = async () => {
try {
errorMsg.value = undefined
await form.submit()
let redirect_url = root.$route.query.redirect || '/dashboard'
root.$router.push({
path: redirect_url,
})
} catch (error) {
errorMsg.value = t(`auth.login.error.${error.code}`)
}
}
Most helpful comment
RETURNING TO THE REQUEST PAGE AFTER LOGIN
Build in a system for keeping track of what page was originally requested and redirect to it after a successful login can be done in 2 steps.
As @belak said:
However, for me his solution didn鈥檛 work as I have problems when trying to import the helpers from the library. Nevertheless, there is a most simple solution:
Create an auth-guard middleware that saves the requested url and redirects to the login with such url saved in the query params.
nuxt.config.js:
middleware/auth-guard.js
Use the query params for redirect after a successful login to the saved path if exists.
pages/login.vue