{"record":{"id":"1f442786a9228508","repo":"clockworklabs/SpacetimeDB","slug":"token-does-not-look-like-a-json-web-token-token","errorCode":null,"errorMessage":"Token does not look like a JSON web token: {token}","messagePattern":"Token does not look like a JSON web token: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/cli/src/util.rs","lineNumber":338,"sourceCode":"    if force {\n        println!(\"Skipping confirmation due to --yes\");\n        return Ok(true);\n    }\n    let mut input = String::new();\n    print!(\"{prompt} [y/N]\");\n    std::io::stdout().flush()?;\n    std::io::stdin().read_line(&mut input)?;\n    let input = input.trim().to_lowercase();\n    Ok(input == \"y\" || input == \"yes\")\n}\n\npub fn decode_identity(token: &String) -> anyhow::Result<String> {\n    // Here, we manually extract and decode the claims from the json web token.\n    // We do this without using the `jsonwebtoken` crate because it doesn't seem to have a way to skip signature verification.\n    // But signature verification would require getting the public key from a server, and we don't necessarily want to do that.\n    let token_parts: Vec<_> = token.split('.').collect();\n    if token_parts.len() != 3 {\n        return Err(anyhow::anyhow!(\"Token does not look like a JSON web token: {token}\"));\n    }\n    let decoded_bytes = BASE_64_STD_NO_PAD.decode(token_parts[1])?;\n    let decoded_string = String::from_utf8(decoded_bytes)?;\n\n    let claims_data: IncomingClaims = serde_json::from_str(decoded_string.as_str())?;\n    let claims_data: SpacetimeIdentityClaims = claims_data.try_into()?;\n\n    Ok(claims_data.identity.to_string())\n}\n\npub async fn get_login_token_or_log_in(\n    config: &mut Config,\n    target_server: Option<&str>,\n    interactive: bool,\n) -> anyhow::Result<String> {\n    if let Some(token) = config.spacetimedb_token() {\n        return Ok(token.clone());\n    }","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/cli/src/util.rs#L320-L356","documentation":"decode_identity in the CLI manually splits a JWT on '.' expecting exactly three segments (header.payload.signature), then base64-decodes the payload to read identity claims without verifying the signature. Anything that is not a three-part JWT — a hex identity string, a truncated token, or a token with extra characters — is rejected before decoding.","triggerScenarios":"Passing a 32-byte hex Identity instead of the JWT to `spacetime identity decode` or the login flow; a token string that includes surrounding quotes, whitespace, or a trailing newline; a mangled or empty token read from a config file or env var.","commonSituations":"Confusing the public identity (hex) with the auth token (JWT); scripts reading the wrong line of a token file; copy-pasting a token from JSON where it was escaped or truncated.","solutions":["Confirm you are passing the JWT (three dot-separated base64url segments), not the hex identity.","Strip whitespace, newlines, and surrounding quotes before passing the token.","Mint a fresh token with `spacetime login` (or re-export SPACETIMEDB_SPACETIME_TOKEN) and retry.","If the token came from a file, check it was not truncated or JSON-escaped."],"exampleFix":"# before — hex identity passed by mistake\nspacetime identity decode 37101e97b3f2...\n# after — pass the JWT produced by `spacetime login`\nspacetime identity decode eyJhbGciOi....eyJ....SIG","handlingStrategy":"validation","validationCode":"function assertJwtShape(token: string): void {\n  const parts = token.trim().split('.');\n  if (parts.length !== 3 || parts.some(p => p.length === 0)) {\n    throw new Error('expected a three-segment JWT (header.payload.signature), not an identity hex string');\n  }\n}","typeGuard":"function isJwtLike(token: string): boolean {\n  const t = token.trim();\n  return t.split('.').length === 3 && /^[A-Za-z0-9_-]+$/.test(t.split('.')[1]);\n}","tryCatchPattern":null,"preventionTips":["Trim whitespace, newlines, and quotes from tokens before use.","Store the JWT and the hex identity under clearly different variable names.","Regenerate tokens with `spacetime login` rather than hand-editing them."],"tags":["spacetimedb","cli","jwt","identity","token"],"backgroundTag":"malformed-jwt","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}