xai-org/grok-build · error · OidcError

OidcError::DiscoveryMissingJwksUri

Error message

OidcError::DiscoveryMissingJwksUri

What it means

OidcError::DiscoveryMissingJwksUri is raised by validate_and_extract_user_info when the fetched discovery document has no `jwks_uri` field. Without the JWKS URL the shell cannot fetch signing keys, so id_token verification is impossible. This indicates an incomplete or non-compliant discovery document.

Source

Thrown at crates/codegen/xai-grok-shell/src/auth/oidc/protocol.rs:652

        ));
    }
    Ok(())
}
pub(super) async fn validate_and_extract_user_info(
    token: &str,
    discovery: &Discovery,
    expected_issuer: &str,
    expected_client_id: &str,
    expected_nonce: &str,
) -> anyhow::Result<OidcUserInfo> {
    let header = jsonwebtoken::decode_header(token)?;
    let kid = header
        .kid
        .ok_or_else(|| anyhow::Error::new(OidcError::IdTokenMissingKid))?;
    let jwks_uri = discovery
        .jwks_uri
        .as_ref()
        .ok_or_else(|| anyhow::Error::new(OidcError::DiscoveryMissingJwksUri))?;
    let jwks: jsonwebtoken::jwk::JwkSet = with_alpha_test_key(
        crate::http::shared_client()
            .get(jwks_uri)
            .timeout(std::time::Duration::from_secs(10)),
        jwks_uri,
    )
    .send()
    .await?
    .error_for_status()?
    .json()
    .await?;
    let jwk = jwks
        .find(&kid)
        .ok_or_else(|| anyhow::Error::new(OidcError::JwkNotFound { kid: kid.clone() }))?;
    let decoding_key = jsonwebtoken::DecodingKey::from_jwk(jwk)?;
    let alg = header.alg;
    ensure_alg_allowed(
        alg,

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Fix the provider's discovery document to include jwks_uri (spec-required for signing-key distribution)
  2. curl the well-known URL and confirm the JSON actually contains jwks_uri (rule out proxies/caches stripping it)
  3. Check for issuer-path misconfig causing discovery to be read from a metadata endpoint that lacks jwks_uri

Example fix

// before (IdP discovery response)
{ "issuer": "https://idp.example.com", "authorization_endpoint": "..." }
// after
{ "issuer": "https://idp.example.com", "jwks_uri": "https://idp.example.com/.well-known/jwks.json", ... }
Defensive patterns

Strategy: validation

Validate before calling

// preflight discovery completeness before the login flow
async fn discovery_has_jwks(issuer: &str) -> anyhow::Result<bool> {
    let url = format!("{}/.well-known/openid-configuration", issuer.trim_end_matches('/'));
    let doc: serde_json::Value = reqwest::get(&url).await?.json().await?;
    Ok(doc.get("jwks_uri").and_then(|v| v.as_str()).is_some())
}

Try / catch

match res {
    Err(e) if matches!(e.downcast_ref::<OidcError>(), Some(OidcError::DiscoveryMissingJwksUri)) => {
        eprintln!("Issuer discovery has no jwks_uri — provider metadata is incomplete");
    }
    other => other?,
}

Prevention

When it happens

Trigger: validate_and_extract_user_info reads discovery.jwks_uri after discovery succeeded; if the Option is None, DiscoveryMissingJwksUri is returned before any JWKS request is made.

Common situations: Minimal or homegrown OIDC providers that omit jwks_uri from their well-known JSON; a reverse proxy stripping fields; caching/interception serving a truncated discovery payload.

Related errors


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