Help us shape the future of Go! Take the 2026 Go Developer Survey

jwt

package
v0.26.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Overview

Package jwt issues and verifies JSON Web Tokens (RFC 7519) with the standard library: HS256, RS256, ES256 and EdDSA, an algorithm allowlist tied to each key (no algorithm confusion, never "none"), key ids with static or remote (JWKS) key sets that rotate, strict claim checks, a Guard for package auth, and rotating refresh tokens with reuse detection.

tok, err := jwt.Sign(key, jwt.Claims{Subject: u.AuthID(), ExpiresAt: time.Now().Add(15 * time.Minute)})
claims, err := verifier.Verify(ctx, tok)

See https://github.com/AlexGalhardo/vukem/blob/main/docs/authentication.md.

Example
package main

import (
	"context"
	"crypto/ed25519"
	"crypto/rand"
	"fmt"
	"time"

	"github.com/AlexGalhardo/vukem/auth/jwt"
)

func main() {
	_, priv, _ := ed25519.GenerateKey(rand.Reader)
	key := jwt.EdDSA("2026-10", priv)

	tok, _ := jwt.Sign(key, jwt.Claims{
		Subject: "42", Issuer: "https://api.example.com", Audience: []string{"api"},
		ExpiresAt: time.Now().Add(15 * time.Minute),
	})

	v := jwt.NewVerifier(jwt.StaticKeys(key), jwt.VerifyOptions{Issuer: "https://api.example.com", Audience: "api"})

	claims, err := v.Verify(context.Background(), tok)
	fmt.Println(claims.Subject, err)
}
Output:
42 <nil>

Index

Examples

Constants

View Source
const (
	AlgHS256 = "HS256"
	AlgRS256 = "RS256"
	AlgES256 = "ES256"
	AlgEdDSA = "EdDSA"
)

Supported algorithms.

Variables

View Source
var ErrInvalid = errors.New("jwt: invalid token")

ErrInvalid is returned for every token that fails verification; the cause is wrapped for logs and never shown to clients.

View Source
var ErrRefreshReused = errors.New("jwt: refresh token reused; family revoked")

ErrRefreshReused is returned when a refresh token is presented again after it was rotated: the whole token family is revoked, since one of its copies was stolen.

Functions

func RefreshTokensMigration

func RefreshTokensMigration(id string) schema.Migration

RefreshTokensMigration creates the refresh_tokens table.

func Sign

func Sign(k Key, c Claims) (string, error)

Sign returns a compact JWS of claims signed with k.

Types

type Claims

type Claims struct {
	Issuer    string
	Subject   string
	Audience  []string
	ExpiresAt time.Time
	NotBefore time.Time
	IssuedAt  time.Time
	ID        string
	// Extra holds the other claims (decoded JSON values).
	Extra map[string]any
}

Claims are the registered claims plus Extra private claims.

func ClaimsFrom

func ClaimsFrom(c *web.Ctx, guard string) (Claims, bool)

ClaimsFrom returns the claims of the token guard authenticated c with.

type Guard

type Guard[U auth.Authenticatable] struct {
	// contains filtered or unexported fields
}

Guard authenticates "Authorization: Bearer <jwt>" requests: the token must verify and its "sub" must name a user of the provider. It implements auth.Checker, so auth.Required(guard) protects routes.

func NewGuard

func NewGuard[U auth.Authenticatable](name string, v *Verifier, p auth.UserProvider[U]) *Guard[U]

NewGuard returns a JWT guard named name. It panics when v.Err() reports a misconfiguration (a RemoteJWKS without Audience or Issuer), so the app fails at boot rather than refusing every token.

func (*Guard[U]) APIOnly added in v0.25.0

func (*Guard[U]) APIOnly()

APIOnly implements auth.APIGuard: auth.Required answers 401 problem+json and never redirects to a login page.

func (*Guard[U]) Check

func (g *Guard[U]) Check(c *web.Ctx) bool

Check implements auth.Checker.

func (*Guard[U]) Name

func (g *Guard[U]) Name() string

Name implements auth.Checker.

func (*Guard[U]) User

func (g *Guard[U]) User(c *web.Ctx) (U, error)

User returns the token's user (cached for the request) or auth.ErrUnauthenticated.

type JWK

type JWK struct {
	Kty string `json:"kty"`
	Kid string `json:"kid,omitempty"`
	Alg string `json:"alg,omitempty"`
	Use string `json:"use,omitempty"`
	N   string `json:"n,omitempty"`
	E   string `json:"e,omitempty"`
	Crv string `json:"crv,omitempty"`
	X   string `json:"x,omitempty"`
	Y   string `json:"y,omitempty"`
}

JWK is a public JSON Web Key (RFC 7517).

func (JWK) Key

func (j JWK) Key() (Key, error)

Key converts j to a verification Key; symmetric keys are refused.

type JWKS

type JWKS struct {
	Keys []JWK `json:"keys"`
}

JWKS is a JSON Web Key Set.

func PublicJWKS

func PublicJWKS(keys ...Key) (JWKS, error)

PublicJWKS returns the public part of keys as a JWKS document, to serve at /.well-known/jwks.json. HMAC keys are never published.

type Key

type Key struct {
	// ID is the "kid" header.
	ID string
	// Alg is the only algorithm this key accepts.
	Alg string
	// Secret is the HS256 secret (at least 32 bytes).
	Secret []byte
	// Private signs (RSA, ECDSA P-256 or Ed25519); nil for verify-only keys.
	Private crypto.Signer
	// Public verifies.
	Public crypto.PublicKey
}

