jwt

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Mar 6, 2026 License: MIT Imports: 30 Imported by: 2

README

GoDoc Build Status Coverage Status Go Report Card

jwt

A lightweight Go library for creating, signing, verifying, encrypting and decrypting JSON Web Tokens.

Supports JWS (RFC 7515) for signed tokens and JWE (RFC 7516) for encrypted tokens, including post-quantum algorithms.

Features

  • Simple API -- create, sign, verify and encrypt tokens in a few lines
  • JWS signing -- HMAC, RSA, RSA-PSS, ECDSA, Ed25519, ML-DSA, SLH-DSA
  • JWE encryption -- RSA-OAEP, ECDH-ES, AES Key Wrap, direct keys, ML-KEM
  • Post-quantum ready -- ML-DSA (FIPS 204), SLH-DSA (FIPS 205), ML-KEM (FIPS 203)
  • Custom algorithms -- implement Algo, KeyAlgo or EncAlgo and register
  • JWK support -- parse, export and use JSON Web Keys (RFC 7517)
  • No magic -- works directly with crypto.Signer, crypto.PublicKey and []byte keys
  • Hardware-friendly -- any crypto.Signer or crypto.Decrypter works (HSMs, KMS, etc.)

JWT?

JWT.io has a great introduction to JSON Web Tokens.

In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for Bearer tokens in Oauth 2. A token is made of three parts, separated by .'s. The first two parts are JSON objects, that have been base64url encoded. The last part is the signature, encoded the same way.

The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used.

The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to RFC 7519 for information about reserved keys and the proper way to add your own.

Supported algorithms

JWS signing algorithms
Family Algorithms
HMAC HS256, HS384, HS512
RSA PKCS#1 v1.5 RS256, RS384, RS512
RSA-PSS PS256, PS384, PS512
ECDSA ES224, ES256, ES384, ES512, ES256K
EdDSA Ed25519
ML-DSA (PQ) ML-DSA-44, ML-DSA-65, ML-DSA-87
SLH-DSA (PQ) All SHA2 and SHAKE variants at 128/192/256 security levels
None none (signing produces no signature; verification always fails)
JWE key management algorithms
Algorithm Description
RSA-OAEP RSA-OAEP with SHA-1
RSA-OAEP-256 RSA-OAEP with SHA-256
A128KW, A192KW, A256KW AES Key Wrap (RFC 3394)
ECDH-ES ECDH Ephemeral Static key agreement (RFC 7518)
ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW ECDH-ES with AES Key Wrap
dir Direct use of a shared symmetric key
ML-KEM-768, ML-KEM-1024 Post-quantum key encapsulation (FIPS 203)
JWE content encryption algorithms
Algorithm Description
A128GCM, A192GCM, A256GCM AES-GCM
A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 AES-CBC + HMAC-SHA2

Installation

go get github.com/KarpelesLab/jwt

Requires Go 1.24 or later (for crypto/mlkem).

Examples

Create & sign a token
import _ "crypto/sha256"

priv := []byte("this is a hmac key")
tok := jwt.New(jwt.HS256)
tok.Header().Set("kid", keyId)
tok.Payload().Set("iss", "myself")
tok.Payload().Set("exp", time.Now().Add(365*24*time.Hour).Unix())
signedToken, err := tok.Sign(rand.Reader, priv)
Verify a token
import _ "crypto/sha256"

