jwt

package
v1.2.30 Latest Latest
Warning

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

Go to latest
Published: Jul 28, 2024 License: MIT Imports: 27 Imported by: 421

README

JWT Go Reference

Package jwt implements JSON Web Tokens as described in RFC7519.

  • Convenience methods for oft-used keys ("aud", "sub", "iss", etc)
  • Convenience functions to extract/parse from http.Request, http.Header, url.Values
  • Ability to Get/Set arbitrary keys
  • Conversion to and from JSON
  • Generate signed tokens
  • Verify signed tokens
  • Extra support for OpenID tokens via github.com/lestrrat-go/jwx/jwt/openid

How-to style documentation can be found in the docs directory.

More examples are located in the examples directory (jwt_example_test.go)

SYNOPSIS

Verify a signed JWT

  token, err := jwt.Parse(payload, jwt.WithKeySet(keyset))
  if err != nil {
    fmt.Printf("failed to parse payload: %s\n", err)
  }

Token Usage

func ExampleJWT() {
  const aLongLongTimeAgo = 233431200

  t := jwt.New()
  t.Set(jwt.SubjectKey, `https://github.com/lestrrat-go/jwx/jwt`)
  t.Set(jwt.AudienceKey, `Golang Users`)
  t.Set(jwt.IssuedAtKey, time.Unix(aLongLongTimeAgo, 0))
  t.Set(`privateClaimKey`, `Hello, World!`)

  buf, err := json.MarshalIndent(t, "", "  ")
  if err != nil {
    fmt.Printf("failed to generate JSON: %s\n", err)
    return
  }

  fmt.Printf("%s\n", buf)
  fmt.Printf("aud -> '%s'\n", t.Audience())
  fmt.Printf("iat -> '%s'\n", t.IssuedAt().Format(time.RFC3339))
  if v, ok := t.Get(`privateClaimKey`); ok {
    fmt.Printf("privateClaimKey -> '%s'\n", v)
  }
  fmt.Printf("sub -> '%s'\n", t.Subject())

  key, err := rsa.GenerateKey(rand.Reader, 2048)
  if err != nil {
    log.Printf("failed to generate private key: %s", err)
    return
  }

  {
    // Signing a token (using raw rsa.PrivateKey)
    signed, err := jwt.Sign(t, jwa.RS256, key)
    if err != nil {
      log.Printf("failed to sign token: %s", err)
      return
    }
    _ = signed
  }

  {
    // Signing a token (using JWK)
    jwkKey, err := jwk.New(key)
    if err != nil {
      log.Printf("failed to create JWK key: %s", err)
      return
    }

    signed, err := jwt.Sign(t, jwa.RS256, jwkKey)
    if err != nil {
      log.Printf("failed to sign token: %s", err)
      return
    }
    _ = signed
  }
}

OpenID Claims

jwt package can work with token types other than the default one. For OpenID claims, use the token created by openid.New(), or use the jwt.WithToken(openid.New()). If you need to use other specialized claims, use jwt.WithToken() to specify the exact token type

func Example_openid() {
  const aLongLongTimeAgo = 233431200

  t := openid.New()
  t.Set(jwt.SubjectKey, `https://github.com/lestrrat-go/jwx/jwt`)
  t.Set(jwt.AudienceKey, `Golang Users`)
  t.Set(jwt.IssuedAtKey, time.Unix(aLongLongTimeAgo, 0))
  t.Set(`privateClaimKey`, `Hello, World!`)

  addr := openid.NewAddress()
  addr.Set(openid.AddressPostalCodeKey, `105-0011`)
  addr.Set(openid.AddressCountryKey, `日本`)
  addr.Set(openid.AddressRegionKey, `東京都`)
  addr.Set(openid.AddressLocalityKey, `港区`)
  addr.Set(openid.AddressStreetAddressKey, `芝公園 4-2-8`)
  t.Set(openid.AddressKey, addr)

  buf, err := json.MarshalIndent(t, "", "  ")
  if err != nil {
    fmt.Printf("failed to generate JSON: %s\n", err)
    return
  }
  fmt.Printf("%s\n", buf)

  t2, err := jwt.Parse(buf, jwt.WithToken(openid.New()))
  if err != nil {
    fmt.Printf("failed to parse JSON: %s\n", err)
    return
  }
  if _, ok := t2.(openid.Token); !ok {
    fmt.Printf("using jwt.WithToken(openid.New()) creates an openid.Token instance")
    return
  }
}

FAQ

Why is jwt.Token an interface?

In this package, jwt.Token is an interface. This is not an arbitrary choice: there are actual reason for the type being an interface.

We understand that if you are migrating from another library this may be a deal breaker, but we hope you can at least appreciate the fact that this was not done arbitrarily, and that there were real technical trade offs that were evaluated.

No uninitialized tokens

First and foremost, by making it an interface, you cannot use an uninitialized token:

