jwt

package
v0.0.0-...-ccd4941 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2023 License: MPL-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package jwt provides a simple and easy-to-use interface for working with JSON Web Tokens (JWTs) as defined by RFC 7519.

It supports creating, parsing, and verifying JWTs, as well as setting custom claims and expiration times. This package is designed to be lightweight and flexible, making it ideal for use in a wide range of applications.

Index

Examples

Constants

View Source
const (
	// ContextKey is the key used to store the JWT in the context.
	ContextKey contextKey = "jwt"
)
View Source
const Type header.ParamaterName = "JWT"

Type "JWT" is the media type used by JSON Web Token (JWT).

Example

header := header.Parameters{
	header.Type:      jwt.Type,
	header.Algorithm: jwa.HS256,
}

https://www.rfc-editor.org/rfc/rfc7515.html#section-3.3

Variables

This section is empty.

Functions

func DefaultAllowedAlogrithms

func DefaultAllowedAlogrithms() []jwa.Algorithm

func FromHTTPAuthorizationHeader

func FromHTTPAuthorizationHeader(r *http.Request) (string, error)

FromHTTPAuthorizationHeader extracts a JWT string from the Authorization header of an HTTP request. If the Authorization header is not set, then an error is returned.

Warning

This value needs to be parsed and verified before it can be used safely.

func GetCalimValue

func GetCalimValue[T any](claims ClaimsSet, name ClaimName) (T, error)

GetCalimValue returns the ClaimValue for the given ClaimName of type T.

It returns an error if the ClaimValue is not of type T, or if the ClaimName is not found in the ClaimsSet.

func SetHTTPAuthorizationHeader

func SetHTTPAuthorizationHeader[T HTTPHeaderValue](r *http.Request, jwt T)

SetHTTPAuthorizationHeader sets the Authorization header of an HTTP request to the given JWT. The JWT is prefixed with "Bearer ", as required by the HTTP Authorization header specification.

https://tools.ietf.org/html/rfc6750#section-2.1

func WithContext

func WithContext(ctx context.Context, token *Token) context.Context

WithContext sets the JWT in the given context.

Types

type ClaimName

type ClaimName = string

There are three classes of JWT Claim Names:

  1. Registered Claim Names
  2. Public Claim Names
  3. Private Claim Names

type ClaimValue

type ClaimValue any

ClaimValue is a piece of information asserted about a subject, represented as a name/value pair consisting of a ClaimName and a ClaimValue.

type ClaimsSet

type ClaimsSet map[ClaimName]ClaimValue

ClaimsSet is a JSON object that contains the claims in a JWT.

A claim is a piece of information asserted about a subject, represented as a name/value pair consisting of a Claim Name and a Claim Value.

func (ClaimsSet) Get

func (claims ClaimsSet) Get(name ClaimName) (ClaimValue, error)

Get returns the ClaimValue for the given ClaimName.

func (ClaimsSet) Names

func (claims ClaimsSet) Names() []ClaimName

Names returns the ClaimNames in the ClaimsSet in sorted order.

func (ClaimsSet) Set

func (claims ClaimsSet) Set(name ClaimName, value ClaimValue)

Set sets the ClaimValue for the given ClaimName.

func (ClaimsSet) String

func (claims ClaimsSet) String() string

String returns the string representation of the ClaimsSet as a base64 encoded JSON object. If the ClaimsSet cannot be encoded, it returns a string representation of the error.

type Clock

type Clock func() time.Time

Clock is type used to represent a function that returns the current time.

type HTTPHeaderValue

type HTTPHeaderValue interface {
	string | *Token
}

HTTPHeaderValue is a type that can be used as a value when setting an HTTP request header.

type Issuers

type Issuers = []string

Issuers is a set of issuers.

type Parseable

type Parseable interface {
	~string | ~[]byte
}

Parseable is a type that can be parsed into a JWT, either a string or byte slice.

type Private

There are three classes of JWT Claim Names:

  1. Registered Claim Names
  2. Public Claim Names
  3. Private Claim Names

type PrivateKey

type PrivateKey interface {
	*rsa.PrivateKey | *ecdsa.PrivateKey | ed25519.PrivateKey | []byte | string
}

PrivateKey is a type that can be used to sign a JWT, such as a *rsa.PrivateKey or *ecdsa.PrivateKey.

This may be a shared secret key, such as a []byte or string, but this is not recommended.

type Public

There are three classes of JWT Claim Names:

  1. Registered Claim Names
  2. Public Claim Names
  3. Private Claim Names

