jwt

package
v0.0.0-...-6697815 Latest Latest
Warning

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

Go to latest
Published: Jan 18, 2023 License: BSD-3-Clause Imports: 20 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ValidationErrorMalformed uint32 = 1 << iota
	ValidationErrorUnverifiable
	ValidationErrorSignatureInvalid

	ValidationErrorAudience      // AUD validation failed
	ValidationErrorExpired       // EXP validation failed
	ValidationErrorIssuedAt      // IAT validation failed
	ValidationErrorIssuer        // ISS validation failed
	ValidationErrorNotValidYet   // NBF validation failed
	ValidationErrorId            // JTI validation failed
	ValidationErrorClaimsInvalid // Generic claims validation error
)

The errors that might occur when parsing and validating a token

Variables

View Source
var (
	ErrInvalidKey      = errors.New("key is invalid")
	ErrInvalidKeyType  = errors.New("key is of invalid type")
	ErrHashUnavailable = errors.New("the requested hash function is unavailable")

	ErrTokenMalformed        = errors.New("token is malformed")
	ErrTokenUnverifiable     = errors.New("token is unverifiable")
	ErrTokenSignatureInvalid = errors.New("token signature is invalid")

	ErrTokenInvalidAudience  = errors.New("token has invalid audience")
	ErrTokenExpired          = errors.New("token is expired")
	ErrTokenUsedBeforeIssued = errors.New("token used before issued")
	ErrTokenInvalidIssuer    = errors.New("token has invalid issuer")
	ErrTokenNotValidYet      = errors.New("token is not valid yet")
	ErrTokenInvalidId        = errors.New("token has invalid id")
	ErrTokenInvalidClaims    = errors.New("token has invalid claims")
)

Error constants

View Source
var ErrNoCookieFound = errors.New("no cookie present with specified name in request")
View Source
var ErrNoTokenInRequest = errors.New("no token present in request")

Functions

func ErrConvertingJSONNumber

func ErrConvertingJSONNumber(err error) error

func ErrParsingNumericDate

func ErrParsingNumericDate(err error) error

func ExtractTokenFromCookie

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

func ExtractTokenFromRequest

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

func GenerateRSAKeyPair

func GenerateRSAKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey)

func GetAlgorithms

func GetAlgorithms() (algs []string)

GetAlgorithms returns a list of registered "alg" names

func RSAPrivateKeyFromString

func RSAPrivateKeyFromString(privateKeyString string) (*rsa.PrivateKey, error)

func RSAPrivateKeyToString

func RSAPrivateKeyToString(key *rsa.PrivateKey) string

func RSAPublicKeyFromString

func RSAPublicKeyFromString(publicKeyString string) (*rsa.PublicKey, error)

func RSAPublicKeyToString

func RSAPublicKeyToString(key *rsa.PublicKey) string

func ReadPEM

func ReadPEM(file string) (*pem.Block, error)

func ReadRSAPrivateKey

func ReadRSAPrivateKey(file string) (*rsa.PrivateKey, error)

func ReadRSAPrivateKeyFromPEM

func ReadRSAPrivateKeyFromPEM(file string) (*rsa.PrivateKey, error)

func ReadRSAPublicKey

func ReadRSAPublicKey(file string) (*rsa.PublicKey, error)

func ReadRSAPublicKeyFromPEM

func ReadRSAPublicKeyFromPEM(file string) (*rsa.PublicKey, error)

func RegisterSigningMethod

func RegisterSigningMethod(alg string, f func() SigningMethod)

RegisterSigningMethod registers the "alg" name and a factory function for signing method. This is typically done during init() in the method's implementation

func WritePEM

func WritePEM(block *pem.Block, file string) error

func WriteRSAPrivateKey

func WriteRSAPrivateKey(key *rsa.PrivateKey, file string) error

func WriteRSAPrivateKeyAsPEM

func WriteRSAPrivateKeyAsPEM(key *rsa.PrivateKey, file string) error

func WriteRSAPublicKey

func WriteRSAPublicKey(key *rsa.PublicKey, file string) error