var token1 jwt.Token // this is nil, you can't just start using this
if err := json.Unmarshal(data, &token1); err != nil { // so you can't do this
   ...
}

// But you _can_ do this, and we _want_ you to do this so the object is properly initialized
token2 = jwt.New()
if err := json.Unmarshal(data, &token2); err != nil { // actually, in practice you should use jwt.Parse()
   ....
}
But why does it need to be initialized?

There are several reasons, but one of the reasons is that I'm using a sync.Mutex to avoid races. We want this to be properly initialized.

The other reason is that we support custom claims out of the box. The map[string]interface{} container is initialized during new. This is important when checking for equality using reflect-y methods (akin to reflect.DeepEqual), because if you allowed zero values, you could end up with "empty" tokens, that actually differ. Consider the following:

// assume jwt.Token was s struct, not an interface
token1 := jwt.Token{ privateClaims: make(map[string]interface{}) }
token2 := jwt.Token{ privateClaims: nil }

These are semantically equivalent, but users would need to be aware of this difference when comparing values. By forcing the user to use a constructor, we can force a uniform empty state.

Standard way to store values

Unlike some other libraries, this library allows you to store standard claims and non-standard claims in the same token.

You want to store standard claims in a properly typed field, which we do for fields like "iss", "nbf", etc. But for non-standard claims, there is just no way of doing this, so we have to use a container like map[string]interface{}

This means that if you allow direct access to these fields via a struct, you will have two different ways to access the claims, which is confusing:

tok.Issuer = ...
tok.PrivateClaims["foo"] = ...

So we want to hide where this data is stored, and use a standard method like Set() and Get() to store all the values. At this point you are effectively going to hide the implementation detail from the user, so you end up with a struct like below, which is fundamentally not so different from providing just an interface{}:

type Token struct {
  // unexported fields
}

func (tok *Token) Set(...) { ... }
Use of pointers to store values

We wanted to differentiate the state between a claim being uninitialized, and a claim being initialized to empty.

So we use pointers to store values:

type stdToken struct {
  ....
  issuer *string // if nil, uninitialized. if &(""), initialized to empty
}

This is fine for us, but we doubt that this would be something users would want to do. This is a subtle difference, but cluttering up the API with slight variations of the same type (i.e. pointers vs non-pointers) seemed like a bad idea to us.

token.Issuer = &issuer // want to avoid this

token.Set(jwt.IssuerKey, "foobar") // so this is what we picked

This way users no longer need to care how the data is internally stored.

Allow more than one type of token through the same interface

dgrijalva/jwt-go does this in a different way, but we felt that it would be more intuitive for all tokens to follow a single interface so there is fewer type conversions required.

See the openid token for an example.

Documentation

Overview

Package jwt implements JSON Web Tokens as described in https://tools.ietf.org/html/rfc7519

Index

Constants

View Source
const (
	AudienceKey   = "aud"
	ExpirationKey = "exp"
	IssuedAtKey   = "iat"
	IssuerKey     = "iss"
	JwtIDKey      = "jti"
	NotBeforeKey  = "nbf"
	SubjectKey    = "sub"
)

Variables

This section is empty.

Functions

func Equal added in v1.1.0

func Equal(t1, t2 Token) bool

Equal compares two JWT tokens. Do not use `reflect.Equal` or the like to compare tokens as they will also compare extra detail such as sync.Mutex objects used to control concurrent access.

The comparison for values is currently done using a simple equality ("=="), except for time.Time, which uses time.Equal after dropping the monotonic clock and truncating the values to 1 second accuracy.

if both t1 and t2 are nil, returns true

func ErrInvalidIssuedAt added in v1.2.13

func ErrInvalidIssuedAt() error

ErrInvalidIssuedAt returns the immutable error used when `iat` claim is not satisfied

func ErrTokenExpired added in v1.2.13

func ErrTokenExpired() error

ErrTokenExpired returns the immutable error used when `exp` claim is not satisfied

func ErrTokenNotYetValid added in v1.2.13

func ErrTokenNotYetValid() error

func IsValidationError added in v1.2.13

func IsValidationError(err error) bool

IsValidationError returns true if the error is a validation error

func RegisterCustomField added in v1.1.2

func RegisterCustomField(name string, object interface{})

RegisterCustomField allows users to specify that a private field be decoded as an instance of the specified type. This option has a global effect.

For example, suppose you have a custom field `x-birthday`, which you want to represent as a string formatted in RFC3339 in JSON, but want it back as `time.Time`.

In that case you would register a custom field as follows

jwt.RegisterCustomField(`x-birthday`, timeT)

Then `token.Get("x-birthday")` will still return an `interface{}`, but you can convert its type to `time.Time`

bdayif, _ := token.Get(`x-birthday`)
bday := bdayif.(time.Time)

func SetValidationCtxClock added in v1.2.7

func SetValidationCtxClock(ctx context.Context, cl Clock) context.Context

