OpenID Connect入門（Authorization Codeフローを画面遷移と共に説明します）

# はじめに
Webサービスで「Googleでログイン」や「Yahoo! IDでログイン」といったボタンをよく見かけます。
このような、SNSなどの外部アカウントと連携してログインできる仕組みを「ID連携」や「ソーシャルログイン」といいます。

本記事は、ID連携を支える技術の代表格である「OpenID Connect」（OIDC）の入門記事です。
ID連携技術の周辺では普段あまり目にしない用語が多く使われています。また、冗長な文章が多いこともあり、なんとなく苦手意識を持っている方も多くいるのかなと思います。
正直、私もその一人でしたが、細かいコトを抜きにして流れをおってみたら意外と理解できるようになった気がします。

本記事はそんな元初心者の私が、はじめの一歩として理解すべき用語とフローを画面遷移と共に説明したものです。
「OIDCが（なんとなく）わかった。基本のフローも想像できる。用語も聞いたことがある。」と、皆さんに思ってもらえたら嬉しいです。

## そもそも、なんで「ID連携」するの？
ID連携とは「Google」や「Yahoo!」といったサービスで利用しているユーザーIDで、他のWebサービスを利用する仕組みのことです。
例えば、普段皆さんが利用している「Google」のアカウントを使用して「GitLab」でリポジトリを作成したり、「LINE」のアカウントを使用して「ふるさとチョイス」でふるさと納税の手続きをすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/3674df98-e298-5225-8b5b-bce359e99a46.png)

ここで、「Google」や「LINE」など、**ユーザーIDを管理している側のサービスを「IdP」**（Identity Providor）、「GitLab」や「ふるさとチョイス」など**ユーザー情報を使う側のアプリを「RP」**（Relying Party）と呼びます。

### ID連携のメリット
ID連携のメリットは、大きく「ユーザー観点」と「アプリ（RP）観点」にわけることができます。

#### ユーザー観点のメリット

- パスワード管理のしやすさ
  - ユーザーは「IdP」にログインすることで「RP」のサービスを利用できますので、覚えておくパスワードはIdPのものだけでOKです。利用するサービス毎にパスワードを管理する必要はありません。詳しくは以降で説明します。
- ユーザー登録の省略または簡略化
  - 「IdP」のユーザー情報が「RP」側に連携されますので、「RP」でユーザー情報を入力する必要が無かったり、予めプリセットされているので少ない項目の入力ですむ場合があります。省略または簡略化の程度は、連携されるユーザー情報や「RP」によります。

#### アプリ（RP）観点のメリット

- ユーザー認証関連コスト大幅低減
  - ID連携を使用する場合、ユーザーのパスワード情報の管理や認証処理は「IdP」側で実施しますので、アプリ側でのパスワード管理や認証処理は不要になります。
- 会員登録途中の離脱防止
  - ユーザーは従来のユーザー登録作業よりも少ない手順でサービスの利用を開始できます。ユーザー情報登録作業の手間や心理的な抵抗が少ないため、登録作業に起因するユーザー離脱を防止できます。


## で、OIDCって何だっけ？
OIDCは「ID連携」で使用する「ID連携プロトコル」のひとつで、デファクト・スタンダードと言えます。

2014年2月発行（同11月 更新）と比較的新しめのプロトコルで、それまで広く使われていた認可プロトコルの「OAuth2.0」に、既存ID連携仕様（OpenID、SAML、Facebook Connect等）を踏まえたID認証機能を組み合わせたものです。
以下は、[公式（https://openid.net/connect/）](https://openid.net/connect/)の説明です。

> 「OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol.」

（OpenID Connect 1.0 は, OAuth 2.0 プロトコルの上にシンプルなアイデンティティレイヤーを付与したものです）


# OIDCでID連携してみる
さっそくOIDCを使用してID連携したときの画面を確認してみましょう。
今回は「LINE」のユーザーIDを使用して「ふるさとチョイス」でID連携してみたいと思います。
先ほどの「IdP」と「RP」を今回のサービスに対応させると、ユーザーIDを管理している「LINE」が「IdP」、ユーザーIDを使用する「ふるさとチョイス」が「RP」になります。

## ふるさとチョイスの会員登録画面でID連携スタート
[ふるさとチョイスの会員登録画面](https://www.furusato-tax.jp/login?header#regist)にアクセスし、「他サービスIDと連携して会員登録」の「LINE」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/9600d0bf-668a-5932-7082-fb7631f8ec9a.png)

## LINE のログイン画面
LINE のログイン画面にリダイレクトされます。LINE のユーザー/パスワードを入力し「ログイン」ボタンをクリックます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/df9088ee-1da9-99d3-ab21-97ddce715145.png)

## LINEの認可画面
LINE の認可画面に遷移します。ふるさとチョイスが LINE のユーザー情報へのアクセスを許可するか、の確認画面です。
「許可する」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/aed1a6ca-8d15-fb74-e956-20e9ee051be9.png)

