jwt

package module
Version: v3.0.1 Latest Latest
Warning

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

Go to latest
Published: Jul 25, 2021 License: MIT Imports: 17 Imported by: 73

README

jwt (JSON Web Token for Go)

JWT compatible

Github Actions Status Go Report Card GoDoc Version compatibility with Go 1.11 onward using modules

About

This package is a JWT signer, verifier and validator for Go (or Golang).

Although there are many JWT packages out there for Go, many lack support for some signing, verifying or validation methods and, when they don't, they're overcomplicated. This package tries to mimic the ease of use from Node JWT library's API while following the Effective Go guidelines.

Support for JWE isn't provided (not yet but is in the roadmap, see #17). Instead, JWS is used, narrowed down to the JWT specification.

Supported signing methods
SHA-256 SHA-384 SHA-512
HMAC ✔️ ✔️ ✔️
RSA ✔️ ✔️ ✔️
RSA-PSS ✔️ ✔️ ✔️
ECDSA ✔️ ✔️ ✔️
EdDSA ✔️

Important

Branch master is unstable, always use tagged versions. That way it is possible to differentiate pre-release tags from production ones. In other words, API changes all the time in master. It's a place for public experiment. Thus, make use of the latest stable version via Go modules.

Usage

Full documentation here.

Installing
Important

For Go 1.11, make sure the environment variable GO111MODULE is set as on when running the install command.

$ go get -u github.com/gbrlsnchs/jwt/v3
Signing
import (
	"time"

	"github.com/gbrlsnchs/jwt/v3"
)

type CustomPayload struct {
	jwt.Payload
	Foo string `json:"foo,omitempty"`
	Bar int    `json:"bar,omitempty"`
}

var hs = jwt.NewHS256([]byte("secret"))

func main() {
	now := time.Now()
	pl := CustomPayload{
		Payload: jwt.Payload{
			Issuer:         "gbrlsnchs",
			Subject:        "someone",
			Audience:       jwt.Audience{"https://golang.org", "https://jwt.io"},
			ExpirationTime: jwt.NumericDate(now.Add(24 * 30 * 12 * time.Hour)),
			NotBefore:      jwt.NumericDate(now.Add(30 * time.Minute)),
			IssuedAt:       jwt.NumericDate(now),
			JWTID:          "foobar",
		},
		Foo: "foo",
		Bar: 1337,
	}

	token, err := jwt.Sign(pl, hs)
	if err != nil {
		// ...
	}

	// ...
}
Verifying
import "github.com/gbrlsnchs/jwt/v3"

type CustomPayload struct {
	jwt.Payload
	Foo string `json:"foo,omitempty"`
	Bar int    `json:"bar,omitempty"`
}

var hs = jwt.NewHS256([]byte("secret"))

func main() {
	// ...

	var pl CustomPayload
	hd, err := jwt.Verify(token, hs, &pl)
	if err != nil {
		// ...
	}

	// ...
}
Other use case examples
Setting "cty" and "kid" claims

The "cty" and "kid" claims can be set by passing options to the jwt.Sign function:

import (
	"time"

	"github.com/gbrlsnchs/jwt/v3"
)

var hs = jwt.NewHS256([]byte("secret"))

func main() {
	pl := jwt.Payload{
		Subject:  "gbrlsnchs",
		Issuer:   "gsr.dev",
		IssuedAt: jwt.NumericDate(time.Now()),
	}

	token, err := jwt.Sign(pl, hs, jwt.ContentType("JWT"), jwt.KeyID("my_key"))
	if err != nil {
		// ...
	}

	// ...
}

Validating claims

import (
	"time"

	"github.com/gbrlsnchs/jwt/v3"
)

type CustomPayload struct {
	jwt.Payload
	Foo string `json:"foo,omitempty"`
	Bar int    `json:"bar,omitempty"`
}

var hs = jwt.NewHS256([]byte("secret"))

