メインコンテンツまでスキップ

RFC 7235 - HTTP/1.1: 認証 (Authentication)

  • ステータス: Proposed Standard
  • 発行日: June 2014
  • ストリーム: IETF
  • 廃止: RFC2616, RFC2617
  • 廃止: RFC9110
  • エラッタ: エラッタなし

ドキュメント情報

  • RFC番号: 7235
  • タイトル: Hypertext Transfer Protocol (HTTP/1.1): Authentication
  • タイトル(日本語): ハイパーテキスト転送プロトコル(HTTP/1.1): 認証
  • 発行日: 2014年6月
  • 著者: R. Fielding (Adobe), J. Reschke (greenbytes)
  • 廃止されたドキュメント: RFC 2616, RFC 2617 (一部)
  • ステータス: Standards Track (標準トラック)

概要

HTTPは、サーバーがクライアントリクエストをチャレンジし、クライアントが認証情報を提供できるシンプルなチャレンジ-レスポンス認証フレームワークを提供します。このドキュメントでは、401、407ステータスコードおよび関連するヘッダーフィールドを含むHTTP認証フレームワークの一般的なメカニズムを定義します。

核心概念

HTTP認証フロー

1. クライアントが保護されたリソースを要求
→ GET /admin HTTP/1.1

2. サーバーがチャレンジを返す
← HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Admin Area"

3. クライアントが資格情報を提供
→ GET /admin HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==

4. サーバーが検証して応答
← HTTP/1.1 200 OK
[保護されたコンテンツ...]

認証スキーム (Authentication Schemes)

HTTPは複数の認証スキームをサポートします:

  • Basic: 基本認証 (RFC 7617)
  • Bearer: Bearerトークン (RFC 6750)
  • Digest: ダイジェスト認証 (RFC 7616)
  • OAuth: OAuth認証 (RFC 6749)

401 Unauthorized

リクエストに有効な認証情報が含まれていないことを示します。

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="WallyWorld"
Content-Type: text/html
Content-Length: 0

重要: 401の名前「Unauthorized」は実際には Unauthenticated (未認証) の意味です。

407 Proxy Authentication Required

クライアントがまずプロキシで認証する必要があることを示します。

HTTP/1.1 407 Proxy Authentication Required
Proxy-Authenticate: Basic realm="Proxy Access"

WWW-Authenticateヘッダー

サーバーはこのヘッダーを使用して認証チャレンジを定義します。

基本構文

WWW-Authenticate: &lt;scheme> realm="&lt;realm>" [, <param>=&lt;value>]*

単一チャレンジ:

WWW-Authenticate: Basic realm="Admin Area"

複数のチャレンジ (クライアントが選択可能):

WWW-Authenticate: Bearer realm="API", Basic realm="API"

追加パラメータ付き:

WWW-Authenticate: Digest
realm="[email protected]",
qop="auth,auth-int",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
opaque="5ccc069c403ebaf9f0171e9517f40e41"

realmパラメータ

realm (領域) は保護空間の範囲を定義します:

WWW-Authenticate: Basic realm="管理者エリア"
  • 通常ブラウザの認証ダイアログに表示されます
  • ユーザーがどの資格情報が必要かを理解するのに役立ちます
  • 同じrealmのリソースは資格情報を共有します

Authorizationヘッダー

クライアントはこのヘッダーを使用して認証情報を提供します。

基本構文

Authorization: &lt;scheme> &lt;credentials>

Basic認証:

Authorization: Basic dXNlcjpwYXNzd29yZA==

Bearerトークン:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Digest認証:

Authorization: Digest username="user",
realm="[email protected]",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
uri="/dir/index.html",
response="6629fae49393a05397450978507c4ef1"

Proxy-AuthenticateとProxy-Authorization

プロキシ認証に使用され、WWW-AuthenticateとAuthorizationと同様に機能します。

プロキシ認証フロー

1. クライアントリクエスト
→ GET http://example.com/ HTTP/1.1

2. プロキシが認証を要求
← HTTP/1.1 407 Proxy Authentication Required
Proxy-Authenticate: Basic realm="Proxy"

3. クライアントが資格情報を提供
→ GET http://example.com/ HTTP/1.1
Proxy-Authorization: Basic cHJveHk6cGFzc3dvcmQ=

4. プロキシがリクエストを転送
[Proxy] → GET / HTTP/1.1
Host: example.com

Basic認証 (RFC 7617)

最もシンプルですが、最も安全でない認証スキーム。

資格情報のエンコード

// 1. ユーザー名とパスワードを結合
const credentials = "username:password";

// 2. Base64エンコード
const encoded = btoa(credentials);
// 結果: "dXNlcm5hbWU6cGFzc3dvcmQ="

// 3. Authorizationヘッダーを構築
const auth = `Basic ${encoded}`;

完全な例

GET /admin HTTP/1.1
Host: example.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

セキュリティ警告

危険: Basic認証は資格情報をBase64エンコードで送信します。暗号化ではありません!

dXNlcm5hbWU6cGFzc3dvcmQ= 
↓ Base64デコード
username:password

HTTPSを使用する必要があります:

✗ http://example.com + Basic認証 = 平文送信
✓ https://example.com + Basic認証 = 暗号化送信

Bearerトークン認証 (RFC 6750)

最新のWeb APIでよく使用される認証スキーム。

使用シナリオ

通常OAuth 2.0と一緒に使用されます:

1. ユーザーがログインし、アクセストークンを取得
← { "access_token": "eyJhbG...", "token_type": "Bearer" }

2. トークンを使用してAPIにアクセス
→ GET /api/user HTTP/1.1
Authorization: Bearer eyJhbG...

