git.iko.soy/typeable/oauth2-proxy
on master help sign in
Create generic Authorization Header constructor
commitd05e08cba3406cda261355324967ae33b2db16d2 authorJoel Speed <joel.speed@hotmail.co.uk> dateSun 17 May 2020, 16:34 (6 years ago) parent9a338d8
10 files changed+130−68
CHANGELOG.md+1 providers/azure.go+3−6 providers/digitalocean.go+2−11 providers/facebook.go+2−12 providers/github.go+14−13 providers/linkedin.go+9−9 providers/nextcloud.go+1−8 providers/oidc.go+1−9 providers/util.go+31 providers/util_test.go+66
CHANGELOG.md+1
@@ -11,6 +11,7 @@
1111
1212## Changes since v6.0.0
1313
14+- [#562](https://github.com/oauth2-proxy/oauth2-proxy/pull/562) Create generic Authorization Header constructor (@JoelSpeed)
1415- [#715](https://github.com/oauth2-proxy/oauth2-proxy/pull/715) Ensure session times are not nil before printing them (@JoelSpeed)
1516- [#714](https://github.com/oauth2-proxy/oauth2-proxy/pull/714) Support passwords with Redis session stores (@NickMeves)
1617- [#719](https://github.com/oauth2-proxy/oauth2-proxy/pull/719) Add Gosec fixes to areas that are intermittently flagged on PRs (@NickMeves)
providers/azure.go+3−6
@@ -4,7 +4,6 @@ import (
44 "bytes"
55 "context"
66 "errors"
7− "fmt"
87 "net/http"
98 "net/url"
109 "time"
@@ -154,10 +153,8 @@ func (p *AzureProvider) Redeem(ctx context.Context, redirectURL, code string) (s
154153 return
155154}
156155
157−func getAzureHeader(accessToken string) http.Header {
158− header := make(http.Header)
159− header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
160− return header
156+func makeAzureHeader(accessToken string) http.Header {
157+ return makeAuthorizationHeader(tokenTypeBearer, accessToken, nil)
161158}
162159
163160func getEmailFromJSON(json *simplejson.Json) (string, error) {
@@ -188,7 +185,7 @@ func (p *AzureProvider) GetEmailAddress(ctx context.Context, s *sessions.Session
188185
189186 json, err := requests.New(p.ProfileURL.String()).
190187 WithContext(ctx).
191− WithHeaders(getAzureHeader(s.AccessToken)).
188+ WithHeaders(makeAzureHeader(s.AccessToken)).
192189 Do().
193190 UnmarshalJSON()
194191 if err != nil {
providers/digitalocean.go+2−11
@@ -3,8 +3,6 @@ package providers
33import (
44 "context"
55 "errors"
6− "fmt"
7− "net/http"
86 "net/url"
97
108 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
@@ -62,13 +60,6 @@ func NewDigitalOceanProvider(p *ProviderData) *DigitalOceanProvider {
6260 return &DigitalOceanProvider{ProviderData: p}
6361}
6462
65−func getDigitalOceanHeader(accessToken string) http.Header {
66− header := make(http.Header)
67− header.Set("Content-Type", "application/json")
68− header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
69− return header
70−}
71−
7263// GetEmailAddress returns the Account email address
7364func (p *DigitalOceanProvider) GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error) {
7465 if s.AccessToken == "" {
@@ -77,7 +68,7 @@ func (p *DigitalOceanProvider) GetEmailAddress(ctx context.Context, s *sessions.
7768
7869 json, err := requests.New(p.ProfileURL.String()).
7970 WithContext(ctx).
80− WithHeaders(getDigitalOceanHeader(s.AccessToken)).
71+ WithHeaders(makeOIDCHeader(s.AccessToken)).
8172 Do().
8273 UnmarshalJSON()
8374 if err != nil {
@@ -93,5 +84,5 @@ func (p *DigitalOceanProvider) GetEmailAddress(ctx context.Context, s *sessions.
9384
9485// ValidateSessionState validates the AccessToken
9586func (p *DigitalOceanProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
96− return validateToken(ctx, p, s.AccessToken, getDigitalOceanHeader(s.AccessToken))
87+ return validateToken(ctx, p, s.AccessToken, makeOIDCHeader(s.AccessToken))
9788}
providers/facebook.go+2−12
@@ -3,8 +3,6 @@ package providers
33import (
44 "context"
55 "errors"
6− "fmt"
7− "net/http"
86 "net/url"
97
108 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
@@ -63,14 +61,6 @@ func NewFacebookProvider(p *ProviderData) *FacebookProvider {
6361 return &FacebookProvider{ProviderData: p}
6462}
6563
66−func getFacebookHeader(accessToken string) http.Header {
67− header := make(http.Header)
68− header.Set("Accept", "application/json")
69− header.Set("x-li-format", "json")
70− header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
71− return header
72−}
73−
7464// GetEmailAddress returns the Account email address
7565func (p *FacebookProvider) GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error) {
7666 if s.AccessToken == "" {
@@ -85,7 +75,7 @@ func (p *FacebookProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess
8575 requestURL := p.ProfileURL.String() + "?fields=name,email"
8676 err := requests.New(requestURL).
8777 WithContext(ctx).
88− WithHeaders(getFacebookHeader(s.AccessToken)).
78+ WithHeaders(makeOIDCHeader(s.AccessToken)).
8979 Do().
9080 UnmarshalInto(&r)
9181 if err != nil {
@@ -100,5 +90,5 @@ func (p *FacebookProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess
10090
10191// ValidateSessionState validates the AccessToken
10292func (p *FacebookProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
103− return validateToken(ctx, p, s.AccessToken, getFacebookHeader(s.AccessToken))
93+ return validateToken(ctx, p, s.AccessToken, makeOIDCHeader(s.AccessToken))
10494}
providers/github.go+14−13
@@ -74,11 +74,12 @@ func NewGitHubProvider(p *ProviderData) *GitHubProvider {
7474 return &GitHubProvider{ProviderData: p}
7575}
7676
77−func getGitHubHeader(accessToken string) http.Header {
78− header := make(http.Header)
79− header.Set("Accept", "application/vnd.github.v3+json")
80− header.Set("Authorization", fmt.Sprintf("token %s", accessToken))
81− return header
77+func makeGitHubHeader(accessToken string) http.Header {
78+ // extra headers required by the GitHub API when making authenticated requests
79+ extraHeaders := map[string]string{
80+ acceptHeader: "application/vnd.github.v3+json",
81+ }
82+ return makeAuthorizationHeader(tokenTypeToken, accessToken, extraHeaders)
8283}
8384
8485// SetOrgTeam adds GitHub org reading parameters to the OAuth2 scope
@@ -129,7 +130,7 @@ func (p *GitHubProvider) hasOrg(ctx context.Context, accessToken string) (bool,
129130 var op orgsPage
130131 err := requests.New(endpoint.String()).
131132 WithContext(ctx).
132− WithHeaders(getGitHubHeader(accessToken)).
133+ WithHeaders(makeGitHubHeader(accessToken)).
133134 Do().
134135 UnmarshalInto(&op)
135136 if err != nil {
@@ -196,7 +197,7 @@ func (p *GitHubProvider) hasOrgAndTeam(ctx context.Context, accessToken string)
196197 // nolint:bodyclose
197198 result := requests.New(endpoint.String()).
198199 WithContext(ctx).
199− WithHeaders(getGitHubHeader(accessToken)).
200+ WithHeaders(makeGitHubHeader(accessToken)).
200201 Do()
201202 if result.Error() != nil {
202203 return false, result.Error()
@@ -296,7 +297,7 @@ func (p *GitHubProvider) hasRepo(ctx context.Context, accessToken string) (bool,
296297 var repo repository
297298 err := requests.New(endpoint.String()).
298299 WithContext(ctx).
299− WithHeaders(getGitHubHeader(accessToken)).
300+ WithHeaders(makeGitHubHeader(accessToken)).
300301 Do().
301302 UnmarshalInto(&repo)
302303 if err != nil {
@@ -324,7 +325,7 @@ func (p *GitHubProvider) hasUser(ctx context.Context, accessToken string) (bool,
324325
325326 err := requests.New(endpoint.String()).
326327 WithContext(ctx).
327− WithHeaders(getGitHubHeader(accessToken)).
328+ WithHeaders(makeGitHubHeader(accessToken)).
328329 Do().
329330 UnmarshalInto(&user)
330331 if err != nil {
@@ -347,7 +348,7 @@ func (p *GitHubProvider) isCollaborator(ctx context.Context, username, accessTok
347348 }
348349 result := requests.New(endpoint.String()).
349350 WithContext(ctx).
350− WithHeaders(getGitHubHeader(accessToken)).
351+ WithHeaders(makeGitHubHeader(accessToken)).
351352 Do()
352353 if result.Error() != nil {
353354 return false, result.Error()
@@ -411,7 +412,7 @@ func (p *GitHubProvider) GetEmailAddress(ctx context.Context, s *sessions.Sessio
411412 }
412413 err := requests.New(endpoint.String()).
413414 WithContext(ctx).
414− WithHeaders(getGitHubHeader(s.AccessToken)).
415+ WithHeaders(makeGitHubHeader(s.AccessToken)).
415416 Do().
416417 UnmarshalInto(&emails)
417418 if err != nil {
@@ -446,7 +447,7 @@ func (p *GitHubProvider) GetUserName(ctx context.Context, s *sessions.SessionSta
446447
447448 err := requests.New(endpoint.String()).
448449 WithContext(ctx).
449− WithHeaders(getGitHubHeader(s.AccessToken)).
450+ WithHeaders(makeGitHubHeader(s.AccessToken)).
450451 Do().
451452 UnmarshalInto(&user)
452453 if err != nil {
@@ -465,7 +466,7 @@ func (p *GitHubProvider) GetUserName(ctx context.Context, s *sessions.SessionSta
465466
466467// ValidateSessionState validates the AccessToken
467468func (p *GitHubProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
468− return validateToken(ctx, p, s.AccessToken, getGitHubHeader(s.AccessToken))
469+ return validateToken(ctx, p, s.AccessToken, makeGitHubHeader(s.AccessToken))
469470}
470471
471472// isVerifiedUser
providers/linkedin.go+9−9
@@ -3,7 +3,6 @@ package providers
33import (
44 "context"
55 "errors"
6− "fmt"
76 "net/http"
87 "net/url"
98
@@ -62,12 +61,13 @@ func NewLinkedInProvider(p *ProviderData) *LinkedInProvider {
6261 return &LinkedInProvider{ProviderData: p}
6362}
6463
65−func getLinkedInHeader(accessToken string) http.Header {
66− header := make(http.Header)
67− header.Set("Accept", "application/json")
68− header.Set("x-li-format", "json")
69− header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
70− return header
64+func makeLinkedInHeader(accessToken string) http.Header {
65+ // extra headers required by the LinkedIn API when making authenticated requests
66+ extraHeaders := map[string]string{
67+ acceptHeader: acceptApplicationJSON,
68+ "x-li-format": "json",
69+ }
70+ return makeAuthorizationHeader(tokenTypeBearer, accessToken, extraHeaders)
7171}
7272
7373// GetEmailAddress returns the Account email address
@@ -79,7 +79,7 @@ func (p *LinkedInProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess
7979 requestURL := p.ProfileURL.String() + "?format=json"
8080 json, err := requests.New(requestURL).
8181 WithContext(ctx).
82− WithHeaders(getLinkedInHeader(s.AccessToken)).
82+ WithHeaders(makeLinkedInHeader(s.AccessToken)).
8383 Do().
8484 UnmarshalJSON()
8585 if err != nil {
@@ -95,5 +95,5 @@ func (p *LinkedInProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess
9595
9696// ValidateSessionState validates the AccessToken
9797func (p *LinkedInProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
98− return validateToken(ctx, p, s.AccessToken, getLinkedInHeader(s.AccessToken))
98+ return validateToken(ctx, p, s.AccessToken, makeLinkedInHeader(s.AccessToken))
9999}
providers/nextcloud.go+1−8
@@ -3,7 +3,6 @@ package providers
33import (
44 "context"
55 "fmt"
6− "net/http"
76
87 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
98 "github.com/oauth2-proxy/oauth2-proxy/pkg/requests"
@@ -24,17 +23,11 @@ func NewNextcloudProvider(p *ProviderData) *NextcloudProvider {
2423 return &NextcloudProvider{ProviderData: p}
2524}
2625
27−func getNextcloudHeader(accessToken string) http.Header {
28− header := make(http.Header)
29− header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
30− return header
31−}
32−
3326// GetEmailAddress returns the Account email address
3427func (p *NextcloudProvider) GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error) {
3528 json, err := requests.New(p.ValidateURL.String()).
3629 WithContext(ctx).
37− WithHeaders(getNextcloudHeader(s.AccessToken)).
30+ WithHeaders(makeOIDCHeader(s.AccessToken)).
3831 Do().
3932 UnmarshalJSON()
4033 if err != nil {
providers/oidc.go+1−9
@@ -3,7 +3,6 @@ package providers
33import (
44 "context"
55 "fmt"
6− "net/http"
76 "strings"
87 "time"
98
@@ -221,13 +220,6 @@ func (p *OIDCProvider) ValidateSessionState(ctx context.Context, s *sessions.Ses
221220 return err == nil
222221}
223222
224−func getOIDCHeader(accessToken string) http.Header {
225− header := make(http.Header)
226− header.Set("Accept", "application/json")
227− header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
228− return header
229−}
230−
231223func (p *OIDCProvider) findClaimsFromIDToken(ctx context.Context, idToken *oidc.IDToken, token *oauth2.Token) (*OIDCClaims, error) {
232224 claims := &OIDCClaims{}
233225 // Extract default claims.
@@ -263,7 +255,7 @@ func (p *OIDCProvider) findClaimsFromIDToken(ctx context.Context, idToken *oidc.
263255 // Make a query to the userinfo endpoint, and attempt to locate the email from there.
264256 respJSON, err := requests.New(profileURL).
265257 WithContext(ctx).
266− WithHeaders(getOIDCHeader(token.AccessToken)).
258+ WithHeaders(makeOIDCHeader(token.AccessToken)).
267259 Do().
268260 UnmarshalJSON()
269261 if err != nil {
providers/util.gonew file+31
@@ -0,0 +1,31 @@
1+package providers
2+
3+import (
4+ "fmt"
5+ "net/http"
6+)
7+
8+const (
9+ tokenTypeBearer = "Bearer"
10+ tokenTypeToken = "token"
11+
12+ acceptHeader = "Accept"
13+ acceptApplicationJSON = "application/json"
14+)
15+
16+func makeAuthorizationHeader(prefix, token string, extraHeaders map[string]string) http.Header {
17+ header := make(http.Header)
18+ for key, value := range extraHeaders {
19+ header.Add(key, value)
20+ }
21+ header.Set("Authorization", fmt.Sprintf("%s %s", prefix, token))
22+ return header
23+}
24+
25+func makeOIDCHeader(accessToken string) http.Header {
26+ // extra headers required by the IDP when making authenticated requests
27+ extraHeaders := map[string]string{
28+ acceptHeader: acceptApplicationJSON,
29+ }
30+ return makeAuthorizationHeader(tokenTypeBearer, accessToken, extraHeaders)
31+}
providers/util_test.gonew file+66
@@ -0,0 +1,66 @@
1+package providers
2+
3+import (
4+ "fmt"
5+ "testing"
6+
7+ . "github.com/onsi/gomega"
8+)
9+
10+func TestMakeAuhtorizationHeader(t *testing.T) {
11+ testCases := []struct {
12+ name string
13+ prefix string
14+ token string
15+ extraHeaders map[string]string
16+ }{
17+ {
18+ name: "With an empty prefix, token and no additional headers",
19+ prefix: "",
20+ token: "",
21+ extraHeaders: nil,
22+ },
23+ {
24+ name: "With a Bearer token type",
25+ prefix: tokenTypeBearer,
26+ token: "abcdef",
27+ extraHeaders: nil,
28+ },
29+ {
30+ name: "With a Token token type",
31+ prefix: tokenTypeToken,
32+ token: "123456",
33+ extraHeaders: nil,
34+ },
35+ {
36+ name: "With a Bearer token type and Accept application/json",
37+ prefix: tokenTypeToken,
38+ token: "abc",
39+ extraHeaders: map[string]string{
40+ acceptHeader: acceptApplicationJSON,
41+ },
42+ },
43+ {
44+ name: "With a Bearer token type and multiple headers",
45+ prefix: tokenTypeToken,
46+ token: "123",
47+ extraHeaders: map[string]string{
48+ acceptHeader: acceptApplicationJSON,
49+ "foo": "bar",
50+ "key": "value",
51+ },
52+ },
53+ }
54+
55+ for _, tc := range testCases {
56+ t.Run(tc.name, func(t *testing.T) {
57+ g := NewWithT(t)
58+
59+ header := makeAuthorizationHeader(tc.prefix, tc.token, tc.extraHeaders)
60+ g.Expect(header.Get("Authorization")).To(Equal(fmt.Sprintf("%s %s", tc.prefix, tc.token)))
61+ for k, v := range tc.extraHeaders {
62+ g.Expect(header.Get(k)).To(Equal(v))
63+ }
64+ })
65+ }
66+}