Skip to content

Commit

Permalink
Merge pull request #262 from ericchiang/jwks
Browse files Browse the repository at this point in the history
oidc: have NewRemoteKeySet return a concrete type
  • Loading branch information
ericchiang committed Jul 20, 2020
2 parents 7a14ede + d1b7e9f commit 3bc5a7e
Showing 1 changed file with 16 additions and 11 deletions.
27 changes: 16 additions & 11 deletions oidc/jwks.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,20 @@ import (
//
// The returned KeySet is a long lived verifier that caches keys based on cache-control
// headers. Reuse a common remote key set instead of creating new ones as needed.
//
// The behavior of the returned KeySet is undefined once the context is canceled.
func NewRemoteKeySet(ctx context.Context, jwksURL string) KeySet {
func NewRemoteKeySet(ctx context.Context, jwksURL string) *RemoteKeySet {
return newRemoteKeySet(ctx, jwksURL, time.Now)
}

func newRemoteKeySet(ctx context.Context, jwksURL string, now func() time.Time) *remoteKeySet {
func newRemoteKeySet(ctx context.Context, jwksURL string, now func() time.Time) *RemoteKeySet {
if now == nil {
now = time.Now
}
return &remoteKeySet{jwksURL: jwksURL, ctx: ctx, now: now}
return &RemoteKeySet{jwksURL: jwksURL, ctx: cloneContext(ctx), now: now}
}

type remoteKeySet struct {
// RemoteKeySet is a KeySet implementation that validates JSON web tokens against
// a jwks_uri endpoint.
type RemoteKeySet struct {
jwksURL string
ctx context.Context
now func() time.Time
Expand Down Expand Up @@ -81,15 +81,20 @@ func (i *inflight) result() ([]jose.JSONWebKey, error) {
return i.keys, i.err
}

func (r *remoteKeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) {
// VerifySignature validates a payload against a signature from the jwks_uri.
//
// Users MUST NOT call this method directly and should use an IDTokenVerifier
// instead. This method skips critical validations such as 'alg' values and is
// only exported to implement the KeySet interface.
func (r *RemoteKeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) {
jws, err := jose.ParseSigned(jwt)
if err != nil {
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
}
return r.verify(ctx, jws)
}

func (r *remoteKeySet) verify(ctx context.Context, jws *jose.JSONWebSignature) ([]byte, error) {
func (r *RemoteKeySet) verify(ctx context.Context, jws *jose.JSONWebSignature) ([]byte, error) {
// We don't support JWTs signed with multiple signatures.
keyID := ""
for _, sig := range jws.Signatures {
Expand Down Expand Up @@ -125,15 +130,15 @@ func (r *remoteKeySet) verify(ctx context.Context, jws *jose.JSONWebSignature) (
return nil, errors.New("failed to verify id token signature")
}

func (r *remoteKeySet) keysFromCache() (keys []jose.JSONWebKey) {
func (r *RemoteKeySet) keysFromCache() (keys []jose.JSONWebKey) {
r.mu.Lock()
defer r.mu.Unlock()
return r.cachedKeys
}

// keysFromRemote syncs the key set from the remote set, records the values in the
// cache, and returns the key set.
func (r *remoteKeySet) keysFromRemote(ctx context.Context) ([]jose.JSONWebKey, error) {
func (r *RemoteKeySet) keysFromRemote(ctx context.Context) ([]jose.JSONWebKey, error) {
// Need to lock to inspect the inflight request field.
r.mu.Lock()
// If there's not a current inflight request, create one.
Expand Down Expand Up @@ -173,7 +178,7 @@ func (r *remoteKeySet) keysFromRemote(ctx context.Context) ([]jose.JSONWebKey, e
}
}

func (r *remoteKeySet) updateKeys() ([]jose.JSONWebKey, error) {
func (r *RemoteKeySet) updateKeys() ([]jose.JSONWebKey, error) {
req, err := http.NewRequest("GET", r.jwksURL, nil)
if err != nil {
return nil, fmt.Errorf("oidc: can't create request: %v", err)
Expand Down

0 comments on commit 3bc5a7e

Please sign in to comment.