OAuth 2.0は、「アプリに、あなたの代わりにAPIを使う権限(アクセストークン)を渡す」ための認可の仕組みです。OpenID Connect(OIDC)は、そのOAuth 2.0の上に、「あなたが誰か」を証明するIDトークンを加えた認証の仕組みです。

「Googleでログイン」のようなソーシャルログインは、OpenID Connectで実現されています。OAuth 2.0だけでログイン機能を作ると、なりすましを許す脆弱性になる場合があるため、この違いを理解しておくことは、Webやアプリの開発者にとって重要です。

この記事では、認可と認証の違いから、登場人物、認可コードフローとPKCEの流れ、3種類のトークンの違い、IDトークンの検証、SPAやスマホアプリでの推奨構成までを解説します。

一言でいうと

OAuth 2.0 OpenID Connect
目的 認可:APIを使う権限を渡す 認証:ユーザーが誰かを伝える
主に受け取るもの アクセストークン IDトークン(+アクセストークン)
トークンの宛先 APIのサーバー ログインさせたいアプリ自身
典型的な例 「このアプリにGoogleカレンダーの閲覧を許可する」 「Googleアカウントでログイン」
仕様 RFC 6749など OpenID Connect Core 1.0(OAuth 2.0の拡張)

認可と認証の違い

  • 認証(Authentication) — 「あなたは誰か」を確かめること
  • 認可(Authorization) — 「何をしてよいか」の権限を与えること

ホテルでたとえると、フロントで身分証を見せて本人確認をするのが認証、受け取ったカードキーで自分の部屋に入れるのが認可です。カードキーには「この部屋に入ってよい」という権限はありますが、持っている人が誰かは書かれていません。

OAuth 2.0のアクセストークンは、このカードキーに相当します。「このトークンを持っていれば、カレンダーを読んでよい」という権限を表しますが、トークンを持っている人が誰かは保証しません。

登場人物

OAuth 2.0での名前 OIDCでの名前 例
リソースオーナー エンドユーザー あなた
クライアント リライングパーティ(RP) あなたが使いたいアプリ
認可サーバー OpenIDプロバイダー(OP) Googleのログイン・同意画面
リソースサーバー ― Google Calendar API

認可コードフロー(+PKCE)の流れ

現在、Webアプリ・SPA・スマホアプリのいずれでも推奨されているのが、認可コードフローにPKCEを組み合わせた方式です。

  1. アプリが、ユーザーを認可サーバーのログイン画面へリダイレクトする
  2. ユーザーがログインし、アプリに渡す権限(スコープ)に同意する
  3. 認可サーバーが、アプリに認可コード(一時的な引換券)を付けてリダイレクトで戻す
  4. アプリが、サーバー間の通信で、認可コードをトークンと交換する
  5. アプリが、アクセストークンでAPIを呼び出す(OIDCならIDトークンでユーザーを識別する)
アプリ → 認可サーバー:
  GET /authorize?response_type=code
     &client_id=my-app
     &redirect_uri=https://app.example.com/callback
     &scope=openid profile email
     &state=ランダムな値
     &nonce=ランダムな値
     &code_challenge=(code_verifierのハッシュ)
     &code_challenge_method=S256

認可サーバー → アプリ(ログイン・同意の後):
  https://app.example.com/callback?code=認可コード&state=同じ値

アプリ → 認可サーバー(トークンの取得):
  POST /token
  grant_type=authorization_code&code=認可コード&code_verifier=元の値 ...

なぜ一度「認可コード」を経由するのか

リダイレクトのURLは、ブラウザの履歴やログに残る可能性があります。そこにアクセストークンそのものを載せず、一度しか使えない短命の引換券(認可コード)を載せ、トークンとの交換は別の通信で行うことで、漏えいのリスクを下げています。

PKCE(ピクシー)

PKCEは、認可コードが途中で盗まれても、盗んだ人がトークンに交換できないようにする仕組みです。

  1. アプリは、ランダムな秘密の値(code_verifier)を作り、そのハッシュ(code_challenge)だけを最初のリクエストで送る
  2. トークンと交換するときに、元の値(code_verifier)を送る
  3. 認可サーバーは、ハッシュが一致するかを確認する

