API連携を検討していると、認証まわりで必ず3つの言葉に出会います。

APIキーOAuth 2.0JWT

「どれを選べばいいのか」と考えてしまいますが、実はこの3つ、並列に比較できるものではありません。

混乱の原因は、次の2点にあります。

  • OAuth 2.0は「認証」ではなく「認可」の仕組み
  • JWTは「方式」ではなく「トークンの形式」

どちらも仕様書にはっきり書かれています。この記事では、公式仕様(RFC)の記述をもとに3つの関係を整理します。

APIそのものについては APIとは?非エンジニアにもわかるビジネス活用のポイント、設計原則は REST APIとは?6つの原則・HTTPメソッド・設計の考え方 をご覧ください。

まず、認証と認可は別物

混同されやすいので、先に整理します。

認証(Authentication) 認可(Authorization)
問い あなたは誰か 何をしてよいか
社員証で本人確認する その社員証でどの部屋に入れるか
API文脈 呼び出し元の身元確認 どのデータにアクセスしてよいかの許可

この区別が、OAuth 2.0を理解する鍵になります。

OAuth 2.0は「認可」の枠組み

仕様書の冒頭には、こう書かれています。

「The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.」
(OAuth 2.0 認可フレームワークは、サードパーティのアプリケーションがHTTPサービスへの限定的なアクセスを取得できるようにする)
——RFC 6749

「authorization framework(認可フレームワーク)」と明記されています。authentication(認証)とは書かれていません。

何を解決する仕組みなのか

OAuthが生まれた背景は、こういう場面です。

あるサービスに「Googleカレンダーの予定を読み取りたい」と言われた。
——Googleのパスワードを、そのサービスに渡してよいのか?

渡してしまえば、そのサービスはGmailもドライブも見られてしまいます。これを避けるのがOAuthです。

パスワードを渡す代わりに、「このサービスに、カレンダーの読み取りだけを許可する」という証明書(アクセストークン)を発行します。仕様がlimited access(限定的なアクセス)と表現しているのは、この点です。

登場人物は4つ

RFC 6749は、4つの役割を定義しています。

役割 仕様の定義 先ほどの例で言うと
resource owner 「An entity capable of granting access to a protected resource.」(保護されたリソースへのアクセスを許可できる主体) あなた
resource server 「The server hosting the protected resources」(保護されたリソースを持つサーバー) Googleカレンダー
client 「An application making protected resource requests on behalf of the resource owner」(リソース所有者に代わって要求を行うアプリ) 連携したいサービス
authorization server 「The server issuing access tokens to the client after successfully authenticating the resource owner」(リソース所有者の認証後にトークンを発行するサーバー) Googleのログイン画面

注目したいのが authorization server の定義です。「after successfully authenticating the resource owner(リソース所有者を認証したうえで)」とあります。

認証は行われますが、それはOAuthの外側の話です。OAuthが標準化しているのは、その後の「トークンを渡す」部分になります。

「OAuthでログイン」はどう説明するか

「Googleでログイン」のようなボタンは、実際には OpenID Connect という別の仕様が使われています。これはOAuth 2.0の上に認証の層を追加したものです。

ログイン(認証)目的ならOpenID Connect、データへのアクセス許可(認可)ならOAuth 2.0——この使い分けになります。

JWTは「方式」ではなく「形式」

もうひとつの誤解がこれです。仕様を見ます。

「JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object…enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.」
(JWTは、2者間で転送されるクレームを表現するためのコンパクトでURLセーフな手段である。クレームはJSONオブジェクトとして符号化され、デジタル署名や暗号化が可能になる)
——RFC 7519

「means of representing claims(クレームを表現する手段)」——つまりデータの入れ物の規格です。

そのため、次のような関係になります。

  • OAuth 2.0でアクセストークンを発行する。そのトークンの形式としてJWTを使う
  • OAuthを使わず、独自の認証でJWTを発行することもある
  • OAuthのトークンがJWTでないこともある(不透明な文字列の場合)

「OAuthかJWTか」という問いは、「宅配便かダンボールか」と聞いているようなものです。層が違います。

署名されているが、暗号化されているとは限らない

実務上の重要な注意点です。JWTは署名によって改ざんを検知できますが、中身が読めなくなるわけではありません。

標準的なJWTのペイロードはBase64URLで符号化されているだけで、暗号化されていません。誰でもデコードして中身を読めます。

