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

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

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

HTTPにおけるCookieとは、クライアントのウェブブラウザ上に保存された一時的なデータを指します。クライアント側のJavaScriptでも、サーバー側のHTTPヘッダーでもクッキーの読み書き・修正・削除が可能です。

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JWT(JSON Web Token)

JWT(JSON Web Token)とは、JSONをベースとしたアクセストークンの仕様。電子署名付きのURL safeなJSONのことを指します。電子署名が付いているため、改ざんをチェックできる点がメリットです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

1099閲覧

DjangoとReactにてJWTを自動でリフレッシュしたい

toshi_worldtrip

総合スコア3

Cookie

HTTPにおけるCookieとは、クライアントのウェブブラウザ上に保存された一時的なデータを指します。クライアント側のJavaScriptでも、サーバー側のHTTPヘッダーでもクッキーの読み書き・修正・削除が可能です。

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JWT(JSON Web Token)

JWT(JSON Web Token)とは、JSONをベースとしたアクセストークンの仕様。電子署名付きのURL safeなJSONのことを指します。電子署名が付いているため、改ざんをチェックできる点がメリットです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

1クリップ

投稿2022/12/21 05:40

編集2022/12/21 18:40

前提

DjangoとReactにてJWTをCookieに保存する認証を実装しているが、リフレッシュトークンの更新がうまくいかない

実現したいこと

・トークンが切れた時点でリフレッシュトークンを取得し、認証をクリアする

発生している問題・エラーメッセージ

https://qiita.com/shitikakei/items/d818fb0aa8670aa4228c#authenticationpy https://www.miracleave.co.jp/contents/1654/react-jwt-axios-interceptors/ こちらのページを参考に、Django側でCookieをResponseヘッダーにセットし、認証を行うところまでは実装できました。 しかし、アクセストークンの期限が切れた時にリフレッシュトークンを取得し、自動更新を行う操作がうまくいきません。 トークンが切れた状態でリロードを行なってもトークンの取得は行われず、再度ログイン認証を行う必要があります。

該当のソースコード

React

1//ログイン時は以下のフックを使用してPOSTリクエストを行なっています。 2const useAuthAxios = () => { 3 const refresh = useRefreshToken(); 4 const { auth } = useContext(AuthContext); 5 const { cookies } = useContext(AuthContext); 6 7 useEffect(() => { 8 // リクエスト前に実行。headerに認証情報を付与する 9 const requestIntercept = authAxios.interceptors.request.use( 10 (config) => { 11 return config; 12 }, 13 (error) => Promise.reject(error) 14 ); 15 16 // レスポンスを受け取った直後に実行。もし認証エラーだった場合、再度リクエストする。 17 const responseIntercept = authAxios.interceptors.response.use( 18 (response) => { 19 //console.log(response) 20 return response; 21 }, 22 async (error) => { 23 if (error.response.status === 401) { 24 // 新しくaccess_tokenを発行する 25 await refresh(); 26 return refresh.response(error.config); 27 } else { 28 return Promise.reject(error); 29 } 30 } 31 ); 32 33 return () => { 34 // 離脱するときにejectする 35 authAxios.interceptors.request.eject(requestIntercept); 36 authAxios.interceptors.response.eject(responseIntercept); 37 }; 38 39 },[auth, refresh]) 40 41 return authAxios; 42 43}; 44 45export default useAuthAxios; 46 47//refresh_tokenを元にaccess_tokenを取得するフック 48const useRefreshToken = () => { 49 const { setAuth } = useContext(AuthContext); 50 const { cookies } = useContext(AuthContext); 51 const navigate = useNavigate(); 52 53 const refresh = async () => { 54 55 // cookieに保存されたrefresh_tokenを送付してaccess_tokenを取得する 56 //authAxiosだとタイムアウト 57 axios.defaults.xsrfCookieName = "csrftoken" 58 axios.defaults.xsrfHeaderName = "X-CSRFTOKEN" 59 60 const res = await axios 61 .post("http://localhost:8000/api/auth/refresh", 62 {}, { 63 headers: 64 { 65 "X-CSRFTOKEN": cookies.get("csrftoken"), 66 "Content-Type":"application/json" 67 }, 68 withCredentials:true, 69 }); 70 const refreshToken = res.data["refresh"] 71 const response = await axios.post("http://localhost:8000/api/auth/newtoken", 72 { 73 "refresh":refreshToken 74 }, 75 { 76 withCredentials:true 77 } 78 ); 79 setAuth((prev) => { 80 return { ...prev, response}; 81 }); 82 return response; 83 }; 84 return refresh; 85}; 86 87export default useRefreshToken;

試したこと

refreshの取得が出来ていることは確認できました。以下でリフレッシュが動作することも確認済みです。以下のエンドポイントはSet-Cookieを含むHttpResponseオブジェクトを返します。

React

1 const response = await axios.post("http://localhost:8000/api/auth/newtoken", 2 { 3 "refresh":refreshToken 4 },

Responseオブジェクトの受け取り方やuseEffectの使い方が間違っているのかと思い、いろいろ試してみましたがうまくいきませんでした。
リクエスト時にトークンの期限が切れていた場合にそのResponseオブジェクトを利用してCookieをセットし、再度アクセスを行いたいのですが難しいのでしょうか?

ログイン時はSet-Cookieを含むオブジェクトにリクエストを投げることで、以下のようなコードで認証に成功しています。

React

1 const login = async (payload) => { 2 await authAxios 3 .post("/api/auth/login",payload) 4 navigate("/main") 5 };

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

yuma.inaura

2022/12/21 05:42

コードはすべてコードブロックで囲うと回答者は読みやすくなると思います
toshi_worldtrip

2022/12/21 05:43

申し訳ございません。修正いたします。
guest

回答1

0

自己解決

useCookieを使っていたためプロパティーを取得できていませんでしたが、new Cookies()を使い、それから値を取得したところ、正常に作動しました。

投稿2022/12/21 09:40

toshi_worldtrip

総合スコア3

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問