Skip to content

Commit 29975d0

Browse files
Merge branch 'go-chi:master' into alovelltroy/add-jwks-support
2 parents 7552877 + 0eb3c51 commit 29975d0

5 files changed

Lines changed: 102 additions & 70 deletions

File tree

Makefile

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
SHELL = bash -o pipefail
2+
TEST_FLAGS ?= -v -race
3+
4+
all:
5+
@echo "make <cmd>"
6+
@echo ""
7+
@echo "commands:"
8+
@echo ""
9+
@echo " + Development:"
10+
@echo " - build"
11+
@echo " - test"
12+
@echo " - todo"
13+
@echo " - clean"
14+
@echo ""
15+
@echo ""
16+
17+
18+
##
19+
## Development
20+
##
21+
build:
22+
go build ./...
23+
24+
clean:
25+
go clean -cache -testcache
26+
27+
test: test-clean
28+
GOGC=off go test $(TEST_FLAGS) -run=$(TEST) ./...
29+
30+
test-clean:
31+
GOGC=off go clean -testcache
32+
33+
bench:
34+
@go test -timeout=25m -bench=.
35+
36+
todo:
37+
@git grep TODO -- './*' ':!./vendor/' ':!./Makefile' || :

go.mod

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
module github.com/go-chi/jwtauth/v5
22

3-
go 1.18
3+
go 1.23.0
4+
5+
toolchain go1.24.2
46

57
require (
6-
github.com/go-chi/chi/v5 v5.0.7
7-
github.com/lestrrat-go/jwx/v2 v2.0.21
8+
github.com/go-chi/chi/v5 v5.2.1
9+
github.com/lestrrat-go/jwx/v2 v2.1.4
810
)
911

1012
require (
11-
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
12-
github.com/goccy/go-json v0.10.2 // indirect
13+
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
14+
github.com/goccy/go-json v0.10.3 // indirect
1315
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
1416
github.com/lestrrat-go/httpcc v1.0.1 // indirect
15-
github.com/lestrrat-go/httprc v1.0.5 // indirect
17+
github.com/lestrrat-go/httprc v1.0.6 // indirect
1618
github.com/lestrrat-go/iter v1.0.2 // indirect
1719
github.com/lestrrat-go/option v1.0.1 // indirect
1820
github.com/segmentio/asm v1.2.0 // indirect
19-
golang.org/x/crypto v0.21.0 // indirect
20-
golang.org/x/sys v0.18.0 // indirect
21+
golang.org/x/crypto v0.37.0 // indirect
22+
golang.org/x/sys v0.32.0 // indirect
2123
)

go.sum

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
22
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3-
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
4-
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
5-
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
6-
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
7-
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
8-
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
3+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
5+
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
6+
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
7+
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
8+
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
9+
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
910
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
1011
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
1112
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
1213
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
13-
github.com/lestrrat-go/httprc v1.0.5 h1:bsTfiH8xaKOJPrg1R+E3iE/AWZr/x0Phj9PBTG/OLUk=
14-
github.com/lestrrat-go/httprc v1.0.5/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
14+
github.com/lestrrat-go/httprc v1.0.6 h1:qgmgIRhpvBqexMJjA/PmwSvhNk679oqD1RbovdCGW8k=
15+
github.com/lestrrat-go/httprc v1.0.6/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
1516
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
1617
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
17-
github.com/lestrrat-go/jwx/v2 v2.0.21 h1:jAPKupy4uHgrHFEdjVjNkUgoBKtVDgrQPB/h55FHrR0=
18-
github.com/lestrrat-go/jwx/v2 v2.0.21/go.mod h1:09mLW8zto6bWL9GbwnqAli+ArLf+5M33QLQPDggkUWM=
18+
github.com/lestrrat-go/jwx/v2 v2.1.4 h1:uBCMmJX8oRZStmKuMMOFb0Yh9xmEMgNJLgjuKKt4/qc=
19+
github.com/lestrrat-go/jwx/v2 v2.1.4/go.mod h1:nWRbDFR1ALG2Z6GJbBXzfQaYyvn751KuuyySN2yR6is=
1920
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
2021
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
2122
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -25,11 +26,13 @@ github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr
2526
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
2627
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
2728
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
28-
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
29-
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
30-
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
31-
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
32-
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
29+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
30+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
31+
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
32+
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
33+
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
34+
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
3335
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3436
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3537
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
38+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

jwtauth.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func Authenticator(ja *JWTAuth) func(http.Handler) http.Handler {
209209
return
210210
}
211211

