ログインが必要なページに対して直接リンクから飛んだ時、トークン切れなどで再ログインが必要な場合は大抵ログイン画面に飛ばされます。
そしてログインしなおしたら、 さっき飛んだページではなくトップページ に戻ってしまった...ということはないでしょうか。
普通に実装すると、「ログインしたらトップに移動」で終わってしまいますが、 UX 的にこれは微妙です。
nuxt.js で「ログインしたらさっき飛んだページに戻る」を実装してみます。
ログインチェックミドルウェア
まずはログイン状態が大丈夫かどうかを確認するミドルウェアをグローバルに配置します。
middleware/auth.js
export default (ctx) => {
if (store.getters['auth/check']) {
// 認証されているので何もしない
return
}
// ログイン画面へ誘導
const redirectUri = encodeURIComponent(ctx.route.fullPath)
ctx.redirect(`/login?redirect_uri=${redirectUri}`)
}
ctx.route.fullPath
を利用して、今飛ぼうとしたページのパス情報を redirect_uri
クエリストリングに記録します。
ログインページ
ログイン後の処理を少し改善します。
pages/login.vue
<template>
<div>DOM は省略</div>
</template>
<script>
export default {
asyncData(ctx) {
const redirectUri = decodeURIComponent(ctx.query.redirect_uri || '/')
if (redirectUri.startsWith('/') === false || redirectUri.startsWith('//')) {
// 相対パスでない・ // 開始で別ドメインに移動するパスは許可しない
return {
redirectUri: '/',
}
}
return {
redirectUri,
}
},
methods: {
async login(username, password) {
await this.$store.dispatch('auth/login', { username, password })
// 事前に取得していたパスへ移動
this.$router.push(this.redirectUri)
},
},
}
</script>
これで元のページに戻ることが出来るようになります。
OAuth によるログインを伴う場合は、一度 sessionStorage などに値を保存して、トークンと共に戻ってきてから保存したパスを読みだして移動することになるので、処理が煩雑になりがちな部分です。
(動作確認していないので動かないかも)