認可済み値には lifetime と再検証の問題が残る
認可後に EditableDocument や request-local scope を作れば、その値の lifetime を HTTP request 程度に限定できる。これは長寿命 credential を配布するより扱いやすいが、request scope にしただけで revocation や TOCTOU が解決するわけではない。
t0: resource を読む
t1: authorization を確認する
t2: AuthorizedResource を作る
t3: 権限・resource state が変わる
t4: 書き込みを行う
t1 で成立した authorization が t4 でも成立する保証は、wrapper の型だけからは得られない。
capability system でも revocation は古くから独立した問題として扱われている。J-Kernel/Luna の研究は、通常の Java pointer を capability として渡すと一度渡した pointer を revoke できない点を明示し、indirection や remote pointer の仕組みを導入している。storage capability の研究でも object version や capability ID/group を使った revocation mechanism が別途必要になる。
cryptographic capability credential でも同様で、Biscuit は token ごとの revocation identifier を提供するものの、revocation list/database などの external state management は specification の外にあると明記している。
したがって request-local authorization evidence については、少なくとも次を別々に考える必要がある。
- lifetime — その値をどこまで持ち出せるか
- revocation — 発行後に authority を失効させられるか
- freshness — authorization が参照した membership / owner / state がまだ同じか
- atomicity — authorization check と side effect の間で前提が変化しないか
request-scoped DI をセキュリティコンテキストとして使う の Registry/DI scope は lifetime を短くするには都合がよい。しかし、それは主に値の生存期間に関する性質であり、authorization state の atomicity を保証するものではない。
たとえば「project member なら更新可」が transaction 中にも変更され得るなら、write transaction の中で membership を再確認する、policy version を比較する、resource update 自体を条件付き SQL にする、といった application-level mechanism が必要になる場合がある。
このため 「認可済みリソース型」は既存研究の直訳ではなく設計上の合成 を設計する際、Authorized<T> を「永続的な権限証明」と考えるより、ある時点・ある scope で認可を通過した evidence と考える方が安全である。