- 技術 💻
OAuth 2.0とOpenID Connectの違いをわかりやすく解説
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を組み合わせた方式です。
- アプリが、ユーザーを認可サーバーのログイン画面へリダイレクトする
- ユーザーがログインし、アプリに渡す権限(スコープ)に同意する
- 認可サーバーが、アプリに認可コード(一時的な引換券)を付けてリダイレクトで戻す
- アプリが、サーバー間の通信で、認可コードをトークンと交換する
- アプリが、アクセストークンで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は、認可コードが途中で盗まれても、盗んだ人がトークンに交換できないようにする仕組みです。
- アプリは、ランダムな秘密の値(code_verifier)を作り、そのハッシュ(code_challenge)だけを最初のリクエストで送る
- トークンと交換するときに、元の値(code_verifier)を送る
- 認可サーバーは、ハッシュが一致するかを確認する
認可コードだけを盗んでも、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だけでログインを作ると危ない理由
「アクセストークンを受け取れたら、そのユーザーとしてログインさせる」という実装は、一見動きますが、なりすましを許す脆弱性になります。
- 攻撃者が、自分の作った別のアプリに、被害者をログインさせてアクセストークンを取得する
- 攻撃者は、そのアクセストークンをあなたのアプリに送る
- あなたのアプリは、そのトークンでプロフィールAPIを呼び、被害者のIDが返ってくる
- 攻撃者が、被害者としてあなたのアプリにログインできてしまう
アクセストークンには「どのアプリ向けに発行されたか」を確認する標準の方法がありません。カードキーを拾った人でも部屋に入れるのと同じです。
IDトークンには aud(宛先) が含まれ、署名されているため、「自分のアプリ向けに発行された、改ざんされていないトークンか」を確認できます。これが、ログインにはOpenID Connectを使うべき理由です。
IDトークンの検証
IDトークンを受け取ったら、次の点を検証します。
- 署名が、プロバイダーの公開鍵(JWKS)で正しく検証できるか
- iss が、期待するプロバイダーか
- aud に、自分のアプリのクライアントIDが含まれているか
- exp の有効期限が切れていないか
- 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期連続の黒字決算。