git.iko.soy/typeable/oauth2-proxy
on master help sign in
Create generic Authorization Header constructor
d05e08cJoel Speed
CHANGELOG.md+1
@@ -11,6 +11,7 @@
11
11
12## Changes since v6.0.0
12## Changes since v6.0.0
13
13
14+- [#562](https://github.com/oauth2-proxy/oauth2-proxy/pull/562) Create generic Authorization Header constructor (@JoelSpeed)
14- [#715](https://github.com/oauth2-proxy/oauth2-proxy/pull/715) Ensure session times are not nil before printing them (@JoelSpeed)
15- [#715](https://github.com/oauth2-proxy/oauth2-proxy/pull/715) Ensure session times are not nil before printing them (@JoelSpeed)
15- [#714](https://github.com/oauth2-proxy/oauth2-proxy/pull/714) Support passwords with Redis session stores (@NickMeves)
16- [#714](https://github.com/oauth2-proxy/oauth2-proxy/pull/714) Support passwords with Redis session stores (@NickMeves)
16- [#719](https://github.com/oauth2-proxy/oauth2-proxy/pull/719) Add Gosec fixes to areas that are intermittently flagged on PRs (@NickMeves)
17- [#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 (
4 "bytes"
4 "bytes"
5 "context"
5 "context"
6 "errors"
6 "errors"
7− "fmt"
8 "net/http"
7 "net/http"
9 "net/url"
8 "net/url"
10 "time"
9 "time"
@@ -154,10 +153,8 @@ func (p *AzureProvider) Redeem(ctx context.Context, redirectURL, code string) (s
154 return
153 return
155}
154}
156
155
157−func getAzureHeader(accessToken string) http.Header {
156+func makeAzureHeader(accessToken string) http.Header {
158− header := make(http.Header)
157+ return makeAuthorizationHeader(tokenTypeBearer, accessToken, nil)
159− header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
160− return header
161}
158}
162
159
163func getEmailFromJSON(json *simplejson.Json) (string, error) {
160func getEmailFromJSON(json *simplejson.Json) (string, error) {
@@ -188,7 +185,7 @@ func (p *AzureProvider) GetEmailAddress(ctx context.Context, s *sessions.Session
188
185
189 json, err := requests.New(p.ProfileURL.String()).
186 json, err := requests.New(p.ProfileURL.String()).
190 WithContext(ctx).
187 WithContext(ctx).
191− WithHeaders(getAzureHeader(s.AccessToken)).
188+ WithHeaders(makeAzureHeader(s.AccessToken)).
192 Do().
189 Do().
193 UnmarshalJSON()
190 UnmarshalJSON()
194 if err != nil {
191 if err != nil {
providers/digitalocean.go+2−11
@@ -3,8 +3,6 @@ package providers
3import (
3import (
4 "context"
4 "context"
5 "errors"
5 "errors"
6− "fmt"
7− "net/http"
8 "net/url"
6 "net/url"
9
7
10 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
8 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
@@ -62,13 +60,6 @@ func NewDigitalOceanProvider(p *ProviderData) *DigitalOceanProvider {
62 return &DigitalOceanProvider{ProviderData: p}
60 return &DigitalOceanProvider{ProviderData: p}
63}
61}
64
62
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−
72// GetEmailAddress returns the Account email address
63// GetEmailAddress returns the Account email address
73func (p *DigitalOceanProvider) GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error) {
64func (p *DigitalOceanProvider) GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error) {
74 if s.AccessToken == "" {
65 if s.AccessToken == "" {
@@ -77,7 +68,7 @@ func (p *DigitalOceanProvider) GetEmailAddress(ctx context.Context, s *sessions.
77
68
78 json, err := requests.New(p.ProfileURL.String()).
69 json, err := requests.New(p.ProfileURL.String()).
79 WithContext(ctx).
70 WithContext(ctx).
80− WithHeaders(getDigitalOceanHeader(s.AccessToken)).
71+ WithHeaders(makeOIDCHeader(s.AccessToken)).
81 Do().
72 Do().
82 UnmarshalJSON()
73 UnmarshalJSON()
83 if err != nil {
74 if err != nil {
@@ -93,5 +84,5 @@ func (p *DigitalOceanProvider) GetEmailAddress(ctx context.Context, s *sessions.
93
84
94// ValidateSessionState validates the AccessToken
85// ValidateSessionState validates the AccessToken
95func (p *DigitalOceanProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
86func (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))
97}
88}
providers/facebook.go+2−12
@@ -3,8 +3,6 @@ package providers
3import (
3import (
4 "context"
4 "context"
5 "errors"
5 "errors"
6− "fmt"
7− "net/http"
8 "net/url"
6 "net/url"
9
7
10 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
8 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
@@ -63,14 +61,6 @@ func NewFacebookProvider(p *ProviderData) *FacebookProvider {
63 return &FacebookProvider{ProviderData: p}
61 return &FacebookProvider{ProviderData: p}
64}
62}
65
63
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−
74// GetEmailAddress returns the Account email address
64// GetEmailAddress returns the Account email address
75func (p *FacebookProvider) GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error) {
65func (p *FacebookProvider) GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error) {
76 if s.AccessToken == "" {
66 if s.AccessToken == "" {
@@ -85,7 +75,7 @@ func (p *FacebookProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess
85 requestURL := p.ProfileURL.String() + "?fields=name,email"
75 requestURL := p.ProfileURL.String() + "?fields=name,email"
86 err := requests.New(requestURL).
76 err := requests.New(requestURL).
87 WithContext(ctx).
77 WithContext(ctx).
88− WithHeaders(getFacebookHeader(s.AccessToken)).
78+ WithHeaders(makeOIDCHeader(s.AccessToken)).
89 Do().
79 Do().
90 UnmarshalInto(&r)
80 UnmarshalInto(&r)
91 if err != nil {
81 if err != nil {
@@ -100,5 +90,5 @@ func (p *FacebookProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess
100
90
101// ValidateSessionState validates the AccessToken
91// ValidateSessionState validates the AccessToken
102func (p *FacebookProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
92func (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))
104}
94}
providers/github.go+14−13
@@ -74,11 +74,12 @@ func NewGitHubProvider(p *ProviderData) *GitHubProvider {
74 return &GitHubProvider{ProviderData: p}
74 return &GitHubProvider{ProviderData: p}
75}
75}
76
76
77−func getGitHubHeader(accessToken string) http.Header {
77+func makeGitHubHeader(accessToken string) http.Header {
78− header := make(http.Header)
78+ // extra headers required by the GitHub API when making authenticated requests
79+ extraHeaders := map[string]string{
79− header.Set("Accept", "application/vnd.github.v3+json")
80+ acceptHeader: "application/vnd.github.v3+json",
80− header.Set("Authorization", fmt.Sprintf("token %s", accessToken))
81+ }
81− return header
82+ return makeAuthorizationHeader(tokenTypeToken, accessToken, extraHeaders)
82}
83}
83
84
84// SetOrgTeam adds GitHub org reading parameters to the OAuth2 scope
85// SetOrgTeam adds GitHub org reading parameters to the OAuth2 scope
@@ -129,7 +130,7 @@ func (p *GitHubProvider) hasOrg(ctx context.Context, accessToken string) (bool,
129 var op orgsPage
130 var op orgsPage
130 err := requests.New(endpoint.String()).
131 err := requests.New(endpoint.String()).
131 WithContext(ctx).
132 WithContext(ctx).
132− WithHeaders(getGitHubHeader(accessToken)).
133+ WithHeaders(makeGitHubHeader(accessToken)).
133 Do().
134 Do().
134 UnmarshalInto(&op)
135 UnmarshalInto(&op)
135 if err != nil {
136 if err != nil {
@@ -196,7 +197,7 @@ func (p *GitHubProvider) hasOrgAndTeam(ctx context.Context, accessToken string)
196 // nolint:bodyclose
197 // nolint:bodyclose
197 result := requests.New(endpoint.String()).
198 result := requests.New(endpoint.String()).
198 WithContext(ctx).
199 WithContext(ctx).
199− WithHeaders(getGitHubHeader(accessToken)).
200+ WithHeaders(makeGitHubHeader(accessToken)).
200 Do()
201 Do()
201 if result.Error() != nil {
202 if result.Error() != nil {
202 return false, result.Error()
203 return false, result.Error()
@@ -296,7 +297,7 @@ func (p *GitHubProvider) hasRepo(ctx context.Context, accessToken string) (bool,
296 var repo repository
297 var repo repository
297 err := requests.New(endpoint.String()).
298 err := requests.New(endpoint.String()).
298 WithContext(ctx).
299 WithContext(ctx).
299− WithHeaders(getGitHubHeader(accessToken)).
300+ WithHeaders(makeGitHubHeader(accessToken)).
300 Do().
301 Do().
301 UnmarshalInto(&repo)
302 UnmarshalInto(&repo)
302 if err != nil {
303 if err != nil {
@@ -324,7 +325,7 @@ func (p *GitHubProvider) hasUser(ctx context.Context, accessToken string) (bool,
324
325
325 err := requests.New(endpoint.String()).
326 err := requests.New(endpoint.String()).
326 WithContext(ctx).
327 WithContext(ctx).
327− WithHeaders(getGitHubHeader(accessToken)).
328+ WithHeaders(makeGitHubHeader(accessToken)).
328 Do().
329 Do().
329 UnmarshalInto(&user)
330 UnmarshalInto(&user)
330 if err != nil {
331 if err != nil {
@@ -347,7 +348,7 @@ func (p *GitHubProvider) isCollaborator(ctx context.Context, username, accessTok
347 }
348 }
348 result := requests.New(endpoint.String()).
349 result := requests.New(endpoint.String()).
349 WithContext(ctx).
350 WithContext(ctx).
350− WithHeaders(getGitHubHeader(accessToken)).
351+ WithHeaders(makeGitHubHeader(accessToken)).
351 Do()
352 Do()
352 if result.Error() != nil {
353 if result.Error() != nil {
353 return false, result.Error()
354 return false, result.Error()
@@ -411,7 +412,7 @@ func (p *GitHubProvider) GetEmailAddress(ctx context.Context, s *sessions.Sessio
411 }
412 }
412 err := requests.New(endpoint.String()).
413 err := requests.New(endpoint.String()).
413 WithContext(ctx).
414 WithContext(ctx).
414− WithHeaders(getGitHubHeader(s.AccessToken)).
415+ WithHeaders(makeGitHubHeader(s.AccessToken)).
415 Do().
416 Do().
416 UnmarshalInto(&emails)
417 UnmarshalInto(&emails)
417 if err != nil {
418 if err != nil {
@@ -446,7 +447,7 @@ func (p *GitHubProvider) GetUserName(ctx context.Context, s *sessions.SessionSta
446
447
447 err := requests.New(endpoint.String()).
448 err := requests.New(endpoint.String()).
448 WithContext(ctx).
449 WithContext(ctx).
449− WithHeaders(getGitHubHeader(s.AccessToken)).
450+ WithHeaders(makeGitHubHeader(s.AccessToken)).
450 Do().
451 Do().
451 UnmarshalInto(&user)
452 UnmarshalInto(&user)
452 if err != nil {
453 if err != nil {
@@ -465,7 +466,7 @@ func (p *GitHubProvider) GetUserName(ctx context.Context, s *sessions.SessionSta
465
466
466// ValidateSessionState validates the AccessToken
467// ValidateSessionState validates the AccessToken
467func (p *GitHubProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
468func (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))
469}
470}
470
471
471// isVerifiedUser
472// isVerifiedUser
providers/linkedin.go+9−9
@@ -3,7 +3,6 @@ package providers
3import (
3import (
4 "context"
4 "context"
5 "errors"
5 "errors"
6− "fmt"
7 "net/http"
6 "net/http"
8 "net/url"
7 "net/url"
9
8
@@ -62,12 +61,13 @@ func NewLinkedInProvider(p *ProviderData) *LinkedInProvider {
62 return &LinkedInProvider{ProviderData: p}
61 return &LinkedInProvider{ProviderData: p}
63}
62}
64
63
65−func getLinkedInHeader(accessToken string) http.Header {
64+func makeLinkedInHeader(accessToken string) http.Header {
66− header := make(http.Header)
65+ // extra headers required by the LinkedIn API when making authenticated requests
67− header.Set("Accept", "application/json")
66+ extraHeaders := map[string]string{
67+ acceptHeader: acceptApplicationJSON,
68− header.Set("x-li-format", "json")
68+ "x-li-format": "json",
69− header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
69+ }
70− return header
70+ return makeAuthorizationHeader(tokenTypeBearer, accessToken, extraHeaders)
71}
71}
72
72
73// GetEmailAddress returns the Account email address
73// GetEmailAddress returns the Account email address
@@ -79,7 +79,7 @@ func (p *LinkedInProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess
79 requestURL := p.ProfileURL.String() + "?format=json"
79 requestURL := p.ProfileURL.String() + "?format=json"
80 json, err := requests.New(requestURL).
80 json, err := requests.New(requestURL).
81 WithContext(ctx).
81 WithContext(ctx).
82− WithHeaders(getLinkedInHeader(s.AccessToken)).
82+ WithHeaders(makeLinkedInHeader(s.AccessToken)).
83 Do().
83 Do().
84 UnmarshalJSON()
84 UnmarshalJSON()
85 if err != nil {
85 if err != nil {
@@ -95,5 +95,5 @@ func (p *LinkedInProvider) GetEmailAddress(ctx context.Context, s *sessions.Sess
95
95
96// ValidateSessionState validates the AccessToken
96// ValidateSessionState validates the AccessToken
97func (p *LinkedInProvider) ValidateSessionState(ctx context.Context, s *sessions.SessionState) bool {
97func (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))
99}
99}
providers/nextcloud.go+1−8
@@ -3,7 +3,6 @@ package providers
3import (
3import (
4 "context"
4 "context"
5 "fmt"
5 "fmt"
6− "net/http"
7
6
8 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
7 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
9 "github.com/oauth2-proxy/oauth2-proxy/pkg/requests"
8 "github.com/oauth2-proxy/oauth2-proxy/pkg/requests"
@@ -24,17 +23,11 @@ func NewNextcloudProvider(p *ProviderData) *NextcloudProvider {
24 return &NextcloudProvider{ProviderData: p}
23 return &NextcloudProvider{ProviderData: p}
25}
24}
26
25
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−
33// GetEmailAddress returns the Account email address
26// GetEmailAddress returns the Account email address
34func (p *NextcloudProvider) GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error) {
27func (p *NextcloudProvider) GetEmailAddress(ctx context.Context, s *sessions.SessionState) (string, error) {
35 json, err := requests.New(p.ValidateURL.String()).
28 json, err := requests.New(p.ValidateURL.String()).
36 WithContext(ctx).
29 WithContext(ctx).
37− WithHeaders(getNextcloudHeader(s.AccessToken)).
30+ WithHeaders(makeOIDCHeader(s.AccessToken)).
38 Do().
31 Do().
39 UnmarshalJSON()
32 UnmarshalJSON()
40 if err != nil {
33 if err != nil {
providers/oidc.go+1−9
@@ -3,7 +3,6 @@ package providers
3import (
3import (
4 "context"
4 "context"
5 "fmt"
5 "fmt"
6− "net/http"
7 "strings"
6 "strings"
8 "time"
7 "time"
9
8
@@ -221,13 +220,6 @@ func (p *OIDCProvider) ValidateSessionState(ctx context.Context, s *sessions.Ses
221 return err == nil
220 return err == nil
222}
221}
223
222
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−
231func (p *OIDCProvider) findClaimsFromIDToken(ctx context.Context, idToken *oidc.IDToken, token *oauth2.Token) (*OIDCClaims, error) {
223func (p *OIDCProvider) findClaimsFromIDToken(ctx context.Context, idToken *oidc.IDToken, token *oauth2.Token) (*OIDCClaims, error) {
232 claims := &OIDCClaims{}
224 claims := &OIDCClaims{}
233 // Extract default claims.
225 // Extract default claims.
@@ -263,7 +255,7 @@ func (p *OIDCProvider) findClaimsFromIDToken(ctx context.Context, idToken *oidc.
263 // Make a query to the userinfo endpoint, and attempt to locate the email from there.
255 // Make a query to the userinfo endpoint, and attempt to locate the email from there.
264 respJSON, err := requests.New(profileURL).
256 respJSON, err := requests.New(profileURL).
265 WithContext(ctx).
257 WithContext(ctx).
266− WithHeaders(getOIDCHeader(token.AccessToken)).
258+ WithHeaders(makeOIDCHeader(token.AccessToken)).
267 Do().
259 Do().
268 UnmarshalJSON()
260 UnmarshalJSON()
269 if err != nil {
261 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+}