Skip to content

Commit

Permalink
Merge pull request #84 from MicahParks/v2-release-candidate
Browse files Browse the repository at this point in the history
V2 release
  • Loading branch information
MicahParks authored Apr 19, 2023
2 parents e2a23c9 + ffe9955 commit b63e165
Show file tree
Hide file tree
Showing 27 changed files with 93 additions and 141 deletions.
42 changes: 23 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/MicahParks/keyfunc)](https://goreportcard.com/report/github.com/MicahParks/keyfunc) [![Go Reference](https://pkg.go.dev/badge/github.com/MicahParks/keyfunc.svg)](https://pkg.go.dev/github.com/MicahParks/keyfunc)
[![Go Report Card](https://goreportcard.com/badge/github.com/MicahParks/keyfunc/v2)](https://goreportcard.com/report/github.com/MicahParks/keyfunc/v2) [![Go Reference](https://pkg.go.dev/badge/github.com/MicahParks/keyfunc/v2.svg)](https://pkg.go.dev/github.com/MicahParks/keyfunc/v2)

# keyfunc

The purpose of this package is to provide a
[`jwt.Keyfunc`](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#Keyfunc) for the
[github.com/golang-jwt/jwt/v4](https://github.com/golang-jwt/jwt) package using a JSON Web Key Set (JWK Set or JWKS) for
[`jwt.Keyfunc`](https://pkg.go.dev/github.com/golang-jwt/jwt/v5#Keyfunc) for the
[github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) package using a JSON Web Key Set (JWK Set or JWKS) for
parsing and verifying JSON Web Tokens (JWTs).

The last version to support `github.com/golang-jwt/jwt/v4`
is [`v1.9.0`](https://github.com/MicahParks/keyfunc/releases/tag/v1.9.0).

There is legacy support for `github.com/dgrijalva/jwt-go` and its popular forks. It's in a separate project to keep this
project minimal. If your use case supports a legacy fork, please
see: [github.com/MicahParks/compatibility-keyfunc](https://github.com/MicahParks/compatibility-keyfunc).
see: [github.com/MicahParks/compatibility-keyfunc](https://github.com/MicahParks/compatibility-keyfunc). If an updated
to `keyfunc` is needed for `github.com/golang-jwt/jwt/v4` users, it will be placed into this separate project.

It's common for an identity provider, such as [Keycloak](https://www.keycloak.org/)
or [Amazon Cognito (AWS)](https://aws.amazon.com/cognito/) to expose a JWKS via an HTTPS endpoint. This package has the
ability to consume that JWKS and produce a
[`jwt.Keyfunc`](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#Keyfunc). It is important that a JWKS endpoint is using
[`jwt.Keyfunc`](https://pkg.go.dev/github.com/golang-jwt/jwt/v5#Keyfunc). It is important that a JWKS endpoint is using
HTTPS to ensure the keys are from the correct trusted source.

This repository only depends on: [github.com/golang-jwt/jwt/v4](https://github.com/golang-jwt/jwt)
This repository only depends on: [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt)

`jwt.Keyfunc` signatures are imported from these, implemented, then exported as methods.

Expand Down Expand Up @@ -50,22 +54,22 @@ this Go package, please open an issue or pull request.
For complete examples, please see the `examples` directory.

```go
import "github.com/MicahParks/keyfunc"
import "github.com/MicahParks/keyfunc/v2"
```

#### A note on read-only keys

The [`JWKS.ReadOnlyKeys`](https://pkg.go.dev/github.com/MicahParks/keyfunc#JWKS.ReadOnlyKeys) method returns a read-only
The [`JWKS.ReadOnlyKeys`](https://pkg.go.dev/github.com/MicahParks/keyfunc/v2#JWKS.ReadOnlyKeys) method returns a read-only
copy of a `map[string]interface{}`. The key to this map is the key ID, `kid`, and the value is the cryptographic key.
This is a useful map for use of keys within a JWKS outside of `github.com/golang-jwt/jwt/v4`.
This is a useful map for use of keys within a JWKS outside of `github.com/golang-jwt/jwt/v5`.

The map itself is a copy. So it can be modified safely. However, the values are of type `interface{}`. If these values
are modified, it may cause undefined behavior.

### Preconditions: Acquire the JWKS URL, JSON, or gather cryptographic keys (given keys)

A JWKS URL is not required, one can be created directly from JSON with the
[`keyfunc.NewJSON`](https://pkg.go.dev/github.com/MicahParks/keyfunc#NewJSON) function.
[`keyfunc.NewJSON`](https://pkg.go.dev/github.com/MicahParks/keyfunc/v2#NewJSON) function.

```go
// Get the JWKS URL from an environment variable.
Expand Down Expand Up @@ -115,11 +119,11 @@ jwks := keyfunc.NewGiven(map[string]keyfunc.GivenKey{
})
```

Additional options can be passed to the [`keyfunc.Get`](https://pkg.go.dev/github.com/golang-jwt/jwt/v4/keyfunc#Get)
function. See [`keyfunc.Options`](https://pkg.go.dev/github.com/golang-jwt/jwt/v4/keyfunc#Options) and the additional
Additional options can be passed to the [`keyfunc.Get`](https://pkg.go.dev/github.com/golang-jwt/jwt/v5/keyfunc#Get)
function. See [`keyfunc.Options`](https://pkg.go.dev/github.com/golang-jwt/jwt/v5/keyfunc#Options) and the additional
features mentioned at the bottom of this `README.md`.

### Step 2: Use the [`JWKS.Keyfunc`](https://pkg.go.dev/github.com/golang-jwt/jwt/v4/keyfunc#JWKS.Keyfunc) method as the [`jwt.Keyfunc`](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#Keyfunc) when parsing tokens
### Step 2: Use the [`JWKS.Keyfunc`](https://pkg.go.dev/github.com/golang-jwt/jwt/v5/keyfunc#JWKS.Keyfunc) method as the [`jwt.Keyfunc`](https://pkg.go.dev/github.com/golang-jwt/jwt/v5#Keyfunc) when parsing tokens

```go
// Parse the JWT.
Expand All @@ -129,7 +133,7 @@ if err != nil {
}
```

The [`JWKS.Keyfunc`](https://pkg.go.dev/github.com/MicahParks/keyfunc#JWKS.Keyfunc) method will automatically select the
The [`JWKS.Keyfunc`](https://pkg.go.dev/github.com/MicahParks/keyfunc/v2#JWKS.Keyfunc) method will automatically select the
key with the matching `kid` (if present) and return its public key as the correct Go type to its caller.

## Test coverage
Expand All @@ -143,8 +147,8 @@ coded JWTs cannot check for parsing and validation errors, just errors within th
## Additional features

These features can be configured by populating fields in the
[`keyfunc.Options`](https://pkg.go.dev/github.com/MicahParks/keyfunc#Options) argument to the
[`keyfunc.Get`](https://pkg.go.dev/github.com/MicahParks/keyfunc#Get) function.
[`keyfunc.Options`](https://pkg.go.dev/github.com/MicahParks/keyfunc/v2#Options) argument to the
[`keyfunc.Get`](https://pkg.go.dev/github.com/MicahParks/keyfunc/v2#Get) function.

* A background refresh of the JWKS keys can be performed.
* A custom background refresh interval can be specified. For an example, please see the `examples/interval`
Expand All @@ -164,10 +168,10 @@ These features can be configured by populating fields in the
* A custom HTTP response extractor can be provided to get the raw JWKS JSON from the `*http.Response`. For example, the
HTTP response code could be checked. Implementations are responsible for closing the response body.
* By default,
the [`keyfunc.ResponseExtractorStatusOK`](https://pkg.go.dev/github.com/MicahParks/keyfunc#ResponseExtractorStatusOK)
the [`keyfunc.ResponseExtractorStatusOK`](https://pkg.go.dev/github.com/MicahParks/keyfunc/v2#ResponseExtractorStatusOK)
function is used. The default behavior changed in `v1.4.0`.
* A custom whitelist of acceptable JSON Web Key `"use"` parameter values can be specified. Values not whitelisted will
cause an error from the [`.Keyfunc`](https://pkg.go.dev/github.com/MicahParks/keyfunc#JWKS.Keyfunc) method. This
cause an error from the [`.Keyfunc`](https://pkg.go.dev/github.com/MicahParks/keyfunc/v2#JWKS.Keyfunc) method. This
whitelist can be disabled with the `JWKUseNoWhitelist` option.
* By default, only JSON Web Keys with a `"use"` parameter value of `"sig"`, an empty string `""`, or a completely
omitted `"use"` parameter will be returned. The default behavior changed in `v1.5.0`.
Expand All @@ -178,7 +182,7 @@ These features can be configured by populating fields in the
the `examples/given` directory.
* A copy of the latest raw JWKS `[]byte` can be returned.
* Custom cryptographic algorithms can be used. Make sure to
use [`jwt.RegisterSigningMethod`](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#RegisterSigningMethod) before
use [`jwt.RegisterSigningMethod`](https://pkg.go.dev/github.com/golang-jwt/jwt/v5#RegisterSigningMethod) before
parsing JWTs. For an example, see the `examples/custom` directory.
* The remote JWKS resource can be refreshed manually using the `.Refresh` method. This can bypass the rate limit, if the
option is set.
Expand Down
4 changes: 2 additions & 2 deletions alg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"errors"
"testing"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func TestAlgMismatch(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions checksum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"reflect"
"testing"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

// TestChecksum confirms that the JWKS will only perform a refresh if a new JWKS is read from the remote resource.
Expand Down
4 changes: 2 additions & 2 deletions ecdsa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"errors"
"testing"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func TestBadCurve(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions examples/aws_cognito/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"log"
"time"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func main() {
Expand Down
4 changes: 2 additions & 2 deletions examples/ctx/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"log"
"time"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func main() {
Expand Down
8 changes: 4 additions & 4 deletions examples/custom/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package main
import (
"log"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/examples/custom/method"
"github.com/MicahParks/keyfunc/v2"
"github.com/MicahParks/keyfunc/v2/examples/custom/method"
)

func main() {
Expand All @@ -29,7 +29,7 @@ func main() {

// Create the JWKS from the given signing method's key.
jwks := keyfunc.NewGiven(map[string]keyfunc.GivenKey{
exampleKID: keyfunc.NewGivenCustomWithOptions(key, keyfunc.GivenKeyOptions{
exampleKID: keyfunc.NewGivenCustom(key, keyfunc.GivenKeyOptions{
Algorithm: method.CustomAlgHeader,
}),
})
Expand Down
6 changes: 3 additions & 3 deletions examples/custom/method/method.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ const CustomAlgHeader = "customalg"
type EmptyCustom struct{}

// Verify helps implement the jwt.SigningMethod interface. It does not verify.
func (e EmptyCustom) Verify(_, _ string, _ interface{}) error {
func (e EmptyCustom) Verify(_ string, _ []byte, _ interface{}) error {
return nil
}

// Sign helps implement the jwt.SigningMethod interface. It does not sign anything.
func (e EmptyCustom) Sign(_ string, _ interface{}) (string, error) {
return CustomAlgHeader, nil
func (e EmptyCustom) Sign(_ string, _ interface{}) ([]byte, error) {
return []byte{}, nil
}

// Alg helps implement the jwt.SigningMethod. It returns the `alg` JSON attribute for JWTs signed with this method.
Expand Down
6 changes: 3 additions & 3 deletions examples/given/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"log"
"time"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func main() {
Expand All @@ -23,7 +23,7 @@ func main() {
hmacSecret := []byte("example secret")
const givenKID = "givenKID"
givenKeys := map[string]keyfunc.GivenKey{
givenKID: keyfunc.NewGivenHMACCustomWithOptions(hmacSecret, keyfunc.GivenKeyOptions{
givenKID: keyfunc.NewGivenHMAC(hmacSecret, keyfunc.GivenKeyOptions{
Algorithm: jwt.SigningMethodHS256.Alg(),
}),
}
Expand Down
6 changes: 3 additions & 3 deletions examples/hmac/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package main
import (
"log"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func main() {
Expand All @@ -23,7 +23,7 @@ func main() {

// Create the JWKS from the HMAC key.
jwks := keyfunc.NewGiven(map[string]keyfunc.GivenKey{
exampleKID: keyfunc.NewGivenHMACCustomWithOptions(key, keyfunc.GivenKeyOptions{
exampleKID: keyfunc.NewGivenHMAC(key, keyfunc.GivenKeyOptions{
Algorithm: jwt.SigningMethodHS512.Alg(),
}),
})
Expand Down
4 changes: 2 additions & 2 deletions examples/interval/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"log"
"time"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func main() {
Expand Down
4 changes: 2 additions & 2 deletions examples/json/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"encoding/json"
"log"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func main() {
Expand Down
4 changes: 2 additions & 2 deletions examples/keycloak/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"log"
"time"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func main() {
Expand Down
4 changes: 2 additions & 2 deletions examples/recommended_options/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"log"
"time"

"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v5"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func main() {
Expand Down
2 changes: 1 addition & 1 deletion get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"testing"
"time"

"github.com/MicahParks/keyfunc"
"github.com/MicahParks/keyfunc/v2"
)

func TestJWKS_Refresh(t *testing.T) {
Expand Down
Loading

0 comments on commit b63e165

Please sign in to comment.