token, err := jwt.ParseString(input)
if err != nil {
	// handle error
}
publicKey := fetchPublicKey(token.GetKeyId())
err = token.Verify(
	jwt.VerifyAlgo(jwt.ES256, jwt.RS256),
	jwt.VerifySignature(publicKey),
	jwt.VerifyExpiresAt(time.Now(), false),
)
if err != nil {
	// handle error
}
log.Printf("token iss value = %s", token.Payload().Get("iss"))
Auto-detect algorithm from key
// The algorithm is inferred from the key type
tok := jwt.New()
tok.Payload().Set("sub", "user123")
signed, err := tok.Sign(rand.Reader, ecdsaPrivateKey)
// tok.GetAlgo().String() == "ES256" (for P-256 keys)
Encrypt a token (JWE)
tok := jwt.New()
tok.Payload().Set("sub", "user123")
encrypted, err := tok.Encrypt(rand.Reader, recipientPublicKey, nil) // auto-detects RSA-OAEP-256 + A256GCM
Decrypt a token (JWE)
tok, err := jwt.ParseString(encrypted)
if err != nil {
	// handle error
}
err = tok.Decrypt(recipientPrivateKey)
if err != nil {
	// handle error
}
log.Printf("sub = %s", tok.Payload().GetString("sub"))
Encrypt with ECDH-ES
// Using crypto/ecdh keys — algorithm auto-detected as ECDH-ES
key, _ := ecdh.P256().GenerateKey(rand.Reader)

tok := jwt.New()
tok.Payload().Set("sub", "user123")
encrypted, err := tok.Encrypt(rand.Reader, key.PublicKey(), nil)

// Decrypt
tok2, _ := jwt.ParseString(encrypted)
err = tok2.Decrypt(key)

// ECDSA keys are also supported — they are converted automatically
ecdsaKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
encrypted, err = tok.Encrypt(rand.Reader, &ecdsaKey.PublicKey, nil)

// Use ECDH-ES+A256KW key wrapping with explicit options
encrypted, err = tok.Encrypt(rand.Reader, &ecdsaKey.PublicKey, &jwt.EncryptOptions{KeyAlgo: jwt.ECDH_ES_A256KW})
Encrypt with a symmetric key
key := make([]byte, 32) // 256-bit key for A256GCM
rand.Read(key)

tok := jwt.New()
tok.Payload().Set("msg", "secret")
encrypted, err := tok.Encrypt(rand.Reader, key, nil) // auto-detects dir + A256GCM

// Decrypt
tok2, _ := jwt.ParseString(encrypted)
err = tok2.Decrypt(key)
Post-quantum signing (ML-DSA)
key, _ := mldsa.GenerateKey65(rand.Reader)

tok := jwt.New(jwt.MLDSA65)
tok.Payload().Set("sub", "pq-user")
signed, err := tok.Sign(rand.Reader, key)

// Verify
tok2, _ := jwt.ParseString(signed)
err = tok2.Verify(jwt.VerifyAlgo(jwt.MLDSA65), jwt.VerifySignature(key.PublicKey()))
Post-quantum encryption (ML-KEM)
dk, _ := mlkem.GenerateKey768()

tok := jwt.New()
tok.Payload().Set("msg", "quantum-safe")
encrypted, err := tok.Encrypt(rand.Reader, dk.EncapsulationKey(), nil) // auto-detects ML-KEM-768 + A256GCM

// Decrypt
tok2, _ := jwt.ParseString(encrypted)
err = tok2.Decrypt(dk)
Non-JSON payload
import _ "crypto/sha256"

priv := []byte("this is a hmac key")
tok := jwt.New(jwt.HS256)
tok.Header().Set("kid", keyId)
tok.SetRawPayload(binData, "octet-stream") // can pass cty="" to not set content type
signedToken, err := tok.Sign(rand.Reader, priv)

Verification options

Function Description
VerifyAlgo(algo...) Ensures the token uses one of the specified algorithms
VerifySignature(key) Verifies the token's signature against a public key or shared secret
VerifyExpiresAt(now, required) Checks the exp claim
VerifyNotBefore(now, required) Checks the nbf claim
VerifyTime(now, required) Checks both exp and nbf
VerifyMultiple(opts...) Combines multiple checks

Why this library?

The main issue I have with the existing JWT lib is that the syntax is too heavy and I had something else in mind in terms of what would make a convenient JWT lib. I've had also issues with it performing checks on incoming crypto.Signer objects that prevent third party signature providers such as hardware modules, and a few other things. JWT is a simple enough standard so building a new lib isn't that much work.

