jwtee

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Feb 14, 2019 License: MIT Imports: 7 Imported by: 0

README

JWTee

GoDoc Build Status Go Report Card

Fast and flexible library to work with JSON Web Token and JSON Web Signature in Go based on the RFC 7519.

The purpose of the library is to use full power of strong typing when working with JWT.

Installation

go get github.com/furdarius/jwtee
Adding as dependency by "go dep"
$ dep ensure -add github.com/furdarius/jwtee

Usage

Parsing and Verifying

Define own claims, embedding RegisteredClaims:

type myclaims struct {
	jwtee.RegisteredClaims

	Name string `json:"name"`
}

Parse and verify token and claims:

hmacSigner := signer.NewHS256()
key := jwtee.NewSharedSecretKey(secret)
verifier := jwtee.NewPartsVerifier(hmacSigner, key)
jsonParser := jwtee.NewJSONParser()
verifyingParser := jwtee.NewVerifyingParser(jsonParser, verifier)
claimsValidator := jwtee.NewClaimsValidator()

secret := []byte("secret_code")
token := []byte("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJteXNlcnZpY2UiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.10i7pIGVUVloV6vrixXDhPdeq09KCdBrUzSzKZxIzLA")

tokenParts, err := verifyingParser.Parse(token)

if err == jwtee.ErrInvalidSignature {
    log.Fatal("token has invalid signature")
}

if err != nil {
    log.Fatalf("failed to parse JWT string: %v", err)
}

var claims myclaims
err = json.Unmarshal(tokenParts.RawClaims(), &claims)
if err != nil {
    log.Fatalf("failed to unmarshal claims: %v", err)
}

errs := claimsValidator.Validate(claims.RegisteredClaims,
    constraint.NewValidAt().WithLeeway(1*time.Minute),
    constraint.NewRelatedTo("myservice"),
)
if errs != nil {
    log.Println("claims is not valid:")
    for _, constraintErr := range errs {
        log.Println("  ", constraintErr)
    }
    os.Exit(1)
}

fmt.Println("Name from claims:", claims.Name)
Token building

Define own claims, embedding RegisteredClaims and implements encoding.BinaryMarshaler:

type myclaims struct {
	jwtee.RegisteredClaims

	Name  string `json:"name"`
	Admin bool   `json:"admin"`
}

// MarshalBinary implements encoding.BinaryMarshaler.
func (c myclaims) MarshalBinary() (data []byte, err error) {
	return json.Marshal(c)
}

Build token from claims:

secret := []byte("secret_code")

hmacSigner := signer.NewHS256()
key := jwtee.NewSharedSecretKey(secret)
builder := jwtee.NewTokenBuilder()

claims := myclaims{
    RegisteredClaims: jwtee.RegisteredClaims{
        Sub: "1234567890",
        Iat: 1516239022,
    },
    Name:  "John Doe",
    Admin: true,
}

tokenParts, err := builder.Build(claims, hmacSigner, key)
if err != nil {
    log.Fatalf("failed to build jwt: %v", err)
}

rawJWT, err := tokenParts.MarshalText()
if err != nil {
    log.Fatalf("failed to marshal token parts: %v", err)
}

fmt.Println(string(rawJWT))

More examples

Contributing

Pull requests are very much welcomed. Make sure a test or example is included that covers your change and your commits represent coherent changes that include a reason for the change.

Use gometalinter to check code with linters:

gometalinter -t --vendor ./...

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidSignature indicates that signature invalid.
	ErrInvalidSignature = errors.New("invalid signature")

	// ErrRequestedHashUnavailable indicates that hash func is not registered.
	ErrRequestedHashUnavailable = errors.New("requested hash function is unavailable")
)
View Source
var (
	// ErrPartMissed indicates that token has invalid format
	ErrPartMissed = errors.New("one of token parts missed")
)

Functions

This section is empty.

Types

type Algorithm

type Algorithm string

Algorithm describes algorithms supported for signing/verifying.

const (
	HS256 Algorithm = "HS256"
	HS384 Algorithm = "HS384"
	HS512 Algorithm = "HS512"
	RS256 Algorithm = "RS256"
	RS384 Algorithm = "RS384"
	RS512 Algorithm = "RS512"
	ES256 Algorithm = "ES256"
	ES384 Algorithm = "ES384"
	ES512 Algorithm = "ES512"
	PS256 Algorithm = "PS256"
	PS384 Algorithm = "PS384"
)

Algorithm constants represents available algorithms values.

type Builder

type Builder interface {
	Build(claims encoding.BinaryMarshaler, signer Signer, key Key) (*DecodedParts, error)
}

Builder used to build encoded and signed token.

type ClaimsValidator

type ClaimsValidator struct{}

ClaimsValidator used to validate RegisteredClaims with Constraints.

func NewClaimsValidator

func NewClaimsValidator() *ClaimsValidator

NewClaimsValidator returns new instance of ClaimsValidator.

func (*ClaimsValidator) Validate

func (v *ClaimsValidator) Validate(claims RegisteredClaims, constraints ...Constraint) (errs []error)

