Skip to content

Commit 81e4c11

Browse files
authored
Fix invalid Bearer prefix format (wrong character instead of a space) (#99)
* Rewrite simple tests to table-driven tests * Add tests cases for invalid Bearer prefixes * Disallow invalid character after BEARER prefix
1 parent 6c2409e commit 81e4c11

File tree

2 files changed

+32
-42
lines changed

2 files changed

+32
-42
lines changed

jwtauth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ func TokenFromCookie(r *http.Request) string {
268268
func TokenFromHeader(r *http.Request) string {
269269
// Get token from authorization header.
270270
bearer := r.Header.Get("Authorization")
271-
if len(bearer) > 7 && strings.ToUpper(bearer[0:6]) == "BEARER" {
271+
if len(bearer) > 7 && strings.ToUpper(bearer[0:7]) == "BEARER " {
272272
return bearer[7:]
273273
}
274274
return ""

jwtauth_test.go

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

69-
// sending unauthorized requests
70-
if status, resp := testRequest(t, ts, "GET", "/", nil, nil); status != 401 || resp != "no token found\n" {
71-
t.Fatalf(resp)
72-
}
73-
74-
h := http.Header{}
75-
h.Set("Authorization", "BEARER "+newJwtToken([]byte("wrong"), map[string]interface{}{}))
76-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 || resp != "token is unauthorized\n" {
77-
t.Fatalf(resp)
78-
}
79-
h.Set("Authorization", "BEARER asdf")
80-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 || resp != "token is unauthorized\n" {
81-
t.Fatalf(resp)
82-
}
83-
// wrong token secret and wrong alg
84-
h.Set("Authorization", "BEARER "+newJwt512Token([]byte("wrong"), map[string]interface{}{}))
85-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 || resp != "token is unauthorized\n" {
86-
t.Fatalf(resp)
87-
}
88-
// correct token secret but wrong alg
89-
h.Set("Authorization", "BEARER "+newJwt512Token(TokenSecret, map[string]interface{}{}))
90-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 || resp != "token is unauthorized\n" {
91-
t.Fatalf(resp)
92-
}
93-
94-
// correct token, but has expired within the skew time
95-
h.Set("Authorization", "BEARER "+newJwtToken(TokenSecret, map[string]interface{}{"exp": time.Now().Unix() - 29}))
96-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 200 || resp != "welcome" {
97-
fmt.Println("status", status, "resp", resp)
98-
t.Fatalf(resp)
99-
}
100-
101-
// correct token, but has expired outside of the skew time
102-
h.Set("Authorization", "BEARER "+newJwtToken(TokenSecret, map[string]interface{}{"exp": time.Now().Unix() - 31}))
103-
if status, resp := testRequest(t, ts, "GET", "/", h, nil); status != 401 || resp != "token is expired\n" {
104-
t.Fatalf(resp)
105-
}
106-
107-
// sending authorized requests
108-
if status, resp := testRequest(t, ts, "GET", "/", newAuthHeader(), nil); status != 200 || resp != "welcome" {
109-
t.Fatalf(resp)
69+
tt := []struct {
70+
Name string
71+
Authorization string
72+
Status int
73+
Resp string
74+
}{
75+
{Name: "empty token", Authorization: "", Status: 401, Resp: "no token found\n"},
76+
{Name: "wrong token", Authorization: "Bearer asdf", Status: 401, Resp: "token is unauthorized\n"},
77+
{Name: "wrong secret", Authorization: "Bearer " + newJwtToken([]byte("wrong")), Status: 401, Resp: "token is unauthorized\n"},
78+
{Name: "wrong secret/alg", Authorization: "Bearer " + newJwt512Token([]byte("wrong")), Status: 401, Resp: "token is unauthorized\n"},
79+
{Name: "wrong alg", Authorization: "Bearer " + newJwt512Token(TokenSecret, map[string]interface{}{}), Status: 401, Resp: "token is unauthorized\n"},
80+
{Name: "expired within skew", Authorization: "Bearer " + newJwtToken(TokenSecret, map[string]interface{}{"exp": time.Now().Unix() - 29}), Status: 200, Resp: "welcome"},
81+
{Name: "expired outside skew", Authorization: "Bearer " + newJwtToken(TokenSecret, map[string]interface{}{"exp": time.Now().Unix() - 31}), Status: 401, Resp: "token is expired\n"},
82+
{Name: "valid token", Authorization: "Bearer " + newJwtToken(TokenSecret), Status: 200, Resp: "welcome"},
83+
{Name: "valid Bearer", Authorization: "Bearer " + newJwtToken(TokenSecret, map[string]interface{}{"service": "test"}), Status: 200, Resp: "welcome"},
84+
{Name: "valid BEARER", Authorization: "BEARER " + newJwtToken(TokenSecret), Status: 200, Resp: "welcome"},
85+
{Name: "valid bearer", Authorization: "bearer " + newJwtToken(TokenSecret), Status: 200, Resp: "welcome"},
86+
{Name: "valid claim", Authorization: "Bearer " + newJwtToken(TokenSecret, map[string]interface{}{"service": "test"}), Status: 200, Resp: "welcome"},
87+
{Name: "invalid bearer_", Authorization: "BEARER_" + newJwtToken(TokenSecret), Status: 401, Resp: "no token found\n"},
88+
{Name: "invalid bearerx", Authorization: "BEARERx" + newJwtToken(TokenSecret), Status: 401, Resp: "no token found\n"},
89+
}
90+
91+
for _, tc := range tt {
92+
h := http.Header{}
93+
if tc.Authorization != "" {
94+
h.Set("Authorization", tc.Authorization)
95+
}
96+
status, resp := testRequest(t, ts, "GET", "/", h, nil)
97+
if status != tc.Status || resp != tc.Resp {
98+
t.Errorf("test '%s' failed: expected Status: %d %q, got %d %q", tc.Name, tc.Status, tc.Resp, status, resp)
99+
}
110100
}
111101
}
112102

0 commit comments

Comments
 (0)