212-
if token == nil || jwt.Validate(token, ja.validateOptions...) != nil {
212+
if token == nil {
213213
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
214214
return
215215
}
@@ -282,7 +282,7 @@ func SetExpiryIn(claims map[string]interface{}, tm time.Duration) {
282282
claims["exp"] = ExpireIn(tm)
283283
}
284284

285-
// TokenFromCookie tries to retreive the token string from a cookie named
285+
// TokenFromCookie tries to retrieve the token string from a cookie named
286286
// "jwt".
287287
func TokenFromCookie(r *http.Request) string {
288288
cookie, err := r.Cookie("jwt")
@@ -292,18 +292,18 @@ func TokenFromCookie(r *http.Request) string {
292292
return cookie.Value
293293
}
294294

295-
// TokenFromHeader tries to retreive the token string from the
296-
// "Authorization" reqeust header: "Authorization: BEARER T".
295+
// TokenFromHeader tries to retrieve the token string from the
296+
// "Authorization" request header: "Authorization: BEARER T".
297297
func TokenFromHeader(r *http.Request) string {
298298
// Get token from authorization header.
299299
bearer := r.Header.Get("Authorization")
300-
if len(bearer) > 7 && strings.ToUpper(bearer[0:6]) == "BEARER" {
300+
if len(bearer) > 7 && strings.ToUpper(bearer[0:7]) == "BEARER " {
301301
return bearer[7:]
302302
}
303303
return ""
304304
}
305305

306-
// TokenFromQuery tries to retreive the token string from the "jwt" URI
306+
// TokenFromQuery tries to retrieve the token string from the "jwt" URI
307307
// query parameter.
308308
//
309309
// To use it, build our own middleware handler, such as:

jwtauth_test.go

Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -142,47 +142,37 @@ func TestSimple(t *testing.T) {
142142
ts := httptest.NewServer(r)
143143
defer ts.Close()
144144

145-
// sending unauthorized requests
146-
if status, resp := testRequest(t, ts, "GET", "/", nil, nil); status != 401 || resp != "no token found\n" {
147-
t.Fatalf(resp)
148-
}
149-
150-
h := http.Header{}
151-
h.Set("Authorization", "BEARER "+newJwtToken([]byte("wrong"), map[string]interface{}{}))
152-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 || resp != "token is unauthorized\n" {
153-
t.Fatalf(resp)
154-
}
155-
h.Set("Authorization", "BEARER asdf")
156-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 || resp != "token is unauthorized\n" {
157-
t.Fatalf(resp)
158-
}
159-
// wrong token secret and wrong alg
160-
h.Set("Authorization", "BEARER "+newJwt512Token([]byte("wrong"), map[string]interface{}{}))
161-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 || resp != "token is unauthorized\n" {
162-
t.Fatalf(resp)
163-
}
164-
// correct token secret but wrong alg
165-
h.Set("Authorization", "BEARER "+newJwt512Token(TokenSecret, map[string]interface{}{}))
166-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 || resp != "token is unauthorized\n" {
167-
t.Fatalf(resp)
168-
}
169-
170-
// correct token, but has expired within the skew time
171-
h.Set("Authorization", "BEARER "+newJwtToken(TokenSecret, map[string]interface{}{"exp": time.Now().Unix() - 29}))
172-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 200 || resp != "welcome" {
173-
fmt.Println("status", status, "resp", resp)
174-
t.Fatalf(resp)
175-
}
176-
177-
// correct token, but has expired outside of the skew time
178-
h.Set("Authorization", "BEARER "+newJwtToken(TokenSecret, map[string]interface{}{"exp": time.Now().Unix() - 31}))
179-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 || resp != "token is expired\n" {
180-
t.Fatalf(resp)
181-
}
182-
183-
// sending authorized requests
184-
if status, resp := testRequest(t, ts, "GET", "/", newAuthHeader(), nil); status != 200 || resp != "welcome" {
185-
t.Fatalf(resp)
145+
tt := []struct {
146+
Name string
147+
Authorization string
148+
Status int
149+
Resp string
150+
}{
151+
{Name: "empty token", Authorization: "", Status: 401, Resp: "no token found\n"},
152+
{Name: "wrong token", Authorization: "Bearer asdf", Status: 401, Resp: "token is unauthorized\n"},
153+
{Name: "wrong secret", Authorization: "Bearer " + newJwtToken([]byte("wrong")), Status: 401, Resp: "token is unauthorized\n"},
154+
{Name: "wrong secret/alg", Authorization: "Bearer " + newJwt512Token([]byte("wrong")), Status: 401, Resp: "token is unauthorized\n"},
155+
{Name: "wrong alg", Authorization: "Bearer " + newJwt512Token(TokenSecret, map[string]interface{}{}), Status: 401, Resp: "token is unauthorized\n"},
156+
{Name: "expired within skew", Authorization: "Bearer " + newJwtToken(TokenSecret, map[string]interface{}{"exp": time.Now().Unix() - 29}), Status: 200, Resp: "welcome"},
157+
{Name: "expired outside skew", Authorization: "Bearer " + newJwtToken(TokenSecret, map[string]interface{}{"exp": time.Now().Unix() - 31}), Status: 401, Resp: "token is expired\n"},
158+
{Name: "valid token", Authorization: "Bearer " + newJwtToken(TokenSecret), Status: 200, Resp: "welcome"},
159+
{Name: "valid Bearer", Authorization: "Bearer " + newJwtToken(TokenSecret, map[string]interface{}{"service": "test"}), Status: 200, Resp: "welcome"},
160+
{Name: "valid BEARER", Authorization: "BEARER " + newJwtToken(TokenSecret), Status: 200, Resp: "welcome"},
161+
{Name: "valid bearer", Authorization: "bearer " + newJwtToken(TokenSecret), Status: 200, Resp: "welcome"},
162+
{Name: "valid claim", Authorization: "Bearer " + newJwtToken(TokenSecret, map[string]interface{}{"service": "test"}), Status: 200, Resp: "welcome"},
163+
{Name: "invalid bearer_", Authorization: "BEARER_" + newJwtToken(TokenSecret), Status: 401, Resp: "no token found\n"},
164+
{Name: "invalid bearerx", Authorization: "BEARERx" + newJwtToken(TokenSecret), Status: 401, Resp: "no token found\n"},
165+
}
166+
167+
for _, tc := range tt {
168+
h := http.Header{}
169+
if tc.Authorization != "" {
170+
h.Set("Authorization", tc.Authorization)
171+
}
172+
status, resp := testRequest(t, ts, "GET", "/", h, nil)
173+
if status != tc.Status || resp != tc.Resp {
174+
t.Errorf("test '%s' failed: expected Status: %d %q, got %d %q", tc.Name, tc.Status, tc.Resp, status, resp)
175+
}
186176
}
187177
}
188178

0 commit comments

Comments
 (0)