func main() {
	// ...

	var (
		now = time.Now()
		aud = jwt.Audience{"https://golang.org"}

		// Validate claims "iat", "exp" and "aud".
		iatValidator = jwt.IssuedAtValidator(now)
		expValidator = jwt.ExpirationTimeValidator(now)
		audValidator = jwt.AudienceValidator(aud)

		// Use jwt.ValidatePayload to build a jwt.VerifyOption.
		// Validators are run in the order informed.
		pl              CustomPayload
		validatePayload = jwt.ValidatePayload(&pl.Payload, iatValidator, expValidator, audValidator)
	)

	hd, err := jwt.Verify(token, hs, &pl, validatePayload)
	if err != nil {
		// ...
	}

	// ...
}

Validating "alg" before verifying

For validating the "alg" field in a JOSE header before verification, the jwt.ValidateHeader option must be passed to jwt.Verify.

import "github.com/gbrlsnchs/jwt/v3"

var hs = jwt.NewHS256([]byte("secret"))

func main() {
	// ...

	var pl jwt.Payload
	if _, err := jwt.Verify(token, hs, &pl, jwt.ValidateHeader); err != nil {
		// ...
	}

	// ...
}

Using an Algorithm resolver

import (
	"errors"

	"github.com/gbrlsnchs/jwt/v3"
	"github.com/gbrlsnchs/jwt/v3/jwtutil"
)

var (
	// ...

	rs256 = jwt.NewRS256(jwt.RSAPublicKey(myRSAPublicKey))
	es256 = jwt.NewES256(jwt.ECDSAPublicKey(myECDSAPublicKey))
)

func main() {
	rv := &jwtutil.Resolver{New: func(hd jwt.Header) (jwt.Algorithm, error) {
		switch hd.KeyID {
		case "foo":
			return rs256, nil
		case "bar":
			return es256, nil
		default:
			return nil, errors.New(`invalid "kid"`)
		}
	}}
	var pl jwt.Payload
	if _, err := jwt.Verify(token, rv, &pl); err != nil {
		// ...
	}

	// ...
}

Contributing

How to help

Documentation

Overview

Package jwt is a JSON Web Token signer, verifier and validator.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrECDSANilPrivKey is the error for trying to sign a JWT with a nil private key.
	ErrECDSANilPrivKey = internal.NewError("jwt: ECDSA private key is nil")
	// ErrECDSANilPubKey is the error for trying to verify a JWT with a nil public key.
	ErrECDSANilPubKey = internal.NewError("jwt: ECDSA public key is nil")
	// ErrECDSAVerification is the error for an invalid ECDSA signature.
	ErrECDSAVerification = internal.NewError("jwt: ECDSA verification failed")
)
View Source
var (
	// ErrEd25519NilPrivKey is the error for trying to sign a JWT with a nil private key.
	ErrEd25519NilPrivKey = internal.NewError("jwt: Ed25519 private key is nil")
	// ErrEd25519NilPubKey is the error for trying to verify a JWT with a nil public key.
	ErrEd25519NilPubKey = internal.NewError("jwt: Ed25519 public key is nil")
	// ErrEd25519Verification is the error for when verification with Ed25519 fails.
	ErrEd25519Verification = internal.NewError("jwt: Ed25519 verification failed")
)
View Source
var (
	// ErrHMACMissingKey is the error for trying to sign or verify a JWT with an empty key.
	ErrHMACMissingKey = internal.NewError("jwt: HMAC key is empty")
	// ErrHMACVerification is the error for an invalid signature.
	ErrHMACVerification = internal.NewError("jwt: HMAC verification failed")
)
View Source
var (
	// ErrRSANilPrivKey is the error for trying to sign a JWT with a nil private key.
	ErrRSANilPrivKey = internal.NewError("jwt: RSA private key is nil")
	// ErrRSANilPubKey is the error for trying to verify a JWT with a nil public key.
	ErrRSANilPubKey = internal.NewError("jwt: RSA public key is nil")
	// ErrRSAVerification is the error for an invalid RSA signature.
	ErrRSAVerification = internal.NewError("jwt: RSA verification failed")
)
View Source
var (
	// ErrAudValidation is the error for an invalid "aud" claim.
	ErrAudValidation = internal.NewError("jwt: aud claim is invalid")
	// ErrExpValidation is the error for an invalid "exp" claim.
	ErrExpValidation = internal.NewError("jwt: exp claim is invalid")
	// ErrIatValidation is the error for an invalid "iat" claim.
	ErrIatValidation = internal.NewError("jwt: iat claim is invalid")
	// ErrIssValidation is the error for an invalid "iss" claim.
	ErrIssValidation = internal.NewError("jwt: iss claim is invalid")
	// ErrJtiValidation is the error for an invalid "jti" claim.
	ErrJtiValidation = internal.NewError("jwt: jti claim is invalid")
	// ErrNbfValidation is the error for an invalid "nbf" claim.
	ErrNbfValidation = internal.NewError("jwt: nbf claim is invalid")
	// ErrSubValidation is the error for an invalid "sub" claim.
	ErrSubValidation = internal.NewError("jwt: sub claim is invalid")
)
View Source
var ErrAlgValidation = internal.NewError(`invalid "alg" field`)

