{"record":{"id":"bdfc0d44f36b75b1","repo":"Pumpkin-MC/Pumpkin","slug":"jwt-chain-validation-failed-0","errorCode":null,"errorMessage":"JWT chain validation failed: {0}","messagePattern":"JWT chain validation failed: (.+?)","errorType":"error_code","errorClass":"LoginError","httpStatus":null,"severity":"error","filePath":"crates/pumpkin/src/net/bedrock/login/mod.rs","lineNumber":34,"sourceCode":"};\nuse pumpkin_protocol::bedrock::{\n    client::{resource_pack_stack::PackInstanceId, resource_packs_info::PackInfoData},\n    server::{login::ClientData, resource_pack_client_response::SResourcePackClientResponse},\n};\nuse pumpkin_util::version::BedrockMinecraftVersion;\nuse pumpkin_world::{CURRENT_BEDROCK_MC_PROTOCOL, CURRENT_BEDROCK_MC_VERSION};\nuse serde::{Deserialize, de::Error};\nuse serde_repr::Deserialize_repr;\nuse std::sync::Arc;\nuse thiserror::Error;\nuse tracing::debug;\nuse uuid::Uuid;\n\n#[derive(Debug, Error)]\npub enum LoginError {\n    #[error(\"Login packet data is not valid JSON\")]\n    InvalidTokenFormat(#[from] serde_json::Error),\n    #[error(\"JWT chain validation failed: {0}\")]\n    ChainValidationFailed(#[from] AuthError),\n    #[error(\"The validated username is invalid\")]\n    InvalidUsername,\n    #[error(\"Could not parse UUID from validated token\")]\n    InvalidUuid,\n    #[error(\"Cannot accept self-signed token. Authentication is enforced by server config.\")]\n    SelfSignedNotAllowed,\n    #[error(\"Got a guest/splitscreen login request. Currently unimplemented.\")]\n    GuestUnimplemented,\n    #[error(\"Failed to decode extra using decode_b64_url_nopad.\")]\n    DecodeExtraError,\n}\n\n#[derive(Deserialize_repr)]\n#[repr(u8)]\nenum AuthenticationType {\n    Full,\n    Guest,","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin/src/net/bedrock/login/mod.rs#L16-L52","documentation":"This is the LoginError::ChainValidationFailed variant of Pumpkin's Bedrock login error enum. It wraps an AuthError produced while validating the client's JWT identity chain during the Bedrock edition login handshake. The library throws it because the Xbox Live / Mojang certificate chain sent in the Login packet failed cryptographic or structural validation, so the client's identity cannot be trusted.","triggerScenarios":"A Bedrock client sends a Login packet whose JWT chain (xbox live -> xsts -> mojang certificates) fails AuthError validation — e.g. an expired XSTS token, a chain with missing or reordered links, a signature that doesn't verify, or a chain signed by an untrusted key.","commonSituations":"Clients with stale Xbox Live sessions, modified/unofficial clients presenting forged certificates, servers whose trusted root keys are outdated after a Mojang key rotation, or proxy setups that strip or mangle the chain.","solutions":["Have the client sign out and back into Xbox Live so a fresh, unexpired JWT chain is issued","Update the server (and its bundled Mojang/Xbox public keys) so the trusted key set matches current Mojang certificates","If the client is modified, revert to a vanilla client that presents a genuine certificate chain","Check middleware/proxies between client and server for packet corruption of the login payload"],"exampleFix":"// before: accepting any login without inspecting the wrapped cause\nmatch login_result { Err(e) => warn!(\"login failed\"), }\n// after: log the underlying AuthError to see why the chain was rejected\nmatch login_result {\n    Err(LoginError::ChainValidationFailed(auth_err)) => {\n        warn!(\"JWT chain rejected: {auth_err}; client should re-authenticate with Xbox Live\");\n    }\n    Err(e) => warn!(\"login failed: {e}\"),\n    Ok(_) => {}\n}","handlingStrategy":"try-catch","validationCode":"// Before treating login as success, verify chain presence and freshness client-side\nfn precheck_chain(jwt_chain: &[String]) -> Result<(), String> {\n    if jwt_chain.is_empty() { return Err(\"empty JWT chain\".into()); }\n    if jwt_chain.iter().any(|j| j.is_empty()) { return Err(\"blank JWT in chain\".into()); }\n    Ok(())\n}","typeGuard":"fn is_chain_validation_failed(e: &LoginError) -> bool {\n    matches!(e, LoginError::ChainValidationFailed(_))\n}","tryCatchPattern":"match login_result {\n    Err(LoginError::ChainValidationFailed(auth)) => {\n        // transient auth problems: prompt re-login; do not retry the same packet\n        disconnect_with(\"Please re-authenticate with Xbox Live and reconnect\")\n    }\n    Err(e) => disconnect_with(&format!(\"Login failed: {e}\")),\n    Ok(p) => admit(p),\n}","preventionTips":["Keep clients signed into Xbox Live so tokens are fresh","Keep the server updated with current Mojang trusted keys","Avoid MITM proxies that alter the login payload","Log the wrapped AuthError to distinguish expired vs untrusted signatures"],"tags":["authentication","jwt","bedrock","minecraft","security"],"backgroundTag":"jwt-validation-failed","analyzedSha":"8d4639e25a57c15e47448ec327c780d41bbf2356","analyzedAt":"2026-09-09T15:32:22.916Z","contentChangedAt":"2026-09-09T15:32:22.916Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}