【図解】APIの認証方式とは?Basic・APIキー・Bearerトークン・署名・クライアント証明書・ワークロードIDの違いを初心者向けに解説

API の資料を読んでいると、「API キーを発行してください」「Bearer トークンを付けてください」「リクエストに署名してください」と、サービスごとに認証のやり方がばらばらです。どれも「誰からのリクエストか」を示すしくみなのに、なぜこんなに種類があるのかを整理したくなりました。この記事では、よく出てくる6つの認証方式を、RFC とベンダーの公式ドキュメントで確かめながら並べて図にしました。

この記事でわかること
  1. API が確かめる「認証」と「認可」、401 と 403 の違い
  2. Basic・API キー・Bearer トークン・署名・クライアント証明書・ワークロード ID のしくみ
  3. 方式ごとに、何がネットワークに流れ、漏れたときにどうなるか
  4. 企業での使われ方の例と、選び方の目安
  5. 401・403 が返ってきたときの見方

API が確かめる2つのこと

API は、リクエストを受けるたびに「誰からか」(認証)と「その人が何をしてよいか」(認可)を確かめます。2つの違いは認証と認可の記事で説明しています。どちらで止まったかは、HTTP のステータスコードでわかります。

クライアントリクエスト① 誰か?認証(Authentication)OK② 何をしてよい?認可(Authorization)200 など401 Unauthorized認証情報がない・正しくないNG403 Forbidden誰かは分かったが権限がないNGAPI はリクエストのたびに、2つのことを確かめる
図1 API が確かめる2つのこと
ステータス意味
401 Unauthorized認証情報がない、または正しくない。名前は Unauthorized ですが、意味は「認証できない」です
403 Forbidden認証はできたが、そのリソースへの権限がない

この記事で比べる「認証方式」は、①の「誰からか」をどうやって示すかの違いです。

認証情報を入れる場所

方式によって、認証情報を入れる場所が違います。多くは HTTP の Authorization ヘッダに入れ、その先頭の言葉(Basic、Bearer など)で方式を表します。API キーは、サービスごとに名前の違うヘッダに入れることがよくあります。クライアント証明書だけは、HTTP のリクエストより前の TLS の段階で出します。

TLS(HTTPS)の通信路GET /v1/items?api_key=…Host: api.example.comAuthorization: Basic …Authorization: Bearer …Authorization: AWS4-HMAC-SHA256 …X-API-Key: …(本文)クエリに入れる(避ける)Basic 認証Bearer トークン署名(例:AWS)API キー(名前はサービスごと)クライアント証明書(TLS の段階で出す)
図2 認証情報を入れる場所

URL のクエリ文字列に入れる方法もありますが、避けます。OWASP は、パスワードやトークン、API キーを URL に入れるとサーバのログなどに残るとして、URL に入れないよう求めています。

6つの認証方式

Basic 認証:ユーザー名とパスワードをそのまま送る

Basic 認証(RFC 7617)は、「ユーザー名:パスワード」を Base64 という形式に変えて、毎回 Authorization ヘッダに入れる方式です。

例:ユーザー名 Aladdin、パスワード open sesame の場合(RFC 7617 の例)

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Base64 は文字の置き換えで、暗号ではありません。もとに戻せば、ユーザー名とパスワードがそのまま読めます。RFC 7617 も、TLS のような安全な通信路と組み合わせなければ、安全な認証方法とは言えないとしています。しかも、パスワードそのものをリクエストのたびに送ります。

API キー:長く使う秘密の文字列

API キーは、サービスが発行するランダムな文字列で、リクエストのたびにそのまま送ります。どのヘッダに入れるかはサービスごとに決まっていて、たとえば Azure API Management のサブスクリプションキーは Ocp-Apim-Subscription-Key ヘッダ、Cisco Meraki の Dashboard API は Authorization: Bearer の形で送ります。

