O lcobucci/jwt separa análise, assinatura e validação: uma Configuration guarda o signatário e as chaves, parser()->parse() lê um token sem verificar nada, e validator()->assert() aplica as restrições que você passa. Chamar assert() sem restrições lança NoConstraintsGiven, o que torna difícil escrever por acidente uma validação que não verifica nada.
SignedWith fixa o signatário e a chave: um token RS256 e um token HS256 forjado com o texto PEM da chave EC falharam, ambos, com Token signer mismatch. Tokens sem assinatura nem sequer podem ser analisados (The JWT string is missing the Signature part). Os tamanhos de chave são impostos no momento da assinatura — o ES256 recusou uma chave P-384 (The length of the provided key is different than 256 bits) e o HS256 recusou uma chave de 40 bits —, o que impede que tokens malformados sejam sequer produzidos.
As verificações de tempo também são restrições, então só rodam quando listadas: um token que tinha expirado uma hora antes passou só com SignedWith. LooseValidAt verifica exp, nbf e iat quando presentes e aceitou um token sem exp; StrictValidAt exige as três — um token sem iat falhou com "Issued At" claim missing, e um com iat e exp, mas sem nbf, com "Not Before" claim missing. Ambas aceitam um intervalo de tolerância opcional, zero por padrão. O exemplo define as três claims e valida assinatura, emissor e validade estrita em uma única chamada.
A versão 5.6.1 oferece suporte a HS, RS e ES em 256/384/512 e a EdDSA; não há signatários PS* nem ES256K, então tokens de emissores que usam RSA-PSS precisam do web-token. As assinaturas ES256 são 64 bytes de r‖s brutos, e uma assinatura DER falha com Token signature mismatch; o depurador de JWT mostra qual codificação um token usa.