DevToolBox

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

レビューでよく指摘されるのが 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

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必ず付ける義務があります。 付けないと仕様違反です。

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

5. 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