(※この記事は 別媒体に投稿した記事 のバックアップです。 canonical も設定しています)
2023-04-22
OAuth2 でリフレッシュトークンを使う場合、そのメリットが何なのか十分理解できていなかったのでまとめました。
「ここの説明は間違っている」「こういったケースで有効だった」などありましたら、コメントいただけると嬉しいです。
OAuth2 の認可コードによる付与(Authorization Code Grant)でリフレッシュトークンを使う場合、という前提のもとに書いていますので、その点ご留意ください。
(他のフローやリフレッシュトークンを使わない場合は異なる場合があるかもしれません)
アクセストークンは、クライアントがリソースサーバーの保護されたリソースにアクセスするために必要のトークンです。
アクセストークンの有効期限は短く設定されている場合が多いです。(イメージとしては数十分〜数時間)
リフレッシュトークンは、アクセストークンを再発行するために使用するトークンです。
リフレッシュトークンは有効期限が長く設定される場合が多いです。(イメージとしては日単位)
アクセストークンを発行できるので、流出した場合のリスクが大きく、厳重に管理する必要があります。
(※補足:OAuth 的にリフレッシュトークンの発行は任意です)
Access Tokenは秘密にしなければなりませんが、存続期間が短いため、セキュリティの考慮事項の制限も緩くなります。
https://auth0.com/blog/jp-refresh-tokens-what-are-they-and-when-to-use-them/
上記の通り、アクセストークンは有効期限が短いため、リフレッシュトークンと比較すると求められるセキュリティレベルは低くなります。
(※補足:あくまで比較すればの話で、どちらも秘匿すべき情報であることに変わりはありません)
先に説明した通り、リフレッシュトークンはアクセストークンを再発行するために使われるトークンです。
その性質上、保持するのはクライアント(ここではアプリケーションサーバーなど)のみで、認可サーバーとの間でのみやりとりされます。
また再発行の際にはクライアントIDとクライアントシークレットも必要です。
限定された通信と追加の秘匿情報が必要なため、流出のリスクを最小化することができます。
JWT は "JSON Web Token" の略称で、トークンの形式の一種です。近年使われるケースが多いと筆者は感じています。
(詳細を知りたい方は、私が書いた JWTについてまとめてみる などを参考にしてください)
その特性の一つとして、トークン自体に有効期限などの情報を含めることができ、更に署名(JWS)により確かに発行者が指定したものであることが保証できます。
また、共通鍵暗号方式や公開鍵暗号方式を使用して署名の検証ができるので、API やデータベースへのアクセスが不要です。
これはサービスのスケーリングの観点で大きなメリットです。
こういった特性からアクセストークンとJWTは相性が良いです。
しかし外部への問い合わせを行わない場合、発行されたJWTを無効化することが実質できません。
そのため有効期限を短くすることで、流出した場合のリスクを最小限にできます。
JWTをアクセストークンとして使うケースでは、リフレッシュトークンを併用するメリットが大きいと思いました。
アクセストークンとリフレッシュトークンの両方を使う理由は、セキュリティと利便性のバランスと取れるケースがあるから、と個人的には感じていました。
ただ Stack Overflow の議論を見ても様々な観点での意見があり、使う人や状況によって意味合いは変わるのかもしれません。
(議論以前のコメントもいくつかありましたが・・・)
例えば、アクセストークンがリフレッシュトークンと同程度の安全な環境で使える場合、リフレッシュトークンを使うメリットはないと思います。
要はバランス的な話になってしまいますが、全ての状況に適した方法はないので、プロダクトの特性に応じて適した方法を採用できるように知識と思考力を広げていきたいところです。
この記事を書いている時にふと思い出したので貼っておきます。
この記事は非常にすぐれていると思いました。その理由は、特定の前提条件においてアーキテクチャを選定した理由が明確であるからです。読者はこの記事の結論よりも方法論を学ぶべきだと思います。結果は前提条件によって変わりますが、方法論は普遍的なものだからです。
読者のために参考記事のURLを再掲します
https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/