GET /api/resource HTTP/1.1
Host: api.example.com
Authorization: Bearer mF_9.B5f-4.1JqM

エラーレスポンス

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="API",
error="invalid_token",
error_description="The access token expired"

Digest認証 (RFC 7616)

Basicより安全ですが、より複雑です。

特徴

  • パスワードを直接送信しない
  • チャレンジ-レスポンスメカニズムを使用
  • リプレイ攻撃を防止 (nonceを通じて)

簡略化されたフロー

1. サーバーがチャレンジを送信 (nonceを含む)
← WWW-Authenticate: Digest realm="...", nonce="..."

2. クライアントがレスポンスを計算
response = MD5(
MD5(username:realm:password) :
nonce :
MD5(method:uri)
)

3. クライアントがレスポンスを送信
→ Authorization: Digest username="...", response="..."

実際の応用シナリオ

シナリオ1: Webアプリケーションログイン

従来のフォーム + Session (推奨):

POST /login HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=user&password=pass

→ HTTP/1.1 302 Found
Set-Cookie: sessionid=abc123; HttpOnly; Secure

HTTP Basic認証を使用しない (HTTPS経由でない限り)。

シナリオ2: API認証

Bearer Token (推奨):

GET /api/users HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

シナリオ3: 管理インターフェースの保護

Basic認証 + HTTPS (シンプルなシナリオ):

GET /admin HTTP/1.1
Host: secure.example.com
Authorization: Basic YWRtaW46c2VjcmV0

シナリオ4: マイクロサービス間認証

相互TLS + Bearer Token:

GET /internal/service HTTP/1.1
Host: internal.example.com
Authorization: Bearer service-token-123

認証 vs. 認可

違い

認証 (Authentication): "あなたは誰ですか?"

Authorization: Bearer [アイデンティティトークン]

認可 (Authorization): "あなたは何ができますか?"

トークンに含まれる権限:
{
"user_id": "123",
"roles": ["admin", "editor"],
"permissions": ["read", "write", "delete"]
}

HTTPステータスコード

  • 401 Unauthorized: 認証失敗または認証不足
  • 403 Forbidden: 認証成功、しかし権限なし
ユーザーAが管理者リソースへのアクセスを試みる:
→ ログインしていない → 401 Unauthorized
→ ログイン済み (一般ユーザー) → 403 Forbidden
→ ログイン済み (管理者) → 200 OK

ベストプラクティス

サーバー側

  1. 常にHTTPSを使用

    ✓ https://api.example.com
    ✗ http://api.example.com
  2. 明確なrealmを提供

    WWW-Authenticate: Bearer realm="My API v1"
  3. 複数の認証スキームをサポート

    WWW-Authenticate: Bearer realm="API", Basic realm="API"
  4. 失敗した試行を制限

    • レート制限を実装
    • 失敗した認証試行を記録
    • アカウントの一時的なロックを検討
  5. 資格情報を安全に保存

    • パスワードは強力なハッシュ化 (bcrypt, Argon2)
    • トークンは安全な乱数生成器

クライアント側

  1. トークンを安全に保存

    // ✓ 推奨
    sessionStorage.setItem('token', token);

    // ✗ 避ける (XSSリスク)
    localStorage.setItem('token', token);
  2. 401レスポンスの処理

    if (response.status === 401) {
    // ローカルトークンをクリア
    // ログインページにリダイレクト
    }
  3. トークンの更新

    // トークンの有効期限が切れる前に自動更新
    if (tokenExpiresIn &lt; 5 * 60) {
    refreshToken();
    }

セキュリティの考慮事項

1. 中間者攻撃

リスク: 暗号化されていない資格情報の送信

防御: HTTPSを使用

✗ HTTP + Basic: 平文の資格情報が盗まれる
✓ HTTPS + Basic: 暗号化された送信、安全

2. リプレイ攻撃

リスク: 攻撃者が認証リクエストを傍受して再生

防御:

  • 短期トークンを使用
  • nonceメカニズムを実装
  • トークンを特定のクライアントにバインド

3. 資格情報の漏洩

リスク: 資格情報がログに記録されるか漏洩

防御:

  • URLで資格情報を渡さない
  • 短期アクセストークンを使用
  • リフレッシュトークンメカニズムを実装
✗ https://api.example.com/data?token=abc123
✓ Authorization: Bearer abc123

4. XSS攻撃

リスク: 悪意のあるスクリプトがトークンを盗む

防御:

  • HttpOnlyクッキーを使用
  • CSPポリシーを実装
  • 入力を検証およびサニタイズ

まとめ

HTTP認証は柔軟なフレームワークを提供します:

  • 信頼性: 認証プロトコルを正確に実装し、セキュリティを確保
  • 明確性: 認証要件を明確に表現し、クライアント実装を容易にする
  • 優雅さ: 認証フローを優雅に設計し、ユーザーエクスペリエンスを向上

核心原則:

  1. 常にHTTPSを使用
  2. シナリオに適した認証スキームを選択
  3. 多層防御戦略を実装
  4. 資格情報を定期的にローテーション

現代的な推奨事項:

  • Webアプリケーション: OAuth 2.0 + OpenID Connect
  • API: Bearer Token (JWT)
  • シンプルなシナリオ: Basic + HTTPS
  • 避ける: Digest (時代遅れで複雑)

関連ドキュメント:

  • RFC 7617: Basic認証
  • RFC 7616: Digest認証
  • RFC 6750: Bearer Token
  • RFC 6749: OAuth 2.0

HTTP/1.1シリーズに戻る