Skip to content

JWK Sources

Use sources

Sources are a powerful way to automatically handle your keys from a provider that implements keys rotation. A Key Source supports fetching multiple keys at once, and caching them to lower resources consumption (keys don't have to be recomputed from their serialized form each time).

To build a source, you first need a fetcher. This is a method that will be executed periodically to retrieve a fresh set of keys. The keys MUST be deserialized into the generic jwa.JWK format.

go
package main

import (
	"context"
	"encoding/json"
	"github.com/a-novel-kit/jwt/jwa"
	"net/http"
)

// Remote URL that serves your keys.
var remoteURL string

// Example implementation with net/http.
func httpKeysFetcher(ctx context.Context) ([]*jwa.JWK, error) {
	req, _ := http.NewRequestWithContext(ctx, http.MethodGet, remoteURL, nil)

	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()

	var out []*jwa.JWK
	_ = json.NewDecoder(resp.Body).Decode(&out)

	return out, nil
}

WARNING

The sources currently provided only support one type of key. It is important that your fetcher filters only key that match the algorithm you are looking for, otherwise retrieving the key will fail.

Once you have a source set, you can consume its keys in 2 ways;

go
package main

import (
	"context"
	"github.com/a-novel-kit/jwt/jwk"
)

func main() {
	var source *jwk.Source[T]

	// Returns every available keys, in order.
	keys, _ := source.List(context.Background())

	// Or use a key ID to retrieve a specific key.
	// If the KID is empty, this returns the first key
	// in the list.
	key, _ := source.Get(context.Background(), "key-id")
}

Symmetric keys

go
package main

import (
	"github.com/a-novel-kit/jwt/jwa"
	"github.com/a-novel-kit/jwt/jwk"
	"time"
)

func main() {
	// Method to retrieve keys into their generic JSON
	// representation. See example above.
	var fetcher jwk.KeysFetcher

	config := jwk.SourceConfig{
		CacheDuration: time.Hour,
        Fetch:       fetcher,
	}

	source := jwk.NewAESSource(config, jwk.A128CBC)
}

Available presets for use as Content-Encryption Keys (CEK) are:

PresetTarget "enc"
jwk.A128CBCA128CBC-HS256
jwk.A192CBCA192CBC-HS384
jwk.A256CBCA256CBC-HS512
jwk.A128GCMA128GCM
jwk.A192GCMA192GCM
jwk.A256GCMA256GCM

Asymmetric keys

go
package main

import (
	"github.com/a-novel-kit/jwt/jwa"
	"github.com/a-novel-kit/jwt/jwk"
	"time"
)

func main() {
	// Method to retrieve keys into their generic JSON
	// representation. See example above.
	var fetcher jwk.KeysFetcher

	config := jwk.SourceConfig{
		CacheDuration: time.Hour,
		Fetch:       fetcher,
	}

	// Beware, as private and public keys are 2 different forms,
	// both sources will require their own fetcher / config.
	privateSource := jwk.NewECDHPrivateSource(config)
	publicSource := jwk.NewECDHPublicSource(config)
}