ErrAlgValidation indicates an incoming JWT's "alg" field mismatches the Validator's.

View Source
var ErrMalformed = internal.NewError("jwt: malformed token")

ErrMalformed indicates a token doesn't have a valid format, as per the RFC 7519.

View Source
var ErrNotJSONObject = errors.New("jwt: payload is not a valid JSON object")

ErrNotJSONObject is the error for when a JWT payload is not a JSON object.

Functions

func ECDSAPrivateKey

func ECDSAPrivateKey(priv *ecdsa.PrivateKey) func(*ECDSASHA)

ECDSAPrivateKey is an option to set a private key to the ECDSA-SHA algorithm.

func ECDSAPublicKey

func ECDSAPublicKey(pub *ecdsa.PublicKey) func(*ECDSASHA)

ECDSAPublicKey is an option to set a public key to the ECDSA-SHA algorithm.

func Ed25519PrivateKey

func Ed25519PrivateKey(priv ed25519.PrivateKey) func(*Ed25519)

Ed25519PrivateKey is an option to set a private key to the Ed25519 algorithm.

func Ed25519PublicKey

func Ed25519PublicKey(pub ed25519.PublicKey) func(*Ed25519)

Ed25519PublicKey is an option to set a public key to the Ed25519 algorithm.

func RSAPrivateKey

func RSAPrivateKey(priv *rsa.PrivateKey) func(*RSASHA)

RSAPrivateKey is an option to set a private key to the RSA-SHA algorithm.

func RSAPublicKey

func RSAPublicKey(pub *rsa.PublicKey) func(*RSASHA)

RSAPublicKey is an option to set a public key to the RSA-SHA algorithm.

func Sign

func Sign(payload interface{}, alg Algorithm, opts ...SignOption) ([]byte, error)

Sign signs a payload with alg.

func ValidateHeader

func ValidateHeader(rt *RawToken) error

ValidateHeader checks whether the algorithm contained in the JOSE header is the same used by the algorithm.

Types

type Algorithm

type Algorithm interface {
	Name() string
	Sign(headerPayload []byte) ([]byte, error)
	Size() int
	Verify(headerPayload, sig []byte) error
}

Algorithm is an algorithm for both signing and verifying a JWT.

func None

func None() Algorithm

None returns a dull, unsecured algorithm.

type Audience

type Audience []string

Audience is a special claim that may either be a single string or an array of strings, as per the RFC 7519.

func (Audience) MarshalJSON

func (a Audience) MarshalJSON() ([]byte, error)

MarshalJSON implements a marshaling function for "aud" claim.

func (*Audience) UnmarshalJSON

func (a *Audience) UnmarshalJSON(b []byte) error

UnmarshalJSON implements an unmarshaling function for "aud" claim.

type ECDSASHA

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

ECDSASHA is an algorithm that uses ECDSA to sign SHA hashes.

func NewES256

