jwt

package module
v0.0.0-...-499ad84 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2018 License: Apache-2.0 Imports: 12 Imported by: 0

README

JWT

CircleCI GoDoc License

Implementation of JSON Web Token (JWT) in Go.

Examples

Creating token

To create token that will contain your payload, you need signer instance to create signature. This package provides several algorithms, but you are most likely to use HMAC variant:

const secret = `my-projects-secret-string`
signer := HMAC256([]byte(secret), "")

When creating token, it is allowed to define payload of any form, as long as it can be serialized as JSON object:

// define payload that will be used as JWT claims
type Payload struct {
    Email string `json:"email"`
    Admin bool   `json:"admin"`

    // JWT specific claims as defined in
    // https://tools.ietf.org/html/rfc7519#section-4.1
    ExpirationTime int64 `json:"exp"`
}

// create JWT token using given signer
token, err := Encode(signer, &Payload{
    Email:          "john.smith@example.com",
    Admin:          true,
    ExpirationTime: 2889062211,
})
if err != nil {
    fmt.Println("cannot create token:", err)
} else {
    fmt.Println("token:", string(token))
}

All registered claim names must be used as defined by standard and will be respected during token's decoding.

Decoding token and verification

To decode token's content, we must provide verifier. Because Signer is implementing Verifier interface, we can use it for decoding as well:

var payload Payload

switch err := DecodeClaims(token, signer, &payload); err {
case nil:
    fmt.Printf("payload: %v\n", payload)
case ErrExpired:
    fmt.Println("please refresh your tokne")
default:
    fmt.Println("invalid token:", err)
}

More examples

See examples section in GoDoc to learn how to use it.

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrAlgorithmNotAvailable is returned when platform does not support
	// required cryptographic algorithm.
	ErrAlgorithmNotAvailable = errors.New("algorithm not available")

	// ErrInvalidSignature is returned when verification of data signature
	// fails, because to signature is incorrect.
	ErrInvalidSignature = errors.New("invalid signature")

	// ErrMalformedToken is returned when given token cannot be deserialized.
	ErrMalformedToken = errors.New("malformed token")

	// ErrInvalidSigner is returned when verifying data with verifier that
	// is using different algorithm than signer or used key ID is provided
	// within token and does not match one returned by verifier.
	ErrInvalidSigner = errors.New("invalid signer")

	// ErrExpired is returned when decoding token that expired.
	ErrExpired = errors.New("expired")

	// ErrNotReady is returned when decoding token that is defining not
	// before information and value is not yet expired.
	ErrNotReady = errors.New("token not yet active")
)

Functions

func DecodeClaims

func DecodeClaims(token []byte, v Verifier, claims interface{}) error

DecodeClaims test JWT token signature and if valid, unpack claims to given structure.

Validation is on purpose part of this function, so that it's not possible to extract claims from invalid tokens.

Example
token := []byte(`eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImpvaG4uc21pdGhAZXhhbXBsZS5jb20iLCJhZG1pbiI6dHJ1ZSwiZXhwIjoyODg5MDYyMjExfQ.JS9RziTEy6dcA9DC6z6aYoiG8RnpfmPY4eoY_6_uc1U`)

// define payload that will be used as JWT claims
type Payload struct {
	Email string `json:"email"`
	Admin bool   `json:"admin"`

	// JWT specific claims as defined in
	// https://tools.ietf.org/html/rfc7519#section-4.1
	ExpirationTime int64 `json:"exp"`
}

var verifier Verifier = HMAC256([]byte(`asdosiahodihqw8qwhqpwfjpfoafphpfwhpqf`), "")

var payload Payload
switch err := DecodeClaims(token, verifier, &payload); err {
case nil:
	fmt.Printf("payload: %v\n", payload)
case ErrExpired:
	fmt.Println("please refresh your tokne")
default:
	fmt.Println("invalid token:", err)
}
Output:

payload: {john.smith@example.com true 2889062211}

func DecodeHeader

func DecodeHeader(token []byte, header interface{}) error

DecodeHeader extract and decode header part of the JWT token into given header structure. Token is not validated, therefore sigature must be checked before extracted data can be trusted. Decoding header might be required before signature check, becase it may contain data relevant for signature computation like signing key id or used algorithm.

func Encode

func Encode(sig Signer, claims interface{}) ([]byte, error)

Encode return claims serialized as signed JWT token. If Signer provides KeyID method, result is attached to header as signature key id ("kid").

