IDENTITY & AUTHENTICATION
OpenIDとは?「別のアカウントでログイン」の仕組みとOpenID Connectを図解
新しいアプリに登録するとき、パスワードを作る代わりに「外部アカウントでログイン」を選ぶことがあります。アプリは、その外部サービスのパスワードを知らないのに、どうしてあなたをログインさせられるのでしょうか。その背景にある認証を別のサービスに任せる仕組みを、OpenIDの歴史と現在のOpenID Connect(OIDC)から理解します。
まずは身近な例:写真整理アプリへの初回ログイン
写真整理アプリ「フォトノート」を使い始める場面を想像してください。独自のID・パスワードを作らず、普段使っているアカウントのログインボタンを押します。すると外部のログイン画面に移動し、本人確認が終わるとフォトノートへ戻り、利用を開始できます。
① フォトノート
「本人確認をお願いします」と外部ログインサービスへ案内
② ログイン提供元
パスキーやパスワード等で本人を確認
③ フォトノート
検証できた認証結果からユーザーを特定しログイン
写真整理アプリへ外部アカウントのパスワードを渡す必要はありません。ただし、提供元を装う偽画面や、不適切な連携アプリには注意が必要です。
OpenIDとOpenID Connectは、同じものではない
従来のOpenID(OpenID Authentication 2.0)は、URLやXRIなどの識別子を用いて、異なるWebサイト間で認証を連携する仕組みです。たとえば自分のOpenID識別子をサイトに入力し、その識別子に対応するプロバイダーで本人確認を行う設計でした。
一方、今日「外部アカウントでログイン」を実装する場面で重要なのがOpenID Connect(OIDC)です。OIDCはOAuth 2.0を基盤にした認証のための仕様で、認証結果をIDトークンとしてアプリに伝えます。名前は似ていますが、従来のOpenIDとOIDCはプロトコルの構造が異なります。
| 観点 | 従来のOpenID | OpenID Connect |
|---|---|---|
| 基盤 | 独自の認証プロトコル | OAuth 2.0の上に認証を追加 |
| 利用者の識別 | URL・XRIなどの識別子 | 発行者(iss)と利用者ID(sub) |
| 認証結果 | OpenIDの認証応答 | IDトークン(通常JWT形式) |
| 主な位置づけ | 歴史的なWeb認証連携 | 現代のWeb・モバイルのログイン連携 |
OIDCの登場人物は3つ
利用者(End User)はあなた自身。RP / Clientはフォトノートのようなログイン先アプリ。OP(OpenID Provider)は本人確認を引き受け、認証結果を発行するサービスです。ログイン先アプリはOPの認証結果を正しく検証して初めて、その利用者にアカウントを紐付けられます。
認可コードフローを6段階で追う
- アプリがOPへの認証リクエストを準備。
scope=openid、state、PKCE用のcode_challengeなどを送ります。 - ブラウザがOPのログイン画面へ移動します。ユーザーはOP上で本人確認します。
- OPがアプリの登録済みリダイレクト先へブラウザを戻し、短命の認可コードと
stateを返します。 - アプリは戻ってきた
stateを照合し、認可コードをトークンエンドポイントで交換します。PKCEではcode_verifierも提示します。 - OPがIDトークンなどを返します。アプリは署名、発行者、対象者、有効期限、必要に応じて
nonceなどを検証します。 - アプリは検証済みの
issとsubを使って利用者を識別し、自サービスのログインセッションを作ります。
認可コードは「ログイン成功の証明そのもの」ではなく、トークンと交換するための短命な値です。アプリはコードが戻っただけでログインを成立させてはいけません。
INTERACTIVE LAB
外部アカウントでログインしてみよう
フォトノートへのログインを6段階で追い、検証のどこかが失敗した場合を試せます。実際の外部サービスへの接続やトークン発行は行いません。
STEP 1 / 6
アプリでログインを開始
フォトノートがOIDCの認証リクエストを準備します。scope=openid / response_type=code / state / PKCEを設定します。
トークン検証シミュレーター
スイッチをオフにすると、どのチェックが失敗し、ログインが拒否されるかを確認できます。ここでの結果は教育用のモデルです。
認証結果の検証とセッション生成へ進めます。実装ではライブラリで実データの検証が必要です。
どのトークンが何をする?
{
"iss": "https://login.example",
"sub": "user-1234",
"aud": "photo-note-app",
"exp": "未来の時刻",
"nonce": "要求時の値"
}本人を特定するための認証結果。表示は模式例で、実際は署名されたJWTなどとして渡されます。
IDトークンとアクセストークンを混同しない
IDトークン
「OPが誰を認証したか」をRPに伝える。iss、sub、aud、expなどを確認する。
アクセストークン
APIなどのリソースへのアクセスを許可する目的で使う。RPのログイン確認として代用しない。
たとえば「写真整理アプリにログインできた」と「そのアプリがクラウド上の写真を取得する許可を持つ」は別の話です。OIDCは認証、OAuth 2.0は主にアクセス権限の委譲を扱う、と役割を分けて理解すると混乱しません。
実装時に確認したいセキュリティ対策
- stateの照合:認証開始時の要求とコールバックを結び付け、ログインCSRFなどを防ぐ。
- PKCE:認可コードを横取りされても第三者がトークン交換しにくくする。現在の実装では認可コードフローと合わせて採用する。
- IDトークンの検証:署名、
iss、aud、expを検証。nonceを送った場合は戻り値も照合する。 - ユーザー識別:メールアドレスだけで外部アカウントを結び付けない。発行者と
subの組を基準に管理する。 - リダイレクトURI:事前登録した値に厳密に制限し、HTTPS通信と安全なセッションCookieを利用する。
OIDCを使うだけで安全性が自動的に保証されるわけではありません。正しいプロバイダーの設定、ライブラリによる検証、アプリ側のセッション管理まで含めた設計が必要です。