🩹

liffのIDTokenの有効期限切れ対策

2022/09/13に公開

課題

liff sdkのgetIDTokenで取得されるIDTokenはlocalStorageにキャッシュされるが、有効期限が切れても更新されないという問題があります。(ver2.1.13現在)

この問題はLINE DCのQ&Aでも報告されているものです。
https://www.line-community.me/ja/question/60370060401690d0b65a88f4

対策

liff sdkはGitHubで公開されている訳ではなかったので、プルリクはできませんでした。

そこで、sdkが使っているlocalStorageの値を無理やり読み書きすることで対策することにしました。

通常の実装

まずは普通に実装した場合のコードです。

index.js(対策前)
const main = async (liffId) => {
  await liff.init({ liffId })
  const idToken = liff.getIDToken();
  // idTokenをサーバに投げるなどの処理...
}

普通に動くんですが、動作確認終了後、半日後くらいに同じブラウザで再度動作確認するとサーバ側で400 Bad Requestエラーが発生します。

対策後の実装

次に対策をした際のコードです。

index.js(対策後)
// liff関連のlocalStorageのキーのリストを取得
const getLiffLocalStorageKeys = (prefix) => {
    const keys = []
    for (var i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i)
      if (key.indexOf(prefix) === 0) {
        keys.push(key)
      }
    }
    return keys
}
// 期限切れのIDTokenをクリアする
const clearExpiredIdToken = (liffId) => {
  const keyPrefix = `LIFF_STORE:${liffId}:`
  const key = keyPrefix + 'decodedIDToken'
  const decodedIDTokenString = localStorage.getItem(key)
  if (!decodedIDTokenString) {
    return
  }
  const decodedIDToken = JSON.parse(decodedIDTokenString)
  // 有効期限をチェック
  if (new Date().getTime() > decodedIDToken.exp * 1000) {
      const keys = getLiffLocalStorageKeys(keyPrefix)
      keys.forEach(function(key) {
        localStorage.removeItem(key)
      })
  }
}

const main = async (liffId) => {
  clearExpiredIdToken(liffId)
  await liff.init({ liffId })
  const idToken = liff.getIDToken()
  // idTokenをサーバに投げるなどの処理...
}

liff sdkが下記のようなキーでlocalStorageを使っているので、その値を読みに行き、idTokenの期限が切れていたら、liff関連のlocalStorageのレコードを消してしまっています。

  • LIFF_STORE:{{YOUR_LIFF_ID}}:IDToken
  • LIFF_STORE:{{YOUR_LIFF_ID}}:accessToken
  • LIFF_STORE:{{YOUR_LIFF_ID}}:clientId
  • LIFF_STORE:{{YOUR_LIFF_ID}}:context
  • LIFF_STORE:{{YOUR_LIFF_ID}}:decodedIDToken

liff.initの前にこの処理を挿入することで、常に有効なIDTokenを使うことができます。

最後に

sdk側で修正されるのがベストなのでLINEさん、修正お願いいたします!

Discussion