認可コードだけを盗んでも、code_verifierを知らなければ交換できません。秘密の値を安全に保管できないSPAやスマホアプリでは必須で、サーバーを持つWebアプリでも使うことが推奨されています。

stateとnonce

パラメータ 防ぐもの 確認するタイミング
state 攻撃者が用意した認可レスポンスを、利用者に処理させる攻撃(CSRF) 認可サーバーから戻ってきたとき、送った値と一致するか
nonce(OIDC) IDトークンの使い回し(リプレイ攻撃) IDトークンの中の値が、送った値と一致するか

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「OAuth 2.0とOpenID Connectの違いをわかりやすく解説」

3種類のトークンの違い

トークン 用途 宛先 中身
アクセストークン APIを呼び出す リソースサーバー(API) 形式は決まっていない(ランダムな文字列やJWT)
IDトークン(OIDC) ユーザーが誰かを伝える クライアント(アプリ自身) JWT(署名付き)。ユーザーの識別子などを含む
リフレッシュトークン アクセストークンを再発行する 認可サーバー 形式は決まっていない

IDトークンの中身

IDトークンはJWT形式で、次のような情報(クレーム)を含みます。

{
  "iss": "https://accounts.google.com",
  "sub": "110169484474386276334",
  "aud": "my-app-client-id",
  "exp": 1790000000,
  "iat": 1789996400,
  "nonce": "送ったランダムな値",
  "email": "user@example.com",
  "name": "山田 太郎"
}
クレーム 意味
iss 発行者(どのOpenIDプロバイダーが発行したか)
sub ユーザーの識別子(発行者の中で一意、変わらない)
aud 宛先(どのアプリ向けに発行したか)
exp・iat 有効期限・発行日時
nonce リクエスト時に送った値

アプリのユーザーを識別するキーには、iss と sub の組み合わせを使います。メールアドレスは変更されることがあり、プロバイダーによっては確認されていない場合もあるため、ユーザーを特定するキーには向きません。

OAuth 2.0だけでログインを作ると危ない理由

「アクセストークンを受け取れたら、そのユーザーとしてログインさせる」という実装は、一見動きますが、なりすましを許す脆弱性になります。

  1. 攻撃者が、自分の作った別のアプリに、被害者をログインさせてアクセストークンを取得する
  2. 攻撃者は、そのアクセストークンをあなたのアプリに送る
  3. あなたのアプリは、そのトークンでプロフィールAPIを呼び、被害者のIDが返ってくる
  4. 攻撃者が、被害者としてあなたのアプリにログインできてしまう

アクセストークンには「どのアプリ向けに発行されたか」を確認する標準の方法がありません。カードキーを拾った人でも部屋に入れるのと同じです。

IDトークンには aud(宛先) が含まれ、署名されているため、「自分のアプリ向けに発行された、改ざんされていないトークンか」を確認できます。これが、ログインにはOpenID Connectを使うべき理由です。

IDトークンの検証

IDトークンを受け取ったら、次の点を検証します。

  1. 署名が、プロバイダーの公開鍵(JWKS)で正しく検証できるか
  2. iss が、期待するプロバイダーか
  3. aud に、自分のアプリのクライアントIDが含まれているか
  4. exp の有効期限が切れていないか
  5. nonce が、リクエスト時に送った値と一致するか

自分で実装せず、実績のあるライブラリを使うのが原則です。プロバイダーの設定(各エンドポイントのURLや公開鍵の場所)は、https://プロバイダー/.well-known/openid-configuration から自動で取得できます(ディスカバリー)。

その他のフロー(グラント)

フロー 用途 現在の扱い
認可コード+PKCE ユーザーがログインするすべてのアプリ 推奨
クライアントクレデンシャル ユーザーが関わらない、サーバー同士の通信 用途に合えば使用
デバイス認可 テレビやCLIなど、入力しにくい機器 用途に合えば使用
リフレッシュトークン アクセストークンの再発行 使用(ローテーションを推奨)
インプリシット かつてSPA向けに使われた 非推奨(トークンがURLに載るため)
リソースオーナーパスワード ユーザーのパスワードをアプリが直接受け取る 非推奨