func SetValidationCtxSkew added in v1.2.7

func SetValidationCtxSkew(ctx context.Context, dur time.Duration) context.Context

func Settings added in v1.2.0

func Settings(options ...GlobalOption)

Settings controls global settings that are specific to JWTs.

func Sign added in v1.0.0

func Sign(t Token, alg jwa.SignatureAlgorithm, key interface{}, options ...SignOption) ([]byte, error)

Sign is a convenience function to create a signed JWT token serialized in compact form.

It accepts either a raw key (e.g. rsa.PrivateKey, ecdsa.PrivateKey, etc) or a jwk.Key, and the name of the algorithm that should be used to sign the token.

If the key is a jwk.Key and the key contains a key ID (`kid` field), then it is added to the protected header generated by the signature

The algorithm specified in the `alg` parameter must be able to support the type of key you provided, otherwise an error is returned.

The protected header will also automatically have the `typ` field set to the literal value `JWT`, unless you provide a custom value for it by jwt.WithHeaders option.

func Validate added in v1.0.6

func Validate(t Token, options ...ValidateOption) error

Validate makes sure that the essential claims stand.

See the various `WithXXX` functions for optional parameters that can control the behavior of this method.

func ValidationCtxSkew added in v1.2.7

func ValidationCtxSkew(ctx context.Context) time.Duration

Types

type Builder added in v1.2.13

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

Builder is a convenience wrapper around the New() constructor and the Set() methods to assign values to Token claims. Users can successively call Claim() on the Builder, and have it construct the Token when Build() is called. This alleviates the need for the user to check for the return value of every single Set() method call. Note that each call to Claim() overwrites the value set from the previous call.

func NewBuilder added in v1.2.13

func NewBuilder() *Builder

func (*Builder) Audience added in v1.2.13

func (b *Builder) Audience(v []string) *Builder

func (*Builder) Build added in v1.2.13

func (b *Builder) Build() (Token, error)

Build creates a new token based on the claims that the builder has received so far. If a claim cannot be set, then the method returns a nil Token with a en error as a second return value

func (*Builder) Claim added in v1.2.13

func (b *Builder) Claim(name string, value interface{}) *Builder

func (*Builder) Expiration added in v1.2.13

func (b *Builder) Expiration(v time.Time) *Builder

func (*Builder) IssuedAt added in v1.2.13

func (b *Builder) IssuedAt(v time.Time) *Builder

func (*Builder) Issuer added in v1.2.13

func (b *Builder) Issuer(v string) *Builder

func (*Builder) JwtID added in v1.2.13

func (b *Builder) JwtID(v string) *Builder

func (*Builder) NotBefore added in v1.2.13

func (b *Builder) NotBefore(v time.Time) *Builder

func (*Builder) Subject added in v1.2.13

func (b *Builder) Subject(v string) *Builder

type ClaimPair added in v0.9.1

type ClaimPair = mapiter.Pair

type Clock

type Clock interface {
	Now() time.Time
}

func ValidationCtxClock added in v1.2.7

func ValidationCtxClock(ctx context.Context) Clock

ValidationCtxClock returns the Clock object associated with the current validation context. This value will always be available during validation of tokens.

type ClockFunc

type ClockFunc func() time.Time

func (ClockFunc) Now

func (f ClockFunc) Now() time.Time

type DecodeCtx added in v1.2.1

type DecodeCtx = json.DecodeCtx

type DecryptParameters added in v1.2.2

type DecryptParameters interface {
	Algorithm() jwa.KeyEncryptionAlgorithm
	Key() interface{}
}

type EncryptOption added in v1.2.2

type EncryptOption interface {
	Option
	// contains filtered or unexported methods
}

EncryptOption describes an Option that can be passed to Encrypt() or (jwt.Serializer).Encrypt

func WithJweHeaders added in v1.2.2

func WithJweHeaders(hdrs jwe.Headers) EncryptOption

WithJweHeaders is passed to "jwt.Serializer".Encrypt() method to allow specifying arbitrary header values to be included in the protected header of the JWE message

type GlobalOption added in v1.2.0

type GlobalOption interface {
	Option
	// contains filtered or unexported methods
}

GlobalOption describes an Option that can be passed to `Settings()`.

func WithFlattenAudience added in v1.2.0

func WithFlattenAudience(v bool) GlobalOption

WithFlattenAudience specifies if the "aud" claim should be flattened to a single string upon the token being serialized to JSON.

This is sometimes important when a JWT consumer does not understand that the "aud" claim can actually take the form of an array of strings.

The default value is `false`, which means that "aud" claims are always rendered as a arrays of strings. This setting has a global effect, and will change the behavior for all JWT serialization.

type Iterator added in v1.0.0

type Iterator = mapiter.Iterator

type KeySetProvider added in v1.2.7