手軽な反面、取り消すまで有効なものが多く、漏れると長く使われます。OWASP は、API キーだけで重要なリソースを守らないよう勧めています。

Bearer トークン:期限の短いトークン

Bearer トークンは、OAuth 2.0 などのしくみで発行されるアクセストークンを、Authorization: Bearer で送る方式です。期限が短く、使える範囲(スコープ)が決まっているのが特徴です。しくみはセッションとトークンの記事で説明しています。

Microsoft も、Exchange Online で Basic 認証をやめて OAuth 2.0 に移した理由として、アクセストークンは使える期間が限られ、発行されたアプリとリソースにしか使えないこと、多要素認証も有効にしやすいことを挙げています。

署名:秘密の鍵は送らず、署名だけを送る

署名の方式では、クライアントとサーバが同じ秘密の鍵を持ち、クライアントはリクエストの中身からその鍵で署名(HMAC)を計算して付けます。サーバも同じ計算をして、署名が一致するかを確かめます。秘密の鍵そのものはネットワークに流れません。HMAC のしくみは暗号の基礎の記事で説明しています。

AWS の API は、この形の Signature Version 4(SigV4)を使います。

例:SigV4 の Authorization ヘッダ(AWS のドキュメントの例。読みやすいよう改行してあり、実際は1行)

Authorization: AWS4-HMAC-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request,
SignedHeaders=host;x-amz-date,
Signature=calculated-signature

Credential にはアクセスキー ID(誰の鍵か)が入りますが、秘密のアクセスキーは入りません。AWS のドキュメントでは、リクエストの一部から計算したハッシュを含めることで途中での改ざんを防ぎ、ほとんどの場合、リクエストに書かれた時刻から5分以内に届かないと拒否する、と説明しています。

Webhook の通知でも同じ考え方が使われます。GitHub は、Webhook に設定した秘密の値と通知の中身から HMAC-SHA256 を計算し、X-Hub-Signature-256 ヘッダに sha256= で始まる値として付けて送ります。

クライアント証明書(mTLS):TLS の段階で相手を確かめる

ふつうの HTTPS では、サーバだけが証明書を出し、クライアントがサーバを確かめます。mTLS(相互 TLS)では、クライアントも証明書を出し、サーバがクライアントを確かめます。証明書の秘密鍵はクライアントの手元から出ず、TLS のやり取りの中で「その証明書の持ち主か」が確かめられます。

Azure API Management では、クライアント証明書を受け取るよう設定し、ポリシーで発行者やサブジェクト、拇印(サムプリント)を確かめられます。

例:拇印が違う証明書を 403 で断るポリシー(Microsoft のドキュメントの例)

<choose>
    <when condition="@(context.Request.Certificate == null || !context.Request.Certificate.Verify() || context.Request.Certificate.Thumbprint != "DESIRED-THUMBPRINT-IN-UPPER-CASE")" >
        <return-response>
            <set-status code="403" reason="Invalid client certificate" />
        </return-response>
    </when>
</choose>
途中で TLS を終わらせる機器に注意

mTLS は TLS の段階の認証なので、途中で TLS を終わらせる機器があると、証明書がその先に届きません。Microsoft のドキュメントでも、API Management の前に Application Gateway(L7 のロードバランサ)を置くと、Application Gateway が API Management と別の TLS 接続を張るため、クライアントの証明書が API Management に渡らないと注意しています。

ワークロード ID:アプリに秘密を持たせない

ここまでの方式は、どれもアプリ側に何かしらの秘密(パスワード、キー、秘密鍵)を置きます。ワークロード ID は、アプリが動いている基盤(Azure や GitHub Actions など)に身元を保証してもらい、トークンをもらう方式です。

Azure の中で動くプログラムにはマネージド ID、GitHub Actions のように Azure の外で動くプログラムにはワークロード ID フェデレーションを使います。Microsoft のドキュメントでは、Azure で動くワークロードにはマネージド ID を使い、資格情報は Azure の基盤が管理する、と説明しています。