Validate inherited from Validator.

type Constraint

type Constraint interface {
	Validate(claims RegisteredClaims) error
}

Constraint used to validate JWT Claims with Constraint.

type DecodedParts

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

DecodedParts stores ready to use parts of the JWT token.

func (*DecodedParts) Header

func (t *DecodedParts) Header() Header

Header returns token's Header.

func (*DecodedParts) MarshalBinary

func (t *DecodedParts) MarshalBinary() (data []byte, err error)

MarshalBinary inherited from encoding.BinaryMarshaler.

func (*DecodedParts) MarshalText

func (t *DecodedParts) MarshalText() (text []byte, err error)

MarshalText inherited from encoding.TextMarshaler.

func (*DecodedParts) Payload

func (t *DecodedParts) Payload() []byte

Payload returns bytes used as JWS Signing Input to compute the JWS Signature. JWS Signing Input formatted as: ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload))

func (*DecodedParts) RawClaims

func (t *DecodedParts) RawClaims() []byte

RawClaims returns bytes with decoded claims string.

func (*DecodedParts) Signature

func (t *DecodedParts) Signature() []byte

Signature returns token's signature.

type Header struct {
	// The type of JWS: it can only be "JWT" here
	// @see https://tools.ietf.org/html/rfc7515#section-4.1.9
	Typ string `json:"typ,omitempty"`

	// The algorithm used
	// @see https://tools.ietf.org/html/rfc7515#section-4.1.1
	Alg Algorithm `json:"alg"`

	// Content type
	// @see https://tools.ietf.org/html/rfc7519#section-5.2
	Cty string `json:"cty,omitempty"`

	// JSON Key URL
	// @see https://tools.ietf.org/html/rfc7515#section-4.1.2
	Jku string `json:"jku,omitempty"`

	// Key ID
	// @see https://tools.ietf.org/html/rfc7515#section-4.1.4
	Kid string `json:"kid,omitempty"`

	// X.509 URL
	// @see https://tools.ietf.org/html/rfc7515#section-4.1.5
	X5u string `json:"x5u,omitempty"`

	// X.509 certificate thumbprint
	// @see https://tools.ietf.org/html/rfc7515#section-4.1.7
	X5t string `json:"x5t,omitempty"`
}

Header stores JWT header data.

type JSONParser

type JSONParser struct{}

JSONParser used to parse JWT token.

func NewJSONParser

func NewJSONParser() *JSONParser

NewJSONParser returns new instance of JSONParser.

func (*JSONParser) Parse

func (p *JSONParser) Parse(jwt json.RawMessage) (*DecodedParts, error)

Parse splits, decode and memoize JWT parts.

type Key

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

Key stores signing key data.

func NewSharedSecretKey

func NewSharedSecretKey(secret []byte) Key

NewSharedSecretKey returns Key with secret inside.

func (Key) Secret

func (k Key) Secret() []byte

Secret returns key's secret.

type Parser

type Parser interface {
	Parse(jwt json.RawMessage) (*DecodedParts, error)
}

Parser used to take JWT apart.

type PartsVerifier

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

PartsVerifier used to verify signature of JWT.

func NewPartsVerifier

func NewPartsVerifier(signer Signer, key Key) *PartsVerifier

NewPartsVerifier returns new instance of PartsVerifier.

func (*PartsVerifier) Verify

func (v *PartsVerifier) Verify(parts *DecodedParts) error

Verify used to check consistency of token signature.

type RegisteredClaims

