web-token implements JWS, JWE, JWK and JWK sets as separate components; web-token/jwt-library bundles them, and a Symfony bundle wires them into services. It is the PHP choice when you need JWE, JWK set management or the full algorithm list: 4.2.3 signed and verified HS, RS, PS and ES at 256/384/512 and EdDSA, including PS384/512 and ES512 that firebase/php-jwt lacks. There is no ES256K or fully specified Ed25519 algorithm class.
Algorithms are allowed explicitly: the AlgorithmManager passed to JWSVerifier is the allow-list, and a token in any other algorithm fails with The algorithm "RS256" is not supported. none exists as an algorithm class but is only accepted if you put it in the manager. An HS256 token forged with the EC key's PEM text failed even with HS256 allowed, because an EC JWK cannot be used as an HMAC key. ES256 with a P-384 key produced a signature that the library's own verifier rejected.
Verification and claim checking are separate steps: JWSVerifier::verifyWithKey() returned true for a token that had expired an hour earlier. Run a ClaimCheckerManager afterwards, list mandatory claims — exp is not mandatory otherwise — and pass a drift to ExpirationTimeChecker, which since version 4 also needs a PSR-20 clock; the sample shows the whole sequence.
ES256 signatures are 64 bytes of raw r‖s and a DER signature makes verifyWithKey() return false; the JWT debugger shows which one a token carries. Keys are JWK objects throughout; JWKFactory builds them from PEM, certificates or key parameters, and the JWKS builder produces key sets in the same format.