Solve "jwt malformed" errors caused by improper Bearer prefix stripping, URL encoding, or truncation in headers.
The provided string cannot be split into three period-separated Base64URL segments (header.payload.signature). This frequently happens when "Bearer " prefix is included in the verification call or undefined is passed.
A valid JWT strictly adheres to RFC 7519 format: `^[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+$`. Any non-base64url characters or missing periods trigger immediate malformed rejection.
// If req.headers.authorization is "Bearer eyJhbGci...", passes entire string
jwt.verify(req.headers.authorization, SECRET);// Strips "Bearer " prefix and handles undefined/null safely
const rawHeader = req.headers.authorization;
if (!rawHeader || !rawHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'missing_or_invalid_auth_header' });
}
const token = rawHeader.slice(7).trim();
const payload = jwt.verify(token, SECRET);Resolution Note: Always verify header format and slice out the 7-character "Bearer " prefix.
Log the raw string being passed to `jwt.verify()` — check for `"Bearer "` or `"undefined"`.
Verify client cookie or localStorage retrieval logic is not returning `"null"`.
Check for newline characters or URL encoding (`%20`) within the token string.
Prevent recurrence by enforcing this verification check in staging or pre-commit hooks:
export function extractBearerToken(headerValue: string | null): string | null {
if (!headerValue) return null;
const match = headerValue.match(/^Bearer\s+([A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*)$/);
return match ? match[1] : null;
}