Key is a signing or verification key bound to one algorithm.

func ES256

func ES256(id string, k *ecdsa.PrivateKey) Key

ES256 returns an ECDSA P-256 SHA-256 key.

func EdDSA

func EdDSA(id string, k ed25519.PrivateKey) Key

EdDSA returns an Ed25519 key.

func HS256

func HS256(id string, secret []byte) Key

HS256 returns an HMAC-SHA256 key.

func RS256

func RS256(id string, k *rsa.PrivateKey) Key

RS256 returns an RSA PKCS#1 v1.5 SHA-256 key (at least 2048 bits).

type KeySet

type KeySet interface {
	Key(ctx context.Context, kid string) (Key, error)
}

KeySet finds verification keys by id (kid); "" asks for the only key.

func StaticKeys

func StaticKeys(keys ...Key) KeySet

StaticKeys is a fixed key set (current and previous keys during a rotation).

type RefreshTokens

type RefreshTokens struct {

	// TTL is the lifetime of each token (default 30 days).
	TTL time.Duration
	// Now is the clock (default time.Now).
	Now func() time.Time
	// contains filtered or unexported fields
}

RefreshTokens stores opaque, rotating refresh tokens (only their SHA-256 is kept). Each Rotate consumes the presented token and returns a new one of the same family; presenting a consumed token revokes the family.

func NewRefreshTokens

func NewRefreshTokens(ex database.Executor) *RefreshTokens

NewRefreshTokens uses the refresh_tokens table (RefreshTokensMigration).

func (*RefreshTokens) Issue

func (r *RefreshTokens) Issue(ctx context.Context, userID string) (string, error)

Issue starts a new token family for userID and returns the plain token.

func (*RefreshTokens) Revoke

func (r *RefreshTokens) Revoke(ctx context.Context, plain string) error

Revoke ends the family of plain (logout); unknown tokens are ignored.

func (*RefreshTokens) RevokeUser

func (r *RefreshTokens) RevokeUser(ctx context.Context, userID string) error

RevokeUser ends every refresh token of userID (password change).

func (*RefreshTokens) Rotate

func (r *RefreshTokens) Rotate(ctx context.Context, plain string) (userID, next string, err error)

Rotate consumes plain and returns its user and a new token of the same family. Unknown, expired or revoked tokens give ErrInvalid; a token that was already consumed gives ErrRefreshReused and revokes its family.

type RemoteJWKS

type RemoteJWKS struct {
	URL string
	// Client fetches the set (default: 10s timeout).
	Client *http.Client
	// MaxAge refreshes the cache after this long (default 1h).
	MaxAge time.Duration
	// MinRefresh limits refetches for unknown key ids (default 1m), so
	// tokens with random kids cannot hammer the provider.
	MinRefresh time.Duration
	// Now is the clock (default time.Now).
	Now func() time.Time
	// contains filtered or unexported fields
}

RemoteJWKS fetches an identity provider's key set and refreshes it when a token names an unknown key id (rotation), at most once per MinRefresh.

func (*RemoteJWKS) Key

func (r *RemoteJWKS) Key(ctx context.Context, kid string) (Key, error)

Key implements KeySet.

func (*RemoteJWKS) SharedKeys added in v0.24.0

func (*RemoteJWKS) SharedKeys() bool

SharedKeys implements SharedKeySet: a provider's JWKS signs tokens for all of its clients.

type SharedKeySet added in v0.24.0

type SharedKeySet interface {
	KeySet
	SharedKeys() bool
}

SharedKeySet is a KeySet whose keys an identity provider also uses for its other clients (RemoteJWKS). A Verifier over one requires Audience and Issuer. Custom KeySets that wrap a RemoteJWKS should forward SharedKeys (embedding *RemoteJWKS does).

type Verifier

type Verifier struct {
	// contains filtered or unexported fields
}

Verifier checks tokens against a key set and claim rules.

func NewVerifier

func NewVerifier(keys KeySet, opts VerifyOptions) *Verifier

NewVerifier returns a Verifier.

func (*Verifier) Err added in v0.24.0

func (v *Verifier) Err() error

Err reports a misconfiguration that makes every Verify fail (a shared key set without Audience or Issuer); check it at boot. NewGuard does.

func (*Verifier) Verify

func (v *Verifier) Verify(ctx context.Context, token string) (Claims, error)

Verify checks the signature and claims of token and returns its claims. Every failure wraps ErrInvalid.

type VerifyOptions

type VerifyOptions struct {
	// Algorithms allowed (default: all supported); each key still only
	// accepts its own algorithm.
	Algorithms []string
	// Issuer, when set, must equal "iss". Required with a *RemoteJWKS.
	Issuer string
	// Audience, when set, must be in "aud". Required with a *RemoteJWKS:
	// an identity provider signs tokens for all of its clients with the
	// same keys, so without it a token issued to another app is accepted.
	Audience string
	// InsecureSkipAudience accepts any "aud" with a *RemoteJWKS.
	// Dangerous: tokens the provider issued to other apps pass.
	InsecureSkipAudience bool
	// InsecureSkipIssuer accepts any "iss" with a *RemoteJWKS.
	// Dangerous: tokens from other tenants of a multi-tenant provider pass.
	InsecureSkipIssuer bool
	// Leeway tolerates clock skew (default 30s).
	Leeway time.Duration
	// AllowMissingExpiry accepts tokens without "exp" (off by default).
	AllowMissingExpiry bool
	// Now is the clock (default time.Now).
	Now func() time.Time
}

VerifyOptions configures a Verifier.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL