タイトルの通りなのですが、 以下の構成で認証する仕組みを試してみたら、思ったよりハマったのでその内容をメモしておきます。
今回試した構成
- フロント: Nuxt.js ライブラリは Auth Moduleを使用バックエンド:
- バックエンド: Ruby on Rails
- 認証および IdP: Auth0
フロントエンドNuxtからでAuth0のauthorizeを呼び出し認証して、認証時にJWTを取得してそれをバックエンドに渡して認証する、ということをやろうとしました。 認証のサービスは Firebase Authや AWS Cognito など他にもありますが、Auth0が一番てっとり早くできそうなのかなと思い、こちらを採用したのですが、以下の点でハマりました。
JWTがAuth0から帰ってこない
フロントからの認証(authorize)まではすんなりいって、どうも返ってくるJWTらしき文字列が短い.. これはJWTでなくOpaque strings
と呼ばれているもので、JWTでは無いようです。調べてみると、どうやらJWTを得るためには、audience
を指定しないとかえってこないとのことでした。
OpenID Connectの仕様をあまり理解できていませんが、audience
ってなんぞや、何のために設定しないと行けないのかももやっとしたまま、とりあえず設定方法を調べました。
Auth-moduleで audienceの指定ができない
Auth Module の以下の issue を見ると、どうやら Auth Module 側で audience を指定することはできない様子。
じゃあどうするのかというと、 Auth0のconfig で default audienceを指定できるので、 それを指定すれば良いとのこと。
というわけで以下の設定画面で default audienceの設定を実施しました。
上記の設定を行なった後に認証を行なったら、 Opaque stringsでなく JWTを得ることができました。
RubyのJWT認証 ライブラリ knockが現在のAuth0に対応していない
RubyでJWTを扱うライブラリでknock というgemがあったので、このgemで バックエンド側のJWTの検証を試しました。
auth0 + knockで認証を行なった例は検索でいくつか引っかかるも、どうやらAuth0から取得した JWTの 読み込みで失敗します。 上記のURLのissueでいくつかtopicが上がっていましたが、どうやら更新が長らく止まっているようで、いくつかクラスを書き換えれば動きそうなものの、ちょっと今後使っていくには厳しい印象を受けました。
なのでこのGemの採用は諦めて、公式のAuth0の Quick Startを参考に認証ロジックを自前で書いてやることで対応しました。
所感
上記の3点を解消したら無事に認証を実装することはできたのですが、思ったよりサクっとは行かず、試行錯誤が結構ありました。 Auth0側での仕様が変更されたりもあったので、過去の事例がそのまま参考にできなかったところが大きいと思います。 また、 実際に運用する上では OpenID Connectの仕組みをもう少し把握しておかなければいけないのかなと感じました。そちらに関しては別途理解をまとめた内容を残せればと思います。