OAuth 2.0 で有効期限がない(ずっと先の) Refresh Token の扱いについて
ritouです。
今日は OAuth 2.0 の話題で少し頭の体操をしましょう。
いきなりまとめ
今回は
- OAuth 2.0 の Refresh Token を用いて非同期の処理を実装するケースはよくある
- "Refresh Tokenの有効期限がない=無効化されない" という前提の設計を見かけるが、よくないと思う
- 無限に有効な Refresh Token が必要になりそうな機能は Client Credentials Grant に持っていくのも一つの手では
みたいな話をします。
OAuth 2.0 の Refresh Token
仕様の参照とかはめんどいのでざっくりまとめると
- Access Token を更新するために利用されるトークン
- Resource Owner が介入しない非同期なタイミングでも利用される場合がある
- 有効期限切れや AuthZ Server / Resource Owner からの無効化があり得る
みたいなところでしょう。
で、今回のポイントになるのは最後のところです。
Refresh Token は何らかの事情で無効化されうるものである
例えば次のようなケースで Refresh Token が利用されます。
- ブログの予約投稿時にSNSに投稿する
- 抽選サイトの定期的な抽選において、当選者の最新の住所を取得して商品を発送する
仮に Refresh Token が無効化されていた場合、上記の処理は実行されないことになります。
- SNSに投稿できない
- 住所が取得できずに商品が発送できない
Client のサービス内でこれらの処理がどのような位置付けにあるかによりますが、前者は許容できるものの後者は避けたいところです。
無限に有効な RefreshToken = 無効化されない わけではない
これまでの経験上、次のような特性があると上述のような "無効化されない" 前提で使おうとしてしまう傾向が出がちです。
- Refresh Token の有効期限が長い
- Resource Owner による無効化機能が提供されていない
このような仕様でAuthZ Serverが機能追加などをせずに平和に運用されているのであれば実態として長期間無効化されない状態になり得ると思います。しかし、盲目的に無効化されない前提で設計/実装を進めて良いものなのでしょうか。
例えばAuthZ Serverがセキュリティ対策の施策などを入れることもあるでしょう。
不正ログインなどの事案が発生した場合、有効なセッションやトークン類を無効化する対応を行うことは珍しいものではありません。Client/AuthZ Serverが密に連携するようなサービスならまだしも、後からAuthZ Server側でResource Ownerによるトークン無効化機能が実装される可能性もあります。
以上のことから、Refresh Token というトークンを保持している以上はそれが無効化される可能性があるとして設計/実装を進める方が良いというのが私の考えです。そもそも疎結合なサービスの機能を組み合わせて提供する場合はRefresh Tokenだからどうこうの前にAPIアクセスが何らかの原因で失敗することを考慮することは当然とも言えるわけですが。
"ずっと使える前提" にしたいなら Client Credentials で何とかしよう
それでは、OAuthを用いてずっとAPIが叩ける状態にするにはどうしたら良いかというところですが、これは Refresh Token ではなく Client Credentials Flow の方で実現すべきかなと考えています。
例えば "Resource Owner の最新の住所を毎回取得する" みたいな要件の場合、
- Client は認可フローにおいて Resource Owner の
address
scopeを要求する - AuthZ Server は Resource Owner が
address
リソースへのClientからのアクセスを許可したらそれを保存する - Client は Client Credentials Flow にて取得した Access Token で Resource Owner の識別子を指定して APIアクセス
- AuthZ Server は Resource Owner が Client に対して
address
scopeを許可していたら最新の住所情報を返す
という流れにすることで Refresh Token を利用せずに "Resource Owner が許可している間はずっと最新の住所情報を取得可能" な状態にできるでしょう。
Client / AuthZ Server 間に信頼関係が存在する場合などは、こういう設計をしても良いのではないかと考えています。
ではまた!
Discussion