Pumpkin-MC/Pumpkin · error · LoginError

Cannot accept self-signed token. Authentication is enforced…

Error message

Cannot accept self-signed token. Authentication is enforced by server config.

What it means

This is the LoginError::SelfSignedNotAllowed variant. Bedrock clients may present a self-signed JWT chain (used for local/LAN play without Xbox Live). When the server is configured to enforce Xbox Live authentication, Pumpkin refuses these self-signed tokens outright. The library throws it to enforce the server's online-auth policy.

Solutions

  1. Have the player sign into Xbox Live in their Bedrock client and reconnect
  2. If offline/self-signed logins are acceptable for this server, disable enforced authentication in the server config and restart
  3. If this is a test harness, generate a token through the real Xbox Live flow instead of self-signing
  4. Communicate the requirement to the player: self-signed tokens can never bypass an auth-enforced server

Example fix

// before (pumpkin.toml)
[authentication]
enforce = true   # offline clients rejected
// after (only if self-signed play is acceptable)
[authentication]
enforce = false  # allows self-signed/local tokens
Defensive patterns

Strategy: try-catch

Validate before calling

// Before connecting, confirm the client holds a real Xbox Live token,
// not a self-signed chain, when the server enforces auth
fn can_attempt_login(has_xbox_token: bool, server_enforces_auth: bool) -> bool {
    !server_enforces_auth || has_xbox_token
}

Type guard

fn is_self_signed_rejected(e: &LoginError) -> bool {
    matches!(e, LoginError::SelfSignedNotAllowed)
}

Try / catch

match login_result {
    Err(LoginError::SelfSignedNotAllowed) => {
        disconnect_with("This server requires Xbox Live authentication. Sign in and retry.")
    }
    Err(e) => disconnect_with(&format!("Login failed: {e}")),
    Ok(p) => admit(p),
}

Prevention

When it happens

Trigger: A client that is not signed into Xbox Live (or a tool that self-generates its key pair) sends a self-signed JWT chain in the Login packet while the server config has authentication enforcement enabled.

Common situations: LAN or offline players trying to join an auth-enforced server, testing tools using self-generated certificates, or server operators who enabled authentication but expect offline clients to connect.

Understand the failure class

Related errors


AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09). Data as JSON: /api/errors/d36981bb4eee3571. Report an issue: GitHub.

Appendix: source

Thrown at crates/pumpkin/src/net/bedrock/login/mod.rs:40

use pumpkin_world::{CURRENT_BEDROCK_MC_PROTOCOL, CURRENT_BEDROCK_MC_VERSION};
use serde::{Deserialize, de::Error};
use serde_repr::Deserialize_repr;
use std::sync::Arc;
use thiserror::Error;
use tracing::debug;
use uuid::Uuid;

#[derive(Debug, Error)]
pub enum LoginError {
    #[error("Login packet data is not valid JSON")]
    InvalidTokenFormat(#[from] serde_json::Error),
    #[error("JWT chain validation failed: {0}")]
    ChainValidationFailed(#[from] AuthError),
    #[error("The validated username is invalid")]
    InvalidUsername,
    #[error("Could not parse UUID from validated token")]
    InvalidUuid,
    #[error("Cannot accept self-signed token. Authentication is enforced by server config.")]
    SelfSignedNotAllowed,
    #[error("Got a guest/splitscreen login request. Currently unimplemented.")]
    GuestUnimplemented,
    #[error("Failed to decode extra using decode_b64_url_nopad.")]
    DecodeExtraError,
}

#[derive(Deserialize_repr)]
#[repr(u8)]
enum AuthenticationType {
    Full,
    Guest,
    SelfSigned,
}

#[derive(Deserialize)]
#[serde(rename_all = "PascalCase")]
struct AuthPayload {

View on GitHub (pinned to 8d4639e25a)