Saltar al contenido
ecdsa.com
Go

golang-jwt/jwt

golang-jwt/jwt, el sucesor de dgrijalva/jwt-go mantenido por la comunidad y el paquete JWT más usado de Go: verificación según el tipo de clave, none solo tras un centinela explícito y caducidad opcional salvo que la exijas.
Licencia
MIT
Versión comprobada
5.3.1 ·
Código fuente
github.com/golang-jwt/jwt
Documentación
pkg.go.dev/github.com/golang-jwt/jwt/v5

Compatibilidad de un vistazo

JOSE y JWT

Algoritmos JWS
HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512EdDSA

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.

Datos y las comprobaciones que los respaldan

Nada de lo que sigue está copiado de la documentación. La comprobación content/libraries/verify/golang-jwt/run.sh ejecutó golang-jwt/jwt 5.3.1 en la imagen de contenedor golang:1.27.3-trixie el 20 de octubre de 2026; la página debe coincidir con lo que imprimió, y cada dato cita esas líneas.

  • Algoritmos JWS

    HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512EdDSA

    Con HS, RS, PS y ES de 256/384/512 bits y EdDSA se firmó y se verificó; ES256K, Ed25519 y Ed448 no tienen ningún método de firma registrado.

    Registrado por la comprobación
    fact jws-algorithms = HS256, HS384, HS512, RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, EdDSA
    evidence jws-algorithms: ES256K: no signing method registered
    evidence jws-algorithms: Ed25519: no signing method registered
    evidence jws-algorithms: Ed448: no signing method registered
  • Codificación de la firma ES256

    raw

    Las firmas ES256 son 64 bytes de r‖s en bruto.

    Registrado por la comprobación
    fact jws-ecdsa-encoding = raw
  • Firma DER dentro de un JWS

    rejected

    Una firma ES256 codificada en DER falla con token signature is invalid: crypto/ecdsa: verification error.

    Registrado por la comprobación
    fact jws-der-signature = rejected
    evidence jws-der-signature: token signature is invalid: crypto/ecdsa: verification error
  • Lista de algoritmos permitidos

    from-key

    Sin WithValidMethods, decide el tipo Go de la clave: un token RS256 contra una keyfunc que devuelve una clave EC falló con key is of invalid type: RSA verify expects *rsa.PublicKey.

    Registrado por la comprobación
    fact jwt-algorithm-allowlist = from-key
    evidence jwt-algorithm-allowlist: RS256 token, keyfunc returning the EC public key, no WithValidMethods: token signature is invalid: key is of invalid type: RSA verify expects *rsa.PublicKey
  • Tokens sin firma (alg none)

    opt-in

    Un token sin firmar falla con 'none' signature type is not allowed salvo que la keyfunc devuelva jwt.UnsafeAllowNoneSignatureType.

    Registrado por la comprobación
    fact jwt-alg-none = opt-in
    evidence jwt-alg-none: with the EC key: token signature is invalid: token is unverifiable: 'none' signature type is not allowed
    evidence jwt-alg-none: keyfunc returning jwt.UnsafeAllowNoneSignatureType: <nil>
  • Clave pública usada como secreto HMAC

    rejected

    Un token HS256 con el texto PEM como clave falló contra una keyfunc que devuelve *ecdsa.PublicKey (HMAC verify expects []byte), pero se verificó cuando la keyfunc devolvió los bytes PEM.

    Registrado por la comprobación
    fact jwt-hmac-public-key = rejected
    evidence jwt-hmac-public-key: keyfunc returning *ecdsa.PublicKey: token signature is invalid: key is of invalid type: HMAC verify expects []byte
    evidence jwt-hmac-public-key: keyfunc returning the PEM bytes (a keyfunc that loads keys as bytes): <nil>
  • Curva cotejada con alg

    enforced

    Firmar ES256 con una clave P-384 falla con key is invalid.

    Registrado por la comprobación
    fact jwt-ecdsa-curve-check = enforced
    evidence jwt-ecdsa-curve-check: key is invalid
  • Desfase de reloj predeterminado

    0s

    Sin tolerancia por defecto: se rechazó un token que había caducado 3 segundos antes.

    Registrado por la comprobación
    fact jwt-clock-skew = 0s
  • Claim de caducidad obligatorio

    no

    Un token sin exp fue válido; WithExpirationRequired() hace que falle con token is missing required claim: exp claim is required.

    Registrado por la comprobación
    fact jwt-exp-required = no
    evidence jwt-exp-required: with WithExpirationRequired: token has invalid claims: token is missing required claim: exp claim is required

Uso

Firma claims registrados con ES256 y vuelve a analizarlos con una keyfunc tipada, el método fijado, y el emisor, la caducidad y la tolerancia aplicados.
package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"fmt"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

func main() {
	key, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	claims := jwt.RegisteredClaims{Subject: "user-42", Issuer: "https://auth.example.com", ExpiresAt: jwt.NewNumericDate(time.Now().Add(10 * time.Minute))}
	signed, _ := jwt.NewWithClaims(jwt.SigningMethodES256, claims).SignedString(key)

	// The keyfunc returns a typed key; the options pin the method and the claims.
	token, err := jwt.ParseWithClaims(signed, &jwt.RegisteredClaims{},
		func(*jwt.Token) (any, error) { return &key.PublicKey, nil },
		jwt.WithValidMethods([]string{"ES256"}),
		jwt.WithIssuer("https://auth.example.com"),
		jwt.WithExpirationRequired(),
		jwt.WithLeeway(30*time.Second),
	)
	fmt.Println("valid:", err == nil && token.Valid, "sub:", token.Claims.(*jwt.RegisteredClaims).Subject)
}

El arnés de pruebas de fragmentos de código ejecuta cada ejemplo tal cual en la imagen de contenedor golang:1.27.3-trixie, y la ejecución falla si la salida no coincide.

Comando
GOFLAGS=-mod=mod go run .
La salida debe coincidir (expresión regular)
valid: true sub: user-42

Bibliotecas