type KeySetProvider interface {
	// KeySetFrom returns the jwk.Set to be used to verify the token.
	// Keep in mind that the token at the point when the method is called is NOT VERIFIED.
	// DO NOT trust the contents of the Token too much. For example, do not take the
	// hint as to which signature algorithm to use from the token itself.
	KeySetFrom(Token) (jwk.Set, error)
}

KeySetProvider is an interface for objects that can choose the appropriate jwk.Set to be used when verifying JWTs

type KeySetProviderFunc added in v1.2.7

type KeySetProviderFunc func(Token) (jwk.Set, error)

KeySetProviderFunc is an implementation of KeySetProvider that is based on a function.

func (KeySetProviderFunc) KeySetFrom added in v1.2.7

func (fn KeySetProviderFunc) KeySetFrom(t Token) (jwk.Set, error)

type Option

type Option = option.Interface

type ParseOption added in v1.0.6

type ParseOption interface {
	ReadFileOption
	// contains filtered or unexported methods
}

ParseOption describes an Option that can be passed to `Parse()`. ParseOption also implements ReadFileOption, therefore it may be safely pass them to `jwt.ReadFile()`

func InferAlgorithmFromKey added in v1.2.7

func InferAlgorithmFromKey(v bool) ParseOption

InferAlgorithmFromKey allows jwt.Parse to guess the signature algorithm passed to `jws.Verify()`, in case the key you provided does not have a proper `alg` header.

Compared to providing explicit `alg` from the key this is slower, and in case our heuristics are wrong or outdated, may fail to verify the token. Also, automatic detection of signature verification methods are always more vulnerable for potential attack vectors.

It is highly recommended that you fix your key to contain a proper `alg` header field instead of resorting to using this option, but sometimes it just needs to happen.

Your JWT still need to have an `alg` field, and it must match one of the candidates that we produce for your key

func UseDefaultKey added in v1.0.6

func UseDefaultKey(value bool) ParseOption

UseDefaultKey is used in conjunction with the option WithKeySet to instruct the Parse method to default to the single key in a key set when no Key ID is included in the JWT. If the key set contains multiple keys then the default behavior is unchanged -- that is, the since we can't determine the key to use, it returns an error.

func WithDecrypt added in v1.2.2

func WithDecrypt(alg jwa.KeyEncryptionAlgorithm, key interface{}) ParseOption

WithDecrypt allows users to specify parameters for decryption using `jwe.Decrypt`. You must specify this if your JWT is encrypted.

func WithFetchBackoff added in v1.2.14

func WithFetchBackoff(b backoff.Policy) ParseOption

WithFetchBackoff specifies the `backoff.Policy` object that should be passed to `jws.VerifyAuto()`, which in turn will be passed to `jwk.Fetch()`

This is a wrapper over `jws.WithFetchBackoff()` that can be passed to `jwt.Parse()`, and will be ignored if you spcify `jws.WithJWKSetFetcher()`

func WithFetchWhitelist added in v1.2.14

func WithFetchWhitelist(wl jwk.Whitelist) ParseOption

WithFetchWhitelist specifies the `jwk.Whitelist` object that should be passed to `jws.VerifyAuto()`, which in turn will be passed to `jwk.Fetch()`

This is a wrapper over `jws.WithFetchWhitelist()` that can be passed to `jwt.Parse()`, and will be ignored if you spcify `jws.WithJWKSetFetcher()`

func WithHTTPClient added in v1.2.14

func WithHTTPClient(httpcl *http.Client) ParseOption

WithHTTPClient specifies the `*http.Client` object that should be passed to `jws.VerifyAuto()`, which in turn will be passed to `jwk.Fetch()`

This is a wrapper over `jws.WithHTTPClient()` that can be passed to `jwt.Parse()`, and will be ignored if you spcify `jws.WithJWKSetFetcher()`

func WithJWKSetFetcher added in v1.2.14

func WithJWKSetFetcher(f jws.JWKSetFetcher) ParseOption

WithJWKSetFetcher specifies the `jws.JWKSetFetcher` object that should be passed to `jws.VerifyAuto()`

This is a wrapper over `jws.WithJWKSetFetcher()` that can be passed to `jwt.Parse()`.

func WithKeySet added in v1.0.3

func WithKeySet(set jwk.Set) ParseOption

WithKeySet forces the Parse method to verify the JWT message using one of the keys in the given key set.

The key and the JWT MUST have a proper `kid` field set. The key to use for signature verification is chosen by matching the Key ID of the JWT and the ID of the given key set.

When using this option, keys MUST have a proper 'alg' field set. This is because we need to know the exact algorithm that you (the user) wants to use to verify the token. We do NOT trust the token's headers, because they can easily be tampered with.

However, there _is_ a workaround if you do understand the risks of allowing a library to automatically choose a signature verification strategy, and you do not mind the verification process having to possibly attempt using multiple times before succeeding to verify. See `jwt.InferAlgorithmFromKey` option

If you have only one key in the set, and are sure you want to use that key, you can use the `jwt.WithDefaultKey` option.

