OAuth
JWT
auth
authentication
OriginalLIFULLDay 19

JWTを使って認証・認可サーバを構築した話 (OAuth2.0もあります)

こんにちは、LIFULLの somary です。
本記事は LIFULL Advent Calendar 19日目の記事になります。

今回は、社内研修の一貫で JWT を使った認証(認可)サーバを作ってみましたので、
その際に参考にしたものや、実装時に感じたことについてまとめてみようと思います。
中身的には大したことはやっていないのでコードは出てきませんし、ほとんどJWTの話をします。

JWTとは

JWT = JSON Web Token
読み方は「ジョット」
署名が可能でURLSafeなトークン
署名が出来るのでリクエストの検証(不正検知)が可能。
URLSafeなので気軽にリクエストに織り交ぜることが出来る。
調べた感じ、便利そうだったので今回はこれを使った。

基本的にはこのトークンをCookieに載せてやりとりする仕様。
(domain, path, secure, httponlyを添えて)

JWTについては、Qiitaなどで調べるとたくさん出てくるので、
詳しくは下記や公式サイトなどをどうぞ。
https://qiita.com/kaiinui/items/21ec7cc8a1130a1a103a
https://jwt.io/
※JWSやJWAやJWEなどには注意

JWTの脆弱性について

調べると、数年前に結構やばめなものがあったらしいので、少し調べてみた。
結論、ライブラリ選定(検証)を間違わなければ現段階だと特に問題はなさそう。

脆弱性のパターンは下記2点
1. Headerの"alg"を“none”に改ざん
経緯としては、JWTのバージョンアップで「alg」に「none」が追加された時期があるらしく(?)、
これを許容してしまうようなロジックのライブラリは、この値を変更してトークンを作りなおすだけで、
ペイロードを改ざんした状態で、検証を行わずに突破できてしまっていたらしい。
が、現状ではもちろん対策されていて、今回使用した下記ライブラリでは、
decode時の第三引数にて明示的に検証を行うかの有無を判定していたので、
これをtrueにしている間はalgをnoneにしても問題はなかった。
falseにしていると、algが一致していようがいまいが問答無用で突破できてしまう。
https://github.com/jwt/ruby-jwt/blob/master/lib/jwt.rb#L25
なぜこのような仕組みが実装されたのかはちょっと分からないし、詳しく調べてもいない。

2. Headerの"alg"を"RSA(公開鍵)"から"HMAC(共通鍵)"へと改ざん
こちらは言語やライブラリ依存による脆弱性。
公開鍵を文字列として扱ってしまうような状況下であると、
署名時(sign)に公開鍵をもとに「HMAC」を指定することで、
検証時(verify)に秘密鍵を共通鍵として誤認させるような脆弱性らしい。
今回使用している下記のライブラリでは、明示的にアルゴリズムを指定しているし、
そもそもrubyだと公開鍵の形式をテキストで扱っていないので、脆弱性は再現できなかった。
(そこまでライブラリをいじる元気がなかった)
https://github.com/jwt/ruby-jwt

OAuthが分からない

まず読み方が分からない。「オーオース」らしいので発音する時はちょっとめんどくさい。
そして仕様が分からない。概要図みたいなのはよく見かけるけど、RFCを読んだ訳でもないので実装レベルまでは見えていない。
かといって概念的に把握しきれていないもののRFCを読み解きたくもないという。この気持ち分かって欲しい。

そんな私でもすんなり理解できる記事があった。めちゃくちゃわかりやすい。
https://qiita.com/TakahikoKawasaki/items/200951e5b5929f840a1f

下記2件も同じ方が書かれている記事だが、
非常にわかりやすく、資料もまとまっているのですんなりと理解できた。
https://qiita.com/TakahikoKawasaki/items/185d34814eb9f7ac7ef3
https://qiita.com/TakahikoKawasaki/items/f2a0d25a4f05790b3baa

ここまで仕様を把握することが出来れば、RFCもすんなりと理解することが出来た。

こちら(OAuth)にも、アクセストークンにJWTを採用している。

まとめ

JWT最強説
とりあえず、トークンにはJWTを使えばいいという盲信状態に入ってきてしまっているので、
考慮しきれていない点やデメリットがある場合は助言をいただきたい。