All signature algorithms are always linked (hmac, rsa, ecdsa, ed25519, mldsa, slhdsa). These are also pulled by Go's crypto/x509 so you probably have most of them compiled in already.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidToken           = errors.New("jwt: invalid token provided")
	ErrNoSignature            = errors.New("jwt: token has no signature")
	ErrInvalidSignature       = errors.New("jwt: token signature is not valid")
	ErrInvalidSignKey         = errors.New("jwt: invalid key provided for signature")
	ErrInvalidSignatureLength = errors.New("jwt: token signature is not valid (bad length)")
	ErrHashNotAvailable       = errors.New("jwt: hash method not available")
	ErrNoHeader               = errors.New("jwt: header is not available (parsing failed?)")
	ErrNoPayload              = errors.New("jwt: payload is not available (parsing failed?)")
	ErrInvalidPublicKey       = errors.New("jwt: invalid public key provided")
	ErrNoPrivateKey           = errors.New("jwt: private key is missing")
	ErrAlgNotSet              = errors.New("jwt: alg has not been set in header")
	ErrUnknownAlg             = errors.New("jwt: unrecognized alg value")

	ErrVerifyMissing = errors.New("jwt: a claim required for verification is missing")
	ErrVerifyFailed  = errors.New("jwt: claim verification has failed")

	ErrNotEncrypted     = errors.New("jwt: token is not encrypted")
	ErrUnknownEnc       = errors.New("jwt: unrecognized enc value")
	ErrDecryptionFailed = errors.New("jwt: decryption failed")
)
View Source
var (
	// Key management algorithms (RFC 7518 Section 4)
	RSA_OAEP     KeyAlgo = rsaOaepKeyAlgo{hash: crypto.SHA1, name: "RSA-OAEP"}.reg()
	RSA_OAEP_256 KeyAlgo = rsaOaepKeyAlgo{hash: crypto.SHA256, name: "RSA-OAEP-256"}.reg()
	Dir          KeyAlgo = dirKeyAlgo{}.reg()
	A128KW       KeyAlgo = aesKwAlgo{keySize: 16}.reg()
	A192KW       KeyAlgo = aesKwAlgo{keySize: 24}.reg()
	A256KW       KeyAlgo = aesKwAlgo{keySize: 32}.reg()

	// Content encryption algorithms (RFC 7518 Section 5)
	A128GCM       EncAlgo = aesGcmEncAlgo{keySize: 16}.reg()
	A192GCM       EncAlgo = aesGcmEncAlgo{keySize: 24}.reg()
	A256GCM       EncAlgo = aesGcmEncAlgo{keySize: 32}.reg()
	A128CBC_HS256 EncAlgo = aesCbcHsEncAlgo{keySize: 32, hash: crypto.SHA256}.reg()
	A192CBC_HS384 EncAlgo = aesCbcHsEncAlgo{keySize: 48, hash: crypto.SHA384}.reg()
	A256CBC_HS512 EncAlgo = aesCbcHsEncAlgo{keySize: 64, hash: crypto.SHA512}.reg()
)
View Source
var (
	DeprecatedAllowEcdsaASN1Signatures = true // this will turn to false eventually
)

DeprecatedAllowEcdsaASN1Signatures controls whether ECDSA signature verification accepts ASN.1 DER-encoded signatures in addition to the fixed-length R||S format required by RFC 7518. This exists for backward compatibility and will eventually default to false.

Functions

func RegisterAlgo

func RegisterAlgo(obj Algo)

RegisterAlgo allows registration of custom algorithms. We assume this will be called during init in a single thread, so no locking is performed.

func RegisterEncAlgo added in v0.2.0

func RegisterEncAlgo(obj EncAlgo)

RegisterEncAlgo registers a JWE content encryption algorithm. This is typically called during init and no locking is performed.

func RegisterKeyAlgo added in v0.2.0

func RegisterKeyAlgo(obj KeyAlgo)

RegisterKeyAlgo registers a JWE key management algorithm. This is typically called during init and no locking is performed.

Types

type Algo

