jwt

package module
v0.0.0-...-553f554 Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2023 License: BSD-3-Clause Imports: 21 Imported by: 0

README

Quickstart

Import

import "github.com/scottcagno/webslinger/pkg/web/jwt"

Choose a Signing Method

...
// RSA signing methods
_ = jwt.RS256
_ = jwt.RS384
_ = jwt.RS512

// HMAC signing methods
_ = jwt.HS256
_ = jwt.HS384
_ = jwt.HS512

// ECDSA signing methods
_ = jwt.ES256
_ = jwt.ES384
_ = jwt.ES512

// RSAPSS signing methods
_ = jwt.PS256
_ = jwt.PS384
_ = jwt.PS512
...

You can generate a key pair

...
// Generate key pair using RSA 512
keys := jwt.RS512.GenerateKeyPair()
...

Or, load your own keys in and create a key pair

...
// Read private key file
privateKeyData, err := os.ReadFile("mykeys/private.pem") 
if err != nil {
    log.Fatal(err)
}

// Read public key file
publicKeyData, err := os.ReadFile("mykeys/public.pem")
if err != nil {
    log.Fatal(err)
}

// Parse your private key
pri, err := jwt.ParsePrivateKeyFromPEM(privateKeyData)
if err != nil {
    log.Fatal(err)
}

// Parse your public key
pub, err := jwt.ParsePublicKeyFromPEM(publicKeyData)
if err != nil {
    log.Fatal(err)
}

// Create a *KeyPair to use with the manager
keys := &jwt.KeyPair{
    PrivateKey: pri,
    PublicKey:  pub,
}
...

Instantiate the manager, and you're off

...
// Instantiate the token manager
keys := jwt.HS256.GenerateKeyPair()
manager := jwt.NewTokenManager(jwt.HS256, keys)
...

Generate a token using the manager

...
// Generating a signed token with no claims
token, err := manager.GenerateToken(nil)
if err != nil {
    log.Fatal(err)
}
...

Generate a token directly, verify a token directly

...
// Generating a signed token directly
token, err := jwt.NewToken(jwt.HS256, claims, privateKey)
if err != nil {
    log.Fatal(err)
}

// Validating a signed token directly
validToken, err := jwt.ValidateToken(token, jwt.HS256, publicKey)
if err != nil {
	log.Fatal(err)
}
...

Generate a token with registered claims

...
// Set some time info
exp := time.Now().Add(1 * time.Hour).Unix()
now := time.Now().Unix()

// Create some registered claims
claims := &jwt.RegisteredClaims{
    Issuer:         "jon doe",
    Subject:        "your mom goes to college",
    Audience:       "anyone",
    ExpirationTime: jwt.NumericDate(exp),
    NotBeforeTime:  jwt.NumericDate(now),
    IssuedAtTime:   jwt.NumericDate(now),
    ID:             "25",
}

// Generating a signed token with registered claims
token, err := manager.GenerateToken(claims)
if err != nil {
    log.Fatal(err)
}

Validate a token using the manager

...
// Validate a token using the manager
validToken, err = manager.ValidateToken(token)
if err != nil {
    log.Fatal(err)
}
...

Validate a token using the validator directly

...
// Validate a token using the manager
validator := &jwt.Validator{SigningMethod: jwt.HS256}
validToken, err := validator.ValidateToken(token, keys.PublicKey)
if err != nil {
    return nil, err
}

// Or simply validate the claims
err := validator.ValidateClaims(claims)
if err != nil {
    log.Fatal(err)
}
...

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidKeyType   = errors.New("alg: invalid key type")
	ErrHashUnavailable  = errors.New("alg: hash unavailable")
	ErrSignatureInvalid = errors.New("alg: signature is invalid")
)

SigningMethod errors

View Source
var (
	ErrTokenExpired             = errors.New("token expired")
	ErrTokenNotValidYet         = errors.New("token not valid yet")
	ErrTokenUsedBeforeIssued    = errors.New("token used before issued")
	ErrTokenInvalidAudience     = errors.New("token contains invalid audience")
	ErrTokenInvalidIssuer       = errors.New("token contains invalid issuer")
	ErrTokenInvalidSubject      = errors.New("token contains invalid subject")
	ErrTokenInvalidCustomClaims = errors.New("token contains invalid custom claims")
	ErrTokenClaimNotFound       = errors.New("token claim not found")
)

