From dd3921fe5c35c70d5e856016ca30dfa9c0222ad3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:13:41 +0000 Subject: [PATCH 1/5] Bump golangci/golangci-lint-action from 6.1.0 to 6.1.1 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.1.0 to 6.1.1. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/aaa42aa0628b4ae2578232a66b541047968fac86...971e284b6050e8a5849b72094c50ab08da042db8) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index eddeb00..d53cd47 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -22,7 +22,7 @@ jobs: check-latest: true - name: golangci-lint - uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # pin@6.1.0 + uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # pin@6.1.1 with: args: -v --timeout=5m skip-build-cache: true From 5f6c6c54957e8eda992ae18b799beda4183eb1ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 14:14:12 +0000 Subject: [PATCH 2/5] Bump Templum/govulncheck-action from 1.0.0 to 1.0.1 Bumps [Templum/govulncheck-action](https://github.com/templum/govulncheck-action) from 1.0.0 to 1.0.1. - [Release notes](https://github.com/templum/govulncheck-action/releases) - [Commits](https://github.com/templum/govulncheck-action/compare/6bb063b41d78c53c2fc7f5589828e30ad7c697ee...0d775f4f6ef4a13921a2996a136cfe6d0e1faee7) --- updated-dependencies: - dependency-name: Templum/govulncheck-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/govulncheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml index f8a790b..97a73b3 100644 --- a/.github/workflows/govulncheck.yml +++ b/.github/workflows/govulncheck.yml @@ -18,7 +18,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha || github.ref }} - name: Scan for Vulnerabilities in Code - uses: Templum/govulncheck-action@6bb063b41d78c53c2fc7f5589828e30ad7c697ee # pin@1.0.0 + uses: Templum/govulncheck-action@0d775f4f6ef4a13921a2996a136cfe6d0e1faee7 # pin@1.0.1 with: go-version: 1.21 package: ./... From 96b88ced6626eb8b0f1423e8ef988b9af6d8ab1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2024 14:03:52 +0000 Subject: [PATCH 3/5] Bump golang.org/x/sync from 0.8.0 to 0.9.0 Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.8.0 to 0.9.0. - [Commits](https://github.com/golang/sync/compare/v0.8.0...v0.9.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7056740..8f0f327 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/google/go-cmp v0.6.0 github.com/stretchr/testify v1.9.0 - golang.org/x/sync v0.8.0 + golang.org/x/sync v0.9.0 gopkg.in/go-jose/go-jose.v2 v2.6.3 ) diff --git a/go.sum b/go.sum index 369d9ac..1e5a7e4 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= From aaca9f1b7ed30ec9ec3bfec017662bfd474b33ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 07:32:43 +0000 Subject: [PATCH 4/5] Bump Templum/govulncheck-action from 1.0.0 to 1.0.1 Bumps [Templum/govulncheck-action](https://github.com/templum/govulncheck-action) from 1.0.0 to 1.0.1. - [Release notes](https://github.com/templum/govulncheck-action/releases) - [Commits](https://github.com/templum/govulncheck-action/compare/6bb063b41d78c53c2fc7f5589828e30ad7c697ee...0d775f4f6ef4a13921a2996a136cfe6d0e1faee7) --- updated-dependencies: - dependency-name: Templum/govulncheck-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/govulncheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml index f8a790b..97a73b3 100644 --- a/.github/workflows/govulncheck.yml +++ b/.github/workflows/govulncheck.yml @@ -18,7 +18,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha || github.ref }} - name: Scan for Vulnerabilities in Code - uses: Templum/govulncheck-action@6bb063b41d78c53c2fc7f5589828e30ad7c697ee # pin@1.0.0 + uses: Templum/govulncheck-action@0d775f4f6ef4a13921a2996a136cfe6d0e1faee7 # pin@1.0.1 with: go-version: 1.21 package: ./... From 24d743eb0952df50150fdbaafd45cdfbefba26a2 Mon Sep 17 00:00:00 2001 From: Chris Moran Date: Wed, 3 Jul 2024 07:21:42 -0400 Subject: [PATCH 5/5] feat: support multiple issuer:audience combinations by introducing an option for the expectedClaims. WithExpectedClaims can be called with multiple jwt.Expected parameters to allow different Issuer:Audience combinations to validate tokens feat: support multiple issuers in a provider using WithAdditionalIssuers option Every effort has been made to ensure backwards compatibility. Some error messages will be different due to the wrapping of errors when multiple jwt.Expected are set. When validating the jwt, if an error is encountered, instead of returning immediately, the current error is wrapped. This is good and bad. Good because all verification failure causes are captured in a single wrapped error; Bad because all verification failure causes are captured in a single monolithic wrapped error. Unwrapping the error can be tedious if many jwt.Expected are included. There is likely a better way but this suits my purposes. A few more test cases will likely be needed in order to achieve true confidence in this change --- README.md | 1 - examples/echo-example/README.md | 1 + examples/echo-example/go.mod | 16 +- examples/echo-example/go.sum | 49 ++-- examples/echo-example/main.go | 8 +- examples/echo-example/middleware.go | 2 +- examples/gin-example/README.md | 1 + examples/gin-example/go.mod | 39 +-- examples/gin-example/go.sum | 93 +++--- examples/gin-example/main.go | 62 +++- examples/gin-example/middleware.go | 56 +++- examples/http-example/README.md | 1 + examples/http-example/go.mod | 2 +- examples/http-example/go.sum | 4 +- examples/http-example/main.go | 13 +- examples/http-example/main_test.go | 6 +- examples/http-jwks-example/go.mod | 4 +- examples/http-jwks-example/go.sum | 8 +- examples/http-jwks-example/main.go | 3 +- examples/http-jwks-example/main_test.go | 6 +- examples/iris-example/README.md | 1 + examples/iris-example/go.mod | 48 ++-- examples/iris-example/go.sum | 111 ++++---- examples/iris-example/main.go | 8 +- examples/iris-example/middleware.go | 2 +- extractor.go | 4 +- extractor_test.go | 2 +- go.mod | 2 +- go.sum | 4 +- jwks/provider.go | 63 ++++- jwks/provider_test.go | 2 +- middleware_test.go | 5 +- validator/option.go | 14 + validator/validator.go | 178 +++++++++--- validator/validator_test.go | 359 ++++++++++++++++++++++-- 35 files changed, 870 insertions(+), 308 deletions(-) diff --git a/README.md b/README.md index fbbb7b1..72f2067 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,6 @@ import ( "log" "net/http" - "github.com/auth0/go-jwt-middleware/v2" "github.com/auth0/go-jwt-middleware/v2/validator" jwtmiddleware "github.com/auth0/go-jwt-middleware/v2" ) diff --git a/examples/echo-example/README.md b/examples/echo-example/README.md index 8822ef6..6e455ea 100644 --- a/examples/echo-example/README.md +++ b/examples/echo-example/README.md @@ -10,3 +10,4 @@ To try this out: * Run `go run .` to start the app. * Use [jwt.io](https://jwt.io/) to generate a JWT signed with the HS256 algorithm and `secret`. * Call `http://localhost:3000` with the JWT to get a response back. +* see `main.go` for example tokens diff --git a/examples/echo-example/go.mod b/examples/echo-example/go.mod index 8cd76ba..3c1aecb 100644 --- a/examples/echo-example/go.mod +++ b/examples/echo-example/go.mod @@ -4,20 +4,20 @@ go 1.23 require ( github.com/auth0/go-jwt-middleware/v2 v2.1.0 - github.com/labstack/echo/v4 v4.11.2 + github.com/labstack/echo/v4 v4.13.3 ) replace github.com/auth0/go-jwt-middleware/v2 => ./../../ require ( - github.com/labstack/gommon v0.4.0 // indirect + github.com/go-jose/go-jose/v4 v4.0.4 // indirect + github.com/labstack/gommon v0.4.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect ) diff --git a/examples/echo-example/go.sum b/examples/echo-example/go.sum index ef4b291..cb1be82 100644 --- a/examples/echo-example/go.sum +++ b/examples/echo-example/go.sum @@ -1,44 +1,35 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/labstack/echo/v4 v4.11.2 h1:T+cTLQxWCDfqDEoydYm5kCobjmHwOwcv4OJAPHilmdE= -github.com/labstack/echo/v4 v4.11.2/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws= -github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= -github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= +github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g= +github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= -gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/echo-example/main.go b/examples/echo-example/main.go index 59b0fb7..1d8a4f5 100644 --- a/examples/echo-example/main.go +++ b/examples/echo-example/main.go @@ -11,9 +11,9 @@ import ( // Try it out with: // -// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyJ9.XFhrzWzntyINkgoRt2mb8dES84dJcuOoORdzKfwUX70 +// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyJ9.DSY4NlpZZ2mOqaKuXvJkOrgZA3nD5HuGaf1wB9-0OVw // -// which is signed with 'secret' and has the data: +// which is signed with 'abcdefghijklmnopqrstuvwxyz012345' and has the data: // // { // "iss": "go-jwt-middleware-example", @@ -26,9 +26,9 @@ import ( // // You can also try out the custom validation with: // -// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyIsInNob3VsZFJlamVjdCI6dHJ1ZX0.Jf13PY_Oyu2x3Gx1JQ0jXRiWaCOb5T2RbKOrTPBNHJA +// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyIsInNob3VsZFJlamVjdCI6dHJ1ZX0.qjjJBgKNomlbEQrCobpEU9ASgvSpLQhQBryRkp6-RQc // -// which is signed with 'secret' and has the data: +// which is signed with 'abcdefghijklmnopqrstuvwxyz012345' and has the data: // // { // "iss": "go-jwt-middleware-example", diff --git a/examples/echo-example/middleware.go b/examples/echo-example/middleware.go index d81d518..1427292 100644 --- a/examples/echo-example/middleware.go +++ b/examples/echo-example/middleware.go @@ -13,7 +13,7 @@ import ( var ( // The signing key for the token. - signingKey = []byte("secret") + signingKey = []byte("abcdefghijklmnopqrstuvwxyz012345") // The issuer of our token. issuer = "go-jwt-middleware-example" diff --git a/examples/gin-example/README.md b/examples/gin-example/README.md index 927b718..6c0be1f 100644 --- a/examples/gin-example/README.md +++ b/examples/gin-example/README.md @@ -10,3 +10,4 @@ To try this out: * Run `go run .` to start the app. * Use [jwt.io](https://jwt.io/) to generate a JWT signed with the HS256 algorithm and `secret`. * Call `http://localhost:3000` with the JWT to get a response back. +* see `main.go` for example tokens diff --git a/examples/gin-example/go.mod b/examples/gin-example/go.mod index 07ce463..36ac75a 100644 --- a/examples/gin-example/go.mod +++ b/examples/gin-example/go.mod @@ -4,36 +4,37 @@ go 1.23 require ( github.com/auth0/go-jwt-middleware/v2 v2.1.0 - github.com/gin-gonic/gin v1.9.1 + github.com/gin-gonic/gin v1.10.0 + github.com/go-jose/go-jose/v4 v4.0.4 ) replace github.com/auth0/go-jwt-middleware/v2 => ./../../ require ( - github.com/bytedance/sonic v1.10.2 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect - github.com/chenzhuoyu/iasm v0.9.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/bytedance/sonic v1.12.6 // indirect + github.com/bytedance/sonic/loader v0.2.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.7 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.15.5 // indirect - github.com/goccy/go-json v0.10.2 // indirect + github.com/go-playground/validator/v10 v10.23.0 // indirect + github.com/goccy/go-json v0.10.4 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect - github.com/leodido/go-urn v1.2.4 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/klauspost/cpuid/v2 v2.2.9 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.11 // indirect - golang.org/x/arch v0.5.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect - gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.12.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/protobuf v1.36.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/gin-example/go.sum b/examples/gin-example/go.sum index 0c20519..cea32b4 100644 --- a/examples/gin-example/go.sum +++ b/examples/gin-example/go.sum @@ -1,50 +1,53 @@ -github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= -github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= -github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= -github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= -github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo= -github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= +github.com/bytedance/sonic v1.12.6 h1:/isNmCUF2x3Sh8RAp/4mh4ZGkcFAX/hLrzrK3AvpRzk= +github.com/bytedance/sonic v1.12.6/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.1 h1:1GgorWTqf12TA8mma4DDSbaQigE2wOgQo7iCjjJv3+E= +github.com/bytedance/sonic/loader v0.2.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gabriel-vasile/mimetype v1.4.7 h1:SKFKl7kD0RiPdbht0s7hFtjl489WcQ1VyPW8ZzUMYCA= +github.com/gabriel-vasile/mimetype v1.4.7/go.mod h1:GDlAgAyIRT27BhFl53XNAFtfjzOkLaF35JdEG0P7LtU= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= -github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o= +github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= +github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= +github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -55,34 +58,28 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= -github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y= -golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg= +golang.org/x/arch v0.12.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ= +google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= -gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/examples/gin-example/main.go b/examples/gin-example/main.go index 03cc34e..7547eb0 100644 --- a/examples/gin-example/main.go +++ b/examples/gin-example/main.go @@ -11,9 +11,9 @@ import ( // Try it out with: // -// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyJ9.XFhrzWzntyINkgoRt2mb8dES84dJcuOoORdzKfwUX70 +// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyJ9.DSY4NlpZZ2mOqaKuXvJkOrgZA3nD5HuGaf1wB9-0OVw // -// which is signed with 'secret' and has the data: +// which is signed with 'abcdefghijklmnopqrstuvwxyz012345' and has the data: // // { // "iss": "go-jwt-middleware-example", @@ -26,9 +26,9 @@ import ( // // You can also try out the custom validation with: // -// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyIsInNob3VsZFJlamVjdCI6dHJ1ZX0.Jf13PY_Oyu2x3Gx1JQ0jXRiWaCOb5T2RbKOrTPBNHJA +// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyIsInNob3VsZFJlamVjdCI6dHJ1ZX0.qjjJBgKNomlbEQrCobpEU9ASgvSpLQhQBryRkp6-RQc // -// which is signed with 'secret' and has the data: +// which is signed with 'abcdefghijklmnopqrstuvwxyz012345' and has the data: // // { // "iss": "go-jwt-middleware-example", @@ -39,9 +39,29 @@ import ( // "username": "user123", // "shouldReject": true // } +// +// You can also try out the /multiple endpoint. This endpoint accepts tokens signed by multiple issuers. Try the +// token below which has a different issuer: +// +// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1tdWx0aXBsZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtbXVsdGlwbGUtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyJ9.d0BmhdqVZ9IdqQNId3XI2kbTegwW5NYe9P4xQCOjQ1Y +// +// which is signed with 'abcdefghijklmnopqrstuvwxyz012345' and has the data: +// +// { +// "iss": "go-jwt-middleware-multiple-example", +// "aud": "audience-multiple-example", +// "sub": "1234567890", +// "name": "John Doe", +// "iat": 1516239022, +// "username": "user123" +// } +// +// You can also try the previous tokens with the /multiple endpoint. The first token will be valid the second will fail because +// the custom validator rejects it (shouldReject: true) func main() { router := gin.Default() + router.GET("/", checkJWT(), func(ctx *gin.Context) { claims, ok := ctx.Request.Context().Value(jwtmiddleware.ContextKey{}).(*validator.ValidatedClaims) if !ok { @@ -52,7 +72,37 @@ func main() { return } - customClaims, ok := claims.CustomClaims.(*CustomClaimsExample) + localCustomClaims, ok := claims.CustomClaims.(*CustomClaimsExample) + if !ok { + ctx.AbortWithStatusJSON( + http.StatusInternalServerError, + map[string]string{"message": "Failed to cast custom JWT claims to specific type."}, + ) + return + } + + if len(localCustomClaims.Username) == 0 { + ctx.AbortWithStatusJSON( + http.StatusBadRequest, + map[string]string{"message": "Username in JWT claims was empty."}, + ) + return + } + + ctx.JSON(http.StatusOK, claims) + }) + + router.GET("/multiple", checkJWTMultiple(), func(ctx *gin.Context) { + claims, ok := ctx.Request.Context().Value(jwtmiddleware.ContextKey{}).(*validator.ValidatedClaims) + if !ok { + ctx.AbortWithStatusJSON( + http.StatusInternalServerError, + map[string]string{"message": "Failed to get validated JWT claims."}, + ) + return + } + + localCustomClaims, ok := claims.CustomClaims.(*CustomClaimsExample) if !ok { ctx.AbortWithStatusJSON( http.StatusInternalServerError, @@ -61,7 +111,7 @@ func main() { return } - if len(customClaims.Username) == 0 { + if len(localCustomClaims.Username) == 0 { ctx.AbortWithStatusJSON( http.StatusBadRequest, map[string]string{"message": "Username in JWT claims was empty."}, diff --git a/examples/gin-example/middleware.go b/examples/gin-example/middleware.go index 104cd07..8ea4cf5 100644 --- a/examples/gin-example/middleware.go +++ b/examples/gin-example/middleware.go @@ -2,6 +2,7 @@ package main import ( "context" + "github.com/go-jose/go-jose/v4/jwt" "log" "net/http" "time" @@ -13,13 +14,15 @@ import ( var ( // The signing key for the token. - signingKey = []byte("secret") + signingKey = []byte("abcdefghijklmnopqrstuvwxyz012345") // The issuer of our token. - issuer = "go-jwt-middleware-example" + issuer = "go-jwt-middleware-example" + issuerTwo = "go-jwt-middleware-multiple-example" // The audience of our token. - audience = []string{"audience-example"} + audience = []string{"audience-example"} + audienceTwo = []string{"audience-multiple-example"} // Our token must be signed using this data. keyFunc = func(ctx context.Context) (interface{}, error) { @@ -76,3 +79,50 @@ func checkJWT() gin.HandlerFunc { } } } + +func checkJWTMultiple() gin.HandlerFunc { + // Set up the validator. + jwtValidator, err := validator.NewValidator( + keyFunc, + validator.HS256, + validator.WithCustomClaims(customClaims), + validator.WithAllowedClockSkew(30*time.Second), + validator.WithExpectedClaims(jwt.Expected{ + Issuer: issuer, + AnyAudience: audience, + }, jwt.Expected{ + Issuer: issuerTwo, + AnyAudience: audienceTwo, + }), + ) + if err != nil { + log.Fatalf("failed to set up the validator: %v", err) + } + + errorHandler := func(w http.ResponseWriter, r *http.Request, err error) { + log.Printf("Encountered error while validating JWT: %v", err) + } + + middleware := jwtmiddleware.New( + jwtValidator.ValidateToken, + jwtmiddleware.WithErrorHandler(errorHandler), + ) + + return func(ctx *gin.Context) { + encounteredError := true + var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { + encounteredError = false + ctx.Request = r + ctx.Next() + } + + middleware.CheckJWT(handler).ServeHTTP(ctx.Writer, ctx.Request) + + if encounteredError { + ctx.AbortWithStatusJSON( + http.StatusUnauthorized, + map[string]string{"message": "JWT is invalid."}, + ) + } + } +} diff --git a/examples/http-example/README.md b/examples/http-example/README.md index c382f48..feb8d2d 100644 --- a/examples/http-example/README.md +++ b/examples/http-example/README.md @@ -10,3 +10,4 @@ To try this out: * Run `go run main.go` to start the app. * Use [jwt.io](https://jwt.io/) to generate a JWT signed with the HS256 algorithm and `secret`. * Call `http://localhost:3000` with the JWT to get a response back. +* see `main.go` for example tokens diff --git a/examples/http-example/go.mod b/examples/http-example/go.mod index 1d95e94..a46be07 100644 --- a/examples/http-example/go.mod +++ b/examples/http-example/go.mod @@ -4,7 +4,7 @@ go 1.23 require ( github.com/auth0/go-jwt-middleware/v2 v2.1.0 - gopkg.in/go-jose/go-jose.v2 v2.6.3 + github.com/go-jose/go-jose/v4 v4.0.4 ) replace github.com/auth0/go-jwt-middleware/v2 => ./../../ diff --git a/examples/http-example/go.sum b/examples/http-example/go.sum index 0a4664e..9284a99 100644 --- a/examples/http-example/go.sum +++ b/examples/http-example/go.sum @@ -1,5 +1,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -8,7 +10,5 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= -gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/http-example/main.go b/examples/http-example/main.go index b7ad5eb..5cc8e89 100644 --- a/examples/http-example/main.go +++ b/examples/http-example/main.go @@ -8,13 +8,12 @@ import ( "net/http" "time" - "github.com/auth0/go-jwt-middleware/v2" - "github.com/auth0/go-jwt-middleware/v2/validator" jwtmiddleware "github.com/auth0/go-jwt-middleware/v2" + "github.com/auth0/go-jwt-middleware/v2/validator" ) var ( - signingKey = []byte("secret") + signingKey = []byte("abcdefghijklmnopqrstuvwxyz012345") issuer = "go-jwt-middleware-example" audience = []string{"audience-example"} ) @@ -94,9 +93,9 @@ func main() { // Try it out with: // - // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyJ9.XFhrzWzntyINkgoRt2mb8dES84dJcuOoORdzKfwUX70 + // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyJ9.DSY4NlpZZ2mOqaKuXvJkOrgZA3nD5HuGaf1wB9-0OVw // - // which is signed with 'secret' and has the data: + // which is signed with 'abcdefghijklmnopqrstuvwxyz012345' and has the data: // { // "iss": "go-jwt-middleware-example", // "aud": "audience-example", @@ -108,9 +107,9 @@ func main() { // // You can also try out the custom validation with: // - // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyIsInNob3VsZFJlamVjdCI6dHJ1ZX0.Jf13PY_Oyu2x3Gx1JQ0jXRiWaCOb5T2RbKOrTPBNHJA + // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyIsInNob3VsZFJlamVjdCI6dHJ1ZX0.qjjJBgKNomlbEQrCobpEU9ASgvSpLQhQBryRkp6-RQc // - // which is signed with 'secret' and has the data: + // which is signed with 'abcdefghijklmnopqrstuvwxyz012345' and has the data: // { // "iss": "go-jwt-middleware-example", // "aud": "audience-example", diff --git a/examples/http-example/main_test.go b/examples/http-example/main_test.go index 81ea91c..3ce6ca5 100644 --- a/examples/http-example/main_test.go +++ b/examples/http-example/main_test.go @@ -5,8 +5,8 @@ import ( "net/http/httptest" "testing" - "gopkg.in/go-jose/go-jose.v2" - "gopkg.in/go-jose/go-jose.v2/jwt" + "github.com/go-jose/go-jose/v4" + "github.com/go-jose/go-jose/v4/jwt" ) func TestHandler(t *testing.T) { @@ -70,7 +70,7 @@ func buildJWTForTesting(t *testing.T, username string) string { Username: username, } - token, err := jwt.Signed(signer).Claims(claims).Claims(customClaims).CompactSerialize() + token, err := jwt.Signed(signer).Claims(claims).Claims(customClaims).Serialize() if err != nil { t.Fatalf("could not build token: %s", err.Error()) } diff --git a/examples/http-jwks-example/go.mod b/examples/http-jwks-example/go.mod index 2f0cd0a..865cf28 100644 --- a/examples/http-jwks-example/go.mod +++ b/examples/http-jwks-example/go.mod @@ -4,12 +4,12 @@ go 1.23 require ( github.com/auth0/go-jwt-middleware/v2 v2.1.0 - gopkg.in/go-jose/go-jose.v2 v2.6.3 + github.com/go-jose/go-jose/v4 v4.0.4 ) replace github.com/auth0/go-jwt-middleware/v2 => ./../../ require ( golang.org/x/crypto v0.31.0 // indirect - golang.org/x/sync v0.8.0 // indirect + golang.org/x/sync v0.10.0 // indirect ) diff --git a/examples/http-jwks-example/go.sum b/examples/http-jwks-example/go.sum index e525849..ec219b4 100644 --- a/examples/http-jwks-example/go.sum +++ b/examples/http-jwks-example/go.sum @@ -1,5 +1,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -8,9 +10,7 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= -gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/http-jwks-example/main.go b/examples/http-jwks-example/main.go index 81776dc..93ee144 100644 --- a/examples/http-jwks-example/main.go +++ b/examples/http-jwks-example/main.go @@ -7,10 +7,9 @@ import ( "net/url" "time" - "github.com/auth0/go-jwt-middleware/v2" + jwtmiddleware "github.com/auth0/go-jwt-middleware/v2" "github.com/auth0/go-jwt-middleware/v2/jwks" "github.com/auth0/go-jwt-middleware/v2/validator" - jwtmiddleware "github.com/auth0/go-jwt-middleware/v2" ) var handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/examples/http-jwks-example/main_test.go b/examples/http-jwks-example/main_test.go index 74d387d..9fa0db9 100644 --- a/examples/http-jwks-example/main_test.go +++ b/examples/http-jwks-example/main_test.go @@ -8,8 +8,8 @@ import ( "net/http/httptest" "testing" - "gopkg.in/go-jose/go-jose.v2" - "gopkg.in/go-jose/go-jose.v2/jwt" + "github.com/go-jose/go-jose/v4" + "github.com/go-jose/go-jose/v4/jwt" ) func TestHandler(t *testing.T) { @@ -120,7 +120,7 @@ func buildJWTForTesting(t *testing.T, jwk *jose.JSONWebKey, issuer, subject stri Subject: subject, } - token, err := jwt.Signed(signer).Claims(claims).CompactSerialize() + token, err := jwt.Signed(signer).Claims(claims).Serialize() if err != nil { t.Fatalf("could not build token: %s", err.Error()) } diff --git a/examples/iris-example/README.md b/examples/iris-example/README.md index 37ec0bd..e5e8472 100644 --- a/examples/iris-example/README.md +++ b/examples/iris-example/README.md @@ -10,3 +10,4 @@ To try this out: * Run `go run .` to start the app. * Use [jwt.io](https://jwt.io/) to generate a JWT signed with the HS256 algorithm and `secret`. * Call `http://localhost:3000` with the JWT to get a response back. +* see `main.go` for example tokens diff --git a/examples/iris-example/go.mod b/examples/iris-example/go.mod index ed2caed..86d2b85 100644 --- a/examples/iris-example/go.mod +++ b/examples/iris-example/go.mod @@ -4,53 +4,53 @@ go 1.23 require ( github.com/auth0/go-jwt-middleware/v2 v2.1.0 - github.com/kataras/iris/v12 v12.2.7 + github.com/kataras/iris/v12 v12.2.11 ) replace github.com/auth0/go-jwt-middleware/v2 => ./../../ require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect github.com/CloudyKit/jet/v6 v6.2.0 // indirect github.com/Joker/jade v1.1.3 // indirect - github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect - github.com/andybalholm/brotli v1.0.5 // indirect + github.com/Shopify/goreferrer v0.0.0-20240724165105-aceaa0259138 // indirect + github.com/andybalholm/brotli v1.1.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 // indirect - github.com/google/uuid v1.3.1 // indirect - github.com/gorilla/css v1.0.0 // indirect + github.com/gomarkdown/markdown v0.0.0-20241205020045-f7e15b2f3e62 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.1 // indirect github.com/iris-contrib/schema v0.0.6 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/kataras/blocks v0.0.8 // indirect - github.com/kataras/golog v0.1.9 // indirect - github.com/kataras/pio v0.0.12 // indirect + github.com/kataras/blocks v0.0.11 // indirect + github.com/kataras/golog v0.1.12 // indirect + github.com/kataras/pio v0.0.13 // indirect github.com/kataras/sitemap v0.0.6 // indirect github.com/kataras/tunnel v0.0.4 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/mailgun/raymond/v2 v2.0.48 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/mailru/easyjson v0.9.0 // indirect + github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/schollz/closestmatch v2.1.0+incompatible // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/tdewolff/minify/v2 v2.12.9 // indirect - github.com/tdewolff/parse/v2 v2.6.8 // indirect + github.com/tdewolff/minify/v2 v2.21.2 // indirect + github.com/tdewolff/parse/v2 v2.7.19 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/yosssi/ace v0.0.5 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.3.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect - gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/time v0.8.0 // indirect + google.golang.org/protobuf v1.36.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/iris-example/go.sum b/examples/iris-example/go.sum index b1b179b..a14c561 100644 --- a/examples/iris-example/go.sum +++ b/examples/iris-example/go.sum @@ -1,5 +1,5 @@ -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= @@ -8,12 +8,12 @@ github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= -github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= -github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/Shopify/goreferrer v0.0.0-20240724165105-aceaa0259138 h1:gjbp60h8IZQbN/TpDaYJedWbbD1h1aDPEwWnYWaDaUY= +github.com/Shopify/goreferrer v0.0.0-20240724165105-aceaa0259138/go.mod h1:NYezi6wtnJtBm5btoprXc5SvAdqH0XTXWnUup0MptAI= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= -github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= +github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -25,22 +25,24 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 h1:EcQR3gusLHN46TAD+G+EbaaqJArt5vHhNpXAa12PQf4= -github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/gomarkdown/markdown v0.0.0-20241205020045-f7e15b2f3e62 h1:pbAFUZisjG4s6sxvRJvf2N7vhpCvx2Oxb3PmS6pDO1g= +github.com/gomarkdown/markdown v0.0.0-20241205020045-f7e15b2f3e62/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= -github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= +github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= @@ -49,33 +51,33 @@ github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvP github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= -github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= -github.com/kataras/golog v0.1.9 h1:vLvSDpP7kihFGKFAvBSofYo7qZNULYSHOH2D7rPTKJk= -github.com/kataras/golog v0.1.9/go.mod h1:jlpk/bOaYCyqDqH18pgDHdaJab72yBE6i0O3s30hpWY= -github.com/kataras/iris/v12 v12.2.7 h1:C9KWZmZT5pB5f2ot1XYWDBdi5XeTz0CGweHRXCDARZg= -github.com/kataras/iris/v12 v12.2.7/go.mod h1:mD76k/tIBFy8pHTFIgUPrVrkI4lTKvFbIcfbStJSBnA= -github.com/kataras/pio v0.0.12 h1:o52SfVYauS3J5X08fNjlGS5arXHjW/ItLkyLcKjoH6w= -github.com/kataras/pio v0.0.12/go.mod h1:ODK/8XBhhQ5WqrAhKy+9lTPS7sBf6O3KcLhc9klfRcY= +github.com/kataras/blocks v0.0.11 h1:JJdYW0AUaJKLx5kEWs/oRVCvKVXo+6CAAeaVAiJf7wE= +github.com/kataras/blocks v0.0.11/go.mod h1:b4UySrJySEOq6drKH9U3bOpMI+dRH148mayYfS3RFb8= +github.com/kataras/golog v0.1.12 h1:Bu7I/G4ilJlbfzjmU39O9N+2uO1pBcMK045fzZ4ytNg= +github.com/kataras/golog v0.1.12/go.mod h1:wrGSbOiBqbQSQznleVNX4epWM8rl9SJ/rmEacl0yqy4= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= -github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= +github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= @@ -96,18 +98,19 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tdewolff/minify/v2 v2.12.9 h1:dvn5MtmuQ/DFMwqf5j8QhEVpPX6fi3WGImhv8RUB4zA= -github.com/tdewolff/minify/v2 v2.12.9/go.mod h1:qOqdlDfL+7v0/fyymB+OP497nIxJYSvX4MQWA8OoiXU= -github.com/tdewolff/parse/v2 v2.6.8 h1:mhNZXYCx//xG7Yq2e/kVLNZw4YfYmeHbhx+Zc0OvFMA= -github.com/tdewolff/parse/v2 v2.6.8/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM= -github.com/tdewolff/test v1.0.9 h1:SswqJCmeN4B+9gEAi/5uqT0qpi1y2/2O47V/1hhGZT0= -github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.21.2 h1:VfTvmGVtBYhMTlUAeHtXM7XOsW0JT/6uMwUPPqgUs9k= +github.com/tdewolff/minify/v2 v2.21.2/go.mod h1:Olje3eHdBnrMjINKffDsil/3NV98Iv7MhWf7556WQVg= +github.com/tdewolff/parse/v2 v2.7.19 h1:7Ljh26yj+gdLFEq/7q9LT4SYyKtwQX4ocNrj45UCePg= +github.com/tdewolff/parse/v2 v2.7.19/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/vmihailenco/msgpack/v5 v5.4.0 h1:hRM0digJwyR6vll33NNAwCFguy5JuBD6jxDmQP3l608= -github.com/vmihailenco/msgpack/v5 v5.4.0/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= @@ -116,6 +119,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= +github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= @@ -127,17 +132,17 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDf github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -147,29 +152,27 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ= +google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= -gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/examples/iris-example/main.go b/examples/iris-example/main.go index ce1e949..1acc08f 100644 --- a/examples/iris-example/main.go +++ b/examples/iris-example/main.go @@ -10,9 +10,9 @@ import ( // Try it out with: // -// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyJ9.XFhrzWzntyINkgoRt2mb8dES84dJcuOoORdzKfwUX70 +// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyJ9.DSY4NlpZZ2mOqaKuXvJkOrgZA3nD5HuGaf1wB9-0OVw // -// which is signed with 'secret' and has the data: +// which is signed with 'abcdefghijklmnopqrstuvwxyz012345' and has the data: // // { // "iss": "go-jwt-middleware-example", @@ -25,9 +25,9 @@ import ( // // You can also try out the custom validation with: // -// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyIsInNob3VsZFJlamVjdCI6dHJ1ZX0.Jf13PY_Oyu2x3Gx1JQ0jXRiWaCOb5T2RbKOrTPBNHJA +// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnby1qd3QtbWlkZGxld2FyZS1leGFtcGxlIiwiYXVkIjoiYXVkaWVuY2UtZXhhbXBsZSIsInN1YiI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjIsInVzZXJuYW1lIjoidXNlcjEyMyIsInNob3VsZFJlamVjdCI6dHJ1ZX0.qjjJBgKNomlbEQrCobpEU9ASgvSpLQhQBryRkp6-RQc // -// which is signed with 'secret' and has the data: +// which is signed with 'abcdefghijklmnopqrstuvwxyz012345' and has the data: // // { // "iss": "go-jwt-middleware-example", diff --git a/examples/iris-example/middleware.go b/examples/iris-example/middleware.go index d27e4fa..b8ffea4 100644 --- a/examples/iris-example/middleware.go +++ b/examples/iris-example/middleware.go @@ -13,7 +13,7 @@ import ( var ( // The signing key for the token. - signingKey = []byte("secret") + signingKey = []byte("abcdefghijklmnopqrstuvwxyz012345") // The issuer of our token. issuer = "go-jwt-middleware-example" diff --git a/extractor.go b/extractor.go index 376e513..3388266 100644 --- a/extractor.go +++ b/extractor.go @@ -23,7 +23,7 @@ func AuthHeaderTokenExtractor(r *http.Request) (string, error) { authHeaderParts := strings.Fields(authHeader) if len(authHeaderParts) != 2 || strings.ToLower(authHeaderParts[0]) != "bearer" { - return "", errors.New("Authorization header format must be Bearer {token}") + return "", errors.New("authorization header format must be Bearer {token}") } return authHeaderParts[1], nil @@ -34,7 +34,7 @@ func AuthHeaderTokenExtractor(r *http.Request) (string, error) { func CookieTokenExtractor(cookieName string) TokenExtractor { return func(r *http.Request) (string, error) { cookie, err := r.Cookie(cookieName) - if err == http.ErrNoCookie { + if errors.Is(err, http.ErrNoCookie) { return "", nil // No cookie, then no JWT, so no error. } diff --git a/extractor_test.go b/extractor_test.go index 3101847..adca044 100644 --- a/extractor_test.go +++ b/extractor_test.go @@ -38,7 +38,7 @@ func Test_AuthHeaderTokenExtractor(t *testing.T) { "Authorization": []string{"i-am-a-token"}, }, }, - wantError: "Authorization header format must be Bearer {token}", + wantError: "authorization header format must be Bearer {token}", }, } diff --git a/go.mod b/go.mod index 1f69a80..e8fe586 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,10 @@ module github.com/auth0/go-jwt-middleware/v2 go 1.22 require ( + github.com/go-jose/go-jose/v4 v4.0.4 github.com/google/go-cmp v0.6.0 github.com/stretchr/testify v1.10.0 golang.org/x/sync v0.10.0 - gopkg.in/go-jose/go-jose.v2 v2.6.3 ) require ( diff --git a/go.sum b/go.sum index b201488..f692492 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -12,7 +14,5 @@ golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= -gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/jwks/provider.go b/jwks/provider.go index 808cae7..21983bc 100644 --- a/jwks/provider.go +++ b/jwks/provider.go @@ -9,8 +9,8 @@ import ( "sync" "time" + "github.com/go-jose/go-jose/v4" "golang.org/x/sync/semaphore" - "gopkg.in/go-jose/go-jose.v2" "github.com/auth0/go-jwt-middleware/v2/internal/oidc" ) @@ -21,9 +21,10 @@ import ( // getting and caching JWKS which can help reduce request time and potential // rate limiting from your provider. type Provider struct { - IssuerURL *url.URL // Required. - CustomJWKSURI *url.URL // Optional. - Client *http.Client + IssuerURL *url.URL // Required. + CustomJWKSURI *url.URL // Optional. + AdditionalProviders []Provider // Optional + Client *http.Client } // ProviderOption is how options for the Provider are set up. @@ -32,14 +33,24 @@ type ProviderOption func(*Provider) // NewProvider builds and returns a new *Provider. func NewProvider(issuerURL *url.URL, opts ...ProviderOption) *Provider { p := &Provider{ - IssuerURL: issuerURL, - Client: &http.Client{}, + Client: &http.Client{}, + AdditionalProviders: make([]Provider, 0), + } + + if issuerURL != nil { + p.IssuerURL = issuerURL } for _, opt := range opts { opt(p) } + for _, provider := range p.AdditionalProviders { + if provider.Client == nil { + provider.Client = p.Client + } + } + return p } @@ -56,6 +67,21 @@ func WithCustomJWKSURI(jwksURI *url.URL) ProviderOption { func WithCustomClient(c *http.Client) ProviderOption { return func(p *Provider) { p.Client = c + for _, provider := range p.AdditionalProviders { + provider.Client = c + } + } +} + +// WithAdditionalProviders allows validation with mutliple IssuerURLs if desired. If multiple issuers are specified, +// a jwt may be signed by any of them and be considered valid +func WithAdditionalProviders(issuerURL *url.URL, customJWKSURI *url.URL) ProviderOption { + return func(p *Provider) { + p.AdditionalProviders = append(p.AdditionalProviders, Provider{ + IssuerURL: issuerURL, + CustomJWKSURI: customJWKSURI, + Client: p.Client, + }) } } @@ -63,6 +89,25 @@ func WithCustomClient(c *http.Client) ProviderOption { // While it returns an interface to adhere to keyFunc, as long as the // error is nil the type will be *jose.JSONWebKeySet. func (p *Provider) KeyFunc(ctx context.Context) (interface{}, error) { + rawJwks, err := p.keyFunc(ctx) + + if len(p.AdditionalProviders) == 0 { + return rawJwks, err + } else { + var jwks *jose.JSONWebKeySet + jwks = rawJwks.(*jose.JSONWebKeySet) + for _, provider := range p.AdditionalProviders { + if rawJwks, err = provider.keyFunc(ctx); err != nil { + continue + } else { + jwks.Keys = append(jwks.Keys, rawJwks.(*jose.JSONWebKeySet).Keys...) + } + } + return jwks, err + } +} + +func (p *Provider) keyFunc(ctx context.Context) (interface{}, error) { jwksURI := p.CustomJWKSURI if jwksURI == nil { wkEndpoints, err := oidc.GetWellKnownEndpointsFromIssuerURL(ctx, p.Client, *p.IssuerURL) @@ -85,10 +130,12 @@ func (p *Provider) KeyFunc(ctx context.Context) (interface{}, error) { if err != nil { return nil, err } - defer response.Body.Close() + defer func() { + _ = response.Body.Close() + }() var jwks jose.JSONWebKeySet - if err := json.NewDecoder(response.Body).Decode(&jwks); err != nil { + if err = json.NewDecoder(response.Body).Decode(&jwks); err != nil { return nil, fmt.Errorf("could not decode jwks: %w", err) } diff --git a/jwks/provider_test.go b/jwks/provider_test.go index 7682010..c49d294 100644 --- a/jwks/provider_test.go +++ b/jwks/provider_test.go @@ -17,10 +17,10 @@ import ( "testing" "time" + "github.com/go-jose/go-jose/v4" "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gopkg.in/go-jose/go-jose.v2" "github.com/auth0/go-jwt-middleware/v2/internal/oidc" ) diff --git a/middleware_test.go b/middleware_test.go index 436a5fb..ef9e9c6 100644 --- a/middleware_test.go +++ b/middleware_test.go @@ -17,7 +17,7 @@ import ( func Test_CheckJWT(t *testing.T) { const ( - validToken = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0SXNzdWVyIiwiYXVkIjoidGVzdEF1ZGllbmNlIn0.Bg8HXYXZ13zaPAcB0Bl0kRKW0iVF-2LTmITcEYUcWoo" + validToken = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0SXNzdWVyIiwiYXVkIjoidGVzdEF1ZGllbmNlIn0.Gyy_wLVaXohXo-QB1dgJWw-FbiS80mKw1OrTwmffvNo" invalidToken = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0aW5nIn0.eM1Jd7VA7nFSI09FlmLmtuv7cLnv8qicZ8s76-jTOoE" issuer = "testIssuer" audience = "testAudience" @@ -30,8 +30,9 @@ func Test_CheckJWT(t *testing.T) { }, } + secret := []byte("abcdefghijklmnopqrstuvwxyz012345") keyFunc := func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return secret, nil } jwtValidator, err := validator.New(keyFunc, validator.HS256, issuer, []string{audience}) diff --git a/validator/option.go b/validator/option.go index 12c1cc6..d95c41a 100644 --- a/validator/option.go +++ b/validator/option.go @@ -1,6 +1,7 @@ package validator import ( + "github.com/go-jose/go-jose/v4/jwt" "time" ) @@ -26,3 +27,16 @@ func WithCustomClaims(f func() CustomClaims) Option { v.customClaims = f } } + +// WithExpectedClaims allows fine-grained customization of the expected claims +func WithExpectedClaims(expectedClaims ...jwt.Expected) Option { + return func(v *Validator) { + if len(expectedClaims) == 0 { + return + } + if v.expectedClaims == nil { + v.expectedClaims = make([]jwt.Expected, 0) + } + v.expectedClaims = append(v.expectedClaims, expectedClaims...) + } +} diff --git a/validator/validator.go b/validator/validator.go index 2a30249..0d02d5a 100644 --- a/validator/validator.go +++ b/validator/validator.go @@ -4,9 +4,11 @@ import ( "context" "errors" "fmt" + "github.com/go-jose/go-jose/v4" + "strings" "time" - "gopkg.in/go-jose/go-jose.v2/jwt" + "github.com/go-jose/go-jose/v4/jwt" ) // Signature algorithms @@ -30,13 +32,14 @@ const ( type Validator struct { keyFunc func(context.Context) (interface{}, error) // Required. signatureAlgorithm SignatureAlgorithm // Required. - expectedClaims jwt.Expected // Internal. + expectedClaims []jwt.Expected // Internal. customClaims func() CustomClaims // Optional. allowedClockSkew time.Duration // Optional. } // SignatureAlgorithm is a signature algorithm. -type SignatureAlgorithm string +type SignatureAlgorithm jose.SignatureAlgorithm +type SignatureAlgorithms []jose.SignatureAlgorithm var allowedSigningAlgorithms = map[SignatureAlgorithm]bool{ EdDSA: true, @@ -66,11 +69,61 @@ func New( if keyFunc == nil { return nil, errors.New("keyFunc is required but was nil") } - if issuerURL == "" { - return nil, errors.New("issuer url is required but was empty") + if _, ok := allowedSigningAlgorithms[signatureAlgorithm]; !ok { + return nil, errors.New("unsupported signature algorithm") + } + + v := &Validator{ + keyFunc: keyFunc, + signatureAlgorithm: signatureAlgorithm, + expectedClaims: make([]jwt.Expected, 0), } - if len(audience) == 0 { + + for _, opt := range opts { + opt(v) + } + + if len(v.expectedClaims) == 0 && issuerURL == "" { + return nil, errors.New("issuer url is required but was empty") + } else if len(v.expectedClaims) == 0 && len(audience) == 0 { return nil, errors.New("audience is required but was empty") + } else if len(issuerURL) > 0 && len(audience) > 0 { + v.expectedClaims = append(v.expectedClaims, jwt.Expected{ + Issuer: issuerURL, + AnyAudience: audience, + }) + } + + if len(v.expectedClaims) == 0 { + return nil, errors.New("expected claims but none provided") + } + + for i, expected := range v.expectedClaims { + if expected.Issuer == "" { + return nil, fmt.Errorf("issuer url %d is required but was empty", i) + } + if len(expected.AnyAudience) == 0 { + return nil, fmt.Errorf("audience %d is required but was empty", i) + } + } + + return v, nil +} + +// NewValidator sets up a new Validator with the required keyFunc +// and signatureAlgorithm as well as custom options. +// This function has been added to provide an alternate function without the required issuer or audience parameters +// so they can be included in the opts parameter via WithExpectedClaims +// This function operates exactly like New with the exception of the two parameters issuer and audience and this function +// expects the inclusion of WithExpectedClaims with at least one valid expected claim. +// A valid expected claim would include an issuer and at least one audience +func NewValidator( + keyFunc func(context.Context) (interface{}, error), + signatureAlgorithm SignatureAlgorithm, + opts ...Option, +) (*Validator, error) { + if keyFunc == nil { + return nil, errors.New("keyFunc is required but was nil") } if _, ok := allowedSigningAlgorithms[signatureAlgorithm]; !ok { return nil, errors.New("unsupported signature algorithm") @@ -79,22 +132,32 @@ func New( v := &Validator{ keyFunc: keyFunc, signatureAlgorithm: signatureAlgorithm, - expectedClaims: jwt.Expected{ - Issuer: issuerURL, - Audience: audience, - }, + expectedClaims: make([]jwt.Expected, 0), } for _, opt := range opts { opt(v) } + if len(v.expectedClaims) == 0 { + return nil, errors.New("expected claims but none provided") + } + + for i, expected := range v.expectedClaims { + if expected.Issuer == "" { + return nil, fmt.Errorf("issuer url %d is required but was empty", i) + } + if len(expected.AnyAudience) == 0 { + return nil, fmt.Errorf("audience %d is required but was empty", i) + } + } + return v, nil } // ValidateToken validates the passed in JWT using the jose v2 package. func (v *Validator) ValidateToken(ctx context.Context, tokenString string) (interface{}, error) { - token, err := jwt.ParseSigned(tokenString) + token, err := jwt.ParseSigned(tokenString, signatureAlgorithms(v.signatureAlgorithm)) if err != nil { return nil, fmt.Errorf("could not parse the token: %w", err) } @@ -134,44 +197,81 @@ func (v *Validator) ValidateToken(ctx context.Context, tokenString string) (inte return validatedClaims, nil } -func validateClaimsWithLeeway(actualClaims jwt.Claims, expected jwt.Expected, leeway time.Duration) error { - expectedClaims := expected - expectedClaims.Time = time.Now() +func validateClaimsWithLeeway(actualClaims jwt.Claims, expectedIn []jwt.Expected, leeway time.Duration) error { + now := time.Now() + var currentError error + for _, expected := range expectedIn { + expectedClaims := expected + expectedClaims.Time = now - if actualClaims.Issuer != expectedClaims.Issuer { - return jwt.ErrInvalidIssuer - } + if actualClaims.Issuer != expectedClaims.Issuer { + currentError = createOrWrapError(currentError, jwt.ErrInvalidIssuer, actualClaims.Issuer, expectedClaims.Issuer) + continue + } - foundAudience := false - for _, value := range expectedClaims.Audience { - if actualClaims.Audience.Contains(value) { - foundAudience = true - break + foundAudience := false + for _, value := range expectedClaims.AnyAudience { + if actualClaims.Audience.Contains(value) { + foundAudience = true + break + } + } + if !foundAudience { + currentError = createOrWrapError( + currentError, + jwt.ErrInvalidAudience, + strings.Join(actualClaims.Audience, ","), + strings.Join(expectedClaims.AnyAudience, ","), + ) + continue } - } - if !foundAudience { - return jwt.ErrInvalidAudience - } - if actualClaims.NotBefore != nil && expectedClaims.Time.Add(leeway).Before(actualClaims.NotBefore.Time()) { - return jwt.ErrNotValidYet - } + if actualClaims.NotBefore != nil && expectedClaims.Time.Add(leeway).Before(actualClaims.NotBefore.Time()) { + return createOrWrapError( + currentError, + jwt.ErrNotValidYet, + actualClaims.NotBefore.Time().String(), + expectedClaims.Time.Add(leeway).String(), + ) + } + + if actualClaims.Expiry != nil && expectedClaims.Time.Add(-leeway).After(actualClaims.Expiry.Time()) { + return createOrWrapError( + currentError, + jwt.ErrExpired, + actualClaims.Expiry.Time().String(), + expectedClaims.Time.Add(leeway).String(), + ) + } - if actualClaims.Expiry != nil && expectedClaims.Time.Add(-leeway).After(actualClaims.Expiry.Time()) { - return jwt.ErrExpired + if actualClaims.IssuedAt != nil && expectedClaims.Time.Add(leeway).Before(actualClaims.IssuedAt.Time()) { + return createOrWrapError( + currentError, + jwt.ErrIssuedInTheFuture, + actualClaims.IssuedAt.Time().String(), + expectedClaims.Time.Add(leeway).String(), + ) + } + + return nil } - if actualClaims.IssuedAt != nil && expectedClaims.Time.Add(leeway).Before(actualClaims.IssuedAt.Time()) { - return jwt.ErrIssuedInTheFuture + return currentError +} + +func createOrWrapError(base, current error, actual, expected string) error { + if base == nil { + return current } - return nil + return errors.Join(base, fmt.Errorf("%v: %s vs %s", current, actual, expected)) } func validateSigningMethod(validAlg, tokenAlg string) error { if validAlg != tokenAlg { return fmt.Errorf("expected %q signing algorithm but token specified %q", validAlg, tokenAlg) } + return nil } @@ -208,5 +308,15 @@ func numericDateToUnixTime(date *jwt.NumericDate) int64 { if date != nil { return date.Time().Unix() } + return 0 } + +func signatureAlgorithms(algs ...SignatureAlgorithm) SignatureAlgorithms { + js := make(SignatureAlgorithms, len(algs)) + for i, alg := range algs { + js[i] = jose.SignatureAlgorithm(alg) + } + + return js +} diff --git a/validator/validator_test.go b/validator/validator_test.go index 08feeb1..511b4b8 100644 --- a/validator/validator_test.go +++ b/validator/validator_test.go @@ -7,9 +7,9 @@ import ( "testing" "time" + "github.com/go-jose/go-jose/v4/jwt" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gopkg.in/go-jose/go-jose.v2/jwt" ) type testClaims struct { @@ -39,9 +39,9 @@ func TestValidator_ValidateToken(t *testing.T) { }{ { name: "it successfully validates a token", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.-R2K2tZHDrgsEh9JNWcyk4aljtR6gZK0s2anNGlfwz0", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.ceqLpnraDGaKbQjIlyTFLj8WwwzGhBV3Eo9NDETEXTo", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, expectedClaims: &ValidatedClaims{ @@ -54,9 +54,9 @@ func TestValidator_ValidateToken(t *testing.T) { }, { name: "it successfully validates a token with custom claims", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJzY29wZSI6InJlYWQ6bWVzc2FnZXMifQ.oqtUZQ-Q8un4CPduUBdGVq5gXpQVIFT_QSQjkOXFT5I", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJzY29wZSI6InJlYWQ6bWVzc2FnZXMifQ.Hu9l6uJppZs_-xoj_kQiLIUqaFV14vCLE3nSgx8VFRI", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, customClaims: func() CustomClaims { @@ -75,25 +75,25 @@ func TestValidator_ValidateToken(t *testing.T) { }, { name: "it throws an error when token has a different signing algorithm than the validator", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.-R2K2tZHDrgsEh9JNWcyk4aljtR6gZK0s2anNGlfwz0", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.ceqLpnraDGaKbQjIlyTFLj8WwwzGhBV3Eo9NDETEXTo", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: RS256, - expectedError: errors.New(`signing method is invalid: expected "RS256" signing algorithm but token specified "HS256"`), + expectedError: errors.New(`could not parse the token: go-jose/go-jose: unexpected signature algorithm "HS256"; expected ["RS256"]`), }, { name: "it throws an error when it cannot parse the token", token: "", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, expectedError: errors.New("could not parse the token: go-jose/go-jose: compact JWS format must have three parts"), }, { name: "it throws an error when it fails to fetch the keys from the key func", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.-R2K2tZHDrgsEh9JNWcyk4aljtR6gZK0s2anNGlfwz0", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.ceqLpnraDGaKbQjIlyTFLj8WwwzGhBV3Eo9NDETEXTo", keyFunc: func(context.Context) (interface{}, error) { return nil, errors.New("key func error message") }, @@ -104,25 +104,25 @@ func TestValidator_ValidateToken(t *testing.T) { name: "it throws an error when it fails to deserialize the claims because the signature is invalid", token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.vR2K2tZHDrgsEh9zNWcyk4aljtR6gZK0s2anNGlfwz0", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, expectedError: errors.New("failed to deserialize token claims: could not get token claims: go-jose/go-jose: error in cryptographic primitive"), }, { name: "it throws an error when it fails to validate the registered claims", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIn0.VoIwDVmb--26wGrv93NmjNZYa4nrzjLw4JANgEjPI28", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIn0.U2heyMGWbMmhJvfYvXVPe1vK4TlNTiRKekU1EeTEN98", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, expectedError: errors.New("expected claims not validated: go-jose/go-jose/jwt: validation failed, invalid audience claim (aud)"), }, { name: "it throws an error when it fails to validate the custom claims", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJzY29wZSI6InJlYWQ6bWVzc2FnZXMifQ.oqtUZQ-Q8un4CPduUBdGVq5gXpQVIFT_QSQjkOXFT5I", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJzY29wZSI6InJlYWQ6bWVzc2FnZXMifQ.Hu9l6uJppZs_-xoj_kQiLIUqaFV14vCLE3nSgx8VFRI", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, customClaims: func() CustomClaims { @@ -134,9 +134,9 @@ func TestValidator_ValidateToken(t *testing.T) { }, { name: "it successfully validates a token even if customClaims() returns nil", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJzY29wZSI6InJlYWQ6bWVzc2FnZXMifQ.oqtUZQ-Q8un4CPduUBdGVq5gXpQVIFT_QSQjkOXFT5I", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJzY29wZSI6InJlYWQ6bWVzc2FnZXMifQ.Hu9l6uJppZs_-xoj_kQiLIUqaFV14vCLE3nSgx8VFRI", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, customClaims: func() CustomClaims { @@ -153,9 +153,9 @@ func TestValidator_ValidateToken(t *testing.T) { }, { name: "it successfully validates a token with exp, nbf and iat", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjE2NjY5Mzc2ODYsIm5iZiI6MTY2NjkzOTAwMCwiZXhwIjo5NjY3OTM3Njg2fQ.FKZogkm08gTfYfPU6eYu7OHCjJKnKGLiC0IfoIOPEhs", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjE2NjY5Mzc2ODYsIm5iZiI6MTY2NjkzOTAwMCwiZXhwIjo5NjY3OTM3Njg2fQ.F57edUPU8AEkIbLV8bLw1mw4RtKh6MtuPzoQQqin9kE", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, expectedClaims: &ValidatedClaims{ @@ -171,36 +171,36 @@ func TestValidator_ValidateToken(t *testing.T) { }, { name: "it throws an error when token is not valid yet", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjE2NjY5Mzc2ODYsIm5iZiI6OTY2NjkzOTAwMCwiZXhwIjoxNjY3OTM3Njg2fQ.yUizJ-zK_33tv1qBVvDKO0RuCWtvJ02UQKs8gBadgGY", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjE2NjY5Mzc2ODYsIm5iZiI6OTY2NjkzOTAwMCwiZXhwIjoxNjY3OTM3Njg2fQ.E8mqR42CRqEBcG9YzBVb8SGmitcU0sAMDbmG_ueM0EU", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, expectedError: fmt.Errorf("expected claims not validated: %s", jwt.ErrNotValidYet), }, { name: "it throws an error when token is expired", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjE2NjY5Mzc2ODYsIm5iZiI6MTY2NjkzOTAwMCwiZXhwIjo2Njc5Mzc2ODZ9.SKvz82VOXRi_sjvZWIsPG9vSWAXKKgVS4DkGZcwFKL8", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjE2NjY5Mzc2ODYsIm5iZiI6MTY2NjkzOTAwMCwiZXhwIjo2Njc5Mzc2ODZ9.iCJyAzGH5WXq8ffK8kEBumpilEqDHdB4V7X0nN4ppl0", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, expectedError: fmt.Errorf("expected claims not validated: %s", jwt.ErrExpired), }, { name: "it throws an error when token is issued in the future", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjkxNjY2OTM3Njg2LCJuYmYiOjE2NjY5MzkwMDAsImV4cCI6ODY2NzkzNzY4Nn0.ieFV7XNJxiJyw8ARq9yHw-01Oi02e3P2skZO10ypxL8", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjkxNjY2OTM3Njg2LCJuYmYiOjE2NjY5MzkwMDAsImV4cCI6ODY2NzkzNzY4Nn0.USKHRD2wUC5UuYLSL-nUJWs06emOxzX2M6Rv1OzxiM4", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, expectedError: fmt.Errorf("expected claims not validated: %s", jwt.ErrIssuedInTheFuture), }, { name: "it throws an error when token issuer is invalid", - token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2hhY2tlZC1qd3QtbWlkZGxld2FyZS5ldS5hdXRoMC5jb20vIiwic3ViIjoiMTIzNDU2Nzg5MCIsImF1ZCI6WyJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLWFwaS8iXSwiaWF0Ijo5MTY2NjkzNzY4NiwibmJmIjoxNjY2OTM5MDAwLCJleHAiOjg2Njc5Mzc2ODZ9.b5gXNrUNfd_jyCWZF-6IPK_UFfvTr9wBQk9_QgRQ8rA", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2hhY2tlZC1qd3QtbWlkZGxld2FyZS5ldS5hdXRoMC5jb20vIiwic3ViIjoiMTIzNDU2Nzg5MCIsImF1ZCI6WyJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLWFwaS8iXSwiaWF0Ijo5MTY2NjkzNzY4NiwibmJmIjoxNjY2OTM5MDAwLCJleHAiOjg2Njc5Mzc2ODZ9.n-p1CVU0b5FwUIZr7nwl6CfpUq6GKmzBBaFVIGOT6w8", keyFunc: func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil }, algorithm: HS256, expectedError: fmt.Errorf("expected claims not validated: %s", jwt.ErrInvalidIssuer), @@ -234,7 +234,227 @@ func TestValidator_ValidateToken(t *testing.T) { } } -func TestNewValidator(t *testing.T) { +func TestNewValidator_ValidateToken(t *testing.T) { + const ( + issuer = "https://go-jwt-middleware.eu.auth0.com/" + audience = "https://go-jwt-middleware-api/" + subject = "1234567890" + issuerB = "https://go-jwt-middleware.us.auth0.com/" + audienceB = "https://go-jwt-middleware-api-b/" + ) + + testCases := []struct { + name string + token string + keyFunc func(context.Context) (interface{}, error) + algorithm SignatureAlgorithm + customClaims func() CustomClaims + expectedError error + expectedClaims *ValidatedClaims + }{ + { + name: "it successfully validates a token", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.ceqLpnraDGaKbQjIlyTFLj8WwwzGhBV3Eo9NDETEXTo", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + expectedClaims: &ValidatedClaims{ + RegisteredClaims: RegisteredClaims{ + Issuer: issuer, + Subject: subject, + Audience: []string{audience}, + }, + }, + }, + { + name: "it successfully validates a token with custom claims", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJzY29wZSI6InJlYWQ6bWVzc2FnZXMifQ.Hu9l6uJppZs_-xoj_kQiLIUqaFV14vCLE3nSgx8VFRI", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + customClaims: func() CustomClaims { + return &testClaims{} + }, + expectedClaims: &ValidatedClaims{ + RegisteredClaims: RegisteredClaims{ + Issuer: issuer, + Subject: subject, + Audience: []string{audience}, + }, + CustomClaims: &testClaims{ + Scope: "read:messages", + }, + }, + }, + { + name: "it throws an error when token has a different signing algorithm than the validator", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.ceqLpnraDGaKbQjIlyTFLj8WwwzGhBV3Eo9NDETEXTo", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: RS256, + expectedError: errors.New(`could not parse the token: go-jose/go-jose: unexpected signature algorithm "HS256"; expected ["RS256"]`), + }, + { + name: "it throws an error when it cannot parse the token", + token: "", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + expectedError: errors.New("could not parse the token: go-jose/go-jose: compact JWS format must have three parts"), + }, + { + name: "it throws an error when it fails to fetch the keys from the key func", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.ceqLpnraDGaKbQjIlyTFLj8WwwzGhBV3Eo9NDETEXTo", + keyFunc: func(context.Context) (interface{}, error) { + return nil, errors.New("key func error message") + }, + algorithm: HS256, + expectedError: errors.New("failed to deserialize token claims: error getting the keys from the key func: key func error message"), + }, + { + name: "it throws an error when it fails to deserialize the claims because the signature is invalid", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdfQ.vR2K2tZHDrgsEh9zNWcyk4aljtR6gZK0s2anNGlfwz0", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + expectedError: errors.New("failed to deserialize token claims: could not get token claims: go-jose/go-jose: error in cryptographic primitive"), + }, + { + name: "it throws an error when it fails to validate the registered claims", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIn0.U2heyMGWbMmhJvfYvXVPe1vK4TlNTiRKekU1EeTEN98", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + expectedError: errors.New("go-jose/go-jose/jwt: validation failed, invalid audience claim (aud)"), + }, + { + name: "it throws an error when it fails to validate the custom claims", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJzY29wZSI6InJlYWQ6bWVzc2FnZXMifQ.Hu9l6uJppZs_-xoj_kQiLIUqaFV14vCLE3nSgx8VFRI", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + customClaims: func() CustomClaims { + return &testClaims{ + ReturnError: errors.New("custom claims error message"), + } + }, + expectedError: errors.New("custom claims not validated: custom claims error message"), + }, + { + name: "it successfully validates a token even if customClaims() returns nil", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJzY29wZSI6InJlYWQ6bWVzc2FnZXMifQ.Hu9l6uJppZs_-xoj_kQiLIUqaFV14vCLE3nSgx8VFRI", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + customClaims: func() CustomClaims { + return nil + }, + expectedClaims: &ValidatedClaims{ + RegisteredClaims: RegisteredClaims{ + Issuer: issuer, + Subject: subject, + Audience: []string{audience}, + }, + CustomClaims: nil, + }, + }, + { + name: "it successfully validates a token with exp, nbf and iat", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjE2NjY5Mzc2ODYsIm5iZiI6MTY2NjkzOTAwMCwiZXhwIjo5NjY3OTM3Njg2fQ.F57edUPU8AEkIbLV8bLw1mw4RtKh6MtuPzoQQqin9kE", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + expectedClaims: &ValidatedClaims{ + RegisteredClaims: RegisteredClaims{ + Issuer: issuer, + Subject: subject, + Audience: []string{audience}, + Expiry: 9667937686, + NotBefore: 1666939000, + IssuedAt: 1666937686, + }, + }, + }, + { + name: "it throws an error when token is not valid yet", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjE2NjY5Mzc2ODYsIm5iZiI6OTY2NjkzOTAwMCwiZXhwIjoxNjY3OTM3Njg2fQ.E8mqR42CRqEBcG9YzBVb8SGmitcU0sAMDbmG_ueM0EU", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + expectedError: fmt.Errorf("expected claims not validated: %s", jwt.ErrNotValidYet), + }, + { + name: "it throws an error when token is expired", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjE2NjY5Mzc2ODYsIm5iZiI6MTY2NjkzOTAwMCwiZXhwIjo2Njc5Mzc2ODZ9.iCJyAzGH5WXq8ffK8kEBumpilEqDHdB4V7X0nN4ppl0", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + expectedError: fmt.Errorf("expected claims not validated: %s", jwt.ErrExpired), + }, + { + name: "it throws an error when token is issued in the future", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLmV1LmF1dGgwLmNvbS8iLCJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjpbImh0dHBzOi8vZ28tand0LW1pZGRsZXdhcmUtYXBpLyJdLCJpYXQiOjkxNjY2OTM3Njg2LCJuYmYiOjE2NjY5MzkwMDAsImV4cCI6ODY2NzkzNzY4Nn0.USKHRD2wUC5UuYLSL-nUJWs06emOxzX2M6Rv1OzxiM4", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + expectedError: fmt.Errorf("expected claims not validated: %s", jwt.ErrIssuedInTheFuture), + }, + { + name: "it throws an error when token issuer is invalid", + token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2hhY2tlZC1qd3QtbWlkZGxld2FyZS5ldS5hdXRoMC5jb20vIiwic3ViIjoiMTIzNDU2Nzg5MCIsImF1ZCI6WyJodHRwczovL2dvLWp3dC1taWRkbGV3YXJlLWFwaS8iXSwiaWF0Ijo5MTY2NjkzNzY4NiwibmJmIjoxNjY2OTM5MDAwLCJleHAiOjg2Njc5Mzc2ODZ9.n-p1CVU0b5FwUIZr7nwl6CfpUq6GKmzBBaFVIGOT6w8", + keyFunc: func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + }, + algorithm: HS256, + expectedError: fmt.Errorf("expected claims not validated: %s", jwt.ErrInvalidIssuer), + }, + } + + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + validator, err := NewValidator( + testCase.keyFunc, + testCase.algorithm, + WithCustomClaims(testCase.customClaims), + WithAllowedClockSkew(time.Second), + WithExpectedClaims(jwt.Expected{ + Issuer: issuer, + AnyAudience: []string{audience, "another-audience"}, + }, jwt.Expected{ + Issuer: issuerB, + AnyAudience: []string{audienceB, "another-audienceb"}, + }), + ) + require.NoError(t, err) + + tokenClaims, err := validator.ValidateToken(context.Background(), testCase.token) + if testCase.expectedError != nil { + assert.ErrorContains(t, err, testCase.expectedError.Error()) + assert.Nil(t, tokenClaims) + } else { + require.NoError(t, err) + assert.Exactly(t, testCase.expectedClaims, tokenClaims) + } + }) + } +} + +func TestNew(t *testing.T) { const ( issuer = "https://go-jwt-middleware.eu.auth0.com/" audience = "https://go-jwt-middleware-api/" @@ -242,7 +462,7 @@ func TestNewValidator(t *testing.T) { ) var keyFunc = func(context.Context) (interface{}, error) { - return []byte("secret"), nil + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil } t.Run("it throws an error when the keyFunc is nil", func(t *testing.T) { @@ -260,12 +480,12 @@ func TestNewValidator(t *testing.T) { assert.EqualError(t, err, "unsupported signature algorithm") }) - t.Run("it throws an error when the issuerURL is empty", func(t *testing.T) { + t.Run("it throws an error when the issuerURL is empty and no expectedClaims option", func(t *testing.T) { _, err := New(keyFunc, algorithm, "", []string{audience}) assert.EqualError(t, err, "issuer url is required but was empty") }) - t.Run("it throws an error when the audience is nil", func(t *testing.T) { + t.Run("it throws an error when the audience is nil if no expectedClaims option included", func(t *testing.T) { _, err := New(keyFunc, algorithm, issuer, nil) assert.EqualError(t, err, "audience is required but was empty") }) @@ -274,4 +494,81 @@ func TestNewValidator(t *testing.T) { _, err := New(keyFunc, algorithm, issuer, []string{}) assert.EqualError(t, err, "audience is required but was empty") }) + + t.Run("it throws an error when the issuerURL is empty and an expectedClaims option with only an audience", func(t *testing.T) { + _, err := New(keyFunc, algorithm, "", []string{}, WithExpectedClaims(jwt.Expected{AnyAudience: []string{audience}})) + assert.EqualError(t, err, "issuer url 0 is required but was empty") + }) + + t.Run("it throws an error when the audience is empty and the expectedClaims are missing an audience", func(t *testing.T) { + _, err := New(keyFunc, algorithm, issuer, []string{}, WithExpectedClaims(jwt.Expected{Issuer: issuer})) + assert.EqualError(t, err, "audience 0 is required but was empty") + }) + + t.Run("it throws no error when the issuerURL is empty but expectedClaims option included", func(t *testing.T) { + _, err := New(keyFunc, algorithm, "", []string{audience}, WithExpectedClaims(jwt.Expected{Issuer: issuer, AnyAudience: []string{audience}})) + assert.NoError(t, err, "no error was expected") + }) + + t.Run("it throws no error when the audience is nil but expectedClaims option included", func(t *testing.T) { + _, err := New(keyFunc, algorithm, issuer, nil, WithExpectedClaims(jwt.Expected{Issuer: issuer, AnyAudience: []string{audience}})) + assert.NoError(t, err, "no error was expected") + }) +} + +func TestNewValidator(t *testing.T) { + const ( + issuer = "https://go-jwt-middleware.eu.auth0.com/" + audience = "https://go-jwt-middleware-api/" + algorithm = HS256 + ) + + var keyFunc = func(context.Context) (interface{}, error) { + return []byte("abcdefghijklmnopqrstuvwxyz012345"), nil + } + + t.Run("it throws an error when the keyFunc is nil", func(t *testing.T) { + _, err := NewValidator(nil, algorithm) + assert.EqualError(t, err, "keyFunc is required but was nil") + }) + + t.Run("it throws an error when the signature algorithm is empty", func(t *testing.T) { + _, err := NewValidator(keyFunc, "") + assert.EqualError(t, err, "unsupported signature algorithm") + }) + + t.Run("it throws an error when the signature algorithm is unsupported", func(t *testing.T) { + _, err := NewValidator(keyFunc, "none") + assert.EqualError(t, err, "unsupported signature algorithm") + }) + + t.Run("it throws an error when there are no expected claims", func(t *testing.T) { + _, err := NewValidator(keyFunc, algorithm) + assert.EqualError(t, err, "expected claims but none provided") + }) + + t.Run("it throws an error when expectedClaims option with only an audience", func(t *testing.T) { + _, err := NewValidator(keyFunc, algorithm, WithExpectedClaims(jwt.Expected{AnyAudience: []string{audience}})) + assert.EqualError(t, err, "issuer url 0 is required but was empty") + }) + + t.Run("it throws an error when expectedClaims option with only an audience in the second jwt.Expected", func(t *testing.T) { + _, err := NewValidator(keyFunc, algorithm, WithExpectedClaims(jwt.Expected{Issuer: issuer, AnyAudience: []string{audience}}, jwt.Expected{AnyAudience: []string{audience}})) + assert.EqualError(t, err, "issuer url 1 is required but was empty") + }) + + t.Run("it throws an error when the audience is empty and the expectedClaims are missing an audience", func(t *testing.T) { + _, err := NewValidator(keyFunc, algorithm, WithExpectedClaims(jwt.Expected{Issuer: issuer})) + assert.EqualError(t, err, "audience 0 is required but was empty") + }) + + t.Run("it throws an error when the audience is empty and the expectedClaims are missing an audience in the second jwt.Expected", func(t *testing.T) { + _, err := NewValidator(keyFunc, algorithm, WithExpectedClaims(jwt.Expected{Issuer: issuer, AnyAudience: []string{audience}}, jwt.Expected{Issuer: issuer})) + assert.EqualError(t, err, "audience 1 is required but was empty") + }) + + t.Run("it throws no error when input is correct", func(t *testing.T) { + _, err := NewValidator(keyFunc, algorithm, WithExpectedClaims(jwt.Expected{Issuer: issuer, AnyAudience: []string{audience}})) + assert.NoError(t, err, "no error was expected") + }) }