...

Source file src/github.com/ory/x/jwksx/fetcher.go

Documentation: github.com/ory/x/jwksx

     1  package jwksx
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  	"sync"
     7  
     8  	"github.com/pkg/errors"
     9  	"gopkg.in/square/go-jose.v2"
    10  )
    11  
    12  // Fetcher is a small helper for fetching JSON Web Keys from remote endpoints.
    13  type Fetcher struct {
    14  	sync.RWMutex
    15  	remote string
    16  	c      *http.Client
    17  	keys   map[string]jose.JSONWebKey
    18  }
    19  
    20  // NewFetcher returns a new fetcher that can download JSON Web Keys from remote endpoints.
    21  func NewFetcher(remote string) *Fetcher {
    22  	return &Fetcher{
    23  		remote: remote,
    24  		c:      http.DefaultClient,
    25  		keys:   make(map[string]jose.JSONWebKey),
    26  	}
    27  }
    28  
    29  // GetKey retrieves a JSON Web Key from the cache, fetches it from a remote if it is not yet cached or returns an error.
    30  func (f *Fetcher) GetKey(kid string) (*jose.JSONWebKey, error) {
    31  	f.RLock()
    32  	if k, ok := f.keys[kid]; ok {
    33  		f.RUnlock()
    34  		return &k, nil
    35  	}
    36  	f.RUnlock()
    37  
    38  	res, err := f.c.Get(f.remote)
    39  	if err != nil {
    40  		return nil, errors.WithStack(err)
    41  	}
    42  	defer res.Body.Close()
    43  	if res.StatusCode != http.StatusOK {
    44  		return nil, errors.Errorf("expected status code 200 but got %d when requesting %s", res.StatusCode, f.remote)
    45  	}
    46  
    47  	var set jose.JSONWebKeySet
    48  	if err := json.NewDecoder(res.Body).Decode(&set); err != nil {
    49  		return nil, errors.WithStack(err)
    50  	}
    51  
    52  	for _, k := range set.Keys {
    53  		f.Lock()
    54  		f.keys[k.KeyID] = k
    55  		f.Unlock()
    56  	}
    57  
    58  	f.RLock()
    59  	defer f.RUnlock()
    60  	if k, ok := f.keys[kid]; ok {
    61  		return &k, nil
    62  	}
    63  
    64  	return nil, errors.Errorf("unable to find JSON Web Key with ID: %s", kid)
    65  }
    66  

View as plain text