type Algo interface {
	// String should return the name of the algo, for example "HS256"
	String() string

	// Sign should sign the provided buffer, and return the resulting
	// signature. If the private key isn't of the appropriate type, an
	// error should be triggered.
	Sign(rand io.Reader, buf []byte, priv crypto.PrivateKey) ([]byte, error)

	// Verify must verify the provided signature and return an error
	// if the public key is not of the appropriate type or the signature
	// is not valid.
	Verify(buf, sign []byte, pub crypto.PublicKey) error
}

Algo is a jwt signature algorithm. Typical values include HS256 and ES256. By implementing this interface, you can also add support for your own custom types. Remember to call RegisterAlgo() so your new algo can be recognized appropriately.

var (
	HS256 Algo = hmacAlgo(crypto.SHA256).reg()
	HS384 Algo = hmacAlgo(crypto.SHA384).reg()
	HS512 Algo = hmacAlgo(crypto.SHA512).reg()

	RS256 Algo = rsaAlgo(crypto.SHA256).reg()
	RS384 Algo = rsaAlgo(crypto.SHA384).reg()
	RS512 Algo = rsaAlgo(crypto.SHA512).reg()

	PS256 Algo = rsaPssAlgo(crypto.SHA256).reg()
	PS384 Algo = rsaPssAlgo(crypto.SHA384).reg()
	PS512 Algo = rsaPssAlgo(crypto.SHA512).reg()

	ES224  Algo = ecdsaAlgo("ES224").reg()
	ES256  Algo = ecdsaAlgo("ES256").reg()
	ES384  Algo = ecdsaAlgo("ES384").reg()
	ES512  Algo = ecdsaAlgo("ES512").reg()
	ES256K Algo = ecdsaAlgo("ES256K").reg()

	EdDSA Algo = ed25519Algo{}.reg()
	None  Algo = noneAlgo{}.reg()
)

note: the .reg() just performs a call to RegisterAlgo() and returns the object itself.

var (
	MLDSA44 Algo = mldsaAlgo{name: "ML-DSA-44", level: 44}.reg()
	MLDSA65 Algo = mldsaAlgo{name: "ML-DSA-65", level: 65}.reg()
	MLDSA87 Algo = mldsaAlgo{name: "ML-DSA-87", level: 87}.reg()
)
var (
	// SLH-DSA SHA2 variants
	SLH_DSA_SHA2_128s Algo = slhdsaAlgo{params: slhdsa.SHA2_128s}.reg()
	SLH_DSA_SHA2_128f Algo = slhdsaAlgo{params: slhdsa.SHA2_128f}.reg()
	SLH_DSA_SHA2_192s Algo = slhdsaAlgo{params: slhdsa.SHA2_192s}.reg()
	SLH_DSA_SHA2_192f Algo = slhdsaAlgo{params: slhdsa.SHA2_192f}.reg()
	SLH_DSA_SHA2_256s Algo = slhdsaAlgo{params: slhdsa.SHA2_256s}.reg()
	SLH_DSA_SHA2_256f Algo = slhdsaAlgo{params: slhdsa.SHA2_256f}.reg()

	// SLH-DSA SHAKE variants
	SLH_DSA_SHAKE_128s Algo = slhdsaAlgo{params: slhdsa.SHAKE_128s}.reg()
	SLH_DSA_SHAKE_128f Algo = slhdsaAlgo{params: slhdsa.SHAKE_128f}.reg()
	SLH_DSA_SHAKE_192s Algo = slhdsaAlgo{params: slhdsa.SHAKE_192s}.reg()
	SLH_DSA_SHAKE_192f Algo = slhdsaAlgo{params: slhdsa.SHAKE_192f}.reg()
	SLH_DSA_SHAKE_256s Algo = slhdsaAlgo{params: slhdsa.SHAKE_256s}.reg()
	SLH_DSA_SHAKE_256f Algo = slhdsaAlgo{params: slhdsa.SHAKE_256f}.reg()
)

func GetAlgoForSigner added in v0.1.7

func GetAlgoForSigner(s crypto.PrivateKey) (Algo, error)

GetAlgoForSigner will guess the correct algorithm for a given crypto.PrivateKey