type PublicKey

type PublicKey interface {
	*rsa.PublicKey | *ecdsa.PublicKey | ed25519.PublicKey
}

PublicKey is a type that can be used to verify a JWT using an asymmetric algorithm, such as *rsa.PublicKey or *ecdsa.PublicKey.

type Set

type Set[T comparable] map[T]struct{}

Set is a set of comparable values for JWT operations.

func NewSet

func NewSet(strings ...string) Set[string]

NewSet creates a new set of strings.

type SigningKey

type SigningKey interface {
	PrivateKey | SymmetricKey
}

SigningKey is a type that can be used to sign a JWT using either a symmetric or asymmetric algorithm.

type SymmetricKey

type SymmetricKey interface {
	[]byte | string
}

SymmetricKey is a type that can be used to sign or verify a JWT using a symmetric algorithm, such as HMAC.

type Token

type Token struct {
	// Header is the set of parameters that are used to describe
	// the cryptographic operations applied to the JWT claims set.
	Header header.Parameters

	// Claims is the set of claims that are asserted by the JWT.
	//
	// This is sometimes referred to as the "payload".
	Claims ClaimsSet

	// Signature is the cryptographic signature or MAC value
	// that is used to validate the JWT.
	Signature []byte
	// contains filtered or unexported fields
}

Token is a decoded JSON Web Token, a string representing a set of claims as a JSON object that is encoded in a JWS or JWE, enabling the claims to be digitally signed or MACed and/or encrypted.

At this time, only JWS JWTs are supported. In other words, these tokens are only signed, not encrypted.

JWTs contain three parts, separated by dots (".") which are:

  1. Header
  2. Claims (Payload)
  3. Signature

https://datatracker.ietf.org/doc/html/rfc7519#section-1

func FromContext

func FromContext(ctx context.Context) *Token

FromContext extracts a JWT from the given context. If the JWT is not in the context, then nil is returned.

func New

func New[T SigningKey](params header.Parameters, claims ClaimsSet, key T) (*Token, error)

New can be used to create a signed Token object. If this fails for any reason, an error is returned with a nil token.

Using this function does not require the given header parameters define the "typ" (header.Type), which is always set to "JWT" (header.TypeJWT), but callers can include it if they like.

The claims set must not be empty, or will return an error.

The given key can be a symmetric or asymmetric (private) key. The type for this argument depends on the algorithm "alg" defined in the header.

Example algorithm(s) to Supported Key Type(s):

  • HS256, HS384, HS512: []byte or string
  • RS256, RS384, RS512: *rsa.PrivateKey
  • PS256, PS384, PS512: *rsa.PrivateKey
  • ES256, ES384, ES512: *ecdsa.PrivateKey
  • EdDSA: ed25519.PrivateKey
Example (Asymmetric)
package main

import (
	"fmt"
	"time"

	"github.com/picatz/jose/pkg/header"
	"github.com/picatz/jose/pkg/jwa"
	"github.com/picatz/jose/pkg/jwt"
	"github.com/picatz/jose/pkg/keyutil"
)

var now = time.Time{}

func main() {
	publicKey, privateKey, _ := keyutil.NewRSAKeyPair()

	token, _ := jwt.New(
		header.Parameters{
			header.Type:      jwt.Type,
			header.Algorithm: jwa.RS256,
		},
		jwt.ClaimsSet{
			jwt.Subject:        "example",
			jwt.IssuedAt:       now,
			jwt.NotBefore:      now.Add(2 * time.Hour),
			jwt.ExpirationTime: now.Add(24 * time.Hour),
		},
		privateKey,
	)

	_ = token.Verify(jwt.WithAllowedAlgorithms(jwa.RS256), jwt.WithKey(publicKey))

	fmt.Println(token.Claims[jwt.Subject])
}
Output:

example
Example (Symmetric)
package main

import (
	"fmt"
	"time"

	"github.com/picatz/jose/pkg/header"
	"github.com/picatz/jose/pkg/jwa"
	"github.com/picatz/jose/pkg/jwt"
)

var now = time.Time{}

// https://www.rfc-editor.org/rfc/rfc7515.html#appendix-A.1
var secretKeyBytes = []byte{
	3, 35, 53, 75, 43, 15, 165, 188, 131, 126, 6, 101, 119, 123, 166,
	143, 90, 179, 40, 230, 240, 84, 201, 40, 169, 15, 132, 178, 210, 80,
	46, 191, 211, 251, 90, 146, 210, 6, 71, 239, 150, 138, 180, 195, 119,
	98, 61, 34, 61, 46, 33, 114, 5, 46, 79, 8, 192, 205, 154, 245, 103,
	208, 128, 163,
}