OAuth 2.0のセキュリティのベストプラクティス(RFC 9700)や、策定中のOAuth 2.1では、インプリシットフローとパスワードフローを使わず、認可コード+PKCEを使う方向に整理されています。

SPA・スマホアプリでの推奨構成

アプリの種類 推奨構成
サーバーを持つWebアプリ 認可コード+PKCE。トークンはサーバー側で保管し、ブラウザにはセッションCookieだけを渡す
SPA(React・Vueなど) BFF(Backend for Frontend):小さなサーバーを用意してトークンを持たせ、ブラウザにはHttpOnlyのCookieだけを渡す構成が推奨される
スマホアプリ 認可コード+PKCE。ログイン画面はOSのブラウザ機能(アプリ内の独自WebViewではなく)で開く

SPAでトークンをブラウザのlocalStorageに保存すると、XSS(悪意あるスクリプトの注入)でトークンを盗まれる危険があります。トークンをJavaScriptから触れない場所に置くのが、BFFの考え方です。

実装で押さえるポイント

  • ライブラリや認証サービスを使う(Auth.js、Spring Security、各クラウドの認証サービスなど)。仕様の細部を自作しない
  • redirect_uri は完全一致で登録する。ワイルドカードの許可は、認可コードの横取りにつながる
  • スコープは必要最小限にする。ユーザーの同意画面で、要求する権限が少ないほど信頼されやすい
  • リフレッシュトークンは安全に保管し、ローテーション(使うたびに新しいものに交換)を有効にする
  • ログアウトは、自分のアプリのセッションと、プロバイダー側のセッションの両方を考慮する

よくある質問

Q. OAuth 2.0とOAuth 1.0は何が違いますか? A. OAuth 1.0はリクエストごとに署名を計算する複雑な方式でした。OAuth 2.0はHTTPSを前提に仕組みを簡素化し、用途別のフローを用意した、互換性のない別の仕様です。現在はOAuth 2.0が主流です。

Q. SAMLとOpenID Connectはどう違いますか? A. どちらもシングルサインオンに使われる認証の仕組みです。SAMLはXMLベースで、企業向けの業務システムで広く使われています。OpenID ConnectはJSONとJWTベースで、Webアプリやスマホアプリと相性がよく、新しく作るシステムではOIDCが選ばれることが多くなっています。

Q. IDトークンでAPIを呼び出してもいいですか? A. 使うべきではありません。IDトークンは、ログインするアプリ自身に向けて発行されたものです。APIの呼び出しには、APIに向けて発行されたアクセストークンを使います。

Q. 自社サービスのログインにも、OAuthやOIDCは必要ですか? A. 自社のサービスだけで完結するなら、通常のセッション認証で十分な場合も多くあります。複数のサービスで同じアカウントを使う(シングルサインオン)、外部のアプリに自社APIを使わせる、といった要件が出てきたときに導入を検討します。

まとめ

  • OAuth 2.0は認可(APIを使う権限を渡す)、OpenID Connectは認証(ユーザーが誰かを伝える)
  • OIDCは、OAuth 2.0にIDトークン(署名付きのJWT)を加えた仕組み
  • 推奨は認可コードフロー+PKCE。インプリシットとパスワードフローは非推奨
  • アクセストークンだけでログインを作るとなりすましの危険。ログインにはIDトークンを検証して使う
  • ユーザーの識別にはiss+subを使い、メールアドレスをキーにしない
  • SPAはBFF、スマホアプリはOSのブラウザ機能でログイン画面を開く。実装はライブラリに任せる

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「OAuth 2.0とOpenID Connectの違いをわかりやすく解説」

株式会社RJCでは、認証・認可のように「動く」だけでなく「守れる」ことが求められる技術を、仕組みから理解することを大切にしています。こうした知識を仲間と共有しながら、一緒に成長を楽しんでいます。

株式会社RJC ― SI事業・SES事業・AI駆動開発。未経験からエンジニアに育てるのが得意な会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?