type EncAlgo added in v0.2.0

type EncAlgo interface {
	String() string

	// KeySize returns the required key size in bytes.
	KeySize() int

	// Encrypt performs authenticated encryption. Returns the IV, ciphertext,
	// and authentication tag. The aad parameter is the Additional
	// Authenticated Data (the base64url-encoded protected header).
	Encrypt(rand io.Reader, key, plaintext, aad []byte) (iv, ciphertext, tag []byte, err error)

	// Decrypt performs authenticated decryption, verifying the tag.
	Decrypt(key, iv, ciphertext, tag, aad []byte) ([]byte, error)
}

EncAlgo represents a JWE content encryption algorithm as defined in RFC 7518 Section 5. It provides authenticated encryption of the plaintext.

type EncryptOptions added in v0.2.1

type EncryptOptions struct {
	// KeyAlgo specifies the key management algorithm. If nil, it is
	// auto-detected from the recipient key type (e.g. *rsa.PublicKey →
	// RSA-OAEP-256, *ecdh.PublicKey → ECDH-ES, []byte → dir).
	KeyAlgo KeyAlgo

	// EncAlgo specifies the content encryption algorithm. If nil, defaults
	// to A256GCM.
	EncAlgo EncAlgo
}

EncryptOptions configures the JWE encryption. All fields are optional; nil values are auto-detected from the recipient key type.

type Header map[string]any

Header type holds values from the token's header for easy access. Values are typically strings, but may be other types (e.g. the "epk" parameter in ECDH-ES is a JSON object).

func (Header) Get

func (h Header) Get(key string) string

Get will return the value of the requested key from the header, or an empty string if the value is not found or is not a string.

func (Header) GetAlgo

func (h Header) GetAlgo() (Algo, error)

GetAlgo will return a Algo based on the alg value of the header, or nil if the algo is invalid or unknown. This will also work with custom algo as long as RegisterAlgo() was called.

func (Header) Has

func (h Header) Has(key string) bool

Has returns true if the key exists in the header (and there is a header), and can be used to test for a given key even if its value is empty.

func (Header) Set

func (h Header) Set(key, value string) error

Set will update the key's value in the header and return nil. If there is no header (because it failed to parse, for example), Set will return an ErrNoHeader error. Calling Set on a nil Header will not panic.

func (Header) Unset added in v0.1.8

func (h Header) Unset(key string)

Unset removes a value from the header

type HeaderKeyAlgo added in v0.2.0

type HeaderKeyAlgo interface {
	KeyAlgo

	// GenerateCEKWithHeader generates a CEK and may return additional header
	// parameters to include in the JWE protected header (e.g. "epk").
	// The header parameter contains user-set headers (e.g. "apu", "apv").
	// The encAlg parameter is the "enc" algorithm name for key derivation.
	GenerateCEKWithHeader(rand io.Reader, keySize int, rcptKey any, header Header, encAlg string) (cek, encryptedKey []byte, extraHeaders map[string]any, err error)

	// UnwrapKeyFromHeader recovers the CEK using header information. The
	// header parameter contains the full protected header including
	// algorithm-specific parameters (e.g. "epk", "apu", "apv").
	UnwrapKeyFromHeader(encryptedKey []byte, keySize int, privKey any, header Header, encAlg string) ([]byte, error)
}

HeaderKeyAlgo is an optional extension of KeyAlgo for algorithms that need access to JWE header parameters during key management. ECDH-ES algorithms use this to include the ephemeral public key (epk) in the protected header and to read it back during decryption.

type JWK added in v0.1.1

type JWK struct {
	PrivateKey crypto.PrivateKey `json:"-"`
	PublicKey  crypto.PublicKey  `json:"-"`
	KeyID      string            `json:"kid,omitempty"`
	Algo       string            `json:"alg,omitempty"` // RSA-OAEP-256
	Use        string            `json:"use,omitempty"`
	Ext        bool              `json:"ext,omitempty"`
	KeyOps     []string          `json:"key_ops,omitempty"`
}

