xai-org/grok-build · error · OidcError
IdTokenValidationFailed
IdTokenValidationFailed
Error message
OidcError::IdTokenValidationFailed(e.to_string())
What it means
OidcError::IdTokenValidationFailed(String) is a wrapper applied by extract_user_info: any error produced by validate_and_extract_user_info (signature failure, expired token, JwkNotFound, IssuerMismatch, etc.) is flattened via e.to_string() into this single error type at protocol.rs:764. The original specific cause is preserved only as a string message.
Source
Thrown at crates/codegen/xai-grok-shell/src/auth/oidc/protocol.rs:764
}
let token = id_token.ok_or_else(|| anyhow::Error::new(OidcError::MissingIdToken))?;
validate_and_extract_user_info(
token,
discovery,
expected_issuer,
expected_client_id,
expected_nonce,
)
.await
.map(|mut user_info| {
user_info.principal_type = principal_type.map(ToOwned::to_owned);
user_info.principal_id = principal_id.map(ToOwned::to_owned);
if user_info.team_id.is_none() {
user_info.team_id = fallback_team_id;
}
user_info
})
.map_err(|e| anyhow::Error::new(OidcError::IdTokenValidationFailed(e.to_string())))
}
#[cfg(test)]
mod tests {
use super::super::test_helpers::*;
use super::*;
#[test]
fn pkce_s256_challenge_matches_verifier() {
let pkce = generate_pkce();
assert_eq!(pkce.code_verifier.len(), 43);
let expected = URL_SAFE_NO_PAD.encode(Sha256::digest(pkce.code_verifier.as_bytes()));
assert_eq!(pkce.code_challenge, expected);
}
#[test]
fn authorize_url_includes_required_oidc_params() {
let config = OidcAuthConfig {
issuer: "https://example.okta.com".into(),
client_id: TEST_CLIENT_ID.into(),
scopes: vec!["openid".into(), "profile".into()],View on GitHub (pinned to bc7f02eddd)
Solutions
- Read the inner message of IdTokenValidationFailed to identify the root cause (expired, signature, issuer, nonce, etc.) and fix that specific issue.
- Sync system clock (NTP) if the message indicates expiration/immature-token errors.
- Re-run the login flow to get a fresh token; verify issuer/client_id/nonce configuration matches the IdP.
- Check network access to the discovery jwks_uri endpoint.
Example fix
// before: opaque wrapper loses typed context
.map_err(|e| anyhow::Error::new(OidcError::IdTokenValidationFailed(e.to_string())))
// after (caller): log full chain for diagnosis
if let Err(e) = result {
tracing::error!(chain = ?e, "id token validation failed"); // inspect root cause
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate the JWT well before the flow: header, kid, exp
let header = jsonwebtoken::decode_header(token)?;
if header.kid.is_none() { eprintln!("token has no kid; validation will fail"); } Try / catch
if let Err(e) = extract_user_info(...).await {
let msg = e.to_string();
if let Some(inner) = msg.strip_prefix("IdTokenValidationFailed(").and_then(|s| s.strip_suffix(')')) {
tracing::error!(cause = inner, "id token validation failed"); // inspect root cause
}
} Prevention
- Keep clocks NTP-synced to avoid spurious exp errors.
- Log the full anyhow chain, not just the wrapper message.
- Validate config (issuer, client_id, nonce) with a smoke-test login in CI.
- Ensure jwks_uri is reachable from the runtime environment.
When it happens
Trigger: Any failure inside validate_and_extract_user_info — JWKS fetch failure, missing kid, unsupported alg, jsonwebtoken::decode errors (expired/invalid signature/missing claims), issuer/audience/nonce mismatch — then re-wrapped as IdTokenValidationFailed.
Common situations: Clock skew making tokens appear expired; IdP key rotation invalidating signatures; misconfigured issuer/client_id/nonce; network failure reaching jwks_uri; debug builds altering token handling.
Related errors
- MissingIdToken
- no OIDC auth entry found in {}. Run `grok login` first.
- auth entry has no refresh_token — cannot refresh expired tok
- auth entry has no oidc_issuer — cannot refresh expired token
- auth entry has no oidc_client_id — cannot refresh expired to
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/f5575071c4479187.
Report an issue: GitHub.