func main() {
	token, _ := jwt.New(
		header.Parameters{
			header.Type:      jwt.Type,
			header.Algorithm: jwa.HS256,
		},
		jwt.ClaimsSet{
			jwt.Subject:        "example",
			jwt.IssuedAt:       now,
			jwt.NotBefore:      now.Add(2 * time.Hour),
			jwt.ExpirationTime: now.Add(24 * time.Hour),
		},
		secretKeyBytes,
	)

	_ = token.Verify(jwt.WithAllowedAlgorithms(jwa.HS256), jwt.WithKey(secretKeyBytes))

	fmt.Println(token)
}
Output:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9Cg.eyJleHAiOi02MjEzNTUxMDQwMCwiaWF0IjotNjIxMzU1OTY4MDAsIm5iZiI6LTYyMTM1NTg5NjAwLCJzdWIiOiJleGFtcGxlIn0K.ha_kAIOiX9BQegjRlPSBMuAcEo8slvXGmJPq8HaTNlU

func Parse

func Parse[T Parseable](input T) (*Token, error)

Parse parses a given JWT, and returns a Token or an error if the JWT fails to parse.

Warning

This is a low-level function that does not verify the signature of the token. Use ParseAndVerify to parse and verify the signature of a token in one step. Otherwise, use Parse to parse a token, and then use the VerifySignature method to verify the signature.

func ParseAndVerify

func ParseAndVerify[T Parseable](input T, veryifyOptions ...VerifyOption) (*Token, error)

ParseAndVerify parses a given JWT, and verifies the signature using the given verification configuration options.

func ParseString

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

ParseString parses a given JWT string, and returns a Token or an error if the JWT fails to parse.

Warning

This is a low-level function that does not verify the signature of the token. Use ParseAndVerify to parse and verify the signature of a token in one step. Otherwise, use Parse to parse a token, and then use the VerifySignature method to verify the signature.

func (*Token) ECDSASignature

func (t *Token) ECDSASignature(hash crypto.Hash, privateKey *ecdsa.PrivateKey) ([]byte, error)

ECDSASignature returns the ECDSA signature of the token using the given hash and private key.

func (*Token) EdDSASignature

func (t *Token) EdDSASignature(privateKey ed25519.PrivateKey) ([]byte, error)

EdDSASignature returns the EdDSA signature of the token using the given private key.

func (*Token) Expired

func (t *Token) Expired(clock Clock) (bool, error)

Expired returns true if the token is expired, false otherwise. If an error occurs while checking expiration, it is returned.

Only use the boolean value if error is nil.

func (*Token) Expires

func (t *Token) Expires() (bool, error)

Expires returns true if the token has an expiration time claim, false otherwise. If an error occurs while checking expiration, it is returned.

Only use the boolean value if error is nil.

func (*Token) HMACSignature

func (t *Token) HMACSignature(hash crypto.Hash, key any) ([]byte, error)

HMACSignature returns the HMAC signature of the token using the given hash and key.

func (*Token) RSAPSSSignature

func (t *Token) RSAPSSSignature(hash crypto.Hash, privateKey *rsa.PrivateKey) ([]byte, error)

RSAPSSSignature returns the RSA-PSS signature of the token using the given hash and private key.

This is similar to RSASignature, but uses the RSA-PSS algorithm, which is probabilistic, and therefore, the signature will be different each time.

func (*Token) RSASignature

func (t *Token) RSASignature(hash crypto.Hash, privateKey *rsa.PrivateKey) ([]byte, error)

RSASignature returns the RSA signature of the token using the given hash and private key.

func (*Token) Sign

func (t *Token) Sign(key any) ([]byte, error)

Sign returns the signature of the token using the given options.

func (*Token) String

func (t *Token) String() string

String returns the string representation of the token, which is the raw JWT string of three base64url encoded parts, separated by a period.

func (*Token) Verify

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

Verify is used to verify a signed Token object with the given config options. If this fails for any reason, an error is returned.

func (*Token) VerifyECDSASignature

func (t *Token) VerifyECDSASignature(hash crypto.Hash, publicKey *ecdsa.PublicKey) error

VerifyECDSASignature verifies the ECDSA signature of the token using the given hash and public key.

func (*Token) VerifyEdDSASignature

func (t *Token) VerifyEdDSASignature(publicKey ed25519.PublicKey) error

VerifyEdDSASignature verifies the EdDSA signature of the token using the given public key.