JWK represents a JSON Web Key as defined in RFC 7517. It can hold either a public key, a private key, or both. JWK implements crypto.Signer when a private key is present, making it usable directly with Sign methods.

func (*JWK) ApplyValues added in v0.1.1

func (jwk *JWK) ApplyValues(values map[string]any) error

ApplyValues populates the JWK from a map of key-value pairs, typically obtained from JSON unmarshaling. The "kty" field is required and determines how the remaining fields are interpreted.

func (*JWK) Decrypt added in v0.2.0

func (jwk *JWK) Decrypt(rand io.Reader, msg []byte, opts crypto.DecrypterOpts) ([]byte, error)

Decrypt decrypts msg using the JWK's private key. Returns ErrNoPrivateKey if no private key is available. This method satisfies the crypto.Decrypter interface.

func (*JWK) ExportRequiredPublicValues added in v0.1.1

func (jwk *JWK) ExportRequiredPublicValues() map[string]any

ExportRequiredPublicValues returns only the required public key fields, suitable for computing JWK Thumbprints per RFC 7638.

func (*JWK) ExportRequiredValues added in v0.1.1

func (jwk *JWK) ExportRequiredValues() map[string]any

ExportRequiredValues returns only the required JWK fields (kty and key material). If a private key is present, private key fields are included.

func (*JWK) ExportValues added in v0.1.1

func (jwk *JWK) ExportValues() map[string]any

ExportValues returns all JWK fields as a map, including optional metadata fields (kid, alg, use, ext, key_ops) and key material.

func (*JWK) MarshalJSON added in v0.1.1

func (jwk *JWK) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. It exports the JWK including private key material if present.

func (*JWK) Public added in v0.1.1

func (jwk *JWK) Public() crypto.PublicKey

Public returns the public key associated with this JWK. If a private key is present, the public key is derived from it. This method satisfies the crypto.Signer interface.

func (*JWK) Sign added in v0.1.6

func (jwk *JWK) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)

Sign signs the digest using the JWK's private key. Returns ErrNoPrivateKey if no private key is available. This method satisfies the crypto.Signer interface.

func (*JWK) String added in v0.1.1

func (jwk *JWK) String() string

String returns a human-readable representation of the JWK showing the key type.

func (*JWK) Thumbprint added in v0.1.1

func (jwk *JWK) Thumbprint(method crypto.Hash) ([]byte, error)

Thumbprint computes the JWK Thumbprint as defined in RFC 7638 using the specified hash method.

func (*JWK) ThumbprintHex added in v0.1.1

func (jwk *JWK) ThumbprintHex(method crypto.Hash) string

ThumbprintHex computes the JWK Thumbprint (RFC 7638) and returns it as a hex-encoded string. Returns an empty string on error.

func (*JWK) UnmarshalJSON added in v0.1.1

func (jwk *JWK) UnmarshalJSON(v []byte) error

UnmarshalJSON implements json.Unmarshaler. It parses a JWK JSON object and populates the key fields accordingly.

type KeyAlgo added in v0.2.0

type KeyAlgo interface {
	String() string

	// GenerateCEK generates a Content Encryption Key and wraps it for the
	// recipient. Returns the CEK and the encrypted key. For "dir", the
	// encrypted key will be nil and the provided key is used directly as CEK.
	GenerateCEK(rand io.Reader, keySize int, rcptKey any) (cek, encryptedKey []byte, err error)

	// UnwrapKey recovers the CEK from the encrypted key using the recipient's
	// private key or shared secret.
	UnwrapKey(encryptedKey []byte, keySize int, privKey any) ([]byte, error)
}

KeyAlgo represents a JWE key management algorithm as defined in RFC 7518 Section 4. It handles wrapping and unwrapping of the Content Encryption Key.

