APIの認証って「トークン認証」くらいしか意識していなかったのですが、整理してみると色々あったのでまとめておきます。ついでに、よく混同される OAuth や JWT との関係もメモしておきます。
APIの主な認証方式
| 方式 | しくみ | 使われている例 | 特徴 |
|---|---|---|---|
| Basic認証 | 毎回 ID:パスワード を Base64 にして送る | 社内ツール、古いAPI | 一番簡単。毎回パスワードを送るので HTTPS 必須 |
| APIキー | 発行した固定のキーを毎回送る | Claude API、Google Maps など多くの SaaS | 簡単で広く使われている。期限がないことが多く、漏れたら作り直し |
| トークン認証 | 一度認証して期限付きトークンをもらい、以後はそれを送る | OAuth 2.0 全般、自前のトークン発行 | 秘密を送る回数が減る。期限を付けられる |
| リクエスト署名(HMAC) | 秘密鍵でリクエストの中身ごと署名する。秘密そのものは送らない | AWS(Signature V4)、決済サービスの Webhook | 改ざんや使い回しを防げる。実装はやや大変 |
| mTLS(クライアント証明書) | 通信開始時にお互いが証明書を見せ合う | 銀行・金融機関同士の API | 秘密の文字列を送らない。とても強いが証明書の管理が手間 |
| セッションCookie | ログイン後、サーバーが覚えたセッションを Cookie で照合 | ブラウザで使う Web アプリ | 画面のある Web アプリ向け。システム間 API ではあまり使わない |
IP制限は単独では「認証」とは言いませんが、どの方式とも組み合わせられる追加の守りになります。
強さのイメージ
- 1Basic認証毎回パスワードを送る
- 2APIキー期限のない固定の秘密
- 3トークン認証期限付きの秘密
- 4リクエスト署名秘密を送らない
改ざんも検知 - 5mTLS証明書で
お互いを確認
※実際の強さは、組み合わせと運用しだいです。
OAuth 2.0 と Bearer は別もの
「Bearer ヘッダーでトークンを送っている=OAuth 2.0」ではありません。決めている仕様が別です。
| 仕様 | 決めていること |
|---|---|
| RFC 6749(OAuth 2.0 本体) | トークンをどうやって発行するか。認可サーバー、grant_type、/token エンドポイントの形式など |
| RFC 6750(Bearer Token Usage) | 発行されたトークンをどうやって送るか。Authorization: Bearer の書き方 |
トークンの発行が独自方式なら「Bearer トークン認証」と呼ぶのが正確です。なお OAuth はもともと認可(何をしてよいか)の仕組みで、「ログインした人が誰か」を伝える部分は OpenID Connect が OAuth 2.0 の上に足したものです。
システム間の API なら、発行エンドポイントの入出力を以下の形に合わせるだけで「OAuth 2.0 Client Credentials Grant 準拠」と言えます。
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=xxx&client_secret=yyy
# 応答
{"access_token":"...","token_type":"Bearer","expires_in":1800}
ちなみに、ID/パスワードを直接送ってトークンをもらう「Resource Owner Password Credentials Grant」は、OAuth のセキュリティ指針(RFC 9700)で使ってはならないとされました。他社のアプリに本人のパスワードを渡すことになるのが理由で、人が使う場合は Authorization Code + PKCE が今の標準です。
トークンはどのヘッダーで送る?
標準は Authorization ヘッダーです(RFC 9110)。
Authorization: Bearer eyJhbGciOi... Authorization: Basic dXNlcjpwYXNz
ただ HTTP はどんなヘッダー名を付けても自由なので、独自ヘッダーも規格違反ではありません。よく見るのは以下です。
- x-api-key / X-API-Key(AWS API Gateway、Claude API など)
- Ocp-Apim-Subscription-Key(Azure API Management)
- Authorization: token xxx(GitHub の古い書き方。ヘッダーは標準でスキームが独自)
独自ヘッダーの弱点
- ログで伏せてもらえない:多くのツールやプロキシは Authorization を秘密として自動でマスクするが、独自ヘッダーはそのまま記録されることがある
- キャッシュ事故:共有キャッシュは Authorization 付きリクエストの応答を他人に使い回さない(RFC 9111)。独自ヘッダーだとこの保護が効かない
- X- で始まる名前は非推奨(RFC 6648)。ただし今も広く残っている
一番避けたいのは URL にトークンを入れる方式(?token=xxx)です。アクセスログやブラウザ履歴、Referer に残ってしまいます。
トークンとパスワードの違い
似ていますが、観点別に比べると違いがみえてきます。
| 観点 | パスワード | トークン |
|---|---|---|
| 何を表すか | 「私は本人です」を証明するもの | 「本人確認が済んだ」という結果 |
| 誰が作るか | 人が決めて覚える | システムが発行(長いランダム文字列や署名付きデータ) |
| 使える範囲 | アカウントでできることすべて | 一部の権限に絞れる(スコープ) |
| 取り消し | 変えると全端末に影響 | 1つだけ無効にできる |
| 送る回数 | ログインのときだけ | リクエストのたびに送る |
毎回送る分だけ盗まれる機会も多いので、トークンには短い有効期限を付けて被害を小さくします。
JWT 認証って何?
JWT(JSON Web Token、RFC 7519)は認証方式ではなく、トークンの形式です。「JWT 認証」は「JWT 形式のトークンを使った Bearer トークン認証」の通称です。ヘッダー・ペイロード・署名を「.」でつないだ形をしています。
{ "alg": "RS256", "typ": "JWT" } ← ヘッダー
{ "sub": "user01", "aud": "order-api",
"exp": 1791960000, "scope": "read" } ← ペイロード(クレーム)
← 署名
| クレーム | 意味 |
|---|---|
| sub | 誰のトークンか |
| exp | 有効期限(1970年からの秒数) |
| iat | 発行時刻 |
| iss | 発行者 |
| aud | どのAPI向けか |
JWT の注意点
- 署名だけの JWT(JWS)は中身を誰でも読める。秘密の情報は入れない(暗号化したいなら JWE)
- 検証時はアルゴリズムを固定する(alg を none に書き換える攻撃がある)
- 期限が来るまで途中で無効にできないので、有効期限は短くする
中身を見たいときは jwt.io が便利です。ただし本番のトークンは貼らないこと。