Validator errors

View Source
var (
	ErrTokenMalformed        = errors.New("token is malformed")
	ErrTokenUnverifiable     = errors.New("token is unverifiable")
	ErrTokenClaimsInvalid    = errors.New("token claims validation error")
	ErrTokenSignatureInvalid = errors.New("token validation signature invalid")
)

Parser errors

View Source
var (
	ErrNoTokenInRequest = errors.New("no token present in request")
	ErrNoCookieFound    = errors.New("no cookie present with specified name in request")
)
View Source
var (
	ErrParsingPEMPublicKey  = errors.New("failed to decode PEM block containing public key")
	ErrParsingPEMPrivateKey = errors.New("failed to decode PEM block containing private key")
)
View Source
var SkipValidation = errors.New("skip validation for this claim")

SkipValidation can be used as a return value from ValidateClaimFunc to indicate that the claim in the call is to be skipped. It is not returned as an error by any function.

Functions

func Base64Decode

func Base64Decode(src []byte) []byte

func Base64Encode

func Base64Encode(src []byte) []byte

func ParsePrivateKeyFromPEM

func ParsePrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error)

ParsePrivateKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key

func ParsePublicKeyFromPEM

func ParsePublicKeyFromPEM(key []byte) (crypto.PublicKey, error)

ParsePublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key

func PrivateKeyType

func PrivateKeyType(key crypto.PrivateKey)

func PublicKeyType

func PublicKeyType(key crypto.PublicKey)

func RegisterSigningMethod

func RegisterSigningMethod(name string, fn func() SigningMethod)

Types

type ClaimsSet

type ClaimsSet interface {

	// GetISS is the issuer of the JWT.
	GetISS() (string, error)

	// GetSUB is the subject of the JWT.
	GetSUB() (string, error)

	// GetAUD is the audience (Recipient for which the JWT is intended.)
	GetAUD() (string, error)

	// GetEXP is the time after which the JWT expires.
	GetEXP() (NumericDate, error)

	// GetNBF is the time before the JWT must not be accepted for processing.
	GetNBF() (NumericDate, error)

	// GetIAT is the time at which the JWT was issued.
	// It can be used to determine the age of the JWT.
	GetIAT() (NumericDate, error)

	// GetJTI is a unique identifier. It can be used to prevent the JWT
	// from being replayed; it allows a token to be used only once.
	GetJTI() (string, error)
}

ClaimsSet is an interface for a set of claims.

type CustomClaimsSet

type CustomClaimsSet interface {
	ClaimsSet
	Validate() error
}

CustomClaimsSet is an interface for representing a custom claim, or a set of custom claims. It is intended to be used for building custom claim validation in addition to the integrated ClaimsSet.

type KeyPair

type KeyPair struct {
	PrivateKey crypto.PrivateKey
	PublicKey  crypto.PublicKey
}

type MapClaims

type MapClaims map[string]any

func (MapClaims) GetAUD

func (m MapClaims) GetAUD() (string, error)

func (MapClaims) GetEXP

func (m MapClaims) GetEXP() (NumericDate, error)

func (MapClaims) GetIAT

func (m MapClaims) GetIAT() (NumericDate, error)

func (MapClaims) GetISS

func (m MapClaims) GetISS() (string, error)

func (MapClaims) GetJTI

func (m MapClaims) GetJTI() (string, error)

func (MapClaims) GetNBF

func (m MapClaims) GetNBF() (NumericDate, error)

func (MapClaims) GetSUB

func (m MapClaims) GetSUB() (string, error)

func (MapClaims) String

func (m MapClaims) String() string

type NumericDate

type NumericDate int64

func NumericDateFromFloat

func NumericDateFromFloat(f float64) NumericDate

func NumericDateFromJsonNumber

func NumericDateFromJsonNumber(n json.Number) NumericDate

func NumericDateNow

func NumericDateNow() NumericDate

func (NumericDate) Add

func (NumericDate) Time

func (n NumericDate) Time() time.Time

type RawToken

type RawToken []byte

func ExtractTokenFromCookie

func ExtractTokenFromCookie(name string, r *http.Request) (RawToken, error)

