OpenID Connect

# 概要
OpenID Connectについて調べたので、まとめてみようと思います。

# OpenID Connectって必要？
[仕様はこちら](http://openid-foundation-japan.github.io/openid-connect-core-1_0.ja.html)。


# OAuth認証とは違うのか
> OpenID Connect 1.0 は, OAuth 2.0 [RFC6749] プロトコルの上にシンプルなアイデンティティレイヤーを付与したものである. 

冒頭にこんなことが書いてありますが、OAuth2.0認証ってなかったっけ？と思いました。Twitter認証とかFacebook認証とか、よく記事を見かけていたような。それに何か追加する必要あるんだっけ？と当初疑問に思いました。

実は**OAuth認証には脆弱性がある**ようです。そもそも、認証のための仕組みではなく、認可のための仕組みらしいですね。OAuth2.0で発行されたTokenからは、一体どのサービスに対して発行されたものであるか、検証するすべがないためです。今やいろんなところで紹介されています。[図解：OAuth 2.0に潜む「5つの脆弱性」と解決法](https://www.atmarkit.co.jp/ait/articles/1710/24/news011.html)。

ただ、調べたところ、TwitterやFacebookなどでは独自にTokenを検証するエンドポイントを設けていました。なので、OAuth認証を行なっているから危険、とは一概に言えなさそうです。OSSを利用してOAuth認証を利用する際は、そういった検証を行なっているかどうかよく確認する必要がありそうですね。

# OpenID Connectを使ってどう認証するのか
## トークン
OpenID ConnectではID TokenとAccess Tokenという２種類のトークンが発行されます。認証をID Token, 認可をAccess Tokenで行うみたいです。このうちID Tokenは[JWT](https://jwt.io/introduction/)という形式です。Access Tokenの形式は実装に寄って異なり、[識別型、内包型、ハイブリッド型](https://qiita.com/TakahikoKawasaki/items/970548727761f9e02bcd)と複数パターンがある様です。

### ID Token
認証されたユーザであることを表すトークンです。JWT(JSON Web Token)という形式のものです。
大雑把にいうと、ユーザ情報や発行先のサービス情報などが含まれていて、それに署名がつけられたトークンです。IDプロバイダーが公開している鍵と署名を使って改ざんされていないか確認することができます。
発行先のサービスの情報も含まれているので、OAuth認証で問題になったToken置き換え攻撃も防げます。

### Access Token
IDプロバイダ側のサービスにアクセスするためのトークンのようです。Google認証したら、そのAccess Tokenを使ってGoogleDriveにアクセスする、とかそういう風に使うんだと思います。

## 認証フロー

細かいフローは[解説記事](https://qiita.com/TakahikoKawasaki/items/4ee9b55db9f7ef352b47)やIDプロバイダーのドキュメント([例えばGoogle](https://developers.google.com/identity/protocols/OpenIDConnect))で詳しく説明されていますのでここでは概要を。

認証フローには大きく分けて3種類（Authorization Code Flow, Implicit Flow, Hybrid Flow)があるみたいです。認証のエンドポイントにはAuthorization EndpointとToken Endpointがあり（他にもありますが）、AuthorizationEndpointで認証後、必要に応じてToken EndpointからID Token, Access Tokenなどを取得することになります（フローによってはAuthorization Endpointから直接Tokenがもらえます）

### Authorization Code Flow
全てのTokenがAuthorization Endpointから返却されたAuthorization Codeと引き換えにToken Endpoint(IDプロバイダーが用意しているエンドポイント)から返されます。

Autorization Codeをサーバ側に送ってからTokenと交換できるので、クライアント側にTokenを残したくない場合に使うと良さそうですね。
ただしRefresh Tokenをサーバ側から出さない場合、クライアント側でTokenを再発行することはできないので、Cookieを利用するなど別途認証状態を判断する仕組みが必要かと思います。

### Implicit Flow
全てのTokenがAuthorization Endpointから返されます。
サーバ側ではクライアントが認証されているかどうかをID Tokenを検証することで判断する様にすれば、ステートレスにサーバサイドを作れそうです。
ただ、クライアントがわにToken類を全て置いておくことは漏洩のリスクにも繋がります。
Google OpenIDConnectのページでも以下の様に記載されています。

> The implicit flow is significantly more complicated because of security risks in handling and using tokens on the client side. If you need to implement an implicit flow, we highly recommend using Google Sign-In.

### Hybrid Flow
名前の通りImplicitとAutorization Codeの合わせ技の様なパターンですね。
Googleで認証して、GoogleDriveにアクセスできるようにしたいけど、クライアントから直接アクセスされたり、AccessTokenを残しておくのは嫌だな。。。とかそういう時に使うのではないかと思います。

# Open IDに対応したIDプロバイダー

* [Google](https://developers.google.com/identity/protocols/OpenIDConnect)
* [livedoor](http://auth.livedoor.com/openid/)
* [yahoo](https://developer.yahoo.co.jp/yconnect/v2/)

意外とFacebookやtwitterはOpen IDではありませんでした。OAuthにトークン検証用のエンドポイントを追加して認証にも使えるようにしている感じです。[openidのサイトに一覧がありました](https://openid.net/certification/)。

# Open IDに対応したBaaS(OpenID Providerを作れる)

> OpenID Connect は OAuth 2.0 認可プロセスを拡張し, 認証目的で利用できるようにする. 本拡張を利用する場合, Client は openid scope を指定して Authorization Request を送信する. 認証結果は ID Token (Section 2 参照) と呼ばれる JSON Web Token (JWT) [JWT] として返される. OpenID Connect をサポートする OAuth 2.0 Authentication Server は, OpenID Provider (OP) とも呼ばれる. OpenID Connect を利用する OAuth 2.0 Client は Relying Party (RP) とも呼ばれる.

ここでいうOpenID Providerになれるという意味で

* Cognito
* Auth0
* Authlete


など。
これらのBaasを使えば、OAuthで外部にAPIを公開することも、OpenIDを提供することもできそうですね。
実際[openidのサイト](https://openid.net/certification/)のCertified OpenID Providersにはこれらを利用したものも記載されています。

Relying Partyを追加していく仕組み（申請フォームなどなど）はCognitoには付随していませんでした。
なんとなく、これらを使ったとしても、Relying Partyを追加していく仕組み（申請する窓口など）まで作り込まないと、「オープンに利用できるID」、と言う感じはしないです。他のサイトでも利用してもらえるIDとして使ってもらいたい、と言うことであればそういった仕組みは自前で作り込んでいくことも必要そうです。