## ふるさとチョイスのログイン画面
元のサイト（ふるさとチョイス）のログイン画面にリダイレクトされます。先ほどID連携した「LINE」ボタンをクリックします。

（※ ログイン画面にリダイレクトされることは「ふるさとチョイス」の仕様です。OIDCのフローとしては必要ありません。IdP（今回は「LINE」）の認可画面の遷移先は、RP（同「ふるさとチョイス」）の会員情報登録画面やRPのサービス画面が多いです。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/51b58765-c70a-d1ab-12d3-071f5873710f.png)

## LINEのログイン画面
LINEのログイン画面にリダイレクトされます。「ログイン」ボタンをクリックします。

（※ 上記「ふるさとチョイスのログイン画面」の「※」に書きましたが、会員登録時にIdP（「LINE」）のログインが2回必要というのはPR（「ふるさとチョイス」）の仕様です。OIDCのフローとしては必要ありません。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/0ab46a43-8e75-8bd6-9e26-f3aa8650c0c9.png)

## ふるさとチョイスの会員情報登録画面
ふるさとチョイスの会員情報登録画面にリダイレクトで戻ってきます。（「LINEの認可画面」で連携した情報がプリセットされます。）
必要な情報を入力し「会員登録」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/7666bcae-4d18-ce12-ce08-dd3e279192b4.png)

## ふるさとチョイスのサービス画面
以上で、ふるさとチョイスのサービスを利用できるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/2fd01e80-393b-0d9c-d0f2-72d3359ba0df.png)


## ID連携の画面遷移のふりかえり
下の図はここまでの画面遷移を整理したものです。
RP（ふるさとチョイス）の画面で「ID連携」や「ログイン」するとIdP（LINE）の画面にリダイレクトされ、そこでパスワード等を入力するとRPの画面にリダイレクトで戻る、といった画面遷移を経てRPのサービス利用に至りました。

（※ 今回はLINEへのログインが2回発生しましたが、それはふるさとチョイスの仕様です。OIDCのフローとしてはIdPに2回ログインする必要はありません。）

ここでのポイントは「パスワード入力はIdPで行ったこと」と「リダイレクトで画面遷移したこと」になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/bcdfa279-84b1-8524-4477-31fa5426f9d0.png)

# Authorization Code フロー
さて、次はOIDCのフローを確認しましょう。
OIDCには次の3つのフローが定義されています。

- Authorization Code フロー：サーバーサイドで認証
- Implicit フロー：クライアントサイドで認証
- Hybrid フロー：サーバーサイド・クライアントサイドの両方で認証

今回は、この中で最も基本となる「Authorization Code フロー」（「認可コードフロー」とも呼ばれます。）を説明させていただきます。
その名の通り「認可コード」を使用して「トークン」（IDトークンやアクセストークン）を取得するフローです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/15cb2ffe-09cd-3ad7-a22f-b08f1561ec7d.png)

ちょっと複雑に見えますが、先ほどの画面をマッピングさせながら少しずつ解説していきたいと思います。

## OIDC スタート
ユーザーが利用したいアプリ（前述の例では「ふるさとチョイス」にあたります。）の画面で、ID連携を選択します。
このアプリを OIDC では「RP」（Relying Party）と呼ぶのでしたね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/c8a45c66-1a85-f0a4-efe4-99cc1d9a0110.png)


## 認可リクエスト（リダイレクト）
IDプロバイダー（同じく「LINE」にあたります。）のログイン画面にリダイレクトされます。
こちらは「IdP」と呼ぶのでしたね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/1b576a2d-0d12-bf74-c254-84445e822521.png)