func WriteRSAPublicKeyAsPEM

func WriteRSAPublicKeyAsPEM(key *rsa.PublicKey, file string) error

Types

type ClaimStrings

type ClaimStrings []string

ClaimStrings is basically just a slice of strings, but it can be either serialized from a string array or just a string. This type is necessary, since the "aud" claim can either be a single string or an array.

func (ClaimStrings) MarshalJSON

func (s ClaimStrings) MarshalJSON() (b []byte, err error)

func (*ClaimStrings) UnmarshalJSON

func (s *ClaimStrings) UnmarshalJSON(data []byte) error

type Claims

type Claims interface {
	// VerifyAudience Compares the aud claim against cmp.
	// If req is false, it will return true, if aut is unset.
	VerifyAudience(cmp string, req bool) bool

	// VerifyExpiresAt compares the exp claim against cmp (cmp <= exp).
	// If req is false, it will return true, if exp is unset.
	VerifyExpiresAt(cmp int64, req bool) bool

	// VerifyIssuedAt compares the exp claim against cmp (cmp >= iat).
	// If req is false, it will return true, if iat is unset.
	VerifyIssuedAt(cmp int64, req bool) bool

	// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
	// If req is false, it will return true, if nbf is unset.
	VerifyNotBefore(cmp int64, req bool) bool

	// VerifyIssuer compares the iss claim against cmp.
	// If req is false, it will return true, if iss is unset.
	VerifyIssuer(cmp string, req bool) bool

	// Valid validates time based claims "exp, iat, nbf".
	// There is no accounting for clock skew.
	// As well, if any of the above claims are not in the token, it will
	// still be considered a valid claim.
	Valid() error
}

type JWTService

type JWTService struct {
	// contains filtered or unexported fields
}
var JWTServiceInstance *JWTService

func NewJWTService

func NewJWTService(privateKeyFile, publicKeyFile string) *JWTService

func (*JWTService) ExpireTime

func (s *JWTService) ExpireTime() time.Time

func (*JWTService) GenerateSignedToken

func (s *JWTService) GenerateSignedToken(username, password, role string) string

func (*JWTService) ValidateTokenString

func (s *JWTService) ValidateTokenString(tokenString string) (*Token, error)

type KeyFunc

type KeyFunc func(*Token) (any, error)

KeyFunc will be used by the Parse functions as a callback function in order to supply the key for verification. The function receives the parsed but un-verified Token. This allows you to use properties in the Header of the token (like "kid") in order to identify which key to use. *** MAKE SURE YOU RETURN A PUBLIC KEY IN HERE ***

type MapClaims

type MapClaims map[string]any

func (MapClaims) Valid

func (m MapClaims) Valid() error

func (MapClaims) VerifyAudience

func (m MapClaims) VerifyAudience(cmp string, req bool) bool

func (MapClaims) VerifyExpiresAt

func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool

func (MapClaims) VerifyIssuedAt

func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool

func (MapClaims) VerifyIssuer

func (m MapClaims) VerifyIssuer(cmp string, req bool) bool

func (MapClaims) VerifyNotBefore

func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool

type NumericDate

type NumericDate struct {
	time.Time
}

NumericDate represents a JSON numeric date value as referenced in the documentation at https://datatracker.ietf.org/doc/html/rfc7519#section-2.

func NewNumericDate

func NewNumericDate(t time.Time) *NumericDate

NewNumericDate constructs a new *NumericDate from a standard library time.Time struct. It will truncate the timestamp according to the precision specified in TimePrecision.

func (NumericDate) MarshalJSON

func (date NumericDate) MarshalJSON() (b []byte, err error)

MarshalJSON is an implementation of the json.RawMessage interface and serializes the UNIX epoch represented in NumericDate to a byte array, using the precision specified in timePrecision.

func (*NumericDate) UnmarshalJSON

func (date *NumericDate) UnmarshalJSON(b []byte) (err error)

