OpenID Connectの３つのフェーズ（仮）

# 前置き
OpenID Connectについて調べて図解してみたけど、確証がないので皆さんに見ていただきたい(´･ω･`)
特に「ログイン時」の章。本当にこれで合っているのだろうか･･･。

### 追記：2020/10/30
ritouさんにコメントいただきましたので、情報を加筆修正しました！
修正箇所につきましては修正履歴にてご確認ください。

あと、**分かりづらさの原因**について、フローの中で「ID連携(認証)」と「API連携(認可)」が混在している事だと感じたので、これを意識して修正してみました。

# ３つのフェーズ

OpenID Connectについて調べたところ、以下３つのフェーズに分けると理解しやすそうである事が分かりました。

- OPへのRP情報登録
- RPへの新規登録＆ログイン
- APIコール

以下にそれぞれの図解を示します。

なお、イメージしやすくするために**「Twitterアカウントを使って、Qiitaにログインする」**という例にしてます。


## OPへのRP情報登録
![20201016_OpenIDConnectについて調べてみた（識別時）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142821/e374bb69-668a-b714-de91-8f721cdb4acd.png)

[TakahikoKawasakiさんのQiita記事](https://qiita.com/TakahikoKawasaki/items/f2a0d25a4f05790b3baa#クライアントアプリケーションのメタ情報)を読むと以下の記載がありました。
> 認可リクエストに先立ち、**クライアントアプリケーションを事前に認可サーバーに登録しておく必要があります。**そのため、認可サーバの実装者は通常、クライアントアプリケーションの属性情報を格納するデータベーステーブルを定義することになります。
>...
>オープンソースの認可サーバーの実装によっては、**クライアントアプリケーションを動的に登録**するため、HTML フォームを提供したり (ForgeRock 社 の Open AM)、Web API を提供したり (MITRE 社の MITREid Connect) するものがあります。ただ、その場合でも、登録作業ができるのは認可サーバーの管理者に限られます。しかしながら、あるべき姿は、Twitter のアプリ管理コンソール同等のものを作り、そこに開発者をログインさせ、個々の開発者がそれぞれのクライアントアプリケーションを登録管理できる環境を提供することでしょう。

つまり、RP管理者はOP管理者に対して「僕のアプリをID連携できるように登録しておいてください」と事前に申告し、OP提供の管理コンソールからRPの属性情報を登録しておく必要がある、、、と認識しました。


## RPへの新規登録＆ログイン

ここが複雑なポイントなので、「ID連携(認証)」と「API連携(認可)」が分かるように表現してみます。
![20201016_OpenIDConnectについて調べてみた.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142821/a2b939e5-8b62-561f-a292-083bbf5e9a17.png)


まず、ここで出てくるエンドポイントは、以下の３つ。

- 認可エンドポイント
- トークンエンドポイント
- UserInfoエンドポイント

それぞれのエンドポイントが、以下の情報を返却。

- IDトークン
- 認可コード
- アクセストークン

どのエンドポイントが、どの情報を返却するのかについては、いくつか手法があるため、どれを採用するかは検討次第。
今回の例では「response_type=code id_token」で図解してみました。（認可EPが認可コード＆IDトークンを返してくれるのが分かりやすかったため）
その他については、[TakahikoKawasakiさんのQiita記事](https://qiita.com/TakahikoKawasaki/items/4ee9b55db9f7ef352b47)にまとめられているためこちらを参照ください。

**※謝罪１※** 「response_type=code id_token」をQiitaが採用しているか分からないですが、考えやすかったので一旦こうしてます。混乱させてしまったらすみません。
**※謝罪２※** 「response_type=code id_token」のフローについて調べてみたけどあまり有益な情報が見当たらなかったので、このフローには推測が含まれてます。混乱させてしまったらすみません。


### ID連携
まずID連携ですが、簡単に言うと**「認可エンドポイントからIDトークンを取得＆検証する」**です。
（IDトークン･･･ID連携(認証)のためのトークン）

例として、TwitterのID連携画面を提示します。
![認証.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142821/001585c9-690f-765a-bd3a-a4977d47bbbd.png)

**【新規登録時】**は、
この認証画面で認証されると、IDトークンが発行されます。
RPはIDトークンを検証し、自分宛のIDトークンである事を確認します。
IDトークンからユーザ識別子を取得し、セッション情報と紐づけて、新規登録完了です。

**【ログイン時】**は、
まだブラウザとセッションが確立してない場合は、Twitter側の認証を行い、ID連携済ユーザならログイン完了です。
既にブラウザとセッションが確立している場合は、そこからユーザを特定し、ID連携済ユーザならログイン完了です。

なお、IDトークンについてはRPサーバ側で検証する必要があります。（中間者攻撃によってトークンの書換などが発生していない事を確認）
検証方法については[SIOS TECH.LABさんの記事](https://tech-lab.sios.jp/archives/8651#i-2)辺りが理解しやすいかなと思います。


### API連携
次にAPI連携ですが、簡単に言うと**「認可エンドポイントから認可コードを取得し、認可コードをトークンエンドポイントに投げてアクセストークンを取得する」**です。
（認可コード･･･API連携(認可)のための一時的なコード）
（アクセストークン･･･API連携によりAPIリソースを取得するためのトークン）

例として、TwitterのAPI連携画面を提示します。
![認可.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142821/96dd8010-41ba-eac2-07d7-3e76d669cc7b.png)

**【新規登録時】**は、
この認可確認画面で承認されると、アクセストークンが発行されます。
あとは、必要に応じてUserInfoエンドポイントからTwitterのユーザ情報(アカウント名、アイコンなど)を取得します。

**【ログイン時】**は、
ログインユーザがTwitterと未認可の場合は、ログイン後の設定画面にTwitter連携ボタンあるため、ここから前述の【新規登録時】と同じフローに入ります。
ログインユーザがTwitterと認可済の場合は、何もせず、必要に応じてUserInfoエンドポイントからTwitterのユーザ情報を取得します。


### 補足
他の認証フローになるとIDトークンやアクセストークンなどの授受タイミングが変わりますが、「ID連携」と「API連携」に分解して考えてみると分かりやすくなると思います。

また、何度も言いますが、今回の例では「response_type=code id_token」で説明しましたがフローに確証はないです。曖昧でごめんなさい、、



## APIコール
![20201016_OpenIDConnectについて調べてみた（APIコール時）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142821/b327e98f-13bc-c1b1-79a5-44f0609984a6.png)

ここで何が言いたいかというと、**「アクセストークン取得したけど、これを使ってどうやってTwitterAPIを呼出すの？」**という事です。

TwitterとのAPI連携で得られる情報は、Qiitaの場合は以下に記載されています。
前章ではUserInfoしか取得してませんでしたが、実際はもっと取得できる情報はある事が分かります。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142821/d0c339cd-71bb-ce2d-cddd-3cf089a7897c.png)



[wadahiroさんのQiita記事](https://qiita.com/wadahiro/items/ad36c7932c6627149873)を見ると、以下の記載がありました。

> 次にアクセストークンですが、OAuth 2.0認証 と呼ばれてIDフェデレーションのユースケースでも使われてしまっていますが、本来的には**リソースサーバのAPIの保護目的**で使うことが想定されています。こちらも**代表的なフローのシーケンス図を書いてみました。**

つまり、「アクセストークンをAPIサーバにぶん投げるが、APIサーバはそのトークンが正しいのか分からないので、OPサーバに確認し、OKであればリソースを返却する」という認識です。
（wadahiroさんのシーケンス図の方が分かりやすいと思うので、そちらを見ていただければ。）


# 最後に
コメントを下さいましたritouさん。
OpenID Connect周辺の技術記事を投稿して下さっていみなさん。
ありがとうございます！

他にも本記事には曖昧な部分がいくつか存在するので、追加で何かあれば誰か教えてほしいです・・・。曖昧な記事で申し訳ないです、、、