アクセストークンの有効期限を適切に処理する

プロアクティブリフレッシュ、リフレッシュ付きリトライ、サイレント再認証パターンを含む、期限切れアクセストークンの処理戦略。

Token Management

詳細な説明

トークン有効期限の処理

アクセストークンは意図的に短命です(通常5-60分)。有効期限が切れるとAPIリクエストは401 Unauthorizedを返します。適切に設計されたクライアントは、ユーザー体験を中断することなくこれを透過的に処理します。

戦略1:プロアクティブリフレッシュ

各APIリクエスト前にトークンの有効期限をチェックします。バッファウィンドウ(例:30秒)以内に有効期限が切れる場合、事前にリフレッシュします:

async function apiRequest(url, options = {}) {
  // トークンがまもなく期限切れかチェック(30秒バッファ)
  if (tokenExpiresAt - Date.now() < 30000) {
    await refreshAccessToken();
  }

  return fetch(url, {
    ...options,
    headers: {
      ...options.headers,
      Authorization: `Bearer ${accessToken}`,
    },
  });
}

戦略2:リアクティブリフレッシュ(401リトライ)

リクエストを試行します。401が返された場合、トークンをリフレッシュして1回リトライ:

async function apiRequest(url, options = {}) {
  let response = await fetch(url, {
    ...options,
    headers: {
      ...options.headers,
      Authorization: `Bearer ${accessToken}`,
    },
  });

  if (response.status === 401) {
    await refreshAccessToken();
    response = await fetch(url, {
      ...options,
      headers: {
        ...options.headers,
        Authorization: `Bearer ${accessToken}`,
      },
    });
  }

  return response;
}

戦略3:トークンリフレッシュキュー

複数のAPIリクエストが同時に失敗した場合、複数のリフレッシュリクエストを避けるためにキューを使用:

let refreshPromise = null;

async function ensureValidToken() {
  if (refreshPromise) return refreshPromise;
  refreshPromise = refreshAccessToken().finally(() => {
    refreshPromise = null;
  });
  return refreshPromise;
}

リフレッシュが失敗した場合

リフレッシュトークンも期限切れまたは取り消された場合:

  1. 保存されたすべてのトークンをクリア
  2. ユーザーをログインページにリダイレクト
  3. ログイン後のリダイレクト用にユーザーの現在のURLを保持
  4. ユーザーフレンドリーなメッセージを表示(「セッションが期限切れです。再度サインインしてください。」)

ベストプラクティス

  • トークンレスポンスのexpires_inを常にチェックして有効期限を計算
  • エッジケースを避けるためにバッファ(30-60秒)を使用
  • 同時リフレッシュリクエストを防ぐシングルフライトリフレッシュメカニズムを実装
  • リフレッシュ中のネットワークエラーを適切に処理

ユースケース

頻繁にAPI呼び出しを行うReactアプリケーション。Axiosインターセプターを使用して401レスポンスをチェックし、保存されたリフレッシュトークンを使用してアクセストークンを自動的にリフレッシュし、元のリクエストをリトライします。すべてユーザーには透過的です。

試してみる — OAuth 2.0 Flow Visualizer

フルツールを開く