導入
API開発やテストを行っている際、短命なアクセストークンの期限切れにより、頻繁に認証エラー(401 Unauthorized)が発生して作業が中断されることはありませんか?そのたびに手動でトークンを取得し、環境変数を書き換える作業は非常に非効率です。本記事では、フロントエンドやNode.js環境で広く使われるHTTPクライアント「Axios」のインターセプター機能を活用し、トークン切れを自動検知して再試行する仕組みを解説します。これにより、認証フローを意識せずにテストに集中できる環境を構築します。
基礎知識
OAuth2における「アクセストークン」は、APIへのアクセス権を証明する鍵です。セキュリティ向上のため短時間で失効するように設計されており、期限が切れた際は「リフレッシュトークン」を使用して新しいアクセストークンを発行します。この「401エラーを検知→トークン再取得→元のリクエストを再送信」という一連の処理をクライアント側で自動化することで、ユーザー体験やテストの継続性を向上させることができます。
実装/解決策
Axiosの「レスポンスインターセプター」を利用します。レスポンスが401を返した場合、Promiseを利用して処理を一時停止させ、トークン更新APIを呼び出します。更新が成功したら、保持していたリクエストを再送します。これにより、呼び出し側は認証の有効性を気にする必要がなくなります。
サンプルプログラム
以下は、Axiosの設定ファイル(axios-client.js)を想定した実装例です。
import axios from 'axios';
const apiClient = axios.create({ baseURL: 'https://api.example.com' });
// リクエスト送信時に最新のトークンをヘッダーに付与
apiClient.interceptors.request.use(config => {
const token = localStorage.getItem('access_token');
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});
// レスポンスインターセプター:401検知時にトークンを更新
apiClient.interceptors.response.use(
response => response,
async error => {
const originalRequest = error.config;
// 401エラーかつ再試行済みでない場合のみ実行
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
// リフレッシュトークンを使用して新しいアクセストークンを取得
const refreshToken = localStorage.getItem('refresh_token');
const { data } = await axios.post('/auth/refresh', { refreshToken });
// 新しいトークンを保存
localStorage.setItem('access_token', data.accessToken);
// 元のリクエストのヘッダーを更新して再試行
originalRequest.headers.Authorization = `Bearer ${data.accessToken}`;
return apiClient(originalRequest);
} catch (refreshError) {
// 更新失敗時はログイン画面へ遷移させる等の処理
return Promise.reject(refreshError);
}
}
return Promise.reject(error);
}
);
export default apiClient;
応用・注意点
同時リクエストへの対応
同時に複数のAPIリクエストが投げられ、全リクエストが同時に401になった場合、トークン更新APIが乱発されるリスクがあります。これを防ぐには、「トークン更新中フラグ」を設け、更新処理中は他のリクエストをキューに入れる(待機させる)仕組みを実装するのが一般的です。
無限ループの回避
リフレッシュトークン自体が期限切れの場合、インターセプター内で無限ループに陥らないよう、`originalRequest._retry` フラグで再試行回数を制限することが不可欠です。また、認証サーバー側のログで「なぜ401が多発しているのか」を確認できるよう、リクエストのトレーサビリティを確保しておくことも推奨します。

コメント