func NewES256(opts ...func(*ECDSASHA)) *ECDSASHA

NewES256 creates a new algorithm using ECDSA and SHA-256.

func NewES384

func NewES384(opts ...func(*ECDSASHA)) *ECDSASHA

NewES384 creates a new algorithm using ECDSA and SHA-384.

func NewES512

func NewES512(opts ...func(*ECDSASHA)) *ECDSASHA

NewES512 creates a new algorithm using ECDSA and SHA-512.

func (*ECDSASHA) Name

func (es *ECDSASHA) Name() string

Name returns the algorithm's name.

func (*ECDSASHA) Sign

func (es *ECDSASHA) Sign(headerPayload []byte) ([]byte, error)

Sign signs headerPayload using the ECDSA-SHA algorithm.

func (*ECDSASHA) Size

func (es *ECDSASHA) Size() int

Size returns the signature's byte size.

func (*ECDSASHA) Verify

func (es *ECDSASHA) Verify(headerPayload, sig []byte) (err error)

Verify verifies a signature based on headerPayload using ECDSA-SHA.

type Ed25519

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

Ed25519 is an algorithm that uses EdDSA to sign SHA-512 hashes.

func NewEd25519

func NewEd25519(opts ...func(*Ed25519)) *Ed25519

NewEd25519 creates a new algorithm using EdDSA and SHA-512.

func (*Ed25519) Name

func (*Ed25519) Name() string

Name returns the algorithm's name.

func (*Ed25519) Sign

func (ed *Ed25519) Sign(headerPayload []byte) ([]byte, error)

Sign signs headerPayload using the Ed25519 algorithm.

func (*Ed25519) Size

func (*Ed25519) Size() int

Size returns the signature byte size.

func (*Ed25519) Verify

func (ed *Ed25519) Verify(payload, sig []byte) (err error)

Verify verifies a payload and a signature.

type HMACSHA

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

HMACSHA is an algorithm that uses HMAC to sign SHA hashes.

func NewHS256

func NewHS256(key []byte) *HMACSHA

NewHS256 creates a new algorithm using HMAC and SHA-256.

func NewHS384

func NewHS384(key []byte) *HMACSHA

NewHS384 creates a new algorithm using HMAC and SHA-384.

func NewHS512

func NewHS512(key []byte) *HMACSHA

NewHS512 creates a new algorithm using HMAC and SHA-512.

func (*HMACSHA) Name

func (hs *HMACSHA) Name() string

Name returns the algorithm's name.

func (*HMACSHA) Sign

func (hs *HMACSHA) Sign(headerPayload []byte) ([]byte, error)

Sign signs headerPayload using the HMAC-SHA algorithm.

func (*HMACSHA) Size

func (hs *HMACSHA) Size() int

Size returns the signature's byte size.

func (*HMACSHA) Verify

func (hs *HMACSHA) Verify(headerPayload, sig []byte) (err error)

Verify verifies a signature based on headerPayload using HMAC-SHA.

type Header struct {
	Algorithm   string `json:"alg,omitempty"`
	ContentType string `json:"cty,omitempty"`
	KeyID       string `json:"kid,omitempty"`
	Type        string `json:"typ,omitempty"`
}

Header is a JOSE header narrowed down to the JWT specification from RFC 7519.

Parameters are ordered according to the RFC 7515.

func Verify

func Verify(token []byte, alg Algorithm, payload interface{}, opts ...VerifyOption) (Header, error)

Verify verifies a token's signature using alg. Before verification, opts is iterated and each option in it is run.

type Payload

type Payload struct {
	Issuer         string   `json:"iss,omitempty"`
	Subject        string   `json:"sub,omitempty"`
	Audience       Audience `json:"aud,omitempty"`
	ExpirationTime *Time    `json:"exp,omitempty"`
	NotBefore      *Time    `json:"nbf,omitempty"`
	IssuedAt       *Time    `json:"iat,omitempty"`
	JWTID          string   `json:"jti,omitempty"`
}

Payload is a JWT payload according to the RFC 7519.

type RSASHA

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