type RegisteredClaims struct {
	//   The "aud" (audience) claim identifies the recipients that the JWT is
	//   intended for.  Each principal intended to process the JWT MUST
	//   identify itself with a value in the audience claim.  If the principal
	//   processing the claim does not identify itself with a value in the
	//   "aud" claim when this claim is present, then the JWT MUST be
	//   rejected.  In the general case, the "aud" value is an array of case-
	//   sensitive strings, each containing a StringOrURI value.  In the
	//   special case when the JWT has one audience, the "aud" value MAY be a
	//   single case-sensitive string containing a StringOrURI value.  The
	//   interpretation of audience values is generally application specific.
	Aud []string `json:"aud,omitempty"`

	//   The "exp" (expiration time) claim identifies the expiration time on
	//   or after which the JWT MUST NOT be accepted for processing.  The
	//   processing of the "exp" claim requires that the current date/time
	//   MUST be before the expiration date/time listed in the "exp" claim.
	//   Implementers MAY provide for some small leeway, usually no more than
	//   a few minutes, to account for clock skew.  Its value MUST be a number
	//   containing a NumericDate value.  Use of this claim is OPTIONAL.
	Exp Timestamp `json:"exp,omitempty"`

	//   The "jti" (JWT ID) claim provides a unique identifier for the JWT.
	//   The identifier value MUST be assigned in a manner that ensures that
	//   there is a negligible probability that the same value will be
	//   accidentally assigned to a different data object; if the application
	//   uses multiple issuers, collisions MUST be prevented among values
	//   produced by different issuers as well.  The "jti" claim can be used
	//   to prevent the JWT from being replayed.  The "jti" value is a case-
	//   sensitive string.  Use of this claim is OPTIONAL.
	Jti string `json:"jti,omitempty"`

	//   The "iat" (issued at) claim identifies the time at which the JWT was
	//   issued.  This claim can be used to determine the age of the JWT.  Its
	//   value MUST be a number containing a NumericDate value.  Use of this
	//   claim is OPTIONAL.
	Iat Timestamp `json:"iat,omitempty"`

	//   The "iss" (issuer) claim identifies the principal that issued the
	//   JWT.  The processing of this claim is generally application specific.
	//   The "iss" value is a case-sensitive string containing a StringOrURI
	//   value.  Use of this claim is OPTIONAL.
	Iss string `json:"iss,omitempty"`

	//   The "nbf" (not before) claim identifies the time before which the JWT
	//   MUST NOT be accepted for processing.  The processing of the "nbf"
	//   claim requires that the current date/time MUST be after or equal to
	//   the not-before date/time listed in the "nbf" claim.  Implementers MAY
	//   provide for some small leeway, usually no more than a few minutes, to
	//   account for clock skew.  Its value MUST be a number containing a
	//   NumericDate value.  Use of this claim is OPTIONAL.
	Nbf Timestamp `json:"nbf,omitempty"`

	//   The "sub" (subject) claim identifies the principal that is the
	//   subject of the JWT.  The claims in a JWT are normally statements
	//   about the subject.  The subject value MUST either be scoped to be
	//   locally unique in the context of the issuer or be globally unique.
	//   The processing of this claim is generally application specific.  The
	//   "sub" value is a case-sensitive string containing a StringOrURI
	//   value.  Use of this claim is OPTIONAL.
	Sub string `json:"sub,omitempty"`
}

RegisteredClaims are the IANA registered “JSON Web Token Claims”.

func (RegisteredClaims) HasBeenCrossedNotBefore

func (c RegisteredClaims) HasBeenCrossedNotBefore(now time.Time) bool

HasBeenCrossedNotBefore returns true if the token activation (Not Before) time is before than given time.

func (RegisteredClaims) HasBeenIssuedBefore

func (c RegisteredClaims) HasBeenIssuedBefore(now time.Time) bool

HasBeenIssuedBefore returns true if the token was issued before of given time.

func (RegisteredClaims) HasBeenIssuedBy

func (c RegisteredClaims) HasBeenIssuedBy(issuers ...string) bool

HasBeenIssuedBy returns true if the token was issued by any of given issuers.

func (RegisteredClaims) IsExpired

func (c RegisteredClaims) IsExpired(now time.Time) bool

IsExpired returns true if the token is expired.

func (RegisteredClaims) IsIdentifiedBy

func (c RegisteredClaims) IsIdentifiedBy(id string) bool

IsIdentifiedBy returns true if claims has the given id.

func (RegisteredClaims) IsPermittedFor

func (c RegisteredClaims) IsPermittedFor(audience string) bool

IsPermittedFor returns true if claims is allowed to be used by the audience.

func (RegisteredClaims) IsRelatedTo

func (c RegisteredClaims) IsRelatedTo(subject string) bool

IsRelatedTo returns true if claims has the given subject.

type Signer

type Signer interface {
	GetAlgorithmID() Algorithm
	Sign(payload []byte, key Key) ([]byte, error)
	Verify(expected, payload []byte, key Key) error
}

Signer used to sign and verify token signature.

type Timestamp

type Timestamp int64

Timestamp represents time as number of seconds from 1970-01-01T00:00:00Z UTC until the specified moment.

func (Timestamp) Time

func (t Timestamp) Time() time.Time

Time used to convert int64 to time.Time.

func (*Timestamp) UnmarshalJSON

func (t *Timestamp) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. It supports number and null input. 0 will not be considered a null Float. It also supports unmarshalling a sql.NullFloat64.

type TokenBuilder

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

TokenBuilder implements Builder.

func NewTokenBuilder

func NewTokenBuilder() *TokenBuilder

NewTokenBuilder returns new instance of TokenBuilder.

func (*TokenBuilder) Build

func (b *TokenBuilder) Build(claims encoding.BinaryMarshaler, signer Signer, key Key) (*DecodedParts, error)

Build used to construct and encode JWT.

func (*TokenBuilder) WithKID

func (b *TokenBuilder) WithKID(kid string) *TokenBuilder

WithKID used to setup the kid (key ID) Header Parameter.

type Validator

type Validator interface {
	Validate(claims RegisteredClaims, constraints ...Constraint) []error
}

Validator used to validate JWT Claims.

type VerifyingParser

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

VerifyingParser used to parse and then verify JWT.

func NewVerifyingParser

func NewVerifyingParser(parser Parser, verifier *PartsVerifier) *VerifyingParser

NewVerifyingParser returns new instance of VerifyingParser.

func (*VerifyingParser) Parse

func (p *VerifyingParser) Parse(jwt json.RawMessage) (*DecodedParts, error)

Parse splits, decode, memoize and verify signature of JWT parts. If token signature is invalid then ErrInvalidSignature returns.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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