lcobucci/jwt · error · Lcobucci\JWT\Token\InvalidTokenStructure

The JWT string is missing the Signature part

Error message

The JWT string is missing the Signature part

What it means

Parser::parse() requires the third JWT segment (the Base64Url-encoded signature) to be non-empty. When it is empty, InvalidTokenStructure::missingSignaturePart() is thrown. A JWT shaped 'header.claims.' cannot be verified.

Solutions

  1. Use the full token exactly as issued — copy all three segments including the final signature
  2. Reject tokens lacking a signature; this library requires signed tokens
  3. Catch InvalidTokenStructure and return 'malformed token' to the client
  4. If you need unsecured JWTs, use a different mechanism — lcobucci/jwt requires verification of the signature segment

Example fix

// before
$token = $parser->parse($jwt); // jwt = 'aaa.bbb.'
// after
$segments = explode('.', $jwt);
if (count($segments) !== 3 || in_array('', $segments, true)) {
    throw new InvalidArgumentException('Malformed JWT: missing signature');
}
$token = $parser->parse($jwt);
Defensive patterns

Strategy: validation

Validate before calling

$parts = explode('.', $jwt); if (count($parts) !== 3 || $parts[2] === '') { throw new InvalidArgumentException('JWT signature missing'); }

Try / catch

try { $token = $parser->parse($jwt); } catch (Lcobucci\JWT\InvalidTokenStructure $e) { return error_401('Malformed token'); }

Prevention

When it happens

Trigger: Calling parse('header.claims.') or parse('header.claims') combined with a trailing dot — unsigned/truncated tokens; also JLS-style unsecured JWTs (alg:none) that this library does not accept.

Common situations: Tokens cut off when copied (signature is the last part and often truncated); unsigned JWTs issued by non-compliant services; tests using hand-made tokens without a signature.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of lcobucci/jwt@375813049c (2026-09-14). Data as JSON: /api/errors/6e6057b604496e74. Report an issue: GitHub.

Appendix: source

Thrown at src/Token/Parser.php:39

    public function __construct(private Decoder $decoder)
    {
    }

    public function parse(string $jwt): TokenInterface
    {
        [$encodedHeaders, $encodedClaims, $encodedSignature] = $this->splitJwt($jwt);

        if ($encodedHeaders === '') {
            throw InvalidTokenStructure::missingHeaderPart();
        }

        if ($encodedClaims === '') {
            throw InvalidTokenStructure::missingClaimsPart();
        }

        if ($encodedSignature === '') {
            throw InvalidTokenStructure::missingSignaturePart();
        }

        $header = $this->parseHeader($encodedHeaders);

        return new Plain(
            new DataSet($header, $encodedHeaders),
            new DataSet($this->parseClaims($encodedClaims), $encodedClaims),
            $this->parseSignature($encodedSignature),
        );
    }

    /**
     * Splits the JWT string into an array
     *
     * @param non-empty-string $jwt
     *
     * @return string[]
     *

View on GitHub (pinned to 375813049c)