Pular para o conteúdo
ecdsa.com
Go

golang-jwt/jwt

O golang-jwt/jwt, sucessor do dgrijalva/jwt-go mantido pela comunidade e o pacote de JWT mais usado em Go: verificação tipada pela chave, none só por trás de um valor sentinela explícito e expiração opcional, a menos que você a exija.
Licença
MIT
Versão verificada
5.3.1 ·
Código-fonte
github.com/golang-jwt/jwt
Documentação
pkg.go.dev/github.com/golang-jwt/jwt/v5

Visão geral da compatibilidade

JOSE e JWT

Algoritmos JWS
HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512EdDSA

github.com/golang-jwt/jwt/v5 analisa, valida e assina JWTs com as chaves da biblioteca padrão: []byte para HMAC, *rsa.PublicKey, *ecdsa.PublicKey e ed25519.PublicKey. A versão 5.3.1 assinou e verificou as famílias HS, RS, PS e ES e o EdDSA; ES256K e os nomes totalmente especificados Ed25519 e Ed448 não têm método de assinatura registrado.

A verificação depende da keyfunc que você passa para jwt.Parse. Cada método de assinatura confere o tipo Go da chave que recebe; assim, com uma keyfunc que retorna *ecdsa.PublicKey, um token RS256 falhou com RSA verify expects *rsa.PublicKey, e um token HS256 que usava o texto PEM como chave falhou com HMAC verify expects []byte. A proteção desaparece se a keyfunc devolver bytes brutos para qualquer token — uma keyfunc que carrega o arquivo PEM como []byte deixou esse token HS256 forjado passar na verificação do teste. Passe jwt.WithValidMethods com o algoritmo exato e mantenha a keyfunc tipada, como faz o exemplo.

alg: none só é verificado quando a keyfunc retorna o sentinela jwt.UnsafeAllowNoneSignatureType; qualquer chave real produz 'none' signature type is not allowed. O ES256 recusa uma chave P-384 no momento da assinatura com um simples key is invalid. As assinaturas ES256 são o r‖s bruto de 64 bytes que o JWS exige; uma assinatura DER falha com crypto/ecdsa: verification error, um erro que o depurador de JWT e o conversor DER ⇄ bruto ajudam a rastrear.

Na v5, a validação das claims vem ativada por padrão, mas exp é opcional — um token sem ela vale para sempre — e não há tolerância. jwt.WithExpirationRequired(), jwt.WithIssuer, jwt.WithAudience e jwt.WithLeeway fecham essas brechas; os erros podem ser identificados com errors.Is(err, jwt.ErrTokenExpired) em vez de comparar strings.

Para verificar tokens de um provedor de identidade, combine a biblioteca com um cliente JWKS e confira o que o provedor publica com o verificador de JWKS; o go-jose é a alternativa quando é preciso lidar com JWE ou JWK.

Os fatos e as verificações por trás deles

Nada abaixo foi copiado da documentação. A verificação content/libraries/verify/golang-jwt/run.sh executou golang-jwt/jwt 5.3.1 na imagem de contêiner golang:1.27.3-trixie em 20 de outubro de 2026; a página precisa corresponder ao que a verificação imprimiu, e cada fato lista essas linhas.

  • Algoritmos JWS

    HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512EdDSA

    Assinatura e verificação funcionaram com HS, RS, PS e ES em 256/384/512 bits e com EdDSA; ES256K, Ed25519 e Ed448 não têm método de assinatura registrado.

    Registrado pela verificação
    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
  • Codificação da assinatura ES256

    raw

    As assinaturas ES256 são 64 bytes de r‖s brutos.

    Registrado pela verificação
    fact jws-ecdsa-encoding = raw
  • Assinatura DER dentro de um JWS

    rejected

    Uma assinatura ES256 codificada em DER falha com token signature is invalid: crypto/ecdsa: verification error.

    Registrado pela verificação
    fact jws-der-signature = rejected
    evidence jws-der-signature: token signature is invalid: crypto/ecdsa: verification error
  • Lista de algoritmos permitidos

    from-key

    Sem WithValidMethods, quem decide é o tipo Go da chave: um token RS256 com uma keyfunc que retorna uma chave EC falhou com key is of invalid type: RSA verify expects *rsa.PublicKey.

    Registrado pela verificação
    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 sem assinatura (alg none)

    opt-in

    Um token sem assinatura falha com 'none' signature type is not allowed, a menos que a keyfunc retorne jwt.UnsafeAllowNoneSignatureType.

    Registrado pela verificação
    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>
  • Chave pública usada como segredo HMAC

    rejected

    Um token HS256 que usava o texto PEM como chave falhou contra uma keyfunc que retorna *ecdsa.PublicKey (HMAC verify expects []byte), mas foi verificado quando a keyfunc retornou os bytes PEM.

    Registrado pela verificação
    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 conferida com o alg

    enforced

    Assinar ES256 com uma chave P-384 falha com key is invalid.

    Registrado pela verificação
    fact jwt-ecdsa-curve-check = enforced
    evidence jwt-ecdsa-curve-check: key is invalid
  • Tolerância padrão de diferença de relógio

    0s

    Sem tolerância por padrão: um token que tinha expirado três segundos antes foi rejeitado.

    Registrado pela verificação
    fact jwt-clock-skew = 0s
  • Claim de expiração obrigatória

    no

    Um token sem exp foi considerado válido; WithExpirationRequired() o faz falhar com token is missing required claim: exp claim is required.

    Registrado pela verificação
    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

Assine claims registradas com ES256 e depois analise o token com uma keyfunc tipada, o método fixado e emissor, expiração e tolerância 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)
}

O executor de trechos de código roda cada exemplo literalmente na imagem de contêiner golang:1.27.3-trixie, e a execução falha se a saída não corresponder.

Comando
GOFLAGS=-mod=mod go run .
A saída deve corresponder a (expressão regular)
valid: true sub: user-42

Bibliotecas