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
- Have the client obtain a fresh token via the login (or refresh) endpoint and retry.
- If refresh tokens are enabled, exchange the expired access token using the refresh flow instead of forcing re-login.
- Increase JWT.ExpiresAt in config.yaml if the configured lifetime is unintentionally short.
- 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
- Implement proactive token refresh before exp rather than after a 401
- Set a reasonable JWT.ExpiresAt in config.yaml and keep server clocks NTP-synced
- Handle the expired sentinel explicitly in middleware to return 401 with a recognizable msg so clients re-auth
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.