func ExtractTokenFromRequest

func ExtractTokenFromRequest(r *http.Request) (RawToken, error)

func NewToken

func NewToken(alg SigningMethod, claims ClaimsSet, key crypto.PrivateKey) (RawToken, error)

func (RawToken) Claims

func (t RawToken) Claims() ClaimsSet

func (RawToken) GetSection

func (t RawToken) GetSection(section Section) (int, int)

GetSection returns the start and end index for section containing the header, the payload or the signature.

func (RawToken) Header

func (t RawToken) Header() *TokenHeader

func (RawToken) Signature

func (t RawToken) Signature() []byte

func (RawToken) SigningSection

func (t RawToken) SigningSection() []byte

type RegisteredClaims

type RegisteredClaims struct {
	Issuer         string      `json:"iss,omitempty"`
	Subject        string      `json:"sub,omitempty"`
	Audience       string      `json:"aud,omitempty"`
	ExpirationTime NumericDate `json:"exp,omitempty"`
	NotBeforeTime  NumericDate `json:"nbf,omitempty"`
	IssuedAtTime   NumericDate `json:"iat,omitempty"`
	ID             string      `json:"jti,omitempty"`
}

RegisteredClaims is the default set of registered claims. It can be used in addition to custom claims by embedding the registered claims in

func (*RegisteredClaims) GetAUD

func (r *RegisteredClaims) GetAUD() (string, error)

func (*RegisteredClaims) GetEXP

func (r *RegisteredClaims) GetEXP() (NumericDate, error)

func (*RegisteredClaims) GetIAT

func (r *RegisteredClaims) GetIAT() (NumericDate, error)

func (*RegisteredClaims) GetISS

func (r *RegisteredClaims) GetISS() (string, error)

func (*RegisteredClaims) GetJTI

func (r *RegisteredClaims) GetJTI() (string, error)

func (*RegisteredClaims) GetNBF

func (r *RegisteredClaims) GetNBF() (NumericDate, error)

func (*RegisteredClaims) GetSUB

func (r *RegisteredClaims) GetSUB() (string, error)

type Section

type Section uint8
const (
	HeaderSection    Section = 0
	PayloadSection   Section = 1
	ClaimsSection    Section = 1
	SignatureSection Section = 2
	PartialToken     Section = 3
	SigningString    Section = 3
)

type SigningMethod

type SigningMethod interface {

	// Name should return the name of the signing method.
	Name() string

	// GenerateKeyPair should generate and return a key pair complient
	// with the implementing signing method.
	GenerateKeyPair() *KeyPair

	// Sign should take a base64 encoded header and payload and return a
	// valid signature.
	Sign(partialToken []byte, key crypto.PrivateKey) (signature []byte, err error)

	// Verify should take a token and signature and verify the token using the
	// provided signature.
	Verify(partialToken []byte, signature []byte, key crypto.PublicKey) error
}

SigningMethod is an interface for implementing singing and verifying methods

func GetSigningMethod

func GetSigningMethod(name string) SigningMethod

type SigningMethodECDSA

type SigningMethodECDSA struct {
	KeySize   int
	CurveBits int
	// contains filtered or unexported fields
}

SigningMethodECDSA implements the ECDSA family of signing methods. Expects *ecdsa.PrivateKey for signing and *ecdsa.PublicKey for verification

func (*SigningMethodECDSA) GenerateKeyPair

func (s *SigningMethodECDSA) GenerateKeyPair() *KeyPair

func (*SigningMethodECDSA) Name

func (s *SigningMethodECDSA) Name() string

func (*SigningMethodECDSA) Sign

func (s *SigningMethodECDSA) Sign(partialToken []byte, key crypto.PrivateKey) ([]byte, error)

func (*SigningMethodECDSA) Verify

func (s *SigningMethodECDSA) Verify(partialToken []byte, signature []byte, key crypto.PublicKey) error

type SigningMethodHMAC

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

SigningMethodHMAC implements the HMAC-SHA family of signing methods. Expects key type of []byte for both signing and validation

func (*SigningMethodHMAC) GenerateKeyPair

func (s *SigningMethodHMAC) GenerateKeyPair() *KeyPair

func (*SigningMethodHMAC) Name

func (s *SigningMethodHMAC) Name() string

