Documentation ¶
Overview ¶
Package jwk implements JWK as described in https://tools.ietf.org/html/rfc7517
Example ¶
package main import ( "log" "github.com/lestrrat-go/jwx/jwk" ) func main() { set, err := jwk.Fetch("https://foobar.domain/json") if err != nil { log.Printf("failed to parse JWK: %s", err) return } // If you KNOW you have exactly one key, you can just // use set.Keys[0] keys := set.LookupKeyID("mykey") if len(keys) == 0 { log.Printf("failed to lookup key: %s", err) return } var key interface{} if err := keys[0].Raw(&key); err != nil { log.Printf("failed to generate public key: %s", err) return } // Use key for jws.Verify() or whatever _ = key }
Output:
Index ¶
- Constants
- func AssignKeyID(key Key, options ...Option) error
- func ParseRawKey(data []byte, rawkey interface{}) error
- func PublicKeyOf(v interface{}) (interface{}, error)
- type AutoRefresh
- type AutoRefreshOption
- type CertificateChain
- type ECDSAPrivateKey
- type ECDSAPublicKey
- type HeaderIterator
- type HeaderPair
- type HeaderVisitor
- type HeaderVisitorFunc
- type Key
- type KeyIterator
- type KeyOperation
- type KeyOperationList
- type KeyPair
- type KeyUsageType
- type OKPPrivateKey
- type OKPPublicKey
- type Option
- type RSAPrivateKey
- type RSAPublicKey
- type Set
- func Fetch(urlstring string, options ...Option) (*Set, error)
- func FetchHTTP(jwkurl string, options ...Option) (*Set, error)
- func FetchHTTPWithContext(ctx context.Context, jwkurl string, options ...Option) (*Set, error)
- func Parse(in io.Reader) (*Set, error)
- func ParseBytes(buf []byte) (*Set, error)
- func ParseString(s string) (*Set, error)
- type SymmetricKey
- type TargetSnapshot
Examples ¶
Constants ¶
const ( ECDSACrvKey = "crv" ECDSADKey = "d" ECDSAXKey = "x" ECDSAYKey = "y" )
const ( KeyTypeKey = "kty" KeyUsageKey = "use" KeyOpsKey = "key_ops" AlgorithmKey = "alg" KeyIDKey = "kid" X509URLKey = "x5u" X509CertChainKey = "x5c" X509CertThumbprintKey = "x5t" X509CertThumbprintS256Key = "x5t#S256" )
const ( OKPCrvKey = "crv" OKPDKey = "d" OKPXKey = "x" )
const ( RSADKey = "d" RSADPKey = "dp" RSADQKey = "dq" RSAEKey = "e" RSANKey = "n" RSAPKey = "p" RSAQKey = "q" RSAQIKey = "qi" )
const (
SymmetricOctetsKey = "k"
)
Variables ¶
This section is empty.
Functions ¶
func AssignKeyID ¶ added in v1.0.2
AssignKeyID is a convenience function to automatically assign the "kid" section of the key, if it already doesn't have one. It uses Key.Thumbprint method with crypto.SHA256 as the default hashing algorithm
func ParseRawKey ¶ added in v1.0.6
ParseRawKey is a combination of ParseKey and Raw. It parses a single JWK key, and assigns the "raw" key to the given parameter. The key must either be a pointer to an empty interface, or a pointer to the actual raw key type such as *rsa.PrivateKey, *ecdsa.PublicKey, *[]byte, etc.
func PublicKeyOf ¶ added in v1.0.0
func PublicKeyOf(v interface{}) (interface{}, error)
PublicKeyOf returns the corresponding public key of the given value `v`. For example, if v is a `*rsa.PrivateKey`, then `*rsa.PublicKey` is returned.
Not to be confused with jwk.Key.PubliKey(). In hindsight, this should have been named PublicRawKeyOf() or some such.
If given a public key, then the same public key will be returned. For example, if v is a `*rsa.PublicKey`, then the same value is returned.
If v is of a type that we don't support, an error is returned.
This is useful when you are dealing with the jwk.Key interface alone and you don't know before hand what the underlying key type is, but you still want to obtain the corresponding public key
Types ¶
type AutoRefresh ¶ added in v1.0.7
type AutoRefresh struct {
// contains filtered or unexported fields
}
AutoRefresh is a container that keeps track of *jwk.Set object by their source URLs. The *jwk.Set objects are refreshed automatically behind the scenes.
Before retrieving the *jwk.Set objects, the user must pre-register the URLs they intend to use by calling `Configure()`
ar := jwk.NewAutoRefresh(ctx) ar.Configure(url, options...)
Once registered, you can call `Fetch()` to retrieve the *jwk.Set object.
All JWKS objects that are retrieved via the auto-fetch mechanism should be treated read-only, as they are shared among the consumers and this object.
func NewAutoRefresh ¶ added in v1.0.7
func NewAutoRefresh(ctx context.Context) *AutoRefresh
NewAutoRefresh creates a container that keeps track of JWKS objects which are automatically refreshed.
The context object in the argument controls the life-span of the auto-refresh worker. If you are using this in a long running process, this should mostly be set to a context that ends when the main loop/part of your program exits:
func MainLoop() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ar := jwk.AutoRefresh(ctx) for ... { ... } }
func (*AutoRefresh) Configure ¶ added in v1.0.7
func (af *AutoRefresh) Configure(url string, options ...AutoRefreshOption)
Configure registers the url to be controlled by AutoRefresh, and also sets any options associated to it.
Note that options are treated as a whole -- you can't just update one value. For example, if you did:
ar.Configure(url, jwk.WithHTTPClient(...)) ar.Configure(url, jwk.WithRefreshInterval(...))
The the end result is that `url` is ONLY associated with the options given in the second call to `Configure()`, i.e. `jwk.WithRefreshInterval`. The other unspecified options, including the HTTP client, is set to their default values.
Configuration must propagate between goroutines, and therefore are not atomic (But changes should be felt "soon enough" for practical purposes)
func (*AutoRefresh) Fetch ¶ added in v1.0.7
If it has previously been fetched, then a cached value is returned. If this the first time `url` was requested, an HTTP request will be sent, synchronously. Also, when accessed via multiple goroutines concurrently, the first time around only one goroutine will be allowed to perform the initialization (HTTP fetch and cache population). All other goroutines will be blocked until the operation is completed.
DO NOT modify the *jwk.Set object returned by this method, as the objects are shared among all consumers and the backend goroutine
func (*AutoRefresh) Refresh ¶ added in v1.0.7
Refresh is the same as Fetch(), except that HTTP fetching is done synchronously. This is useful for when you want to force an HTTP fetch instead of waiting for the background goroutine to do it, for example when you want to make sure the AutoRefresh cache is warmed up before starting your main loop
func (*AutoRefresh) Snapshot ¶ added in v1.0.7
func (af *AutoRefresh) Snapshot() <-chan TargetSnapshot
type AutoRefreshOption ¶ added in v1.0.7
type AutoRefreshOption interface { Option // contains filtered or unexported methods }
func WithHTTPClient ¶
func WithHTTPClient(cl *http.Client) AutoRefreshOption
WithHTTPClient allows users to specify the "net/http".Client object that is used when fetching *jwk.Set objects.
For historical reasons this method is also used in `jwk.Fetch*` functions, eventhough the return value is marked as an `AutoRefreshOption`
func WithMinRefreshInterval ¶ added in v1.0.7
func WithMinRefreshInterval(d time.Duration) AutoRefreshOption
WithMinRefreshInterval specifies the minimum refresh interval to be used when using AutoRefresh. This value is ONLY used if you did not specify a user-supplied static refresh interval via `WithRefreshInterval`.
This value is used as a fallback value when tokens are refreshed.
When we fetch the key from a remote URL, we first look at the max-age directive from Cache-Control response header. If this value is present, we compare the max-age value and the value specified by this option and take the larger one.
Next we check for the Expires header, and similarly if the header is present, we compare it against the value specified by this option, and take the larger one.
Finally, if neither of the above headers are present, we use the value specified by this option as the next refresh timing
If unspecified, the minimum refresh interval is 1 hour
func WithRefreshBackoff ¶ added in v1.0.7
func WithRefreshBackoff(v backoff.Policy) AutoRefreshOption
WithRefreshRetryBackoff specifies the backoff policy to use when refreshing a JWKS from a remote server fails. This does not have any effect on initial `Fetch()`, or any of the `Refresh()` calls -- the backoff is applied ONLY on the background refreshing goroutine.
func WithRefreshInterval ¶ added in v1.0.7
func WithRefreshInterval(d time.Duration) AutoRefreshOption
WithRefreshInterval specifies the static interval between refreshes of *jwk.Set objects controlled by jwk.AutoRefresh.
Providing this option overrides the adaptive token refreshing based on Cache-Control/Expires header (and jwk.WithMinRefreshInterval), and refreshes will *always* happen in this interval.
type CertificateChain ¶
type CertificateChain struct {
// contains filtered or unexported fields
}
func (*CertificateChain) Accept ¶
func (c *CertificateChain) Accept(v interface{}) error
func (CertificateChain) Get ¶
func (c CertificateChain) Get() []*x509.Certificate
func (CertificateChain) MarshalJSON ¶ added in v1.0.0
func (c CertificateChain) MarshalJSON() ([]byte, error)
func (*CertificateChain) UnmarshalJSON ¶ added in v1.0.0
func (c *CertificateChain) UnmarshalJSON(buf []byte) error
type ECDSAPrivateKey ¶
type ECDSAPrivateKey interface { Key FromRaw(*ecdsa.PrivateKey) error Crv() jwa.EllipticCurveAlgorithm D() []byte X() []byte Y() []byte PublicKey() (ECDSAPublicKey, error) }
func NewECDSAPrivateKey ¶ added in v1.0.0
func NewECDSAPrivateKey() ECDSAPrivateKey
type ECDSAPublicKey ¶
type ECDSAPublicKey interface { Key FromRaw(*ecdsa.PublicKey) error Crv() jwa.EllipticCurveAlgorithm X() []byte Y() []byte }
func NewECDSAPublicKey ¶ added in v1.0.0
func NewECDSAPublicKey() ECDSAPublicKey
type HeaderIterator ¶ added in v1.0.0
type HeaderPair ¶ added in v1.0.0
type HeaderVisitor ¶ added in v1.0.0
type HeaderVisitor = iter.MapVisitor
type HeaderVisitorFunc ¶ added in v1.0.0
type HeaderVisitorFunc = iter.MapVisitorFunc
type Key ¶
type Key interface { // Get returns the value of a single field. The second boolean return value // will be false if the field is not stored in the source // // This method, which returns an `interface{}`, exists because // these objects can contain extra _arbitrary_ fields that users can // specify, and there is no way of knowing what type they could be Get(string) (interface{}, bool) // Set sets the value of a single field. Note that certain fields, // notably "kty" cannot be altered, but will not return an error // // This method, which takes an `interface{}`, exists because // these objects can contain extra _arbitrary_ fields that users can // specify, and there is no way of knowing what type they could be Set(string, interface{}) error // Raw creates the corresponding raw key. For example, // EC types would create *ecdsa.PublicKey or *ecdsa.PrivateKey, // and OctetSeq types create a []byte key. // // If you do not know the exact type of a jwk.Key before attempting // to obtain the raw key, you can simply pass a pointer to an // empty interface as the first argument. // // If you already know the exact type, it is recommended that you // pass a pointer to the actual key type (e.g. *rsa.PrivateKey, *ecdsa.PublicKey // for efficiency Raw(interface{}) error // Thumbprint returns the JWK thumbprint using the indicated // hashing algorithm, according to RFC 7638 Thumbprint(crypto.Hash) ([]byte, error) // Iterate returns an iterator that returns all keys and values Iterate(ctx context.Context) HeaderIterator // Walk is a utility tool that allows a visitor to iterate all keys and values Walk(context.Context, HeaderVisitor) error // AsMap is a utility tool returns a map that contains the same fields as the source AsMap(context.Context) (map[string]interface{}, error) // PrivateParams returns the non-standard elements in the source structure // WARNING: DO NOT USE PrivateParams() IF YOU HAVE CONCURRENT CODE ACCESSING THEM. // Use AsMap() to get a copy of the entire header instead PrivateParams() map[string]interface{} KeyType() jwa.KeyType KeyUsage() string KeyOps() KeyOperationList Algorithm() string KeyID() string X509URL() string X509CertChain() []*x509.Certificate X509CertThumbprint() string X509CertThumbprintS256() string }
Key defines the minimal interface for each of the key types. Their use and implementation differ significantly between each key types, so you should use type assertions to perform more specific tasks with each key
func New ¶
New creates a jwk.Key from the given key (RSA/ECDSA/symmetric keys).
The constructor auto-detects the type of key to be instantiated based on the input type:
* "crypto/rsa".PrivateKey and "crypto/rsa".PublicKey creates an RSA based key * "crypto/ecdsa".PrivateKey and "crypto/ecdsa".PublicKey creates an EC based key * "crypto/ed25519".PrivateKey and "crypto/ed25519".PublicKey creates an OKP based key * []byte creates a symmetric key
type KeyIterator ¶ added in v1.0.0
type KeyOperation ¶
type KeyOperation string
const ( KeyOpSign KeyOperation = "sign" // (compute digital signature or MAC) KeyOpVerify KeyOperation = "verify" // (verify digital signature or MAC) KeyOpEncrypt KeyOperation = "encrypt" // (encrypt content) KeyOpDecrypt KeyOperation = "decrypt" // (decrypt content and validate decryption, if applicable) KeyOpWrapKey KeyOperation = "wrapKey" // (encrypt key) KeyOpUnwrapKey KeyOperation = "unwrapKey" // (decrypt key and validate decryption, if applicable) KeyOpDeriveKey KeyOperation = "deriveKey" // (derive key) KeyOpDeriveBits KeyOperation = "deriveBits" // (derive bits not to be used as a key) )
type KeyOperationList ¶
type KeyOperationList []KeyOperation
func (*KeyOperationList) Accept ¶
func (ops *KeyOperationList) Accept(v interface{}) error
func (*KeyOperationList) Get ¶
func (ops *KeyOperationList) Get() KeyOperationList
type KeyUsageType ¶
type KeyUsageType string
KeyUsageType is used to denote what this key should be used for
const ( // ForSignature is the value used in the headers to indicate that // this key should be used for signatures ForSignature KeyUsageType = "sig" // ForEncryption is the value used in the headers to indicate that // this key should be used for encrypting ForEncryption KeyUsageType = "enc" )
func (*KeyUsageType) Accept ¶ added in v1.0.7
func (k *KeyUsageType) Accept(v interface{}) error
func (KeyUsageType) String ¶ added in v1.0.7
func (k KeyUsageType) String() string
type OKPPrivateKey ¶ added in v1.0.7
type OKPPrivateKey interface { Key FromRaw(interface{}) error Crv() jwa.EllipticCurveAlgorithm D() []byte X() []byte PublicKey() (OKPPublicKey, error) }
func NewOKPPrivateKey ¶ added in v1.0.7
func NewOKPPrivateKey() OKPPrivateKey
type OKPPublicKey ¶ added in v1.0.7
type OKPPublicKey interface { Key FromRaw(interface{}) error Crv() jwa.EllipticCurveAlgorithm X() []byte }
func NewOKPPublicKey ¶ added in v1.0.7
func NewOKPPublicKey() OKPPublicKey
type Option ¶
func WithThumbprintHash ¶ added in v1.0.2
type RSAPrivateKey ¶
type RSAPrivateKey interface { Key FromRaw(*rsa.PrivateKey) error D() []byte DP() []byte DQ() []byte E() []byte N() []byte P() []byte Q() []byte QI() []byte PublicKey() (RSAPublicKey, error) }
func NewRSAPrivateKey ¶ added in v1.0.0
func NewRSAPrivateKey() RSAPrivateKey
type RSAPublicKey ¶
func NewRSAPublicKey ¶ added in v1.0.0
func NewRSAPublicKey() RSAPublicKey
type Set ¶
type Set struct {
Keys []Key
}
Set is a convenience struct to allow generating and parsing JWK sets as opposed to single JWKs
func FetchHTTPWithContext ¶ added in v0.9.2
FetchHTTPWithContext fetches the remote JWK and parses its contents
func Parse ¶
Parse parses JWK from the incoming io.Reader. This function can handle both single-key and multi-key formats. If you know before hand which format the incoming data is in, you might want to consider using "github.com/lestrrat-go/jwx/internal/json" directly
Note that a successful parsing does NOT guarantee a valid key
func ParseBytes ¶
ParseBytes parses JWK from the incoming byte buffer.
Note that a successful parsing does NOT guarantee a valid key
func ParseString ¶
ParseString parses JWK from the incoming string.
Note that a successful parsing does NOT guarantee a valid key
func (Set) LookupKeyID ¶
LookupKeyID looks for keys matching the given key id. Note that the Set *may* contain multiple keys with the same key id
func (*Set) UnmarshalJSON ¶
type SymmetricKey ¶
func NewSymmetricKey ¶ added in v1.0.0
func NewSymmetricKey() SymmetricKey