WSL + Docker でFirebaseのJWT認証ができない

作成: 2021年08月12日

更新: 2021年08月12日

困ったこと

Ruby on Rails + Next.js + Firebase authの構成でアプリの認証部分を実装していてWSL+Dockerでローカル開発しているときにFirebase ID token has invalid signature. Invalid iatのエラーが出てうまく認証できないときがあった.

RubyにはFirebaseの公式SDKがないため以下の2記事を参考に自前でFirebaseのJWTトークン認証を実装していた.

RubyでFirebaseのidトークンを認証に使ってみる - Qiita

Rails+Firebase認証のサンプルアプリ - Qiita

エラーメッセージの箇所を調べると以下のJWT.decodeの部分でInvalid iatが原因で失敗しているようだった.

def _decode_token(token, key=nil, verify=false, options={})
  begin
    decoded_token = JWT.decode(token, key, verify, options)
  rescue JWT::ExpiredSignature => e
    raise 'Firebase ID token has expired. Get a fresh token from your client app and try again.'
  rescue => e
    raise "Firebase ID token has invalid signature. #{e.message}"
  end

  {
    payload: decoded_token[0],
    header: decoded_token[1]
  }
end

厄介なことに発生するときとしないときがあった.

原因と解決策

JWTのiatはJWTトークンが発行された時間を表していてこれは過去の時点であることが必要です.

ID トークンを検証する | Firebase

つまりJWTトークンの発行はFirebaseのサーバーで行われるので発行時間そのものは正しいとするとローカルのサーバーの時刻が遅れている可能性が高い.

そこで調べてみるとWSLはPCのスリーブ時などで時刻のずれが起きることがあるそうでこれが原因っぽいです.(以下の記事では時刻のずれでapt-getが失敗しています)

WSL2で困ったときに使う魔法の呪文 - Qiita

解決策としては以下のコマンドでWSLをシャットダウンすることです(自動で再起動される)

wsl --shutdown

ディストリビューションの再起動ではwsl -t Ubuntuでは直ったり直らなかったりしたのでシャットダウンが確実です.

一度シャットダウンすればまたずれるまでしばらくはエラーが発生しません.