func (*SigningMethodHMAC) Sign

func (s *SigningMethodHMAC) Sign(partialToken []byte, key crypto.PrivateKey) ([]byte, error)

func (*SigningMethodHMAC) Verify

func (s *SigningMethodHMAC) Verify(partialToken []byte, signature []byte, key crypto.PublicKey) error

type SigningMethodRSA

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

SigningMethodRSA implements the RSA family of signing methods. Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation

var (
	RS256 *SigningMethodRSA
	RS384 *SigningMethodRSA
	RS512 *SigningMethodRSA
)

func (*SigningMethodRSA) GenerateKeyPair

func (s *SigningMethodRSA) GenerateKeyPair() *KeyPair

func (*SigningMethodRSA) Name

func (s *SigningMethodRSA) Name() string

func (*SigningMethodRSA) Sign

func (s *SigningMethodRSA) Sign(partialToken []byte, key crypto.PrivateKey) ([]byte, error)

func (*SigningMethodRSA) Verify

func (s *SigningMethodRSA) Verify(partialToken []byte, signature []byte, key crypto.PublicKey) error

type SigningMethodRSAPSS

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

SigningMethodRSA implements the RSAPSS family of signing methods. Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation

func (*SigningMethodRSAPSS) GenerateKeyPair

func (s *SigningMethodRSAPSS) GenerateKeyPair() *KeyPair

func (*SigningMethodRSAPSS) Name

func (s *SigningMethodRSAPSS) Name() string

func (*SigningMethodRSAPSS) Sign

func (s *SigningMethodRSAPSS) Sign(partialToken []byte, key crypto.PrivateKey) ([]byte, error)

func (*SigningMethodRSAPSS) Verify

func (s *SigningMethodRSAPSS) Verify(partialToken []byte, signature []byte, key crypto.PublicKey) error

type Token

type Token struct {
	RawToken
	Header    TokenHeader
	Payload   MapClaims
	Method    SigningMethod
	Signature []byte
	Valid     bool
}

func ParseRawToken

func ParseRawToken(raw RawToken) (*Token, error)

func ValidateToken

func ValidateToken(rawToken RawToken, method SigningMethod, key crypto.PublicKey) (*Token, error)

type TokenHeader

type TokenHeader struct {
	Typ string `json:"typ"`
	Alg string `json:"alg"`
}

type TokenManager

type TokenManager struct {
	Validator
	// contains filtered or unexported fields
}

func NewTokenManager

func NewTokenManager(method SigningMethod, keys *KeyPair) *TokenManager

func (*TokenManager) GenerateToken

func (m *TokenManager) GenerateToken(claims ClaimsSet) (RawToken, error)

func (*TokenManager) ValidateToken

func (m *TokenManager) ValidateToken(raw RawToken) (*Token, error)

func (*TokenManager) ValidateTokenFromRequest

func (m *TokenManager) ValidateTokenFromRequest(r *http.Request) (*Token, error)

type ValidateClaimFunc

type ValidateClaimFunc func(name string, claim any) error

ValidateClaimFunc is the type of function called by ValidateClaims in order to validate a claims set. It makes it possible to implement custom claims validation. If you do not want a claim to be validated the SkipValidation error is returned.

type Validator

type Validator struct {

	// Margin is an optional time margin that can be applied
	// to account for clock skew
	Margin time.Duration

	// ValidateIAT specifies whether the issued at time claim
	// will be validated.
	ValidateIAT bool

	// ExpectedAUD holds the audience this token expects; if
	// it is left as an empty string, audience validation will
	// be disabled.
	ExpectedAUD string

	// ExpectedISS holds the issuer this token expects; if
	// it is left as an empty string, issuer validation will
	// be disabled.
	ExpectedISS string

	// ExpectedSUB holds the subject this token expects; if
	// it is left as an empty string, subject validation will
	// be disabled.
	ExpectedSUB string

	Method SigningMethod
}

Validator is the main validation structure for validating claims, etc.

func (*Validator) ValidateClaims

func (v *Validator) ValidateClaims(claims ClaimsSet) error

func (*Validator) ValidateToken

func (v *Validator) ValidateToken(raw RawToken, key crypto.PublicKey) (*Token, error)

Jump to

Keyboard shortcuts

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