DevToolBox

HTTP 401 と 403 の違い・使い分け

最終更新日: 2026-07-13公開日: 2026-04-19執筆: DevToolBox編集部

レビューでよく指摘されるのが 401 Unauthorized403 Forbidden の 取り違えです。RFC 9110 の定義に沿えば迷いません。

The canonical rule: 401 means "who are you?" (authentication), 403 means "I know who you are, but you may not" (authorization).

TL;DR

1. 正しい使い分け表 / When to use

状況 / Situation返すコード / Status補足 / Notes
ログインしていない401WWW-Authenticate: Bearer
トークン期限切れ401error="invalid_token"
トークン署名不正401認証自体が失敗
ログイン済み・権限不足403ロール外のリソース
料金プラン未加入403 (または 402)402 は実質未定着
private リポジトリ404存在を隠す設計

2. RFC 9110 の定義 / RFC definition

一次情報は RFC 9110 の401 Unauthorized(15.5.2節)403 Forbidden(15.5.4節)です。実装やレビューで判断が割れたときは、この定義に戻ると整理できます。

401 Unauthorized: "the request has not been applied because it lacks valid authentication credentials for the target resource."

403 Forbidden: "the server understood the request but refuses to authorize it."

401 では認証方式を示すため WWW-Authenticate必ず付ける義務があります。 付けないと仕様違反です。

図1: 401 / 403 の判断フロー
HTTP 401と403の判断フローチャート未認証なら401、認証済みで権限不足なら403を返す判断手順未認証(トークン無し /無効)か?401認証済みだが権限不足か?403YesNoYes

3. 実装例 / Examples

Express (Node.js)

// 401 — 認証必要
res.set("WWW-Authenticate", 'Bearer realm="api"').status(401).json({ error: "unauthenticated" });

// 403 — 権限なし
res.status(403).json({ error: "forbidden", reason: "role:admin required" });

FastAPI (Python)

from fastapi import HTTPException

raise HTTPException(
    status_code=401,
    detail="Invalid token",
    headers={"WWW-Authenticate": "Bearer"},
)

4. 間違いやすいパターン / Anti-patterns

401 に対して無条件リトライする

期限切れや無効なトークンを付けたまま同じリクエストを繰り返しても、認証状態は変わりません。サーバー負荷を増やすだけでなく、レート制限やアカウント保護に引っかかる原因にもなります。401 を受けたクライアントはリトライを止め、保存済み認証情報を破棄してログイン画面へ誘導します。

const response = await fetch("/api/profile", { headers: authHeaders });

if (response.status === 401) {
  localStorage.removeItem("accessToken");
  window.location.assign("/login?reason=session-expired");
  return;
}

if (response.status === 403) {
  showMessage("この操作を行う権限がありません");
}

403 は再ログインで直るとは限らないため、必要なロールや申請方法を案内するほうが適切です。401 と 403 を分けることは、HTTP上の正しさだけでなくユーザー体験にも直結します。

5. よくある質問 / FAQ

期限切れトークンには 401 と 403 のどちらを返す?

有効な認証資格情報がない状態なので 401 です。Bearer 認証では WWW-Authenticate に認証方式やエラー情報を示し、クライアントが再ログインやトークン更新を判断できるようにします。

ログイン済みでも 401 を返すことはある?

送信されたトークンが失効・改ざん・対象API向けでないなど、認証に失敗した場合は 401 です。「画面上でログイン済み」かではなく、今回の要求に有効な認証資格情報があるかで判断します。

403 を受けたら再ログインすべき?

通常は不要です。認証済みで権限が足りない状態なので、権限申請や別アカウントの利用を案内します。

6. English summary

Per RFC 9110, return 401when the client isn't authenticated (no token, expired token, invalid signature) — and include a WWW-Authenticate header so clients know what scheme to use. Return 403when the client is authenticated but lacks permission; re-authenticating won't help. If you need to hide the existence of a resource (private repos, internal records), return 404to avoid leaking metadata.

関連ツール / Related tools

関連ガイド / Related guides