## ログイン／連携同意
IdPの画面で、ユーザー/パスワード（必要であれば、MFA等も）入力し、データ連携に同意します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/da1345e7-f669-7556-773a-e4b2526b25cd.png)


## 認可コード（リダイレクト）
IdP → RPにリダイレクトされます。このとき「認可コード」が渡されます。

ここは重要ですのでちょっと細かく説明させていただけたらと思います。ですが、難しいなーと思ったら次の「トークンリクエスト」に進んでくださってOKです。

/* 細かい説明：ここから
ここで「何で認可コードが返ってくるんだろう？ 最終的にほしいのはトークンなのになー。」と思った方、さすがでございます。
Idpからリダイレクトで戻ってくるということは、「IdP → ユーザー → RP」とユーザーを経由して戻ってくるということです。
もう少し具体的に言うと、IdPからユーザーへのレスポンスに遷移先としてRPのURLが設定されていて、認可コードはそのリクエストパラメーターとして設定されています。
ユーザー側を経由する方式のため、何らかの不具合やセキュリティ的な攻撃により、漏洩するリスクがあります。

認可コードでなくトークンを設定して漏洩した場合を考えてみます。
実はトークンが漏洩するとかなり大変なのです。ざっくり言うと「トークンが漏洩する＝そのユーザーとしてIdPの操作が可能となる」です。まあ一発アウトです。
そのため認可コードを設定しています。

じゃあ、認可コードなら漏洩してもいいのか？となりますが、実は「認可リクエスト」と「トークンリクエスト」で「[PKCE](https://tools.ietf.org/html/rfc7636)」という横取り対策をしています。入門編の範疇を超えるのでここでは説明を割愛させてください。
細かい説明：ここまで */

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/894af90e-1da7-104d-ba48-02a3532226c3.png)

## トークンリクエスト
RPは受け取った「認可コード」をパラメータとしてトークンをリクエストします。
IdPはレスポンスとして「アクセストークン」、「リフレッシュトークン」、「IDトークン」を返します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/00b179a7-f35a-7ce5-3d52-4e117dadbc83.png)

## IDトークン検証
受け取ったIDトークンの発行元IdPが正しいこと、RP向けに発行されたものであること、改ざんされていないこと、有効期限等を検証します。要するに「このIDトークンは正しいのか？」を検証します。
もしNGの場合、正しいユーザーでないことになるので大変なことです。

/* 細かい説明（その2）：ここから
ここで、認可コードフローの場合はTLSで保護されたチャネル経由で直接IDトークンが発行されるため、TLSサーバー証明書の検証さえ行っていればIDトークンの改ざんリスクは無視できます。そのためIDトークン自体の署名検証はOPTIONAL（任意）とされているようです。
細かい説明（その2）：ここまで */

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/39dae457-badb-12a9-be14-83f9db32d9f7.png)

## ユーザー情報取得
RPは、IdPからユーザー情報を取得します。
取得したユーザー情報は、ユーザー情報画面にプリセットされたりします。
（ここで前述のふるさとチョイスの場合、会員登録後にログインして会員情報登録画面に入力する必要がありましたが、ここでは説明上 2回目のログインを省略しました。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/9252ab19-88de-f37d-e7c2-602227a0fc6c.png)

## サービス開始
RPのサービスを利用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321204/fcd42a3a-2079-f1fb-5589-9b33efcf7493.png)

# 用語の整理
ID連携関連で頻出する用語です。
同じ概念に対しても、プロトコルによって異なる名前となる場合があります。よく使われる略語を「略語」列に記載しました。

