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

  1. Read the inner message of IdTokenValidationFailed to identify the root cause (expired, signature, issuer, nonce, etc.) and fix that specific issue.
  2. Sync system clock (NTP) if the message indicates expiration/immature-token errors.
  3. Re-run the login flow to get a fresh token; verify issuer/client_id/nonce configuration matches the IdP.
  4. 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

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


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/f5575071c4479187. Report an issue: GitHub.