From 58cc0dce95b4276007448e3e9e87af683a155455 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Tue, 11 Apr 2017 00:16:14 +0200 Subject: [PATCH] Get the token from the access_token query parameter Signed-off-by: Jan Olszak --- introspect.go | 12 +++++++++++- introspect_test.go | 35 +++++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/introspect.go b/introspect.go index 408f98e99..61ac9fc7d 100644 --- a/introspect.go +++ b/introspect.go @@ -13,10 +13,20 @@ type TokenIntrospector interface { } func AccessTokenFromRequest(req *http.Request) string { + // Acording to https://tools.ietf.org/html/rfc6750 you can pass tokens through: + // - Form-Encoded Body Parameter. Recomended, more likely to appear. e.g.: Authorization: Bearer mytoken123 + // - URI Query Parameter e.g. access_token=mytoken123 + auth := req.Header.Get("Authorization") split := strings.SplitN(auth, " ", 2) if len(split) != 2 || !strings.EqualFold(split[0], "bearer") { - return "" + // Nothing in Authorization header, try access_token + // Empty string returned if there's no such parameter + err := req.ParseForm() + if err != nil { + return "" + } + return req.Form.Get("access_token") } return split[1] diff --git a/introspect_test.go b/introspect_test.go index 16d4b4d05..8e6da4acf 100644 --- a/introspect_test.go +++ b/introspect_test.go @@ -2,7 +2,6 @@ package fosite_test import ( "net/http" - "net/url" "testing" "github.com/golang/mock/gomock" @@ -15,18 +14,38 @@ import ( "golang.org/x/net/context" ) +func TestAccessTokenFromRequestNoToken(t *testing.T) { + req, _ := http.NewRequest("GET", "http://example.com/test", nil) + + assert.Equal(t, AccessTokenFromRequest(req), "", "No token should produce an empty string") +} + +func TestAccessTokenFromRequestHeader(t *testing.T) { + token := "TokenFromHeader" + + req, _ := http.NewRequest("GET", "http://example.com/test", nil) + req.Header.Add("Authorization", "Bearer "+token) + + assert.Equal(t, AccessTokenFromRequest(req), token, "Token should be obtainable from header") +} + +func TestAccessTokenFromRequestQuery(t *testing.T) { + token := "TokenFromQueryParam" + + req, _ := http.NewRequest("GET", "http://example.com/test?access_token="+token, nil) + + assert.Equal(t, AccessTokenFromRequest(req), token, "Token should be obtainable from access_token query parameter") +} + func TestIntrospect(t *testing.T) { ctrl := gomock.NewController(t) validator := internal.NewMockTokenIntrospector(ctrl) defer ctrl.Finish() f := compose.ComposeAllEnabled(new(compose.Config), storage.NewMemoryStore(), []byte{}, nil).(*Fosite) - httpreq := &http.Request{ - Header: http.Header{ - "Authorization": []string{"bearer some-token"}, - }, - Form: url.Values{}, - } + + req, _ := http.NewRequest("GET", "http://example.com/test", nil) + req.Header.Add("Authorization", "bearer some-token") for k, c := range []struct { description string @@ -77,7 +96,7 @@ func TestIntrospect(t *testing.T) { }, } { c.setup() - _, err := f.IntrospectToken(nil, AccessTokenFromRequest(httpreq), AccessToken, nil, c.scopes...) + _, err := f.IntrospectToken(nil, AccessTokenFromRequest(req), AccessToken, nil, c.scopes...) assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) t.Logf("Passed test case %d", k) }