| 用語 | 説明 | 略語 |
|:--|:--|:--|
| 認証  |  Authentication。アクセスしている相手の正当性をチェックして正規の利用者であるかを確認する。パスワード、生体情報、Authenticator、クライアント証明書などで確認する。 | AuthN  |
| 認可  | Authorization。利用者が、RPにサービスの利用やリソースへのアクセスなどの権限を与えること。金庫の合鍵をRPに渡すイメージ。  | AuthZ  |
| ユーザー  | アプリを利用する人。OIDCでは「End-User」、OAuthでは「Resource Owner」という。  |   |
| アプリ  | ユーザーが利用するサービス。OIDCでは「RP（Relying Party）」、OAuthでは「OAuth Client」という。（SAMLでは「SP（Service Providor）」という）  |  RP, SP |
| IDプロバイダー  | ユーザーIDを管理・検証するサービス。OIDCでは「IdP（Identity Providor）」や「OP（OpenID Providor）」、OAuthでは「OAuth Server」という。  |  IdP, OP |
| リソースサーバー  | リソースまたはデータが存在する場所です。アクセストークンを持つアプリからの認証済みリクエストを処理します。  |   |
| 認可コード  | ユーザーが、リソースサーバーへのアクセスを認可することで発行されます。アプリはユーザーの認可コードをIdPに送信し、対応するトークンを取得します。  |   |
| IDトークン  |  IdPがRPに発行する、End-Userを認証したかを示す改ざん検知用の署名付きトークン。JWTフォーマットでエンコードされる。 |   |
| アクセストークン  | IdPのリソースサーバーにアクセスするためのトークン。  |   |
| リフレッシュトークン  | アクセストークンを更新するために使用するトークン。  |   |
| JWT  | JSON Web Token。属性情報をJSONデータ構造で表現した、トークンの仕様。ヘッダー、ペイロード、シグネチャで構成される。署名、暗号化が可能でURLSafeであることが特徴。  |   |

# おわりに
非常に簡単でしたが OIDC について説明させていただきました。

ID連携のメリットから、OIDCがID連携プロトコルのデファクト・スタンダードであること。認可コードフローでは、Webアプリ（RP）からIdPにリダイレクトされてログインすること。ログイン後「認可コード」付きでWebアプリに戻ってきて、認可コードをトークンと交換すること。
「なんとなくわかった」になっていただけましたでしょうか。

今回は細かいコトはだいぶ省略させていただきましたので「かえって、細かいところが気になる。」という方もいらっしゃるかもしれません。
付録に参考サイトをあげさせていただきました。皆さんの気になるポイントの解消にお役立てください。

本記事が、皆さまのOIDCの理解のお役に立てたら幸いです。

## 付録：参考サイト
本記事の作成にあたり参考にさせていただいた記事や、より詳細な解説サイトです。

- [Yahoo! ID連携 v2](https://developer.yahoo.co.jp/yconnect/v2/)
  - ID連携するうえでの情報がよくまとまっています。具体的なリクエストやレスポンス例もあり、かなり参考になります。
- [OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜](https://www.slideshare.net/kura_lab/openid-connect-id)
  - OAuth2.0との違いや、各リクエストの具体的なパラメータなどをフローに沿って確認できます。
- [OpenID Foundation Japan](https://www.openid.or.jp/document/)
  - OIDCの日本語訳された仕様を確認できます。
- [OAuth 2.0 Playground](https://www.oauth.com/playground/)
  - okta社が提供している、OAuth2.0やOIDCのチュートリアル。実際に送信するパラメータや、受信したトークンを確認しながら進めることができます。
  - （[クラメソさんの紹介記事「OAuth 2.0 PlaygroundでOAuth 2.0のクライアントの気持ちになろう」を先に読むとイメージがわきます](https://dev.classmethod.jp/articles/oauth-2-playground/)）
- [JWT Debugger](https://jwt.io/)
  - JWTを貼り付けてデコードすることができます。
- [SAML / OpenID Connect / OAuth / SCIM 技術解説 ](https://www.slideshare.net/matake/idit-2014)
  - OIDCと他主要ID連携プロトコルの解説です。
- [IDトークンが分かれば OpenID Connect が分かる](https://qiita.com/TakahikoKawasaki/items/8f0e422c7edd2d220e06)
  - IDトークンについて具体例を交えて詳細に解説してる記事です。
- [PKCE: 認可コード横取り攻撃対策のために OAuth サーバーとクライアントが実装すべきこと](https://qiita.com/TakahikoKawasaki/items/00f333c72ed96c4da659)
  - 認可コード横取り対策である「PKCE」解説記事です。
- [OAuth 2.0＆OpenID Connectユースケースと関連仕様まとめ](https://www.buildinsider.net/enterprise/openid/oauth20)
  - OpenID Foundation Japan事務局長によるOAuth2.0とOIDCの解説記事です。