本文へスキップ
ecdsa.com
golang-jwt/jwt (Go)Go

エラーメッセージ

token has invalid claims: token is expired

別の表記

  • Token is expired
  • token has invalid claims: token is not valid yet
  • token has invalid claims: token used before issued

golang-jwt v4 は「Token is expired」(先頭が大文字の T)と出力します。v5 のほかのクレームエラーも、同じ「token has invalid claims:」というプレフィックスを使います。

golang-jwt/jwt (Go) — jwt.ErrTokenInvalidClaims joined with jwt.ErrTokenExpired

このエラーの意味

トークンの署名は検証に成功しましたが、`exp` クレームが過去の時刻です(設定した許容誤差を考慮しても過ぎています)。golang-jwt v5 はこれを、`ErrTokenInvalidClaims` と `ErrTokenExpired` を結合したエラーとして報告します。同じ系統のエラーとして、`nbf` が未来の時刻なら「token is not valid yet」、`iat` が未来の時刻なら「token used before issued」が返されます。解析済みのトークンはエラーと一緒に返されますが、信頼してはいけません。

発生する理由

修正方法

  1. 1.

    期限切れを検出し、クライアントにトークンを更新させる

    `ErrTokenExpired` は、`invalid_token` というヒントを付けて 401 にマッピングしてください。そうすればクライアントはリフレッシュトークンを使い(または再認証し)、リクエストを再試行します。

    go
    token, err := jwt.Parse(raw, keyfunc, jwt.WithValidMethods([]string{"ES256"}))
    if errors.Is(err, jwt.ErrTokenExpired) {
    	w.Header().Set("WWW-Authenticate", `Bearer error="invalid_token", error_description="token expired"`)
    	http.Error(w, "token expired", http.StatusUnauthorized) // client refreshes and retries
    	return
    }
  2. 2.

    わずかな時刻のずれを許容し、exp を必須にする

    数秒の許容誤差を設ければ、マシン間の時計のずれを吸収できます。`WithExpirationRequired` は逆方向の抜け穴をふさぎます。これを指定しないと、`exp` のないトークンはいつまでも期限切れになりません。

    go
    parser := jwt.NewParser(
    	jwt.WithValidMethods([]string{"ES256"}),
    	jwt.WithLeeway(30*time.Second), // absorbs clock skew for exp, nbf and iat
    	jwt.WithExpirationRequired(),   // tokens without exp are rejected too
    )

関連するエラー

署名エラーデータベースをすべて見る