こんにちは。JMDCインシュアランス本部ソリューション部の檜山です。
最近、初めてLaravel11でJWTトークン認証を実装しました。 実装にあたり私の知見不足により苦戦したことがいくつかありましたので、他山の石として参考になれば幸いです。
環境
Laravel11
使用ライブラリ
GitHub - tymondesigns/jwt-auth: 🔐 JSON Web Token Authentication for Laravel & Lumengithub.com
苦戦したところ①
JWT自体にはリフレッシュトークンの標準的な仕組みは無い
リフレッシュトークンとは、クライアント-サーバ間で認証したのちに発行される期限の短いアクセストークンを更新するために使われる、1回きり使用可能な期間の長いトークンです。詳しくは下記のOAuth 2.0のドキュメントをご参照いただければと思います。
openid-foundation-japan.github.io
tymon/jwt-authでは1つのJWTに「通常の有効期限(ttl)」と「リフレッシュが可能な最大期間(refresh_ttl)」の2つの期限を持たせる設計になっています。 私の認証に対する知見が無かったこともあり、JWTを使った認証と、OAuth 2.0のような認可フローとの違いを理解するのに時間がかかりました...
結局のところトークンは2種類発行したかったため、ログイン認証時に2種類のJWTトークンを発行するよう実装しました。
アクセストークン :JWT認証、期限短め、何度でも使用可能
リフレッシュトークン:JWT認証、期限長め、1回使用したら無効化
上記実装は力技なところもあるため、OAuth 2.0認可フローの仕組みに寄せるのであれば使用ライブラリはLaravel Passportをお勧めします。
苦戦したところ②
トークンリフレッシュ有効期限にデフォルト値が設定されている
上記の通り、リフレッシュトークンの仕組みを力技で実装し、試験フェーズまで来ました。
試験を進めていくと、「リフレッシュトークン発行から2週間経つとトークンの更新に失敗する」という事象が起きました。調べてみると、トークンのリフレッシュ有効期限がデフォルト値(2週間)になっていることが原因でした。
トークン種別 | 有効期限種別 | 期間 |
---|---|---|
アクセストークン | 認証有効期限 | 10分 |
アクセストークン | リフレッシュ有効期限 | 2週間 |
リフレッシュトークン | 認証有効期限 | 20日 |
リフレッシュトークン | リフレッシュ有効期限 | 2週間 |
※上記有効期限は検証用の値です。
リフレッシュトークン自体の認証はまだ有効期間内のためトークンとしては使えますが、refresh_ttl(リフレッシュ有効期限)を過ぎていたため、新しいトークンの再発行に失敗していました。
苦戦したところ①で力技で実装したと記載しましたが、ライブラリの意図とは異なる実装をしてしまったことが根本原因だと思います。
tymon/jwt-auth は 1トークン運用を前提とした設計思想があるため、2トークン(アクセストークンとリフレッシュトークン)を分けて運用したことが、今回の問題の一因だったと考えています。
下記のように設定値を修正することで、想定通りの挙動をするようになりました。
トークン種別 | 有効期限種別 | 期間 |
---|---|---|
アクセストークン | 認証有効期限 | 10分 |
アクセストークン | リフレッシュ有効期限 | 20日 |
リフレッシュトークン | 認証有効期限 | 20日 |
リフレッシュトークン | リフレッシュ有効期限 | 20日 |
※上記有効期限は検証用の値です。
設定の変更方法
ライブラリのconfigにてJWT_REFRESH_TTLのデフォルト値が20160分(2週間)で設定されています。
.envファイルにJWT_REFRESH_TTLを設定することでトークンリフレッシュ有効期限を指定することができます!
(下記では28800分=20日)
JWT_REFRESH_TTL=28800 // リフレッシュ有効期限(分)
まとめ
今回の開発では認証処理の知見不足、使用ライブラリ選定など自分の勉強不足が目立つところがありました。
ただ、実装していく中でライブラリや認証に対する理解を深めていくことができたのは良かったことかなと思います。
今後、認証処理を実装する際にはこの経験を生かし、より適切な認証設計を心掛けたいと思います。