APIリクエスト送信ボタンクリック時に、401 (Unauthorized)が返ってくる

JWTキーを使用してログインを管理するための機能を実装。

import axios from 'axios'

// APIのベースURLを設定したインスタンスを作成
const api = axios.create({
  baseURL: 'http://localhost:8080/v1', //全てのAPIのプレフィックス
  headers: {
    'Content-Type': 'application/json',
    // 初期化時にlocalStorageからトークンを読み込む
    Authorization: localStorage.getItem('jwtToken')
      ? `Bearer ${localStorage.getItem('jwtToken')}`
      : undefined,
  },
})

// ログイン成功後にヘッダーを更新
export const setAuthHeader = (token: string | null) => {
  if (token) {
    api.defaults.headers.common['Authorization'] = `Bearer ${token}`
  } else {
    delete api.defaults.headers.common['Authorization']
  }
}

// レスポンスインターセプター: エラー共通処理
api.interceptors.response.use(
  (Response) => Response,
  (error) => {
    // 401エラーの場合、自動でログアウト処理などに誘導
    if (error.response && error.response.status === 401) {
      console.error('認証エラー:トークンをリフレッシュするか、ログインが必要です。')
      // 後にrouter.push('/login')などのロジック追加
    }
    return Promise.reject(error)
  },
)

export default api

ログイン後、JWTトークンを発行。ユーザによりAPIリクエストが実行されると、DBに保存される。
というのが理想だけど、401エラーが返ってくる。という無限ループにハマった。

以下、私の解決策です。
※赤文字が今回の問題のコード

エラー内容

  • POST http://localhost:8080/v1/character-create 401 (Unauthorized)
  • api.ts:30 認証エラー:トークンをリフレッシュするか、ログインが必要です。
  • AxiosError {message: 'Request failed with status code 401', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}

ログイン後、1分も立たずにトークンが無くなるってそんなわけあるか。

その他確認事項

  • jwtキーがログイン時に発行されるも、APIリクエスト送信時に消える。(devtoolのApplicationタブを確認)
  • request headerにauthorizationが存在しない(devtoolのNetworkタブを確認)

結論

初期化時のAuthorizationヘッダー設定を削除し、初期化前にヘッダー設定を行う。

import axios from 'axios'

// APIのベースURLを設定したインスタンスを作成
const api = axios.create({
  baseURL: 'http://localhost:8080/v1', //全てのAPIのプレフィックス
  headers: {
    'Content-Type': 'application/json',
  },
})

// すべてのリクエスト送信直前に実行されるインターセプターを設定
api.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('jwtToken')

    // トークンが存在する場合のみヘッダーを設定
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    } else {
      // トークンがない場合はAuthorizationヘッダーを削除(または設定しない)
      delete config.headers.Authorization
    }

    return config
  },
  (error) => {
    return Promise.reject(error)
  },
)

// レスポンスインターセプター: エラー共通処理
api.interceptors.response.use(
  (Response) => Response,
  (error) => {
    // 401エラーの場合、自動でログアウト処理などに誘導
    if (error.response && error.response.status === 401) {
      console.error('認証エラー:トークンをリフレッシュするか、ログインが必要です。')
      // 後にrouter.push('/login')などのロジック追加
    }
    return Promise.reject(error)
  },
)

export default api

原因

  1. アプリ起動時(初期化時)にlocalstrageを確認。初回起動なのでjwtToken無し。
  2. ログイン直後のAPIコールでjwtTokenを発行し、ヘッダーにAuthorizationを追加。localstrageに格納。
  3. APIリクエスト送信時、再初期化が実行される。
  4. 初期化時にlocalstrageを確認。初期化後の為headerにはAuthorizationがいない。
  5. 401 (Unauthorized)エラー

というアンジャッシュネタロジックだった。

初期化前(リクエスト送信直前)にlocalstrageを確認して、headerを設定して完了。

APIリクエスト送信ボタンクリック時に、401 (Unauthorized)が返ってくる” に対して1件のコメントがあります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です