UnmarshalJSON is an implementation of the json.RawMessage interface and de-serialises a NumericDate from a JSON representation, i.e. a json.Number. This number represents a UNIX epoch with either integer or non-integer seconds.

type Parser

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

func NewParser

func NewParser(validMethods []string, useJSONNumber, skipClaimsValidation bool) *Parser

func (*Parser) Parse

func (p *Parser) Parse(token string, keyFn KeyFunc) (*Token, error)

func (*Parser) ParseUnverified

func (p *Parser) ParseUnverified(token string, claims Claims) (*Token, []string, error)

func (*Parser) ParseWithClaims

func (p *Parser) ParseWithClaims(token string, claims Claims, keyFn KeyFunc) (*Token, error)

type ParserOptions

type ParserOptions struct {
	ValidMethods         []string
	UseJSONNumber        bool
	SkipClaimsValidation bool
}

type RegisteredClaims

type RegisteredClaims struct {
	// Issuer is the "iss" claim.
	Issuer string `json:"iss,omitempty"`

	// Subject is the "sub"  claim.
	Subject string `json:"sub,omitempty"`

	// Audience is the "aud"  claim.
	Audience ClaimStrings `json:"aud,omitempty"`

	// ExpiresAt is the "exp"  claim.
	ExpiresAt *NumericDate `json:"exp,omitempty"`

	// NotBefore is the "nbf" claim.
	NotBefore *NumericDate `json:"nbf,omitempty"`

	// IssuedAt is the "iat" claim.
	IssuedAt *NumericDate `json:"iat,omitempty"`

	// ID is the "jti" claim.
	ID string `json:"jti,omitempty"`
}

RegisteredClaims are a structured version of the JWT Claims set which is restricted to Registered Claim Names as referenced in the documentation found at https://datatracker.ietf.org/doc/html/rfc7519#section-4.1. The RegisteredClaims type can be used on its own, but any additional private or public claims embedded in the Token will not be parsed. The default use case is to embed the RegisteredClaims type in a user-defined claim type.

func (RegisteredClaims) Valid

func (r RegisteredClaims) Valid() error

func (RegisteredClaims) VerifyAudience

func (r RegisteredClaims) VerifyAudience(cmp string, req bool) bool

func (RegisteredClaims) VerifyExpiresAt

func (r RegisteredClaims) VerifyExpiresAt(cmp int64, req bool) bool

func (RegisteredClaims) VerifyIssuedAt

func (r RegisteredClaims) VerifyIssuedAt(cmp int64, req bool) bool

func (RegisteredClaims) VerifyIssuer

func (r RegisteredClaims) VerifyIssuer(cmp string, req bool) bool

func (RegisteredClaims) VerifyNotBefore

func (r RegisteredClaims) VerifyNotBefore(cmp int64, req bool) bool

type SigningMethod

type SigningMethod interface {
	// Verify returns nil if signature is valid
	Verify(signingString, signature string, key interface{}) error
	// Sign returns encoded signature or error
	Sign(signingString string, key interface{}) (string, error)
	// Alg returns the alg identifier for this method
	Alg() string
}

SigningMethod can be used add new methods for signing or verifying tokens.

func GetSigningMethod

func GetSigningMethod(alg string) (method SigningMethod)

GetSigningMethod retrieves a signing method from an "alg" string

type SigningMethodHMAC

type SigningMethodHMAC struct {
	Name string
	Hash crypto.Hash
}

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

var (
	SigningMethodHS256  *SigningMethodHMAC
	SigningMethodHS384  *SigningMethodHMAC
	SigningMethodHS512  *SigningMethodHMAC
	ErrSignatureInvalid = errors.New("signature is invalid")
)

Specific instances for HS256 and company

func (*SigningMethodHMAC) Alg

func (m *SigningMethodHMAC) Alg() string

func (*SigningMethodHMAC) Sign

func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error)

Sign implements token signing for the SigningMethod. Key must be []byte

func (*SigningMethodHMAC) Verify

func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error

Verify implements token verification for the SigningMethod. Returns nil if the signature is valid.

type SigningMethodRSA

