APIが「誰からのリクエストか」を確かめるとき、よく使われるのが Authorization ヘッダーです。
値には認証方式を示す scheme と、その方式で使う credentials を入れます。
Authorization: <scheme> <credentials>
この記事では、クライアントがヘッダーを送り、サーバーが検証してレスポンスを返す1回の往復を中心に、BasicとBearerを比べます。
認証方式・検証・401/403を含む総合仕様は本記事で扱い、SPAが直接送る構成とBFF経由の構成を選ぶ判断はSPA・BFFでAuthorizationヘッダーをどう使い分けるかで比較します。

先に結論
Authorizationヘッダーの流れは次の4段階です。
- クライアントがAPI仕様に合うschemeを選ぶ
- credentialsを付けてリクエストする
- サーバーがcredentialsの正当性と有効性を検証する
- 認証後、対象resourceを操作できるか認可する
代表例は次の2つです。
Authorization: Basic YWxpY2U6c2VjcmV0
Authorization: Bearer eyJhbGciOi...
Basic や Bearer がscheme、その後ろがcredentialsです。
認証と認可を分ける
似た言葉ですが、役割は異なります。
- 認証(authentication): 誰なのかを確かめる
- 認可(authorization): その人が操作してよいかを確かめる
有効なトークンを持っているだけで、すべてのデータへアクセスできるわけではありません。
たとえば、ログイン済みの生徒が自分の提出物を読めても、別の生徒の提出物を読めるとは限りません。サーバーは認証後に、resourceの所有者やroleも確認します。
Basic認証
Basicでは、一般に ユーザー名:パスワード をBase64で表現します。
たとえば次の文字列を使います。
alice:secret
Base64にすると次の値です。
YWxpY2U6c2VjcmV0
リクエストは次のようになります。
GET /api/profile HTTP/1.1
Host: example.com
Authorization: Basic YWxpY2U6c2VjcmV0
サーバーは概ね次を確認します。
Authorizationがあるか- schemeが
Basicか - credentialsをBase64デコードできるか
- 最初のコロンでユーザー名とパスワードを分けられるか
- 保存済み情報と安全な方法で照合できるか
- 利用者が対象resourceへアクセスできるか
Base64は暗号化ではない
Base64はバイナリを文字列として表す符号化です。誰でも元へ戻せます。
printf 'YWxpY2U6c2VjcmV0' | base64 --decode
結果:
alice:secret
したがってBasic認証は必ずHTTPS上で使います。HTTPで送れば、通信を観察できる相手に認証情報を知られる危険があります。
さらに、毎回パスワード相当の値を送る性質があります。用途を限定し、現在の一般ユーザー向けWebログインではセッションやトークン方式も検討します。
Basicをcurlで試す
curlは -u でBasic認証ヘッダーを作れます。
curl -i \
-u 'alice:secret' \
https://example.com/api/profile
実際に作られる値を確認するには、次のようにBase64へ変換できます。
printf 'alice:secret' | base64
出力:
YWxpY2U6c2VjcmV0
シェル履歴やプロセス一覧に秘密情報が残る可能性があります。本物のパスワードをコマンドへ直接書く運用は避け、検証用の値だけで試してください。
Bearer認証
Bearerでは、発行済みのアクセストークンを送ります。
GET /api/profile HTTP/1.1
Host: example.com
Authorization: Bearer eyJhbGciOi...
Bearerは「その値を持っている人が使える」という性質を表します。盗まれたトークンを第三者が送っても、サーバーから見れば正規の所持者と区別できない場合があります。
そのため、次が重要です。
- HTTPSだけで送る
- ログへトークン全体を出さない
- URLのquery stringへ入れない
- 必要最小限の権限と有効期限にする
- 漏えい時に無効化または失効できるようにする
Bearerトークンは必ずJWTではない
BearerはAuthorization schemeの名前です。credentialsの形式をJWTに限定しません。
サーバー内部でだけ意味が分かるランダム文字列もBearerトークンとして使えます。JWTかどうかは、そのAPIや認証基盤の仕様を確認します。
Bearerをサーバーが検証する
サーバーはschemeを確認し、トークンを認証基盤の仕様に従って検証します。
JWTなら、一般に専用ライブラリを使って次を確認します。
- 署名が正しいか
- 許可したalgorithmか
- issuer(発行者)が正しいか
- audience(利用先)が正しいか
- expiration(有効期限)が切れていないか
署名を確認せずpayloadを読むだけでは認証になりません。また、payloadの値を確認できても、その利用者が対象resourceを操作できるかは別に認可します。
不透明なランダムトークンなら、データベースや認証サーバーへ照会し、有効期限・失効状態・scopeなどを確認します。
自作の文字列解析だけで済ませず、利用する認証サービスやフレームワークの公式ライブラリに従います。
Bearerをcurlで送る
curl -i \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
https://example.com/api/profile
YOUR_ACCESS_TOKEN は説明用のplaceholderです。実際のトークンを共有チャット、ソースコード、スクリーンショットへ貼らないでください。
環境変数を使う場合も、端末の履歴やCIログへ表示されないよう扱います。
fetchで送る
ブラウザのJavaScriptからBearerトークンを送る例です。
const response = await fetch("https://api.example.com/profile", {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
別originのAPIなら、サーバー側のCORS設定で Authorization ヘッダーを許可する必要があります。
ブラウザへ渡したトークンは、ページ上で動くJavaScriptから触れられる可能性があります。保存場所を安易に決めず、XSS対策、トークンの寿命、更新方法を認証基盤の推奨構成に合わせます。
サーバー専用のAPIキーや長期secretをフロントエンドへ埋め込んではいけません。配信されたJavaScriptは利用者から見えます。
401 Unauthorized
認証情報がない、壊れている、期限切れなどで認証できない場合は、通常 401 Unauthorized を返します。
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
Content-Type: application/json
{"error":"invalid_token"}
WWW-Authenticate は、どの認証schemeで資格情報を提示すべきかを示すchallengeです。
Basicなら次のような形です。
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="members"
名前はUnauthorizedですが、実務では「まだ認証できていない」と覚えると区別しやすくなります。
403 Forbidden
認証はできたが、その操作を許可されていない場合は通常 403 Forbidden を返します。
HTTP/1.1 403 Forbidden
Content-Type: application/json
{"error":"insufficient_permission"}
例:
- 一般利用者が管理者APIを呼んだ
- 別の利用者が所有するresourceを編集しようとした
- 必要なscopeを持たないトークンで操作した
つまり、基本の区別は次の通りです。
| 状態 | ステータス |
|---|---|
| 認証情報がない、または無効 | 401 |
| 認証済みだが権限不足 | 403 |
存在自体を隠したいresourceでは、情報露出を避けるため別の応答設計を選ぶこともあります。API全体で方針を統一します。
API Keyは送付方法がAPI次第
API keyはサービスが発行する識別・認証用の秘密値です。ただし、API Key という標準Authorization schemeが一律に決まっているわけではありません。
API仕様によって Authorization: Bearer YOUR_API_KEY や X-API-Key: YOUR_API_KEY などの形式があります。必ず公式ドキュメントに従います。
query stringへAPI keyを入れる方式は、アクセスログや履歴、参照元情報に残りやすいため、選べるならヘッダーを使います。
API keyもソースコードへ直書きせず、サーバー側の環境変数やsecret管理機能で扱います。ブラウザへ配信するコードへ入れた値は秘密にできません。
よくある間違い
- schemeを書かずトークンだけ送る: Bearerを要求するAPIなら
Authorization: Bearer <token>とします。 - BasicのBase64を暗号化だと思う: すぐ復号できるためHTTPSが前提です。
- JWTなら検証せず信用する: 署名、issuer、audience、期限などを検証します。
- 401と403を同じ意味で使う: 認証できなければ401、認証後の権限不足なら403が基本です。
- 有効なトークンなら全resourceを許可する: 所有者、role、scopeなども確認します。
DevToolsで確認する
NetworkタブでRequest Headersのscheme、Status、401応答の WWW-Authenticate を確認できます。画面共有時はAuthorizationの値を隠してください。
まとめ
Authorization: <scheme> <credentials> という形で送り、往復で見ると処理は明確です。
クライアントがcredentialsを送る
→ サーバーが認証する
→ 対象resourceへの権限を確認する
→ 成功、401、403のいずれかを返す
覚える要点は次の通りです。
- Basicはユーザー名とパスワード相当をBase64で表すが、暗号化ではない
- Bearerは所持者が使えるため、漏えいさせない
- Bearerトークンは必ずしもJWTではない
- 401は認証できない状態、403は認証後の権限不足
- API keyの送付場所はAPI仕様に従う
- 認証と認可はサーバーで別々に確認する
次に読む
- APIでAuthorizationヘッダーを送る - ブラウザ直接送付とSPA・BFFの違い
- Bearer Tokenとは何か - tokenの所持者性と漏えい時の影響
- Cookieの仕組み
- セッションIDとサーバー側セッション
- JWTの仕組み