Package jwks
Overview
Package jwks verifies JWT access tokens (RFC 9068) with the keys an authorization server publishes as a JSON Web Key Set, using go-jose. It builds a bearer.VerifyTokenOpFunc, so a resource server protects itself with:
v := jwks.New(jwksURL, issuer, rfc8707.MustResource(resource)).Verifier()
_ = v.Warm(ctx) // Optional: fetch the keys before the first request.
protect := bearer.New(v.Op(), challenge).WithScope("read").Middleware()The key set is cached for as long as its Cache-Control allows, within bounds, and fetched again early when a token names a key it doesn't have, so a rotated key is picked up straight away. Fetches are limited to one per interval, so tokens naming made-up keys can't make it hammer the authorization server, and while a fetch fails the last good keys are kept.
It's in its own package so that only resource servers depend on go-jose.
Index
Constants
const (
// DefaultLeeway is the clock skew allowed when checking a token's
// times. RFC 9068, Section 4, says it's "usually no more than a few
// minutes".
DefaultLeeway = 30 * time.Second
// DefaultRefetchInterval is the least time between fetches of the key
// set.
DefaultRefetchInterval = 30 * time.Second
// DefaultCacheFloor is the shortest time a key set is cached, used too
// when its response has no max-age.
DefaultCacheFloor = 5 * time.Minute
// DefaultCacheCeiling is the longest time a key set is cached.
DefaultCacheCeiling = 24 * time.Hour
// DefaultTimeout is how long fetching the key set may take.
DefaultTimeout = 10 * time.Second
)Defaults, used unless a With method changes them.
Variables
var (
// ErrKeySet is returned, wrapped in [bearer.ErrUnavailable], when the
// key set can't be fetched or read.
ErrKeySet = errors.New("key set unavailable")
)Types
Builder source
type Builder struct {
// contains filtered or unexported fields
}Builder configures a Verifier. Its With methods return a modified copy.
New source
func New(jwksURL, issuer string, audience rfc8707.Resource) BuilderNew returns a builder for a verifier that accepts tokens signed with the keys at jwksURL, issued by issuer, for audience. It panics if jwksURL or issuer is empty.
(Builder) Verifier source
func (b Builder) Verifier() *VerifierVerifier returns the verifier. It fetches nothing until it's first needed, or Verifier.Warm is called.
(Builder) WithAlgorithms source
func (b Builder) WithAlgorithms(alg jose.SignatureAlgorithm, more ...jose.SignatureAlgorithm) BuilderWithAlgorithms sets the signature algorithms accepted. The default is RS256 only, which RFC 9068, Section 2.1, requires every resource server to support. "none" is never accepted.
(Builder) WithCacheBounds source
func (b Builder) WithCacheBounds(minAge, maxAge time.Duration) BuilderWithCacheBounds sets the shortest and longest time a key set is cached, whatever its Cache-Control says.
(Builder) WithClient source
func (b Builder) WithClient(c *http.Client) BuilderWithClient sets the HTTP client that fetches the key set. The default times out after 10 seconds and doesn't follow redirects. Give it a timeout: a fetch isn't cancelled when the request that started it is, since other requests may be waiting for it.
(Builder) WithLeeway source
func (b Builder) WithLeeway(d time.Duration) BuilderWithLeeway sets the clock skew allowed when checking a token's times.
(Builder) WithNow source
func (b Builder) WithNow(now func() time.Time) BuilderWithNow sets the clock.
(Builder) WithRefetchInterval source
func (b Builder) WithRefetchInterval(d time.Duration) BuilderWithRefetchInterval sets the least time between fetches of the key set.
Verifier source
type Verifier struct {
Builder
// contains filtered or unexported fields
}Verifier verifies tokens with a cached key set. It's safe for concurrent use. Build one with New.
(Verifier) Op source
func (v *Verifier) Op() bearer.VerifyTokenOpFuncOp returns the operation that verifies a token. A token is accepted when it's a JWS signed with one of the accepted algorithms by the key its kid names, its typ is at+jwt, and its claims pass rfc9068.Claims.Validate (RFC 9068, Section 4). Otherwise the error wraps bearer.ErrInvalidToken, unless the key set has never been fetched, when it wraps bearer.ErrUnavailable.
(Verifier) Warm source
func (v *Verifier) Warm(ctx context.Context) errorWarm fetches the key set, so the first request doesn't wait for it. An error isn't fatal: the verifier tries again when it needs the keys.