マネージド ID:VM の中から、基盤にトークンを頼む

Azure の VM でマネージド ID を有効にすると、Azure が VM 用の ID(サービスプリンシパル)を Microsoft Entra ID に作り、その証明書を VM の外側の基盤に用意します。VM の中のプログラムは、VM の中からしか届かない IMDS(Instance Metadata Service)にトークンを頼むだけです。

Azure の VM(中から届く範囲)VM のプログラムIMDSVM の中からだけ届くMicrosoft Entra IDAzure のサービスStorage など① トークンを頼む② VM の ID の証明書で依頼③ アクセストークン(JWT)④ アクセストークン⑤ Authorization: Bearer …VM の ID の権限で処理証明書は Azure が管理し、IMDS の側にあるプログラムはパスワードも鍵も持たない事前:Azure が VM の ID を Entra ID に作り、その ID に Azure の役割(RBAC)を割り当てる
図3 マネージド ID の流れ
手順何が起きるか
事前VM の ID に、使ってよい Azure のリソースへの役割(RBAC)を割り当てておく
①VM の中のプログラムが、IMDS(http://169.254.169.254/metadata/identity/oauth2/token)にトークンを頼む
②③④VM の ID のクライアント ID と証明書で Entra ID にトークンを頼み、JWT のアクセストークンがプログラムに返る
⑤プログラムはアクセストークンを Authorization: Bearer で Azure のサービスに送る。サービスは VM の ID に割り当てた権限で処理する

証明書はプログラムの手元になく、プログラムのコードや設定ファイルに秘密を書く必要がありません。実際のリクエストと応答の例は、セッションとトークンの記事で紹介しています。

ワークロード ID フェデレーション:外の基盤のトークンを、Entra ID のトークンと引き換える

GitHub Actions のように Azure の外で動くプログラムには、Azure の基盤がありません。そこで、その基盤(GitHub)が発行するトークンを、Microsoft Entra ID に「信頼する」と登録しておき、Entra ID のアクセストークンと引き換えます。

GitHub ActionsのジョブGitHubトークンの発行元Microsoft Entra ID信頼の設定ありAzureApp Service など① トークンを頼む② GitHub のトークン③ GitHub のトークンを出して、アクセストークンを頼む④ 署名の鍵を取得して確かめる⑤ Entra ID のアクセストークン⑥ Authorization: Bearer … でデプロイ事前:Entra ID のマネージド ID(またはアプリ)に「フェデレーション資格情報」を登録する= どの発行元(issuer)の、どのリポジトリ・ジョブ(subject)のトークンを信頼するかGitHub に置くのはクライアント ID などの ID だけで、パスワードや証明書は置かない
図4 ワークロード ID フェデレーションの流れ(GitHub Actions の例)
手順何が起きるか
事前Entra ID のユーザー割り当てマネージド ID(またはアプリの登録)に、フェデレーション資格情報を登録する。どの発行元(issuer)の、どの対象(subject:リポジトリやジョブ)、どの宛先(audience)のトークンを信頼するかを決める
①②ジョブが GitHub にトークンを頼み、GitHub がトークンを発行する
③ジョブ(Azure へのサインインのアクション)が、GitHub のトークンを Entra ID に出してアクセストークンを頼む
④Entra ID は信頼の設定と照合し、GitHub の OIDC の発行元 URL から署名の鍵を取って、トークンを確かめる。issuer・subject・audience は、登録した値と大文字・小文字まで一致する必要がある
⑤⑥確かめられたら Entra ID がアクセストークンを返し、ジョブはそれで Azure にデプロイする

GitHub に保存するのは、クライアント ID・テナント ID・サブスクリプション ID といった「どの ID を使うか」を表す値だけで、パスワードや証明書は置きません。期限切れのシークレットを更新する手間や、漏れる心配もなくなります。同じしくみは、Kubernetes や Google Cloud、AWS で動くプログラムにも使えます。

最後に API に送るのは Bearer トークンなので、送り方だけを見ると Bearer と同じです。違いは、そのトークンをもらうためにアプリが長く使う秘密を持たなくてよい点です。

6つを並べて比べる

違いがいちばん出るのは、「何がネットワークに流れるか」と「漏れたときにどうなるか」です。

ネットワークに流れるもの特徴Basicユーザー名とパスワード毎回そのまま送る(Base64 は暗号ではない)API キー長く使う秘密の文字列毎回そのまま送る。取り消すまで有効なことが多いBearer期限の短いトークン毎回送るが、期限が切れれば使えない署名署名だけ秘密の鍵は送らない。中身を変えると署名が合わない証明書証明書(公開鍵)秘密鍵は送らない。TLS で持ち主かを確かめるワークロード ID基盤が渡すトークンアプリは長く使う秘密を持たない漏れたときの影響が小さくなる
図5 何が流れて、漏れたらどうなるか
方式送るもの・場所期限よく使う場面
Basicユーザー名とパスワード(Authorization: Basic)パスワードを変えるまで古いシステム。新しく選ばない
API キーキー(サービスごとのヘッダ)取り消すまでのことが多いサービスや製品の API を手軽に使う
Bearer トークンアクセストークン(Authorization: Bearer)短い(例:1時間前後)ユーザーやアプリの権限で API を使う
署名署名と鍵の ID(Authorization など)鍵は長く使い、署名はリクエストごと改ざんを防ぎたい API、Webhook
クライアント証明書証明書(TLS の段階)証明書の有効期限まで取引先や決まったシステムどうし
ワークロード ID基盤からもらうトークン(最後は Bearer)短いクラウドの中のプログラム、CI/CD

企業での使われ方(例)

会社のシステムでよく見る例を並べました。製品名と送るものは、どれも公式ドキュメントで確かめたものです。

呼ぶ側送るもの呼ばれる側Basic古いメールアプリID・パスワードExchange Online多くの通信で廃止API キー社内アプリOcp-Apim-Subscription-KeyAzure API ManagementサブスクリプションキーBearer運用スクリプトAuthorization: BearerMicrosoft GraphOAuth のアクセストークン署名自動化ツールAWS4-HMAC-SHA256AWS の APISignature Version 4証明書取引先のシステムクライアント証明書Azure API ManagementmTLS で相手を確かめるワークロード IDGitHub ActionsOIDC のトークンAzure(Entra ID)シークレットを置かない
図6 企業での使われ方の例
方式場面ポイント
Basic古いメールアプリやスクリプトから Exchange Online へExchange Online は、EWS、POP、IMAP、Exchange ActiveSync などで Basic 認証を廃止し、OAuth 2.0 による認証に移った。SMTP AUTH の Basic 認証も廃止の予定が発表されている(時期は Microsoft の最新の告知で確認)
API キー社内アプリから Azure API Management で公開した API へOcp-Apim-Subscription-Key ヘッダでサブスクリプションキーを送る。キーは既定でバックエンドにも渡るので、ログに残したくなければポリシーで外す
API キー自動化ツールから Meraki Dashboard API へAPI キーを Authorization: Bearer で送る。キーは発行した管理者と同じ権限を持ち、取り消すまで有効
Bearer運用スクリプトから Microsoft Graph へEntra ID からアクセストークンをもらい、Authorization: Bearer で送る
署名自動化ツールや SDK から AWS の API へSigV4 で署名する。時刻から5分を過ぎたリクエストは、ほとんどの場合拒否される
署名GitHub から社内の Webhook の受け口へX-Hub-Signature-256 を受け口で計算し直して比べる
クライアント証明書取引先のシステムから Azure API Management へ証明書の発行者や拇印をポリシーで確かめる
ワークロード IDGitHub Actions から Azure へデプロイOIDC のフェデレーションで、GitHub にシークレットを置かない
ワークロード IDAzure の VM から Azure Resource Manager や Storage へマネージド ID で、VM の中からトークンをもらう

1つの API が複数の方式を受け付けることもあります。Azure API Management は、サブスクリプションキーのほかに、OAuth 2.0 やクライアント証明書、呼び出し元の IP アドレスの制限も使えます。

選び方の目安

使う相手のサービスが決まっていれば、そのサービスが対応している方式から選ぶことになります。自分たちで API を作る・選べる場面では、次の順に考えると、アプリが持つ秘密を減らせます。

呼び出し元が Azure 上のリソースやGitHub Actions のような基盤?はいワークロード IDマネージド ID・フェデレーションいいえユーザーの代わりに、その人の権限で操作する?はいBearer トークンOAuth でトークンをもらういいえWebhook などで、送り主と中身が変わっていないかを確かめたい?はい署名共有した秘密で HMACいいえ相手が決まった会社やシステムで、通信路の段階でも確かめたい?はいクライアント証明書mTLSいいえAPI キー保管場所と権限を絞って使うBasic 認証は、新しく選ばない
図7 認証方式の選び方の目安

どの方式でも共通して大事なのは、次の点です。

  • HTTPS で送る。Basic や API キー、Bearer トークンは、通信路で読まれればそのまま使われます。
  • URL に入れない。ログや履歴に残ります。
  • コードや設定ファイルに秘密を書かない。書く必要がない方式(ワークロード ID)を選ぶか、Key Vault のような保管場所に置きます。
  • 権限を絞る。キーやトークンで何ができるかを、必要な範囲だけにします。

401・403 が返ってきたら

認証で止まったときは、まずステータスコードと WWW-Authenticate ヘッダを見ます。

状態よくある原因確認すること
401(invalid_token)トークンの期限切れ、取り消し、形式の誤りトークンを取り直す。RFC 6750 では、このエラーに 401 を返すとしている
401(ヘッダなし)ヘッダ名や方式の書き間違い(Bearer と Basic、キーのヘッダ名)サービスのドキュメントと、送ったヘッダを見比べる
403(insufficient_scope)トークンの権限(スコープ)が足りないトークンをもらうときに頼んだ権限を見直す。RFC 6750 では、このエラーに 403 を返すとしている
403(認証は通っている)ロールや権限の割り当てがないAPI 側で、その ID に権限を割り当てているか確かめる
署名のエラー端末の時刻のずれ、署名に含めるヘッダの違い時刻を合わせる(SigV4 は時刻から5分が目安)
証明書が届かない途中の L7 の機器で TLS が終わっている証明書を確かめる場所まで、TLS がつながっているかを見る

まとめ

項目ポイント
確かめること認証(誰か)で失敗すると 401、認可(何をしてよいか)で失敗すると 403
Basicパスワードを毎回送る。Base64 は暗号ではない。新しく選ばない
API キー手軽だが長く使う秘密。ヘッダ名はサービスごと。重要なものはキーだけで守らない
Bearer トークン期限と範囲が限られたトークンを Authorization: Bearer で送る
署名秘密の鍵を送らず、署名で送り主と改ざんを確かめる(AWS SigV4、Webhook)
クライアント証明書TLS の段階で相手を確かめる。途中で TLS を終わらせる機器に注意
ワークロード ID基盤に身元を保証してもらい、アプリに秘密を置かない

参考にした資料

この記事は、次の標準と公式ドキュメントで内容を確かめて書きました。仕様や対応状況は変わることがあるので、最新の情報はリンク先で確かめてください。

あとがき

6つを並べてみて、方式の違いは「アプリにどんな秘密を持たせるか」の違いだと整理できました。パスワードをそのまま送る Basic から、秘密を持たないワークロード ID まで、新しい方式ほど漏れたときの影響を小さくする方向に進んでいます。ネットワークの立場では、mTLS が途中の L7 の機器で切れてしまう点が、設計のときにいちばん気をつけたいところだと感じました。

コメント