OpenID Connectの始め方

この記事は[CrowdWorks Advent Calendar 2018](https://qiita.com/advent-calendar/2018/crowdworks)の13日目の記事です。

認証チームの[@sawadashota](https://qiita.com/sawadashota)です。
認証チームでは、クラウドワークスの周辺サービスがクラウドワークスのリソースにアクセスするための認証基盤をOpenID Connectの規格で開発中です。

認証チームにジョインしてまず思ったことは、**「OpenID Connectってなんぞ？何からキャッチアップすればいいんだ・・・？」**ということです。
今日は認証について知識ゼロだった私がOpenID Connectをどうやってキャッチアップしてきたかを書きたいと思います。

公開鍵暗号・電子署名
---

「暗号」と言われると、「私、文系なので・・・」と逃げたくなりますが、一旦アルゴリズムは置いといて大丈夫です。

OpenID Connectでも公開鍵暗号や電子署名の技術が使われており、**「なぜ公開鍵暗号・電子署名を使うのか」**「なにが嬉しいのか」は知っておいたほうがいいです。

おすすめとしては[結城 浩さんの暗号技術入門 第3版](http://amzn.asia/d/adHchja)ですが、
本を買わないとキャッチアップできないのも微妙なので、いい感じに説明してくれているリンクも貼っておきます。

[非エンジニアに捧げる公開鍵暗号方式 ｜ DevelopersIO](https://dev.classmethod.jp/security/publickey-cryptography-for-nonprogrammer/)

読むだけだと、なかなか理解が深まらなかったので、[GPG](https://www.gnupg.org/)で遊んでみるといいかもしれません。
[Keybase](https://keybase.io/)や[terraformのaws_iam_access_key](https://www.terraform.io/docs/providers/aws/r/iam_access_key.html)あたりが実践としてとっつきやすかったです。

OAuth2.0
---

OpenID ConnectはOAuth2.0をベースに作られているので、まずはOAuth2.0を理解するところから始めましょう。

OAuth2.0はRFCが策定した、3rdパーティに限定的なリソースアクセスを可能にする認可フレームワークです。これにより、**ユーザのID/Passwordが3rdパーティで入力されることなく、APIを提供することができます**。

いきなりRFC読み始めても意味がわからないので、わかりやすく説明してくれている記事から読み始めます。
[OAuth 2.0 全フローの図解と動画 - Qiita](https://qiita.com/TakahikoKawasaki/items/200951e5b5929f840a1f)

RFCのリンクも貼っておきますが、ここで時間をかけすぎるとモチベーションが保たないので、そこそこにして次に進むことをおすすめします。
（OpenID Connectのドキュメントを読み進めていると、きっとここに戻ってきます）

[RFC 6749 - The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749)
[The OAuth 2.0 Authorization Framework](https://openid-foundation-japan.github.io/rfc6749.ja.html)（日本語訳）

### PKCE

ネイティブアプリでは、認可コード横取り攻撃という攻撃方法があり、PKCE（Proof Key for Code Exchange）というプラスアルファでケアが必要です。

[RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients](https://tools.ietf.org/html/rfc7636)
[PKCE: 認可コード横取り攻撃対策のために OAuth サーバーとクライアントが実装すべきこと - Qiita](https://qiita.com/TakahikoKawasaki/items/00f333c72ed96c4da659)

この攻撃はCustom URL Schemeを使っている場合のみ成立するので、iOS9以上および、Android M以上で使える[Universal Links](https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html)や[App Links](https://developer.android.com/training/app-links/)を使えば対応する必要はなくなります。

JW\*シリーズ
---

OpenID Connectでは、Tokenを渡すためにJWTを使ったり、Tokenの電子署名を複合するための暗号鍵を受け渡しするためにJWKが使われていたりします。
事前に理解する、というよりは、OpenID Connectを読み進めながら、調べるスタイルでもいいかもしれません。

JWS（JSONで電子署名を表現するための標準仕様）
[RFC 7515 - JSON Web Signature (JWS)](https://tools.ietf.org/html/rfc7515)

JWE（JWSを暗号化するための標準仕様）
[RFC 7516 - JSON Web Encryption (JWE)](https://tools.ietf.org/html/rfc7516)

JWK（JSONで暗号鍵を表現するための標準仕様）
[RFC 7517 - JSON Web Key (JWK)](https://tools.ietf.org/html/rfc7517)
[JSON Web Key (JWK)](https://openid-foundation-japan.github.io/rfc7517.ja.html)（日本語訳）

JWA（JSONを暗号化するためのアルゴリズムを定めた標準仕様。JWEで使う。）
[RFC 7518 - JSON Web Algorithms (JWA)](https://tools.ietf.org/html/rfc7518)

JWT（JSONでTokenを表現するための標準仕様）
[RFC 7519 - JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519)

OpenID Connect
---

ついに本題のOpenID Connectです。
OpenID ConnectはOAuth2.0に認証レイヤーを追加したものです。もっと言うと、OAuth2.0で標準化されていないID連携の部分を標準化したものです。
・・・と言われても理解できないので、**まずは、以下の記事を3周くらいします**。

[OpenID Connectユースケース、OAuth 2.0の違い・共通点まとめ - Build Insider](https://www.buildinsider.net/enterprise/openid/connect)
[OpenID Connect 全フロー解説 - Qiita](https://qiita.com/TakahikoKawasaki/items/4ee9b55db9f7ef352b47)
[一番分かりやすい OpenID Connect の説明 - Qiita](https://qiita.com/TakahikoKawasaki/items/498ca08bbfcc341691fe)
[[前編] IDトークンが分かれば OpenID Connect が分かる - Qiita](https://qiita.com/TakahikoKawasaki/items/8f0e422c7edd2d220e06)

なんとなくわかった気になるので、自分でシーケンス図とかを書きはじめてみます。
わからないことがあれば公式のドキュメントを参考にしましょう。

[Final: OpenID Connect Core 1.0 incorporating errata set 1](https://openid.net/specs/openid-connect-core-1_0.html)

私の場合はこんな感じで書いていました。

![download.png](https://qiita-image-store.s3.amazonaws.com/0/83325/b3803fe7-ea46-9776-66b3-921ebe5cfdf5.png)

### 他社の事例を見てみる

実際に自社の都合に合わせてOpenID Connectを適応しようとすると、「あれ？これってどうすればいいんだ？」って思うことがあります。
そんなときは他社の事例を見てみると解決するかもしれません。

[OpenID Connect 対応してるWebサービス/製品のログイン認証関連のドキュメントリンク集 - Qiita](https://qiita.com/minamijoyo/items/62c90abd7785820705eb)

日本語に起因する悩みは[Yahoo! ID連携](https://developer.yahoo.co.jp/yconnect/)が参考になります。

### OpenID ConnectのOSSライブラリ実装を読んで見る

ドキュメントを読んでシーケンス図を書いてみたものの、「自分の理解って正しいんだっけ？」と不安になります。
公式認定のライブラリの実装を読んでみたり、実際に動かしながらログを眺めてみると、間違いに気づけるのでおすすめです。

[Certified OpenID Connect Implementations – OpenID](https://openid.net/developers/certified/)

私は[ory/hydra](https://github.com/ory/hydra)を読んでいますが、ライブラリ独自の概念が登場するので、OpenID Connectのドキュメントと行き来しながら、OpenID Connectの概念なのかを見分ける必要があります。

Next?
---

ここまで実践みると、なんとなくOpenID Connectの輪郭が見えてくるのではないでしょうか。
とはいえ、まだまだ読んでおきたい資料はたくさんあるので、ここまで実践したら次に読みたいものを雑にリストアップしておきます。

関連仕様を読み漁ってみる
[OAuth &amp; OpenID Connect 関連仕様まとめ - Qiita](https://qiita.com/TakahikoKawasaki/items/185d34814eb9f7ac7ef3)

各パラメータを追ってみる
[Final: OpenID Connect Core 1.0 incorporating errata set 1](https://openid.net/specs/openid-connect-core-1_0.html)

セキュリティーに関して考慮すべき事項を読み漁ってみる
[RFC 6819 - OAuth 2.0 Threat Model and Security Considerations](https://tools.ietf.org/html/rfc6819)
[OAuth 2.0 Threat Model and Security Considerations](https://openid-foundation-japan.github.io/rfc6819.ja.html)（日本語訳）

攻撃方法を読み漁ってみる
[OAuth / Connect における CSRF Attack の新パターン - OAuth.jp](https://oauth.jp/blog/2016/05/06/another-csrf-attack/)
[OAuth IdP Mix-Up Attack とは？ - OAuth.jp](https://oauth.jp/blog/2016/01/12/oauth-idp-mix-up-attack/)
[Implicit Flow では Covert Redirect で Token 漏れるね - OAuth.jp](https://oauth.jp/blog/2014/05/07/covert-redirect-in-implicit-flow/)
[HTTPS でも Full URL が漏れる？OAuth の code も漏れるんじゃね？？ - OAuth.jp](https://oauth.jp/blog/2016/07/27/https-full-url-leaks/)
[OpenID Connect Security Considerations](https://www.nds.ruhr-uni-bochum.de/media/ei/veroeffentlichungen/2017/01/13/OIDCSecurity_1.pdf)

OAuth2.0のImplcit Flowを認証に使っちゃいけない話
[単なる OAuth 2.0 を認証に使うと、車が通れるほどのどでかいセキュリティー・ホールができる – @_Nat Zone](https://www.sakimura.org/2012/02/1487/)

セキュリティインシデントの事例を読んで危機感を高める
[記事一覧 - piyolog](http://d.hatena.ne.jp/Kango/archive)

おわりに
---

私の場合、ここまでキャッチアップするのに1ヶ月くらいかかりました。

幸い、一緒にキャッチアップしてくれる仲間がいたので、自分の理解をぶつけることで、話しながら自分の理解を定着させたり、早めに間違いに気づけたりできたかなと思っています。

読み物が多く、進んでる感が出にくいので、シーケンス図を書いてみたり、ライブラリを動かしてみたりと手を動かす作業をはさんでいくと、自分の理解が進んでいることを確認できるのでおすすめです。