Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: MicahParks/keyfunc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.2.9
Choose a base ref
...
head repository: MicahParks/keyfunc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v3.3.0
Choose a head ref
  • 3 commits
  • 4 files changed
  • 1 contributor

Commits on Mar 12, 2024

  1. Verified

    This commit was signed with the committer’s verified signature.
    ljharb Jordan Harband
    Copy the full SHA
    9fe4a24 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    accaf1a View commit details

Commits on Mar 25, 2024

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    a6bfa43 View commit details
Showing with 54 additions and 48 deletions.
  1. +1 −1 README.md
  2. +1 −1 go.mod
  3. +2 −2 go.sum
  4. +50 −44 keyfunc.go
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ example.

```go
// Create the keyfunc.Keyfunc.
k, err := keyfunc.NewDefault([]string{server.URL})
k, err := keyfunc.NewDefaultCtx(ctx, []string{server.URL}) // Context is used to end the refresh goroutine.
if err != nil {
log.Fatalf("Failed to create a keyfunc.Keyfunc from the server's URL.\nError: %s", err)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ module github.com/MicahParks/keyfunc/v3
go 1.21

require (
github.com/MicahParks/jwkset v0.5.15
github.com/MicahParks/jwkset v0.5.17
github.com/golang-jwt/jwt/v5 v5.2.0
)

4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/MicahParks/jwkset v0.5.15 h1:ACJY045Zuvo2TVWikeFLnKTIsEDQQHUHrNYiMW+gj24=
github.com/MicahParks/jwkset v0.5.15/go.mod h1:q8ptTGn/Z9c4MwbcfeCDssADeVQb3Pk7PnVxrvi+2QY=
github.com/MicahParks/jwkset v0.5.17 h1:DrcwyKwSP5adD0G2XJTvDulnWXjD6gbjROMgMXDbkKA=
github.com/MicahParks/jwkset v0.5.17/go.mod h1:q8ptTGn/Z9c4MwbcfeCDssADeVQb3Pk7PnVxrvi+2QY=
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
94 changes: 50 additions & 44 deletions keyfunc.go
Original file line number Diff line number Diff line change
@@ -112,58 +112,64 @@ func NewJWKSetJSON(raw json.RawMessage) (Keyfunc, error) {
return New(options)
}

func (k keyfunc) Keyfunc(token *jwt.Token) (any, error) {
kidInter, ok := token.Header[jwkset.HeaderKID]
if !ok {
return nil, fmt.Errorf("%w: could not find kid in JWT header", ErrKeyfunc)
}
kid, ok := kidInter.(string)
if !ok {
return nil, fmt.Errorf("%w: could not convert kid in JWT header to string", ErrKeyfunc)
}
algInter, ok := token.Header["alg"]
if !ok {
return nil, fmt.Errorf("%w: could not find alg in JWT header", ErrKeyfunc)
}
alg, ok := algInter.(string)
if !ok {
// For test coverage purposes, this should be impossible to reach because the JWT package rejects a token
// without an alg parameter in the header before calling jwt.Keyfunc.
return nil, fmt.Errorf(`%w: the JWT header did not contain the "alg" parameter, which is required by RFC 7515 section 4.1.1`, ErrKeyfunc)
}
func (k keyfunc) KeyfuncCtx(ctx context.Context) func(token *jwt.Token) (any, error) {
return func(token *jwt.Token) (any, error) {
kidInter, ok := token.Header[jwkset.HeaderKID]
if !ok {
return nil, fmt.Errorf("%w: could not find kid in JWT header", ErrKeyfunc)
}
kid, ok := kidInter.(string)
if !ok {
return nil, fmt.Errorf("%w: could not convert kid in JWT header to string", ErrKeyfunc)
}
algInter, ok := token.Header["alg"]
if !ok {
return nil, fmt.Errorf("%w: could not find alg in JWT header", ErrKeyfunc)
}
alg, ok := algInter.(string)
if !ok {
// For test coverage purposes, this should be impossible to reach because the JWT package rejects a token
// without an alg parameter in the header before calling jwt.Keyfunc.
return nil, fmt.Errorf(`%w: the JWT header did not contain the "alg" parameter, which is required by RFC 7515 section 4.1.1`, ErrKeyfunc)
}

jwk, err := k.storage.KeyRead(k.ctx, kid)
if err != nil {
return nil, fmt.Errorf("%w: could not read JWK from storage", errors.Join(err, ErrKeyfunc))
}
jwk, err := k.storage.KeyRead(ctx, kid)
if err != nil {
return nil, fmt.Errorf("%w: could not read JWK from storage", errors.Join(err, ErrKeyfunc))
}

if a := jwk.Marshal().ALG.String(); a != "" && a != alg {
return nil, fmt.Errorf(`%w: JWK "alg" parameter value %q does not match token "alg" parameter value %q`, ErrKeyfunc, a, alg)
}
if len(k.useWhitelist) > 0 {
found := false
for _, u := range k.useWhitelist {
if jwk.Marshal().USE == u {
found = true
break
if a := jwk.Marshal().ALG.String(); a != "" && a != alg {
return nil, fmt.Errorf(`%w: JWK "alg" parameter value %q does not match token "alg" parameter value %q`, ErrKeyfunc, a, alg)
}
if len(k.useWhitelist) > 0 {
found := false
for _, u := range k.useWhitelist {
if jwk.Marshal().USE == u {
found = true
break
}
}
if !found {
return nil, fmt.Errorf(`%w: JWK "use" parameter value %q is not in whitelist`, ErrKeyfunc, jwk.Marshal().USE)
}
}
if !found {
return nil, fmt.Errorf(`%w: JWK "use" parameter value %q is not in whitelist`, ErrKeyfunc, jwk.Marshal().USE)

type publicKeyer interface {
Public() crypto.PublicKey
}
}

type publicKeyer interface {
Public() crypto.PublicKey
}
key := jwk.Key()
pk, ok := key.(publicKeyer)
if ok {
key = pk.Public()
}

key := jwk.Key()
pk, ok := key.(publicKeyer)
if ok {
key = pk.Public()
return key, nil
}

return key, nil
}
func (k keyfunc) Keyfunc(token *jwt.Token) (any, error) {
keyF := k.KeyfuncCtx(k.ctx)
return keyF(token)
}
func (k keyfunc) Storage() jwkset.Storage {
return k.storage