If provided with WithKeySetProvider(), this option takes precedence.

func WithKeySetProvider added in v1.2.7

func WithKeySetProvider(p KeySetProvider) ParseOption

WithKeySetProvider allows users to specify an object to choose which jwk.Set to use for verification.

If provided with WithKeySet(), WithKeySet() option takes precedence.

func WithPedantic added in v1.2.2

func WithPedantic(v bool) ParseOption

WithPedantic enables pedantic mode for parsing JWTs. Currently this only applies to checking for the correct `typ` and/or `cty` when necessary.

func WithToken added in v1.0.0

func WithToken(t Token) ParseOption

WithToken specifies the token instance that is used when parsing JWT tokens.

func WithTypedClaim added in v1.2.1

func WithTypedClaim(name string, object interface{}) ParseOption

WithTypedClaim allows a private claim to be parsed into the object type of your choice. It works much like the RegisterCustomField, but the effect is only applicable to the jwt.Parse function call which receives this option.

While this can be extremely useful, this option should be used with caution: There are many caveats that your entire team/user-base needs to be aware of, and therefore in general its use is discouraged. Only use it when you know what you are doing, and you document its use clearly for others.

First and foremost, this is a "per-object" option. Meaning that given the same serialized format, it is possible to generate two objects whose internal representations may differ. That is, if you parse one _WITH_ the option, and the other _WITHOUT_, their internal representation may completely differ. This could potentially lead to problems.

Second, specifying this option will slightly slow down the decoding process as it needs to consult multiple definitions sources (global and local), so be careful if you are decoding a large number of tokens, as the effects will stack up.

Finally, this option will also NOT work unless the tokens themselves support such parsing mechanism. For example, while tokens obtained from `jwt.New()` and `openid.New()` will respect this option, if you provide your own custom token type, it will need to implement the TokenWithDecodeCtx interface.

func WithValidate added in v1.0.6

func WithValidate(b bool) ParseOption

WithValidate is passed to `Parse()` method to denote that the validation of the JWT token should be performed after a successful parsing of the incoming payload.

func WithVerify

func WithVerify(alg jwa.SignatureAlgorithm, key interface{}) ParseOption

WithVerify forces the Parse method to verify the JWT message using the given key. XXX Should have been named something like WithVerificationKey

func WithVerifyAuto added in v1.2.14

func WithVerifyAuto(v bool) ParseOption

WithVerifyAuto specifies that the JWS verification should be performed using `jws.VerifyAuto()`, which in turn attempts to verify the message using values that are stored within the JWS message.

Only passing this option to `jwt.Parse()` will not result in a successful verification. Please make sure to carefully read the documentation in `jws.VerifyAuto()`, and provide the necessary Whitelist object via `jwt.WithFetchWhitelist()`

You might also consider using a backoff policy by using `jwt.WithFetchBackoff()` to control the number of requests being made.

type ParseRequestOption added in v1.1.4

type ParseRequestOption interface {
	ParseOption
	// contains filtered or unexported methods
}

ParseRequestOption describes an Option that can be passed to `ParseRequest()`.

func WithFormKey added in v1.1.4

func WithFormKey(v string) ParseRequestOption

WithFormKey is used to specify header keys to search for tokens.

While the type system allows this option to be passed to jwt.Parse() directly, doing so will have no effect. Only use it for HTTP request parsing functions

func WithHeaderKey added in v1.1.4

func WithHeaderKey(v string) ParseRequestOption

WithHeaderKey is used to specify header keys to search for tokens.

While the type system allows this option to be passed to jwt.Parse() directly, doing so will have no effect. Only use it for HTTP request parsing functions

type ReadFileOption added in v1.1.0

type ReadFileOption interface {
	Option
	// contains filtered or unexported methods
}

ReadFileOption describes options that can be passed to ReadFile.

type SerializeCtx added in v1.2.2

type SerializeCtx interface {
	Step() int
	Nested() bool
}

type SerializeStep added in v1.2.2

type SerializeStep interface {
	Serialize(SerializeCtx, interface{}) (interface{}, error)
}

type Serializer added in v1.2.2

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

Serializer is a generic serializer for JWTs. Whereas other conveinience functions can only do one thing (such as generate a JWS signed JWT), Using this construct you can serialize the token however you want.

By default the serializer only marshals the token into a JSON payload. You must set up the rest of the steps that should be taken by the serializer.

For example, to marshal the token into JSON, then apply JWS and JWE in that order, you would do:

serialized, err := jwt.NewSerialer().
   Sign(jwa.RS256, key).
   Encrypt(jwa.RSA_OAEP, key.PublicKey).
   Serialize(token)

The `jwt.Sign()` function is equivalent to

serialized, err := jwt.NewSerializer().
   Sign(...args...).
   Serialize(token)

func NewSerializer added in v1.2.2

func NewSerializer() *Serializer

NewSerializer creates a new empty serializer.

