Saltar al contenido
ecdsa.com
golang-jwt/jwt (Go)Go

Mensaje de error

token signature is invalid: crypto/ecdsa: verification error

También se muestra como

  • token signature is invalid: crypto/rsa: verification error
  • token signature is invalid: signature is invalid
  • token signature is invalid: ed25519: verification error
  • crypto/ecdsa: verification error

golang-jwt v4 solo devuelve el texto interno, por ejemplo «crypto/ecdsa: verification error». Usa `errors.Is(err, jwt.ErrTokenSignatureInvalid)` (v5) en lugar de comparar cadenas.

golang-jwt/jwt (Go) — jwt.ErrTokenSignatureInvalid joined with the algorithm's verification error

Qué significa

golang-jwt analiza el token, acepta su algoritmo y obtiene una clave de tu `Keyfunc`, pero la firma no se verifica con esa clave. En la v5, el error une `jwt.ErrTokenSignatureInvalid` («token signature is invalid») con el error propio del algoritmo: `crypto/ecdsa: verification error` para ES*, `crypto/rsa: verification error` para RS*/PS*, `signature is invalid` para HS*. Los bytes del token y la clave simplemente no corresponden entre sí.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Resolver la clave por kid desde el JWKS

    Deja que la Keyfunc elija, del conjunto de claves del emisor, la clave que nombra el encabezado del token, y que actualice ese conjunto tras cada rotación (por ejemplo, con `github.com/MicahParks/keyfunc`). Fija siempre `WithValidMethods`.

    go
    import (
    	"context"
    	"github.com/MicahParks/keyfunc/v3"
    	"github.com/golang-jwt/jwt/v5"
    )
    
    // Resolve the verification key from the issuer's JWKS by the token's kid.
    k, err := keyfunc.NewDefaultCtx(ctx, []string{"https://issuer.example.com/.well-known/jwks.json"})
    if err != nil {
    	return err
    }
    token, err := jwt.Parse(raw, k.Keyfunc,
    	jwt.WithValidMethods([]string{"ES256"}),
    	jwt.WithIssuer("https://issuer.example.com/"),
    	jwt.WithAudience("https://api.example.com"))
  2. 2.

    Demostrar que ambos lados usan la misma clave

    Calcula el hash de la clave pública codificada en DER en el verificador y el de la mitad pública de la clave privada del emisor. Si los hashes difieren, la investigación termina ahí.

    bash
    # Same key on both sides? Compare SPKI fingerprints.
    openssl pkey -pubin -in verifier-public.pem -outform DER | sha256sum
    openssl pkey -in issuer-private.pem -pubout -outform DER | sha256sum
  3. 3.

    Gestionar la clase de error, no la cadena

    golang-jwt v5 expone errores centinela. Asigna a un fallo de firma una respuesta 401 y no recurras a probar otras claves ni a omitir la verificación.

    go
    switch {
    case errors.Is(err, jwt.ErrTokenSignatureInvalid):
    	return http.StatusUnauthorized // wrong key or tampered token: never retry with another key blindly
    case errors.Is(err, jwt.ErrTokenExpired):
    	return http.StatusUnauthorized // client should refresh
    case errors.Is(err, jwt.ErrTokenMalformed):
    	return http.StatusBadRequest
    }

Errores relacionados

Explorar toda la base de datos de errores de firma