func (*Token) VerifyHMACSignature

func (t *Token) VerifyHMACSignature(hash crypto.Hash, key any) error

VerifyHMACSignature verifies the HMAC signature of the token using the given hash and key.

func (*Token) VerifyRSAPSSSignature

func (t *Token) VerifyRSAPSSSignature(hash crypto.Hash, publicKey *rsa.PublicKey) error

VerifyRSAPSSSignature verifies the RSA-PSS signature of the token using the given hash and public key.

This is similar to VerifyRSASignature, but uses the RSA-PSS algorithm, which is probabilistic, and therefore, the signature will be different each time.

func (*Token) VerifyRSASignature

func (t *Token) VerifyRSASignature(hash crypto.Hash, publicKey *rsa.PublicKey) error

VerifyRSASignature verifies the RSA signature of the token using the given hash and public key.

func (*Token) VerifySignature

func (t *Token) VerifySignature(allowedAlgs []string, allowedKeys map[string]any) error

VerifySignature verifies the signature of the token using the given verification configuration options.

Warning

This only verifies the signature, and does not verify any other claims, such as expiration time, issuer, audience, etc.

type VerifyConfig

type VerifyConfig struct {
	// InsecureAllowNone allows the "none" algorithm to be used, which
	// is considered insecure, dangerous, and disabled by default. It must be
	// set in addition to being enabled in the allowed algorithms.
	InsecureAllowNone bool

	// AllowedAlgorithms is a set of allowed algorithms for the JWT.
	//
	// If not set, then jwt.DefaultAllowedAlgorithms will be used.
	AllowedAlgorithms []jwa.Algorithm

	// AllowedIssuers is a set of allowed issuers for the JWT.
	//
	// If not set, then any issuers are allowed.
	AllowedIssuers []string

	// AllowedAudiences is a set of allowed audiences for the JWT.
	//
	// If not set, then any audiences are allowed.
	AllowedAudiences []string

	// AllowedKeys is a set of allowed keys for the JWT keyed by
	// the corresponding "kid" header parameter.
	//
	// If not set, then verification will fail if the algorithm
	// is not "none".
	AllowedKeys map[string]any

	// Clock is a function that returns the current time.
	//
	// This is used to verify the "exp", "nbf", and "iat" claims.
	//
	// If not set, then time.Now will be used.
	Clock func() time.Time
}

VerifyConfig is a configuration type for verifying JWTs.

type VerifyKey

type VerifyKey interface {
	PublicKey | SymmetricKey
}

VerifyKey is a type that can be used to verify a JWT using either a symmetric or asymmetric algorithm.

type VerifyOption

type VerifyOption func(*VerifyConfig) error

VerifyOption is a functional option type used to configure the verification requirements for JWTs.

func WithAllowInsecureNoneAlgorithm

func WithAllowInsecureNoneAlgorithm(value bool) VerifyOption

WithAllowInsecureNoneAlgorithm allows the "none" algorithm to be used. Users must explicitly enable this option, as it is considered insecure, dangerous, and disabled by default.

WARNING

This is not recommended, and should only be used for testing purposes.

func WithAllowedAlgorithms

func WithAllowedAlgorithms(algs ...jwa.Algorithm) VerifyOption

WithAllowedAlgorithms sets the allowed algorithms for the JWT.

func WithAllowedAudiences

func WithAllowedAudiences(audiences ...string) VerifyOption

WithAllowedAudiences sets the allowed audiences for the JWT.

func WithAllowedIssuers

func WithAllowedIssuers(issuers ...string) VerifyOption

WithAllowedIssuers sets the allowed issuers for the JWT.

func WithClock

func WithClock(clock Clock) VerifyOption

WithClock sets the clock function for verifying the JWT.

func WithDefaultClock

func WithDefaultClock() VerifyOption

WithDefaultClock sets the clock function for verifying the JWT to time.Now.

func WithIdentifiableKey

func WithIdentifiableKey[T VerifyKey](kid string, key T) VerifyOption

WithIdentifiableKey adds a key by ID to the set of allowed keys for the JWT.

This is the preferred way to add a key to the set of allowed keys, because it will ensure that the givne key is of the correct type at compile time.

func WithKey

func WithKey[T VerifyKey](key T) VerifyOption

WithKey appends a key to the set of allowed keys for the JWT using a randomly generated key ID.

This is the preferred way to add a key to the set of allowed keys, because it will ensure that the givne key is of the correct type at compile time.

Jump to

Keyboard shortcuts

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