fatedier/frp · error
invalid OIDC token in login: %v
Error message
invalid OIDC token in login: %v
What it means
frps-side verification of an OIDC login. OidcAuthConsumer.VerifyLogin passes loginMsg.PrivilegeKey (the JWT from frpc) to the configured TokenVerifier (typically a Keycloak/oidc IDTokenVerifier). Any JWT validation failure — bad signature, expired token, wrong issuer or audience, malformed token — is wrapped with this message. On success the token's subject is recorded for later ping cross-checks (see error 146).
Source
Thrown at pkg/auth/oidc.go:301
SkipClientIDCheck: cfg.Audience == "",
SkipExpiryCheck: cfg.SkipExpiryCheck,
SkipIssuerCheck: cfg.SkipIssuerCheck,
}
return provider.Verifier(&verifierConf)
}
func NewOidcAuthVerifier(additionalAuthScopes []v1.AuthScope, verifier TokenVerifier) *OidcAuthConsumer {
return &OidcAuthConsumer{
additionalAuthScopes: additionalAuthScopes,
verifier: verifier,
subjectsFromLogin: make(map[string]struct{}),
}
}
func (auth *OidcAuthConsumer) VerifyLogin(loginMsg *msg.Login) (err error) {
token, err := auth.verifier.Verify(context.Background(), loginMsg.PrivilegeKey)
if err != nil {
return fmt.Errorf("invalid OIDC token in login: %v", err)
}
auth.mu.Lock()
auth.subjectsFromLogin[token.Subject] = struct{}{}
auth.mu.Unlock()
return nil
}
func (auth *OidcAuthConsumer) verifyPostLoginToken(privilegeKey string) (err error) {
token, err := auth.verifier.Verify(context.Background(), privilegeKey)
if err != nil {
return fmt.Errorf("invalid OIDC token in ping: %v", err)
}
auth.mu.RLock()
_, ok := auth.subjectsFromLogin[token.Subject]
auth.mu.RUnlock()
if !ok {
return fmt.Errorf("received different OIDC subject in login and ping. "+
"new subject: %s",View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Decode the failing JWT (jwt.io or cut -d. -f2 | base64 -d) and check exp, iss, aud against frps's oidc config
- Ensure frps's oidc.issuer (and audience, if set) exactly matches the claims in tokens frpc obtains
- Sync clocks (NTP/chrony) on frps, frpc, and the IdP — expired-token failures are usually skew
- If keys rotated, restart frps or otherwise refresh the JWKS; confirm the issuer still serves the JWKS endpoint
- Check that frpc is actually sending an OIDC token, not a static auth token (mixed authentication.mode between sides)
Example fix
# frps before — issuer mismatch with tokens frpc gets authentication.oidc.issuer = "https://idp.example.com" # after — exact issuer including realm path authentication.oidc.issuer = "https://idp.example.com/realms/frp" authentication.oidc.audience = "frp-client"
Defensive patterns
Strategy: validation
Validate before calling
// client-side preflight before sending Login
tok, _, err := jwt.NewParser().ParseUnverified(privilegeKey, jwt.MapClaims{})
if err == nil {
if exp, ok := tok.Claims.(jwt.MapClaims)["exp"].(float64); ok && time.Until(time.Unix(int64(exp), 0)) < 30*time.Second {
return errors.New("token about to expire; refresh before login")
}
} Try / catch
if err := consumer.VerifyLogin(loginMsg); err != nil {
log.Warnf("oidc login rejected: %v", err)
return err // do not retry without a fresh token; re-login with new credentials instead
} Prevention
- Pin frps oidc.issuer to the exact realm URL the IdP advertises
- Run NTP on frps, frpc, and the IdP
- Alert on JWKS fetch failures so key rotations are noticed early
When it happens
Trigger: frpc logs in with a PrivilegeKey JWT that: is expired by the time frps verifies it; was signed with a key not in the JWKS from the configured issuer; has iss/aud claims that don't match frps's oidc configuration; or is not a valid JWT at all.
Common situations: frps and frpc point at different IdP realms or different issuer URLs; large clock skew between frpc, frps, and the IdP; the IdP rotated signing keys and frps has a stale JWKS cache; audience/clientid mismatch between the two sides.
Related errors
- invalid OIDC token in ping: %v
- couldn't generate OIDC token for login: %v
- failed to parse OIDC proxy URL %q: %w
- failed to create OIDC HTTP client: %w
- couldn't acquire OIDC token for login: %v
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/85f1a82881d73274.
Report an issue: GitHub.