RSASHA is an algorithm that uses RSA to sign SHA hashes.

func NewPS256

func NewPS256(opts ...func(*RSASHA)) *RSASHA

NewPS256 creates a new algorithm using RSA-PSS and SHA-256.

func NewPS384

func NewPS384(opts ...func(*RSASHA)) *RSASHA

NewPS384 creates a new algorithm using RSA-PSS and SHA-384.

func NewPS512

func NewPS512(opts ...func(*RSASHA)) *RSASHA

NewPS512 creates a new algorithm using RSA-PSS and SHA-512.

func NewRS256

func NewRS256(opts ...func(*RSASHA)) *RSASHA

NewRS256 creates a new algorithm using RSA and SHA-256.

func NewRS384

func NewRS384(opts ...func(*RSASHA)) *RSASHA

NewRS384 creates a new algorithm using RSA and SHA-384.

func NewRS512

func NewRS512(opts ...func(*RSASHA)) *RSASHA

NewRS512 creates a new algorithm using RSA and SHA-512.

func (*RSASHA) Name

func (rs *RSASHA) Name() string

Name returns the algorithm's name.

func (*RSASHA) Sign

func (rs *RSASHA) Sign(headerPayload []byte) ([]byte, error)

Sign signs headerPayload using either RSA-SHA or RSA-PSS-SHA algorithms.

func (*RSASHA) Size

func (rs *RSASHA) Size() int

Size returns the signature's byte size.

func (*RSASHA) Verify

func (rs *RSASHA) Verify(headerPayload, sig []byte) (err error)

Verify verifies a signature based on headerPayload using either RSA-SHA or RSA-PSS-SHA.

type RawToken

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

RawToken is a representation of a parsed JWT string.

type Resolver

type Resolver interface {
	Resolve(Header) error
}

Resolver is an Algorithm that needs to set some variables based on a Header before performing signing and verification.

type SignOption

type SignOption func(*Header)

SignOption is a functional option for signing.

func ContentType

func ContentType(cty string) SignOption

ContentType sets the "cty" claim for a Header before signing.

func KeyID

func KeyID(kid string) SignOption

KeyID sets the "kid" claim for a Header before signing.

type Time

type Time struct {
	time.Time
}

Time is the allowed format for time, as per the RFC 7519.

func NumericDate

func NumericDate(tt time.Time) *Time

NumericDate is a resolved Unix time.

func (Time) MarshalJSON

func (t Time) MarshalJSON() ([]byte, error)

MarshalJSON implements a marshaling function for time-related claims.

func (*Time) UnmarshalJSON

func (t *Time) UnmarshalJSON(b []byte) error

UnmarshalJSON implements an unmarshaling function for time-related claims.

type Validator

type Validator func(*Payload) error

Validator is a function that validates a Payload pointer.

func AudienceValidator

func AudienceValidator(aud Audience) Validator

AudienceValidator validates the "aud" claim. It checks if at least one of the audiences in the JWT's payload is listed in aud.

func ExpirationTimeValidator

func ExpirationTimeValidator(now time.Time) Validator

ExpirationTimeValidator validates the "exp" claim.

func IDValidator

func IDValidator(jti string) Validator

IDValidator validates the "jti" claim.

func IssuedAtValidator

func IssuedAtValidator(now time.Time) Validator

IssuedAtValidator validates the "iat" claim.

func IssuerValidator

func IssuerValidator(iss string) Validator

IssuerValidator validates the "iss" claim.

func NotBeforeValidator

func NotBeforeValidator(now time.Time) Validator

NotBeforeValidator validates the "nbf" claim.

func SubjectValidator

func SubjectValidator(sub string) Validator

SubjectValidator validates the "sub" claim.

type VerifyOption

type VerifyOption func(*RawToken) error

VerifyOption is a functional option for verifying.

func ValidatePayload

func ValidatePayload(pl *Payload, vds ...Validator) VerifyOption

ValidatePayload runs validators against a Payload after it's been decoded.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
t or T : Toggle theme light dark auto