var (
	// ECDH-ES key agreement algorithms (RFC 7518 Section 4.6)
	ECDH_ES        KeyAlgo = ecdhEsAlgo{name: "ECDH-ES"}.reg()
	ECDH_ES_A128KW KeyAlgo = ecdhEsAlgo{name: "ECDH-ES+A128KW", wrapKeySize: 16}.reg()
	ECDH_ES_A192KW KeyAlgo = ecdhEsAlgo{name: "ECDH-ES+A192KW", wrapKeySize: 24}.reg()
	ECDH_ES_A256KW KeyAlgo = ecdhEsAlgo{name: "ECDH-ES+A256KW", wrapKeySize: 32}.reg()
)
var (
	MLKEM768  KeyAlgo = mlkemAlgo{name: "ML-KEM-768", level: 768}.reg()
	MLKEM1024 KeyAlgo = mlkemAlgo{name: "ML-KEM-1024", level: 1024}.reg()
)

func GetKeyAlgoForKey added in v0.2.1

func GetKeyAlgoForKey(key any) (KeyAlgo, error)

GetKeyAlgoForKey returns the default JWE key management algorithm for the given key. This is used by Encrypt when no KeyAlgo is specified.

type Payload

type Payload map[string]any

Payload represents the claims part of a JWT token as a map of key-value pairs. Standard claims such as "iss", "sub", "exp", "nbf", "iat", "jti" can be accessed via Get/Set, and convenience methods are provided for type conversion.

func (Payload) Get

func (b Payload) Get(key string) any

Get is a safe get that will return nil if the body itself is null or the value is nil. If you want to check if a value exists or not, use Has().

func (Payload) GetFloat

func (b Payload) GetFloat(key string) float64

GetFloat will attempt to parse the requested key as a float and return it. If the value is an int or any other kind of number-y value, it will be converted to float64 and returned, or return 0 in case of failure.

func (Payload) GetInt

func (b Payload) GetInt(key string) int64

GetInt will attempt to parse the requested key as an integer and return it. If the value is a float or any other kind of number-y value, it will be converted (truncated) and returned as an int, or 0 in case of failure.

func (Payload) GetNumericDate

func (b Payload) GetNumericDate(key string) time.Time

GetNumericDate will return a time value based on the requested header, or a zero time if the parsing failed or the key is not set. Check IsZero() for success.

func (Payload) GetString

func (b Payload) GetString(key string) string

GetString will get a value as a string, convert it to a string if possible or return an empty string if the value is not set or cannot be converted. GetString will return an empty string in case of failure.

func (Payload) Has

func (b Payload) Has(key string) bool

Has returns true if the payload was parsed and the key exists.

func (Payload) Set

func (b Payload) Set(key string, value any) error

Set will set the specified value in the payload. It will return an error if the payload failed to parse, for example because it is not a JSON object.

type Token

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

Token represents a JWT token

func New

func New(algopt ...Algo) *Token

New will return a fresh and empty token that can be filled with information to be later signed using the Sign method. By default only the "alg" value of the header will be set if alg was passed.

func ParseString

func ParseString(value string) (*Token, error)

ParseString will generate a Token object from an encoded string. No verification is performed at this point, so it is up to you to call the Verify method.

func (*Token) Decrypt added in v0.2.0

func (tok *Token) Decrypt(privKey any) error

Decrypt decrypts a JWE token, making the payload accessible via Payload() and GetRawPayload(). The privKey is the recipient's private key (for RSA-OAEP, ECDH-ES) or shared secret (for dir, AES-KW).

func (*Token) Encrypt added in v0.2.0

func (tok *Token) Encrypt(rand io.Reader, rcptKey any, opts *EncryptOptions) (string, error)

Encrypt encrypts the token's payload and returns the JWE compact serialization string. The rcptKey is the recipient's public key (for RSA-OAEP, ECDH-ES), shared secret (for dir, AES-KW), or encapsulation key (for ML-KEM).

If opts is nil, the key management algorithm is auto-detected from the key type and A256GCM is used for content encryption. Individual fields in opts may also be left nil for auto-detection.

func (*Token) GetAlgo

func (tok *Token) GetAlgo() Algo

GetAlgo will determine the algorithm in use from the header and return the appropriate Algo object, or nil if unknown or no algo is specified.

func (*Token) GetAlgoErr added in v0.1.8

