flipped-aurora/gin-vue-admin · error

token已过期

Error message

token已过期

What it means

TokenExpired is returned by ParseToken when the JWT's exp claim is in the past. The token was correctly signed and formed, but its lifetime has elapsed, so it must not be accepted.

Source

Thrown at server/utils/jwt.go:19

package utils

import (
	"context"
	"errors"
	"time"

	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
	jwt "github.com/golang-jwt/jwt/v5"
)

type JWT struct {
	SigningKey []byte
}

var (
	TokenValid            = errors.New("未知错误")
	TokenExpired          = errors.New("token已过期")
	TokenNotValidYet      = errors.New("token尚未激活")
	TokenMalformed        = errors.New("这不是一个token")
	TokenSignatureInvalid = errors.New("无效签名")
	TokenInvalid          = errors.New("无法处理此token")
)

func NewJWT() *JWT {
	return &JWT{
		[]byte(global.GVA_CONFIG.JWT.SigningKey),
	}
}

func (j *JWT) CreateClaims(baseClaims request.BaseClaims) request.CustomClaims {
	bf, _ := ParseDuration(global.GVA_CONFIG.JWT.BufferTime)
	ep, _ := ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
	claims := request.CustomClaims{
		BaseClaims: baseClaims,
		BufferTime: int64(bf / time.Second), // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Have the client obtain a fresh token via the login (or refresh) endpoint and retry.
  2. If refresh tokens are enabled, exchange the expired access token using the refresh flow instead of forcing re-login.
  3. Increase JWT.ExpiresAt in config.yaml if the configured lifetime is unintentionally short.
  4. Sync the server clock (NTP) if skew is causing premature expiry.

Example fix

// client before
fetch('/api/user/info', { headers: { 'x-token': staleToken } }) // 401 token已过期
// after
if (res.code === 401 && isExpired(res.msg)) {
    await reLogin() // or use refreshToken endpoint
    retry(request)
}
Defensive patterns

Strategy: retry

Validate before calling

const EXP_GRACE = 60 * 1000
function willExpireSoon(token) {
    const payload = JSON.parse(atob(token.split('.')[1]))
    return payload.exp * 1000 - Date.now() < EXP_GRACE
}
if (willExpireSoon(token)) await refreshToken()

Type guard

function parseExp(token) {
    try { return JSON.parse(atob(token.split('.')[1])).exp * 1000 } catch { return 0 }
}

Try / catch

claims, err := utils.ParseToken(token)
if errors.Is(err, utils.TokenExpired) {
    // client flow: redirect to login or call refresh-token endpoint, then retry once
    return nil, ErrNeedReAuth
}

Prevention

When it happens

Trigger: Any request whose x-token/Authorization token has an exp earlier than the current time — long-lived sessions, tokens issued long ago, or clocks skewed far ahead on the server.

Common situations: User leaves a tab open past ExpiresAt; client caches a token across deployments; server clock drift (NTP failure) making valid tokens appear expired; very short ExpiresAt configured in config.yaml.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/782ef7d2d8a387d0. Report an issue: GitHub.