func (*Serializer) Encrypt added in v1.2.2

func (s *Serializer) Encrypt(keyalg jwa.KeyEncryptionAlgorithm, key interface{}, contentalg jwa.ContentEncryptionAlgorithm, compressalg jwa.CompressionAlgorithm, options ...EncryptOption) *Serializer

func (*Serializer) Reset added in v1.2.2

func (s *Serializer) Reset() *Serializer

Reset clears all of the registered steps.

func (*Serializer) Serialize added in v1.2.2

func (s *Serializer) Serialize(t Token) ([]byte, error)

func (*Serializer) Sign added in v1.2.2

func (s *Serializer) Sign(alg jwa.SignatureAlgorithm, key interface{}, options ...SignOption) *Serializer

func (*Serializer) Step added in v1.2.2

func (s *Serializer) Step(step SerializeStep) *Serializer

Step adds a new Step to the serialization process

type SignOption added in v1.2.2

type SignOption interface {
	Option
	// contains filtered or unexported methods
}

SignOption describes an Option that can be passed to Sign() or (jwt.Serializer).Sign

func WithHeaders added in v1.0.3

func WithHeaders(hdrs jws.Headers) SignOption

WithHeaders is passed to `jwt.Sign()` function, to allow specifying arbitrary header values to be included in the header section of the jws message

This option will be deprecated in the next major version. Use jwt.WithJwsHeaders() instead.

func WithJwsHeaders added in v1.2.2

func WithJwsHeaders(hdrs jws.Headers) SignOption

WithJwsHeaders is passed to `jwt.Sign()` function or "jwt.Serializer".Sign() method, to allow specifying arbitrary header values to be included in the header section of the JWE message

type Token

type Token interface {

	// Audience returns the value for "aud" field of the token
	Audience() []string

	// Expiration returns the value for "exp" field of the token
	Expiration() time.Time

	// IssuedAt returns the value for "iat" field of the token
	IssuedAt() time.Time

	// Issuer returns the value for "iss" field of the token
	Issuer() string

	// JwtID returns the value for "jti" field of the token
	JwtID() string

	// NotBefore returns the value for "nbf" field of the token
	NotBefore() time.Time

	// Subject returns the value for "sub" field of the token
	Subject() string

	// PrivateClaims return the entire set of fields (claims) in the token
	// *other* than the pre-defined fields such as `iss`, `nbf`, `iat`, etc.
	PrivateClaims() map[string]interface{}

	// Get returns the value of the corresponding field in the token, such as
	// `nbf`, `exp`, `iat`, and other user-defined fields. If the field does not
	// exist in the token, the second return value will be `false`
	//
	// If you need to access fields like `alg`, `kid`, `jku`, etc, you need
	// to access the corresponding fields in the JWS/JWE message. For this,
	// you will need to access them by directly parsing the payload using
	// `jws.Parse` and `jwe.Parse`
	Get(string) (interface{}, bool)

	// Set assigns a value to the corresponding field in the token. Some
	// pre-defined fields such as `nbf`, `iat`, `iss` need their values to
	// be of a specific type. See the other getter methods in this interface
	// for the types of each of these fields
	Set(string, interface{}) error
	Remove(string) error
	Clone() (Token, error)
	Iterate(context.Context) Iterator
	Walk(context.Context, Visitor) error
	AsMap(context.Context) (map[string]interface{}, error)
}

Token represents a generic JWT token. which are type-aware (to an extent). Other claims may be accessed via the `Get`/`Set` methods but their types are not taken into consideration at all. If you have non-standard claims that you must frequently access, consider creating accessors functions like the following

func SetFoo(tok jwt.Token) error func GetFoo(tok jwt.Token) (*Customtyp, error)

Embedding jwt.Token into another struct is not recommended, because jwt.Token needs to handle private claims, and this really does not work well when it is embedded in other structure

func New

func New() Token

New creates a standard token, with minimal knowledge of possible claims. Standard claims include"aud", "exp", "iat", "iss", "jti", "nbf" and "sub". Convenience accessors are provided for these standard claims

func Parse

func Parse(s []byte, options ...ParseOption) (Token, error)

Parse parses the JWT token payload and creates a new `jwt.Token` object. The token must be encoded in either JSON format or compact format.

This function can work with encrypted and/or signed tokens. Any combination of JWS and JWE may be applied to the token, but this function will only attempt to verify/decrypt up to 2 levels (i.e. JWS only, JWE only, JWS then JWE, or JWE then JWS)

If the token is signed and you want to verify the payload matches the signature, you must pass the jwt.WithVerify(alg, key) or jwt.WithKeySet(jwk.Set) option. If you do not specify these parameters, no verification will be performed.

During verification, if the JWS headers specify a key ID (`kid`), the key used for verification must match the specified ID. If you are somehow using a key without a `kid` (which is highly unlikely if you are working with a JWT from a well know provider), you can workaround this by modifying the `jwk.Key` and setting the `kid` header.

