github.com/golang-jwt/jwt/v5 analiza, valida y firma JWT con las claves de la biblioteca estándar: []byte para HMAC, *rsa.PublicKey, *ecdsa.PublicKey y ed25519.PublicKey. Con la 5.3.1 se firmó y se verificó con las familias HS, RS, PS y ES y con EdDSA; ES256K y los nombres totalmente especificados Ed25519 y Ed448 no tienen ningún método de firma registrado.
La verificación depende de la keyfunc que pasas a jwt.Parse. Cada método de firma comprueba el tipo Go de la clave que recibe, así que, con una keyfunc que devuelve *ecdsa.PublicKey, un token RS256 falló con RSA verify expects *rsa.PublicKey y un token HS256 con el texto PEM como clave falló con HMAC verify expects []byte. La protección desaparece si la keyfunc devuelve bytes sin más para cualquier token: en la comprobación, una keyfunc que carga el archivo PEM como []byte permitió verificar ese token HS256 falsificado. Pasa jwt.WithValidMethods con el algoritmo exacto y mantén la keyfunc tipada, como hace el ejemplo.
alg: none solo se verifica cuando la keyfunc devuelve el centinela jwt.UnsafeAllowNoneSignatureType; cualquier clave real produce 'none' signature type is not allowed. ES256 rechaza una clave P-384 al firmar con un escueto key is invalid. Las firmas ES256 son el r‖s en bruto de 64 bytes que exige JWS; una firma DER falla con crypto/ecdsa: verification error, un error que ayudan a localizar el decodificador de JWT y el conversor DER ⇄ en bruto.
En la v5, la validación de los claims está activada por defecto, pero exp es opcional —un token sin él es válido para siempre— y no hay tolerancia. jwt.WithExpirationRequired(), jwt.WithIssuer, jwt.WithAudience y jwt.WithLeeway cubren esas carencias; los errores se pueden identificar con errors.Is(err, jwt.ErrTokenExpired) en lugar de comparar cadenas.
Para verificar tokens de un proveedor de identidad, combínalo con un cliente JWKS y comprueba lo que publica el proveedor con el comprobador de JWKS; go-jose es la alternativa cuando se necesita manejar JWE o JWK.