個人情報や機密情報をJWTのペイロードに入れないでください。これは実際によくある事故です。

APIキーの位置づけ

最後にAPIキーです。3つのなかで唯一、標準仕様(RFC)が存在しません。

単なる文字列をリクエストに付けるだけの仕組みで、サービスごとに送り方も異なります(ヘッダー、クエリパラメータ、独自ヘッダーなど)。

APIキー OAuth 2.0 JWT
正体 文字列 認可の枠組み トークンの形式
標準仕様 なし RFC 6749 RFC 7519
識別できるもの アプリ・契約単位 ユーザー単位の許可 (形式なので該当なし)
権限の細分化 できないことが多い スコープで指定できる
有効期限 基本的になし あり(短命) 形式として持てる
向いている場面 自社システム間の連携 他社サービスとの連携

APIキーの弱点

APIキーは「持っている人=正当な利用者」と見なすだけの仕組みです。漏れたら、そのまま使われます。

しかも有効期限がないことが多く、権限も分けられません。読み取りだけ許可したくても、キー1本ですべてできてしまうケースが一般的です。

そのため、次の運用が前提になります。

  • ソースコードに直接書かない(環境変数やシークレット管理へ)
  • 公開リポジトリに含めない——GitHubへの誤コミットは典型的な漏えい経路
  • 設定ファイルに注意YAMLJSONにそのまま書いたまま共有しない)
  • 定期的に再発行する

どう選ぶか

場面 適した方式
自社システム同士の連携 APIキーで足りることが多い
ユーザーのデータを他社サービスから扱う OAuth 2.0(同意を得る仕組みが必要)
ログイン連携をしたい OpenID Connect
社内サービス間でユーザー情報を引き回す JWT(形式として)

実際には利用するサービス側が方式を決めているため、選ぶ場面は多くありません。重要なのは、提示された方式が何をしているかを理解して運用することです。

よくある質問

Q. APIキーは安全ではないのですか?

用途によります。自社システム間の連携で、通信がHTTPSであり、キーが適切に管理されているなら実務上の選択肢になります。

問題になるのは、ユーザーのデータを第三者のサービスに扱わせる場面です。ここでAPIキーを使うと、ユーザーの同意も権限の限定もできません。

Q. JWTの有効期限は短いほうがよいのですか?

一般にアクセストークンは短命にし、リフレッシュトークンで更新する設計が推奨されます。

JWTはいったん発行すると、期限が切れるまで無効化しにくいという性質があるためです。漏えい時の影響時間を短くする意味があります。

Q. トークンはどこに保存すべきですか?

保存場所の選択は攻撃手法との兼ね合いになるため、利用するサービスやフレームワークの公式ガイダンスに従ってください。

共通して言えるのは、ログに出力しない・URLに含めないことです。URLに含めるとアクセスログや履歴に残ります。

Q. 社内にセキュリティの担当者がいません

方式を自前で設計しないでください。利用するサービスが提供する標準的な方法をそのまま使うのが最も安全です。

ノーコードの連携ツールを使えば、認証まわりをツール側が引き受けてくれます(ノーコード・ローコードとは?中小企業向けツール比較)。

Q. 企業ネットワークから接続できません

認証以前に、通信そのものがプロキシで止められている可能性があります。証明書エラーが出ている場合は SSLインスペクションとは?企業ネットワークで証明書エラーが起きる仕組み をご覧ください。

参考にした主な調査・資料

※RFCの引用は原文(英語)からの抜粋で、和訳は本記事によるものです。実際の実装は利用するサービスの公式ドキュメントに従ってください。

まとめ

  • 3つは並列に比較できない。層が違う
  • OAuth 2.0は「authorization framework(認可フレームワーク)」——RFC 6749に明記されている
  • 解決するのは「パスワードを渡さずに、限定的なアクセスを許可する」という課題
  • ログイン(認証)目的なら、その上位仕様であるOpenID Connect
  • JWTは「クレームを表現する手段」=トークンの形式——RFC 7519に明記されている
  • JWTは署名されるが暗号化されない。ペイロードは誰でも読める
  • APIキーだけ標準仕様がない。有効期限も権限分離もないことが多い
  • キーの管理はコードに書かない・リポジトリに含めない・定期的に再発行

認証まわりの用語が分かりにくいのは、層の違うものが同じ土俵で語られているからです。

「OAuthは認可」「JWTは形式」——この2つを押さえるだけで、ベンダーとの会話がかみ合うようになります。