If you also want to assert the validity of the JWT itself (i.e. expiration and such), use the `Validate()` function on the returned token, or pass the `WithValidate(true)` option. Validate options can also be passed to `Parse`

This function takes both ParseOption and ValidateOption types: ParseOptions control the parsing behavior, and ValidateOptions are passed to `Validate()` when `jwt.WithValidate` is specified.

func ParseForm added in v1.1.4

func ParseForm(values url.Values, name string, options ...ParseOption) (Token, error)

ParseForm parses a JWT stored in a url.Value.

func ParseHeader added in v1.1.4

func ParseHeader(hdr http.Header, name string, options ...ParseOption) (Token, error)

ParseHeader parses a JWT stored in a http.Header.

For the header "Authorization", it will strip the prefix "Bearer " and will treat the remaining value as a JWT.

func ParseReader added in v1.1.0

func ParseReader(src io.Reader, options ...ParseOption) (Token, error)

ParseReader calls Parse against an io.Reader

func ParseRequest added in v1.1.4

func ParseRequest(req *http.Request, options ...ParseOption) (Token, error)

ParseRequest searches a http.Request object for a JWT token.

Specifying WithHeaderKey() will tell it to search under a specific header key. Specifying WithFormKey() will tell it to search under a specific form field.

By default, "Authorization" header will be searched.

If WithHeaderKey() is used, you must explicitly re-enable searching for "Authorization" header.

# searches for "Authorization"
jwt.ParseRequest(req)

# searches for "x-my-token" ONLY.
jwt.ParseRequest(req, jwt.WithHeaderKey("x-my-token"))

# searches for "Authorization" AND "x-my-token"
jwt.ParseRequest(req, jwt.WithHeaderKey("Authorization"), jwt.WithHeaderKey("x-my-token"))

func ParseString

func ParseString(s string, options ...ParseOption) (Token, error)

ParseString calls Parse against a string

func ReadFile added in v1.1.0

func ReadFile(path string, options ...ReadFileOption) (Token, error)

type TokenWithDecodeCtx added in v1.2.1

type TokenWithDecodeCtx = json.DecodeCtxContainer

type ValidateOption added in v1.0.6

type ValidateOption interface {
	ParseOption
	// contains filtered or unexported methods
}

ValidateOption describes an Option that can be passed to Validate(). ValidateOption also implements ParseOption, therefore it may be safely passed to `Parse()` (and thus `jwt.ReadFile()`)

func WithAcceptableSkew

func WithAcceptableSkew(dur time.Duration) ValidateOption

WithAcceptableSkew specifies the duration in which exp and nbf claims may differ by. This value should be positive

func WithAudience

func WithAudience(s string) ValidateOption

WithAudience specifies that expected audience value. `Validate()` will return true if one of the values in the `aud` element matches this value. If not specified, the value of issuer is not verified at all.

func WithClaimValue added in v0.9.2

func WithClaimValue(name string, v interface{}) ValidateOption

WithClaimValue specifies the expected value for a given claim

func WithClock

func WithClock(c Clock) ValidateOption

WithClock specifies the `Clock` to be used when verifying claims exp and nbf.

func WithContext added in v1.2.7

func WithContext(ctx context.Context) ValidateOption

WithContext allows you to specify a context.Context object to be used with `jwt.Validate()` option.

Please be aware that in the next major release of this library, `jwt.Validate()`'s signature will change to include an explicit `context.Context` object.

func WithIssuer

func WithIssuer(s string) ValidateOption

WithIssuer specifies that expected issuer value. If not specified, the value of issuer is not verified at all.

func WithJwtID

func WithJwtID(s string) ValidateOption

WithJwtID specifies that expected jti value. If not specified, the value of jti is not verified at all.

func WithMaxDelta added in v1.2.2

func WithMaxDelta(dur time.Duration, c1, c2 string) ValidateOption

WithMaxDelta specifies that given two claims `c1` and `c2` that represent time, the difference in time.Duration must be less than equal to the value specified by `d`. If `c1` or `c2` is the empty string, the current time (as computed by `time.Now` or the object passed via `WithClock()`) is used for the comparison.

`c1` and `c2` are also assumed to be required, therefore not providing either claim in the token will result in an error.

Because there is no way of reliably knowing how to parse private claims, we currently only support `iat`, `exp`, and `nbf` claims.

If the empty string is passed to c1 or c2, then the current time (as calculated by time.Now() or the clock object provided via WithClock()) is used.

For example, in order to specify that `exp` - `iat` should be less than 10*time.Second, you would write

jwt.Validate(token, jwt.WithMaxDelta(10*time.Second, jwt.ExpirationKey, jwt.IssuedAtKey))

If AcceptableSkew of 2 second is specified, the above will return valid for any value of `exp` - `iat` between 8 (10-2) and 12 (10+2).

func WithMinDelta added in v1.2.2