type SigningMethodRSA struct {
	Name string
	Hash crypto.Hash
}

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

var (
	SigningMethodRS256 *SigningMethodRSA
	SigningMethodRS384 *SigningMethodRSA
	SigningMethodRS512 *SigningMethodRSA
)

Specific instances for RS256 and company

func (*SigningMethodRSA) Alg

func (m *SigningMethodRSA) Alg() string

func (*SigningMethodRSA) Sign

func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error)

Sign implements token signing for the SigningMethod For this signing method, must be an *rsa.PrivateKey structure.

func (*SigningMethodRSA) Verify

func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error

Verify implements token verification for the SigningMethod For this signing method, must be an *rsa.PublicKey structure.

type Token

type Token struct {
	// Raw is the raw token. It is populated when you parse a token.
	Raw string

	// Method is the signing method that is used to sign the token.
	Method SigningMethod

	// Header is the first segment of the token and holds the token
	// type and the algorithm of the signing method.
	Header map[string]any

	// Claims is the second segment of a token and holds the payload.
	Claims Claims

	// Signature is the third segment of a token and is populated when you
	// parse a token.
	Signature string

	// Valid is populated when you parse or verify a token.
	Valid bool
}

Token represents a JWT. Different fields will be used depending on if you are creating, parsing or verifying a token.

func NewToken

func NewToken(method SigningMethod) *Token

NewToken creates and returns a new Token with the specified signing method and an empty map of claims.

func NewTokenWithClaims

func NewTokenWithClaims(method SigningMethod, claims Claims) *Token

NewTokenWithClaims creates and returns a new Token with the specified signing method and provided claims.

func Parse

func Parse(token string, keyFn KeyFunc, options ParserOptions) (*Token, error)

Parse parses, validates, verifies the signature and returns the parsed token. keyFn will receive the parsed token and should return the cryptographic key for verifying the signature. The caller is strongly encouraged to set the WithValidMethods option to validate the 'alg' claim in the token matches the expected algorithm.

func ParseWithClaims

func ParseWithClaims(token string, claims Claims, keyFn KeyFunc, options ParserOptions) (*Token, error)

ParseWithClaims is a shortcut for NewParser().ParseWithClaims().

Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims), make sure that a: you either embed a non-pointer version of the claims or b: if you are using a pointer, allocate the proper memory for it before passing in the overall claims, otherwise you might run into a panic.

func ValidateTokenString

func ValidateTokenString(signingMethod SigningMethod, public *rsa.PublicKey, tokenString string) (*Token, error)

func (*Token) Sign

func (t *Token) Sign() (string, error)

Sign generates the signing string. This is the most expensive call. Try to use SignedString when possible, and if the signature already exists, it will be returned, otherwise SignedString will call Sign to generate it.

func (*Token) SignedString

func (t *Token) SignedString(key any) (string, error)

SignedString returns the token Signature. If the signature has not been generated yet, Sign will be called.

type ValidationError

type ValidationError struct {
	Inner  error  // stores the error returned by external dependencies, i.e.: KeyFunc
	Errors uint32 // bitfield.  see ValidationError... constants
	// contains filtered or unexported fields
}

ValidationError represents an error from Parse if token is not valid

func NewValidationError

func NewValidationError(errorText string, errorFlags uint32) *ValidationError

NewValidationError is a helper for constructing a ValidationError with a string error message

func (ValidationError) Error

func (e ValidationError) Error() string

Error is the implementation of the err interface.

func (*ValidationError) Is

func (e *ValidationError) Is(err error) bool

Is checks if this ValidationError is of the supplied error. We are first checking for the exact error message by comparing the inner error message. If that fails, we compare using the error flags. This way we can use custom error messages (mainly for backwards compatability) and still leverage errors.Is using the global error variables.

func (*ValidationError) Name

func (e *ValidationError) Name(err error) string

func (*ValidationError) Unwrap

func (e *ValidationError) Unwrap() error

Unwrap gives errors.Is and errors.As access to the inner error.

Jump to

Keyboard shortcuts

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