lcobucci/jwt separates parsing, signing and validation: a Configuration holds the signer and keys, parser()->parse() reads a token without checking anything, and validator()->assert() applies the constraints you pass. Calling assert() with no constraints throws NoConstraintsGiven, which makes a validation that checks nothing hard to write by accident.
SignedWith pins the signer and key: an RS256 token and an HS256 token forged with the EC key's PEM text both failed with Token signer mismatch. Unsigned tokens cannot even be parsed (The JWT string is missing the Signature part). Key sizes are enforced at signing time — ES256 refused a P-384 key (The length of the provided key is different than 256 bits) and HS256 refused a 40-bit key — which keeps malformed tokens from being produced at all.
Time checks are constraints too, so they only run when listed: a token that had expired an hour earlier passed SignedWith alone. LooseValidAt checks exp, nbf and iat when present and accepted a token without exp; StrictValidAt requires all three — a token without iat failed with "Issued At" claim missing, and one with iat and exp but no nbf with "Not Before" claim missing. Both take an optional leeway interval, zero by default. The sample sets all three claims and asserts signature, issuer and strict validity in one call.
5.6.1 supports HS, RS and ES at 256/384/512 and EdDSA; there are no PS* signers and no ES256K, so tokens from issuers using RSA-PSS need web-token. ES256 signatures are 64 bytes of raw r‖s, and a DER signature fails with Token signature mismatch; the JWT debugger shows which encoding a token carries.