質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Nuxt.js

Nuxt.jsは、ユニバーサルなSPAが開発可能なVue.jsベースのフレームワーク。UIの描画サポートに特化しており、SSRにおけるサーバーサイドとクライアントサイドのUIレンダリングなどさまざまな機能を持ちます。

Q&A

解決済

1回答

4693閲覧

【Nuxt × JWT】axiosでトークン認証後、初回アクションメソッド実行時にHTTPリクエストに認証情報が付けられない

matsuo_basho

総合スコア88

Nuxt.js

Nuxt.jsは、ユニバーサルなSPAが開発可能なVue.jsベースのフレームワーク。UIの描画サポートに特化しており、SSRにおけるサーバーサイドとクライアントサイドのUIレンダリングなどさまざまな機能を持ちます。

0グッド

0クリップ

投稿2020/10/10 03:14

いつもお世話になっております。

NuxtでJWTを利用したログイン認証の勉強をしているのですが、
ページを開いて初回ログイン後のUser情報取得で認証エラーが発生してしまいます。

ログイン画面

イメージ説明

エラー内容

イメージ説明

流れとしては、
ログイン時(store/auth.js/login())に返ってきたトークンを即時ローカルストレージに保存し、
axiosの通信時にリクエストヘッダーに自動でトークンを付与するように設定。

その後、User情報(store/auth.js/reload())を取得しようとしているのですが、
ページを開いて初回ログインボタン押下後は必ずUser情報を取得しようとすると401(認証エラー)が発生します。

もう一度ログインボタンを押すと、問題なくUser情報の取得が可能です。

また、一度ログアウトを押して、ローカルストレージに保存しているトークンを削除後、
再度ログインボタンを押下すると問題なくUser情報の取得が可能です。

手順結果
ページを開いて初回「ログインボタン押下」401エラー
2回目以降「ログインボタン押下」正常終了
ログアウトボタン押下後、「ログインボタン押下」正常終了

エラー自体は、store/auth.js/reloao() に記述している this.$axios.get( URL )で発生しているのですが、
なぜ初回のみエラーが出るのかがわかりません。
どなたか原因が分かる方がいらっしゃったらご教授いただけると幸いです。

宜しくお願い申し上げます。

ソースコード

plugins/axios.js

javascript

1export default function( {store, $axios} ){ 2 3 $axios.onRequest( ( config ) => { 4 5 const token = localStorage.getItem( 'access' ) 6 7 if ( token ){ 8 9 console.log( "" ); 10 console.log( "$axios.setToken 実行!" ); 11 12 $axios.setToken( token, 'JWT' ) 13 14 } else { 15 console.log( "" ); 16 console.log( "localStorageにtokenがありません! たぶん初回(アクセストークン取得時)! 初回はreload()がなぜか失敗する!" ); 17 } 18 19 } ) 20 21 22 $axios.onResponse( response => { 23 return Promise.resolve( response ); 24 } ) 25 26 27 $axios.onError( error => { 28 29 30 let messages; 31 32 if ( error.response.status === 400 ){ 33 34 35 /* バリデーションエラー */ 36 console.log( "バリデーションエラー" ); 37 38 let messages = [].concat.apply( [], Object.values( error.response.data ) ) 39 store.dispatch( 'message/setWarningsMessages', {messages: messages} ) 40 41 42 } else if ( error.response.status === 401 ){ 43 44 45 /* 認証エラー */ 46 console.log( "認証エラー" ); 47 48 const token = localStorage.getItem( 'access' ) 49 50 if ( token != null ){ 51 messages = 'ログイン有効期限切れ' 52 } else { 53 messages = '認証エラーです。' 54 } 55 56 console.log( "$axios.onError で auth/logout()実行!" ); 57 58 store.dispatch( 'auth/logout' ) 59 store.dispatch( 'message/setErrorMessages', {messages: messages} ) 60 61 62 } else if ( error.response.status === 403 ){ 63 64 65 /* 権限エラー */ 66 console.log( "権限エラー" ); 67 68 messages = '権限エラーです。' 69 store.dispatch( 'message/setErrorMessages', {messages: messages} ) 70 71 72 } else if ( error.response.status === 500 ){ 73 74 75 /* その他のエラー */ 76 console.log( "その他のエラー" ); 77 78 messages = '想定外のエラーです。' 79 store.dispatch( 'message/setErrorMessages', {messages: messages} ) 80 81 82 } 83 84 return Promise.reject( error.response ); 85 86 } ) 87 88}

store/auth.js

javascript

1export const state = () => ( { 2 3 username: '', 4 authenticated: false 5 6} ) 7 8 9export const getters = { 10 11 username: state => state.username, 12 authenticated: state => state.authenticated, 13 14} 15 16 17export const mutations = { 18 19 set: ( state, payload ) => { 20 21 state.username = payload.user.username 22 state.authenticated = true 23 24 console.log( '[state.username] : ' + state.username ); 25 console.log( '[state.authenticated] : ' + state.authenticated ); 26 27 }, 28 29 30 clear: ( state ) => { 31 32 state.username = '' 33 state.authenticated = false 34 35 }, 36 37} 38 39export const actions = { 40 41 /* ログイン */ 42 login( context, payload ){ 43 44 const params = new URLSearchParams(); 45 46 params.append( 'username', payload.username ); 47 params.append( 'password', payload.password ); 48 49 50 const URL = '/auth/jwt/create/' 51 52 this.$axios.post( URL, params ) 53 .then( res => { 54 55 // 認証用トークンをlocalStorageに保存 56 localStorage.setItem( 'access', res.data.access ) 57 58 context.dispatch( 'reload' ).then( user => user ) 59 60 } ) 61 }, 62 63 64 /* ログアウト */ 65 logout( context ){ 66 67 localStorage.removeItem( 'access' ) 68 context.commit( 'clear' ) 69 70 }, 71 72 73 /* ユーザー情報更新 */ 74 reload( context ){ 75 76 const URL = '/auth/users/me/' 77 78 return this.$axios.get( URL ).then( ( res ) => { 79 80 const user = res.data 81 82 context.commit( 'set', {user: user} ) 83 return user 84 85 } ) 86 87 } 88 89}

pages/index.vue

html

1<template> 2 <div> 3 4 <input v-model="form.username" placeholder="username"> 5 <input v-model="form.password" placeholder="password" type="password"> 6 7 <button @click="login">ログイン</button> 8 <button @click="logout">ログアウト</button> 9 10 </div> 11</template> 12 13<script> 14export default { 15 16 data(){ 17 return { 18 19 form: { 20 username: '', 21 password: '', 22 } 23 24 } 25 }, 26 27 28 methods: { 29 30 async login(){ 31 await this.$store.dispatch( 'auth/login', this.form ) 32 }, 33 34 async logout(){ 35 await this.$store.dispatch( 'auth/logout' ) 36 } 37 38 } 39 40} 41</script> 42 43<style> 44input { 45 border : 1px solid #ccc; 46 border-radius : 5px; 47 display : block; 48 padding : 3px; 49 margin-bottom : 10px; 50} 51</style>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

下記と同様の問題です。
https://teratail.com/questions/297147

Javascript

1$axios.onRequest(config => { 2 config.headers.Authorization = `Bearer ${token}` 3 return config 4})

投稿2020/10/10 13:44

yuhigash

総合スコア327

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

matsuo_basho

2020/10/10 14:43

yuhigashさん、ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問