🧊

アクセストークンをWebWorkerで扱う

というアプローチを紹介してる記事があって、なるほど?と思ったのでまとめてみる。

元記事はこちら。

Leveraging Web Workers to Safely Store Access Tokens – The New Stack

毎度のことながら、今にはじまったことではない。

元記事いわく

WebWorkerであれば、メインスレッドで実行されるであろうXSSや3rdのコードから触れないので安全!

設計としては、

  • メイン: まず`Worker`をロード
  • メイン: 初期化のメッセージを`postMessage()`
    • クレデンシャルがあるならそれを渡す
  • ワーカー: アクセストークンの準備
    • 受け取ったやつ or そこで`fetch()`して、オンメモリに保存
  • (これで準備OK)
  • メイン: APIにリクエストしてほしいと`postMessage()`
  • ワーカー: APIに向けてアクセストークンつけて`fetch()`
  • ワーカー: レスポンスをメインスレッドに`postMessage()`
  • メイン: それを受け取って使う!

大事なのは、アクセスできるAPIのリストを、ワーカー内にホワイトリストとして定義しておくこと。
そうすることで、メインスレッドから悪意のあるコードによって、意図しないドメインに送信されることがない。

ただしWebWorker自体のライフサイクルはそのセッションと同じで、永続化ができるわけではない。
とはいえ、最近のAuthベンダーであれば、セキュアなセッションCookieを使ってユーザー入力なくアクセストークンを更新できるはずなので、UXに影響はないであろう。

とのこと。

まとめ

この記事を読み始めたときは、「LocalStorageを使わなくても、WebWorkerならセキュアにトークンを永続化できる・・?」って思ってたけど、まったく関係のない話だった。言われてみれば当然なんやけど、なぜか永続化の話だと思いこんでしまってた。

「大事なトークンを一瞬たりともメインスレッドに置きたくない!」というのを実現する方法としては、実装コスパとしては妥当なのかな〜と思った。(ワーカー内にスコープが狭まっただけではあるけど)

あとはトークンそれ自体のIOだけを隠蔽するのでは不十分で、結局それがリクエストに載っていくならば、`fetch()`なんかもXSSの対象になることを忘れるなということかね。

Auth0のSPA用のSDKでも、オンメモリのStorage + FetcherとしてWebWorkerを使うようになってた。

[SDK-1516] Use Web Workers for token endpoint call for in-memory storage by adamjmcgrath · Pull Request #409 · auth0/auth0-spa-js · GitHub

あとWebWorker使えっていう話は、Auth0のドキュメントにも書かれてた。

Token Storage

ちなみに先行実装とかないかなーと思って探したけど、見つけられたのはこれだけだった。

まあやるからには自作するか・・。

永続化は結局どうする

元記事は大丈夫って言ってるけど、実際には3rdのCookieに対する風向きも微妙な昨今では、Cookieに頼る方法はぜんぜん大丈夫じゃないと思う。

となるとやはりリフレッシュトークン + ローテーションを必須にしつつ、LocalStorageに入れるしかないんやろうけど、なんかもっと画期的なソリューションは出てこないもんかね〜。

const auth0 = await createAuth0Client({
    domain: '<your Auth0 domain>',
    client_id: '<your Auth0 client ID>',
    cacheLocation: 'localstorage',
    useRefreshTokens: true,
});
    
// Logging-in will automatically request the offline_access scope
// and store the resulting refresh token
auth0.loginWithRedirect();
    
// Silently refreshing the access token will use the /token endpoint
// with ‘refresh_token’ grant and the refresh token from the cache
await auth0.getTokenSilently();

`auth0-spa.js`だとこんな感じのコードになるらしい。

Secure Browser Storage: The Facts

こっちの記事もブラウザのストレージまわりについてよくまとまってたのでおすすめ。