php-jwt encodes and decodes tokens with JWT::encode() and JWT::decode() on top of the openssl extension and libsodium. Since version 6 a Key object — key material plus algorithm — is mandatory, so the algorithm comes from your code, not from the token: an RS256 token and an HS256 token forged with the EC key's PEM text both failed against new Key($pem, 'ES256') with Incorrect key for this algorithm, and an unsigned token fails with Algorithm not supported. The guard holds only while the application builds the Key; new Key($pem, 'HS256') verified the forged token.
Version 7.2.1 handles HS256/384/512, RS256/384/512, ES256, ES384, ES256K and EdDSA. ES512 is not supported (Algorithm not supported), PS256 needs phpseclib/phpseclib installed, and PS384 and PS512 are not available at all — tokens from issuers using those algorithms need web-token or lcobucci/jwt. HMAC keys shorter than the hash are rejected (Provided key is too short).
ES256 is not bound to P-256: a token signed with a P-384 key under an ES256 header was produced and accepted by the library itself, though other libraries refuse it. ES256 signatures are converted to the 64-byte raw r‖s JWS requires; a DER signature fails with Signature verification failed. Check a token's signature in the JWT debugger.
Claims handling is minimal. exp, nbf and iat are checked only when present, JWT::$leeway is a global static defaulting to 0, and there is no issuer or audience validation at all — the sample checks exp and iss itself. For JWKS-based verification, JWK::parseKeySet() turns a key set into Key objects; inspect a provider's set with the JWKS checker.