func (tok *Token) GetAlgoErr() (Algo, error)

GetAlgoErr performs similarly to GetAlgo but also return an error that can be either ErrAlgNotSet or ErrUnknownAlg

func (*Token) GetContentType added in v0.0.3

func (tok *Token) GetContentType() string

GetContentType returns the value of "cty" claim in the token's header, ro "application/jwt" if not set. It will prepend "application/" to values that have no slashes in them as defined in RFC 7515, Section 4.1.10.

func (*Token) GetKeyId

func (tok *Token) GetKeyId() string

GetKeyId is a short hand for Header().Get("kid").

func (*Token) GetRawPayload added in v0.0.3

func (tok *Token) GetRawPayload() ([]byte, error)

GetRawPayload returns the raw value for the token's payload, or an error if it could not be decoded.

func (*Token) GetRawSignature added in v0.0.3

func (tok *Token) GetRawSignature() ([]byte, error)

GetRawSignature returns the raw signature of a parsed token or of a freshly signed token.

func (Token) GetSignString added in v0.0.3

func (tok Token) GetSignString() []byte

GetSignString is used by VerifySignature to get the part of the string that is used to generate a signature. It avoids duplicating memory in order to provide better performance.

func (*Token) Header

func (tok *Token) Header() Header

Header returns the decoded header part of the token and is useful to read the key id value for the signature.

func (*Token) IsEncrypted added in v0.2.0

func (tok *Token) IsEncrypted() bool

IsEncrypted returns true if the token is a JWE (encrypted) token, identified by having 5 dot-separated parts.

func (*Token) Payload

func (tok *Token) Payload() Payload

Payload returns the payload part of the token, which contains the claims. If parsing failed, then this function will return nil. Payload methods such as Get() and Set() can still be called without causing a panic.

func (*Token) SetRawPayload added in v0.0.3

func (tok *Token) SetRawPayload(payload []byte, cty string) error

SetRawPayload sets the raw value of payload to any kind of data that can be later signed. This can be used to store non-JSON data in the payload.

func (*Token) Sign

func (tok *Token) Sign(rand io.Reader, priv crypto.PrivateKey) (string, error)

Sign will generate the token and sign it, making it ready for distribution.

func (*Token) Verify

func (tok *Token) Verify(opts ...VerifyOption) error

Verify will perform the verifications passed as parameter in sequence, stopping at the first failure. If all verifications are successful, nil will be returned.

type VerifyOption

type VerifyOption func(*Token) error

VerifyOption is a function that performs a single verification check on a token. Multiple options can be composed via Token.Verify or VerifyMultiple.

func VerifyAlgo

func VerifyAlgo(algo ...Algo) VerifyOption

VerifyAlgo returns a VerifyOption that will ensure the token's alg value is one of the specified algos. This allows to easily limit the acceptable signature scheme and should always be used.

func VerifyExpiresAt

func VerifyExpiresAt(now time.Time, req bool) VerifyOption

VerifyExpiresAt returns a VerifyOption that will check the token's expiration to not be before now.

Example use: VerifyExpiresAt(time.Now(), false)

func VerifyMultiple

func VerifyMultiple(opts ...VerifyOption) VerifyOption

VerifyMultiple compounds multiple conditions and fails if any of the passed condition fails. This will return success if no options are passed at all.

func VerifyNotBefore

func VerifyNotBefore(now time.Time, req bool) VerifyOption

VerifyNotBefore returns a VerifyOption that will check the token's not before claim (nbf).

Example use: VerifyNotBefore(time.Now(), false)

func VerifySignature

func VerifySignature(pub crypto.PublicKey) VerifyOption

VerifySignature will check the token's signature against the specified public key based on the algo used for the token. This will always fail for tokens which alg is set to "none".

func VerifyTime

func VerifyTime(now time.Time, req bool) VerifyOption

VerifyTime will verify both the not before and the expires at claims, and is typically used with req=false so those checks only happen if the claims are specified.

If you know both nbf and exp claims will always be there, setting req=true will ensure this and improve security.

Jump to

Keyboard shortcuts

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