vxcontrol/pentagi · warning

Auth.TokenExpired

Auth.TokenExpired

Error message

state signature expired

What it means

parseState checks the 'exp' timestamp embedded in the signed OAuth state payload against the current time. If the state has aged past its expiration, the callback rejects it with Auth.TokenExpired. OAuth state is single-use and short-lived by design to prevent replay and CSRF, so expired state is a normal, expected rejection.

Source

Thrown at backend/pkg/server/services/auth.go:729

	}

	if _, ok := stateData["provider"]; !ok {
		err := fmt.Errorf("missing required field: provider")
		logger.FromContext(c).WithError(err).Errorf("error on validating state data")
		response.Error(c, response.ErrAuthInvalidAuthorizationState, err)
		return nil, err
	}

	exp, err := strconv.ParseInt(expStr, 10, 64)
	if err != nil {
		logger.FromContext(c).WithError(err).Errorf("error on parsing expiration time")
		response.Error(c, response.ErrAuthInvalidAuthorizationState, err)
		return nil, err
	}

	if time.Now().Unix() > exp {
		logger.FromContext(c).Errorf("error on checking expiration time")
		err := fmt.Errorf("state signature expired")
		response.Error(c, response.ErrAuthTokenExpired, err)
		return nil, err
	}

	return stateData, nil
}

func (s *AuthService) setCallbackCookie(
	w http.ResponseWriter, r *http.Request,
	name, value string, maxAge int,
	sameSite http.SameSite,
) {
	// Check both direct TLS and X-Forwarded-Proto header (for reverse proxy setups)
	useTLS := r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https"

	c := &http.Cookie{
		Name:     name,
		Value:    value,

View on GitHub (pinned to ea665308ba)

Solutions

  1. Restart the login flow to get a freshly signed state — expired state cannot be renewed.
  2. If expirations happen routinely on slow networks, increase the state TTL when the state is minted.
  3. Check NTP/ clock sync on the server if valid states are rejected immediately.
  4. Ensure the user agent is not caching the callback URL across sessions.
Defensive patterns

Strategy: retry

Validate before calling

const payload = decodeState(state);
if (!payload || Date.now() / 1000 > payload.exp) {
  restartLoginFlow(); // state already expired, do not call the API
}

Try / catch

try { await oauthCallback(state, code); } catch (e) { if (isTokenExpired(e)) redirectToLogin(); else throw e; }

Prevention

When it happens

Trigger: User completes the OAuth consent screen after the state TTL has elapsed; user bookmarked the callback URL and reuses it later; slow redirect chain or network delays push completion past expiry.

Common situations: User leaves the provider consent page open for many minutes before clicking 'Allow'; browser restores an old tab with a stale callback URL; clock skew between servers making recently minted state appear expired.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/71f2be8883702139. Report an issue: GitHub.