Skip to content

Commit fdaf0eb

Browse files
authored
Implement a BearerExtractor (#226)
* Implement a BearerExtractor This is a rather common extractor; it extracts the JWT from the HTTP Authorization header, expecting it to include the "Bearer " prefix. This patterns is rather common and this snippet is repeated in enough applications that it's probably best to just include it upstream and allow reusing it. * Ignore case-sensitivity for "Bearer"
1 parent f2878bb commit fdaf0eb

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

request/extractor.go

+16
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package request
33
import (
44
"errors"
55
"net/http"
6+
"strings"
67
)
78

89
// Errors
@@ -79,3 +80,18 @@ func (e *PostExtractionFilter) ExtractToken(req *http.Request) (string, error) {
7980
return "", err
8081
}
8182
}
83+
84+
// BearerExtractor extracts a token from the Authorization header.
85+
// The header is expected to match the format "Bearer XX", where "XX" is the
86+
// JWT token.
87+
type BearerExtractor struct{}
88+
89+
func (e BearerExtractor) ExtractToken(req *http.Request) (string, error) {
90+
tokenHeader := req.Header.Get("Authorization")
91+
// The usual convention is for "Bearer" to be title-cased. However, there's no
92+
// strict rule around this, and it's best to follow the robustness principle here.
93+
if tokenHeader == "" || !strings.HasPrefix(strings.ToLower(tokenHeader), "bearer ") {
94+
return "", ErrNoTokenInRequest
95+
}
96+
return tokenHeader[7:], nil
97+
}

request/extractor_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,23 @@ func makeExampleRequest(method, path string, headers map[string]string, urlArgs
8989
}
9090
return r
9191
}
92+
93+
func TestBearerExtractor(t *testing.T) {
94+
request := makeExampleRequest("POST", "https://example.com/", map[string]string{"Authorization": "Bearer ToKen"}, nil)
95+
token, err := BearerExtractor{}.ExtractToken(request)
96+
if err != nil || token != "ToKen" {
97+
t.Errorf("ExtractToken did not return token, returned: %v, %v", token, err)
98+
}
99+
100+
request = makeExampleRequest("POST", "https://example.com/", map[string]string{"Authorization": "Bearo ToKen"}, nil)
101+
token, err = BearerExtractor{}.ExtractToken(request)
102+
if err == nil || token != "" {
103+
t.Errorf("ExtractToken did not return error, returned: %v, %v", token, err)
104+
}
105+
106+
request = makeExampleRequest("POST", "https://example.com/", map[string]string{"Authorization": "BeArEr HeLO"}, nil)
107+
token, err = BearerExtractor{}.ExtractToken(request)
108+
if err != nil || token != "HeLO" {
109+
t.Errorf("ExtractToken did not return token, returned: %v, %v", token, err)
110+
}
111+
}

0 commit comments

Comments
 (0)