Example
// define payload that will be used as JWT claims
type Payload struct {
	Email string `json:"email"`
	Admin bool   `json:"admin"`

	// JWT specific claims as defined in
	// https://tools.ietf.org/html/rfc7519#section-4.1
	ExpirationTime int64 `json:"exp"`
}

var signer Signer = HMAC256([]byte(`asdosiahodihqw8qwhqpwfjpfoafphpfwhpqf`), "")

// create JWT token using given signer
token, err := Encode(signer, &Payload{
	Email:          "john.smith@example.com",
	Admin:          true,
	ExpirationTime: 2889062211,
})
if err != nil {
	fmt.Println("cannot create token:", err)
} else {
	fmt.Println("token:", string(token))
}
Output:

Types

type Signer

type Signer interface {
	Verifier

	// Sign returns signature computed for given data.
	Sign(data []byte) ([]byte, error)
}

Signer is the interface implemented by objects that can compute data signature. In addition, every Signer is also Verifier.

func HMAC256

func HMAC256(key []byte, keyID string) Signer

HMAC256 returns signer using symetric key and SHA256 hashing function.

Example
secret := []byte(`9u109qfiophfqwihyqwofihiugblwaigfaui`)
signer := HMAC256(secret, "")

// define payload that will be used as JWT claims
type Payload struct {
	UserEmail   string `json:"email"`
	UserIsAdmin bool   `json:"admin"`

	// JWT specific claims as defined in
	// https://tools.ietf.org/html/rfc7519#section-4.1
	ExpirationTime int64 `json:"exp"`
}

// create JWT token using given HMAC algorithm as signer
token, err := Encode(signer, &Payload{
	UserEmail:      "john.smith@example.com",
	UserIsAdmin:    true,
	ExpirationTime: time.Now().Add(3 * time.Hour).Unix(),
})
if err != nil {
	panic(err)
}

// decode token, but extract only user email - we can safely ignore any
// fields that we are not interested in
var claims struct {
	UserEmail string `json:"email"`
}
switch err := DecodeClaims(token, signer, &claims); err {
case nil:
	// token is valid and claims structure was successfuly filled
	// with payload data
	fmt.Println("user email:", claims.UserEmail)
case ErrExpired:
	// although we did not extract ExpirationTime from the payload,
	// token is still validated and if expired, error is returned
	fmt.Println("please review your token")
default:
	fmt.Println("invalid token:", err)
}
Output:

func HMAC384

func HMAC384(key []byte, keyID string) Signer

HMAC384 returns signer using symetric key and SHA384 hashing function.

func HMAC512

func HMAC512(key []byte, keyID string) Signer

HMAC512 returns signer using symetric key and SHA512 hashing function.

func RSA256Signer

func RSA256Signer(key *rsa.PrivateKey, keyID string) Signer

RSA256Signer returns signer using asymmetric RSA algorithm to sign data.

keyID is optional (can be empty) argument that is helpful when using several keys to sign data, to determine which key to use during verification.

func RSA384Signer

func RSA384Signer(key *rsa.PrivateKey, keyID string) Signer

RSA384Signer returns signer using asymmetric RSA algorithm to sign data.

keyID is optional (can be empty) argument that is helpful when using several keys to sign data, to determine which key to use during verification.

func RSA512Signer

func RSA512Signer(key *rsa.PrivateKey, keyID string) Signer

RSA512Signer returns signer using asymmetric RSA algorithm to sign data.

keyID is optional (can be empty) argument that is helpful when using several keys to sign data, to determine which key to use during verification.

type Verifier

type Verifier interface {
	// Algorithm returns JWS alg value as defined in RFC7518
	// https://tools.ietf.org/html/rfc7518#section-3.1
	Algorithm() string

	// Verify returns error if signature computed for given data is
	// different than expected values.
	Verify(signature, data []byte) error
}

Verifier is the interface implemented by objects that can verify data signature. Verifier can only verify signature and cannot create one. This is because asymmetric algorithms use separate key for those processes.

func RSA256Verifier

func RSA256Verifier(key *rsa.PublicKey) Verifier

RSA256Verifier returns verifier using asymmetric RSA algorithm to verify data signature.

func RSA384Verifier

func RSA384Verifier(key *rsa.PublicKey) Verifier

RSA384Verifier returns verifier using asymmetric RSA algorithm to verify data signature.

func RSA512Verifier

func RSA512Verifier(key *rsa.PublicKey) Verifier

RSA512Verifier returns verifier using asymmetric RSA algorithm to verify data signature.

Jump to

Keyboard shortcuts

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