Zum Inhalt springen
ecdsa.com
Go

golang-jwt/jwt

golang-jwt/jwt, der von der Community gepflegte Nachfolger von dgrijalva/jwt-go und das meistgenutzte JWT-Paket für Go: Prüfung nach Schlüsseltyp, none nur über einen expliziten Sentinel-Wert und ein Ablauf, der nur Pflicht ist, wenn du ihn verlangst.
Lizenz
MIT
Geprüfte Version
5.3.1 ·
Quellcode
github.com/golang-jwt/jwt
Dokumentation
pkg.go.dev/github.com/golang-jwt/jwt/v5

Kompatibilität auf einen Blick

JOSE und JWT

JWS-Algorithmen
HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512EdDSA

github.com/golang-jwt/jwt/v5 parst, validiert und signiert JWTs mit den Schlüsseltypen der Standardbibliothek: []byte für HMAC, *rsa.PublicKey, *ecdsa.PublicKey und ed25519.PublicKey. In 5.3.1 funktionierten Signieren und Prüfen mit den Familien HS, RS, PS und ES sowie mit EdDSA; für ES256K und die vollständig spezifizierten Namen Ed25519 und Ed448 ist keine Signaturmethode registriert.

Ob die Prüfung greift, hängt von der Keyfunc ab, die du an jwt.Parse übergibst. Jede Signaturmethode prüft den Go-Typ des Schlüssels, den sie erhält: Mit einer Keyfunc, die *ecdsa.PublicKey zurückgibt, scheiterte ein RS256-Token mit RSA verify expects *rsa.PublicKey und ein HS256-Token mit dem PEM-Text als Schlüssel mit HMAC verify expects []byte. Der Schutz verschwindet, wenn die Keyfunc für jedes Token rohe Bytes zurückgibt – mit einer Keyfunc, die die PEM-Datei als []byte lädt, bestand dieses gefälschte HS256-Token die Prüfung. Übergib jwt.WithValidMethods mit genau dem Algorithmus und sorge dafür, dass die Keyfunc typisierte Schlüssel zurückgibt, wie es das Beispiel tut.

Ein Token mit alg: none besteht die Prüfung nur, wenn die Keyfunc den Sentinel-Wert jwt.UnsafeAllowNoneSignatureType zurückgibt; jeder echte Schlüssel führt zu 'none' signature type is not allowed. ES256 lehnt einen P-384-Schlüssel schon beim Signieren mit einem knappen key is invalid ab. ES256-Signaturen sind das 64 Byte lange rohe r‖s, das JWS verlangt; eine DER-Signatur scheitert mit crypto/ecdsa: verification error – diesen Fehler aufzuspüren helfen der JWT-Debugger und der Konverter DER ⇄ Raw.

In v5 ist die Validierung der Claims standardmäßig aktiv, aber exp ist optional – ein Token ohne diesen Claim ist für immer gültig –, und es gibt keine Toleranz (Leeway). jwt.WithExpirationRequired(), jwt.WithIssuer, jwt.WithAudience und jwt.WithLeeway schließen diese Lücken; Fehler lassen sich mit errors.Is(err, jwt.ErrTokenExpired) erkennen, statt Strings zu vergleichen.

Um Tokens eines Identity Providers zu prüfen, kombiniere golang-jwt mit einem JWKS-Client und prüfe mit dem JWKS-Checker, was der Anbieter veröffentlicht; go-jose ist die Alternative, wenn du JWE oder JWK verarbeiten musst.

Fakten und die Prüfungen dahinter

Nichts im Folgenden ist aus einer Dokumentation abgeschrieben. Das Prüfskript content/libraries/verify/golang-jwt/run.sh hat golang-jwt/jwt 5.3.1 am 20. Oktober 2026 im Container-Image golang:1.27.3-trixie ausgeführt; die Seite muss mit seiner Ausgabe übereinstimmen, und jeder Fakt führt die zugehörigen Zeilen auf.

  • JWS-Algorithmen

    HS256HS384HS512RS256RS384RS512PS256PS384PS512ES256ES384ES512EdDSA

    Signieren und Prüfen funktionierten mit HS, RS, PS und ES bei 256/384/512 Bit sowie mit EdDSA; für ES256K, Ed25519 und Ed448 ist keine Signaturmethode registriert.

    Von der Prüfung aufgezeichnet
    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
  • Kodierung von ES256-Signaturen

    raw

    ES256-Signaturen bestehen aus 64 Byte rohem r‖s.

    Von der Prüfung aufgezeichnet
    fact jws-ecdsa-encoding = raw
  • DER-Signatur in einer JWS

    rejected

    Eine DER-kodierte ES256-Signatur scheitert mit token signature is invalid: crypto/ecdsa: verification error.

    Von der Prüfung aufgezeichnet
    fact jws-der-signature = rejected
    evidence jws-der-signature: token signature is invalid: crypto/ecdsa: verification error
  • Allowlist der Algorithmen

    from-key

    Ohne WithValidMethods entscheidet der Go-Typ des Schlüssels: Ein RS256-Token scheiterte an einer Keyfunc, die einen EC-Schlüssel zurückgibt, mit key is of invalid type: RSA verify expects *rsa.PublicKey.

    Von der Prüfung aufgezeichnet
    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
  • Unsignierte Tokens (alg none)

    opt-in

    Ein unsigniertes Token scheitert mit 'none' signature type is not allowed, sofern die Keyfunc nicht jwt.UnsafeAllowNoneSignatureType zurückgibt.

    Von der Prüfung aufgezeichnet
    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>
  • Öffentlicher Schlüssel als HMAC-Secret

    rejected

    Ein HS256-Token mit dem PEM-Text als Schlüssel scheiterte an einer Keyfunc, die *ecdsa.PublicKey zurückgibt (HMAC verify expects []byte), bestand die Prüfung aber, als die Keyfunc die PEM-Bytes zurückgab.

    Von der Prüfung aufgezeichnet
    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>
  • Abgleich der Kurve mit alg

    enforced

    Das Signieren mit ES256 und einem P-384-Schlüssel scheitert mit key is invalid.

    Von der Prüfung aufgezeichnet
    fact jwt-ecdsa-curve-check = enforced
    evidence jwt-ecdsa-curve-check: key is invalid
  • Standardtoleranz für Uhrabweichungen

    0s

    Standardmäßig keine Toleranz (Leeway): Ein Token, das drei Sekunden zuvor abgelaufen war, wurde abgelehnt.

    Von der Prüfung aufgezeichnet
    fact jwt-clock-skew = 0s
  • Ablauf-Claim erforderlich

    no

    Ein Token ohne exp war gültig; mit WithExpirationRequired() scheitert es mit token is missing required claim: exp claim is required.

    Von der Prüfung aufgezeichnet
    fact jwt-exp-required = no
    evidence jwt-exp-required: with WithExpirationRequired: token has invalid claims: token is missing required claim: exp claim is required

Verwendung

Signiere registrierte Claims mit ES256 und parse das Token wieder – mit typisierter Keyfunc, festgelegter Methode, vorgeschriebenem Aussteller und Ablauf sowie gesetzter Toleranz.
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)
}

Die Snippet-Testumgebung führt jedes Beispiel unverändert im Container-Image golang:1.27.3-trixie aus, und der Lauf schlägt fehl, wenn die Ausgabe nicht übereinstimmt.

Befehl
GOFLAGS=-mod=mod go run .
Ausgabe muss passen (regulärer Ausdruck)
valid: true sub: user-42

Bibliotheken