func WithMinDelta(dur time.Duration, c1, c2 string) ValidateOption

WithMinDelta is almost exactly the same as WithMaxDelta, but force validation to fail if the difference between time claims are less than dur.

For example, in order to specify that `exp` - `iat` should be greater than 10*time.Second, you would write

jwt.Validate(token, jwt.WithMinDelta(10*time.Second, jwt.ExpirationKey, jwt.IssuedAtKey))

The validation would fail if the difference is less than 10 seconds.

func WithRequiredClaim added in v1.2.2

func WithRequiredClaim(name string) ValidateOption

WithRequiredClaim specifies that the claim identified the given name must exist in the token. Only the existence of the claim is checked: the actual value associated with that field is not checked.

func WithSubject

func WithSubject(s string) ValidateOption

WithSubject specifies that expected subject value. If not specified, the value of subject is not verified at all.

func WithValidator added in v1.2.7

func WithValidator(v Validator) ValidateOption

WithValidator validates the token with the given Validator.

For example, in order to validate tokens that are only valid during August, you would write

 validator := jwt.ValidatorFunc(func(_ context.Context, t jwt.Token) error {
   if time.Now().Month() != 8 {
     return fmt.Errorf(`tokens are only valid during August!`)
   }
   return nil
 })
err := jwt.Validate(token, jwt.WithValidator(validator))

type ValidationError added in v1.2.13

type ValidationError interface {
	error
	// contains filtered or unexported methods
}

func NewValidationError added in v1.2.13

func NewValidationError(err error) ValidationError

type Validator added in v1.2.7

type Validator interface {
	// Validate should return an error if a required conditions is not met.
	// This method will be changed in the next major release to return
	// jwt.ValidationError instead of error to force users to return
	// a validation error even for user-specified validators
	Validate(context.Context, Token) error
}

Validator describes interface to validate a Token.

func ClaimContainsString added in v1.2.7

func ClaimContainsString(name, value string) Validator

ClaimContainsString can be used to check if the claim called `name`, which is expected to be a list of strings, contains `value`. Currently because of the implementation this will probably only work for `aud` fields.

func ClaimValueIs added in v1.2.7

func ClaimValueIs(name string, value interface{}) Validator

ClaimValueIs creates a Validator that checks if the value of claim `name` matches `value`. The comparison is done using a simple `==` comparison, and therefore complex comparisons may fail using this code. If you need to do more, use a custom Validator.

func IsExpirationValid added in v1.2.7

func IsExpirationValid() Validator

IsExpirationValid is one of the default validators that will be executed. It does not need to be specified by users, but it exists as an exported field so that you can check what it does.

The supplied context.Context object must have the "clock" and "skew" populated with appropriate values using SetValidationCtxClock() and SetValidationCtxSkew()

func IsIssuedAtValid added in v1.2.7

func IsIssuedAtValid() Validator

IsIssuedAtValid is one of the default validators that will be executed. It does not need to be specified by users, but it exists as an exported field so that you can check what it does.

The supplied context.Context object must have the "clock" and "skew" populated with appropriate values using SetValidationCtxClock() and SetValidationCtxSkew()

func IsNbfValid added in v1.2.7

func IsNbfValid() Validator

IsNbfValid is one of the default validators that will be executed. It does not need to be specified by users, but it exists as an exported field so that you can check what it does.

The supplied context.Context object must have the "clock" and "skew" populated with appropriate values using SetValidationCtxClock() and SetValidationCtxSkew()

func IsRequired added in v1.2.7

func IsRequired(name string) Validator

IsRequired creates a Validator that checks if the required claim `name` exists in the token

func MaxDeltaIs added in v1.2.7

func MaxDeltaIs(c1, c2 string, dur time.Duration) Validator

MaxDeltaIs implements the logic behind `WithMaxDelta()` option

func MinDeltaIs added in v1.2.7

func MinDeltaIs(c1, c2 string, dur time.Duration) Validator

MinDeltaIs implements the logic behind `WithMinDelta()` option

type ValidatorFunc added in v1.2.7

type ValidatorFunc func(context.Context, Token) error

ValidatorFunc is a type of Validator that does not have any state, that is implemented as a function

func (ValidatorFunc) Validate added in v1.2.7

func (vf ValidatorFunc) Validate(ctx context.Context, tok Token) error

type VerifyParameters

type VerifyParameters interface {
	Algorithm() jwa.SignatureAlgorithm
	Key() interface{}
}

type Visitor added in v0.9.1

type Visitor = iter.MapVisitor

type VisitorFunc added in v1.0.0

type VisitorFunc = iter.MapVisitorFunc

Directories

Path Synopsis
internal
cmd/gentoken Module
Package openid provides a specialized token that provides utilities to work with OpenID JWT tokens.
Package openid provides a specialized token that provides utilities to work with OpenID JWT tokens.

Jump to

Keyboard shortcuts

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