git.iko.soy/typeable/oauth2-proxy
on 01da2ac help sign in
442 lines 13 kB history raw
1package providers
3import (
4 "context"
5 "net/http"
6 "net/http/httptest"
7 "net/url"
8 "testing"
10 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
11 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
12 . "github.com/onsi/gomega"
13 "github.com/stretchr/testify/assert"
16func testGitHubProvider(hostname string, opts options.GitHubOptions) *GitHubProvider {
17 p := NewGitHubProvider(
18 &ProviderData{
19 ProviderName: "",
20 LoginURL: &url.URL{},
21 RedeemURL: &url.URL{},
22 ProfileURL: &url.URL{},
23 ValidateURL: &url.URL{},
24 Scope: ""},
25 opts)
26 if hostname != "" {
27 updateURL(p.Data().LoginURL, hostname)
28 updateURL(p.Data().RedeemURL, hostname)
29 updateURL(p.Data().ProfileURL, hostname)
30 updateURL(p.Data().ValidateURL, hostname)
31 }
32 return p
35func testGitHubBackend(payloads map[string][]string) *httptest.Server {
36 pathToQueryMap := map[string][]string{
37 "/repos/oauth2-proxy/oauth2-proxy": {""},
38 "/repos/oauth2-proxy/oauth2-proxy/collaborators/mbland": {""},
39 "/user": {""},
40 "/user/emails": {""},
41 "/user/orgs": {"page=1&per_page=100", "page=2&per_page=100", "page=3&per_page=100"},
42 }
44 return httptest.NewServer(http.HandlerFunc(
45 func(w http.ResponseWriter, r *http.Request) {
46 query, ok := pathToQueryMap[r.URL.Path]
47 validQuery := false
48 index := 0
49 for i, q := range query {
50 if q == r.URL.RawQuery {
51 validQuery = true
52 index = i
53 }
54 }
55 payload := []string{}
56 if ok && validQuery {
57 payload, ok = payloads[r.URL.Path]
58 }
59 if !ok {
60 w.WriteHeader(404)
61 } else if !validQuery {
62 w.WriteHeader(404)
63 } else if payload[index] == "" {
64 w.WriteHeader(204)
65 } else {
66 w.WriteHeader(200)
67 w.Write([]byte(payload[index]))
68 }
69 }))
72func TestNewGitHubProvider(t *testing.T) {
73 g := NewWithT(t)
75 // Test that defaults are set when calling for a new provider with nothing set
76 providerData := NewGitHubProvider(&ProviderData{}, options.GitHubOptions{}).Data()
77 g.Expect(providerData.ProviderName).To(Equal("GitHub"))
78 g.Expect(providerData.LoginURL.String()).To(Equal("https://github.com/login/oauth/authorize"))
79 g.Expect(providerData.RedeemURL.String()).To(Equal("https://github.com/login/oauth/access_token"))
80 g.Expect(providerData.ProfileURL.String()).To(Equal(""))
81 g.Expect(providerData.ValidateURL.String()).To(Equal("https://api.github.com/"))
82 g.Expect(providerData.Scope).To(Equal("user:email"))
85func TestGitHubProviderOverrides(t *testing.T) {
86 p := NewGitHubProvider(
87 &ProviderData{
88 LoginURL: &url.URL{
89 Scheme: "https",
90 Host: "example.com",
91 Path: "/login/oauth/authorize"},
92 RedeemURL: &url.URL{
93 Scheme: "https",
94 Host: "example.com",
95 Path: "/login/oauth/access_token"},
96 ValidateURL: &url.URL{
97 Scheme: "https",
98 Host: "api.example.com",
99 Path: "/"},
100 Scope: "profile"},
101 options.GitHubOptions{})
102 assert.NotEqual(t, nil, p)
103 assert.Equal(t, "GitHub", p.Data().ProviderName)
104 assert.Equal(t, "https://example.com/login/oauth/authorize",
105 p.Data().LoginURL.String())
106 assert.Equal(t, "https://example.com/login/oauth/access_token",
107 p.Data().RedeemURL.String())
108 assert.Equal(t, "https://api.example.com/",
109 p.Data().ValidateURL.String())
110 assert.Equal(t, "profile", p.Data().Scope)
113func TestGitHubProvider_getEmail(t *testing.T) {
114 b := testGitHubBackend(map[string][]string{
115 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
116 })
117 defer b.Close()
119 bURL, _ := url.Parse(b.URL)
120 p := testGitHubProvider(bURL.Host, options.GitHubOptions{})
122 session := CreateAuthorizedSession()
123 err := p.getEmail(context.Background(), session)
124 assert.NoError(t, err)
125 assert.Equal(t, "michael.bland@gsa.gov", session.Email)
128func TestGitHubProvider_getEmailNotVerified(t *testing.T) {
129 b := testGitHubBackend(map[string][]string{
130 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": false, "primary": true} ]`},
131 })
132 defer b.Close()
134 bURL, _ := url.Parse(b.URL)
135 p := testGitHubProvider(bURL.Host, options.GitHubOptions{})
137 session := CreateAuthorizedSession()
138 err := p.getEmail(context.Background(), session)
139 assert.NoError(t, err)
140 assert.Empty(t, session.Email)
143func TestGitHubProvider_getEmailWithOrg(t *testing.T) {
144 b := testGitHubBackend(map[string][]string{
145 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
146 "/user/orgs": {
147 `[ {"login":"testorg"} ]`,
148 `[ {"login":"testorg1"} ]`,
149 `[ ]`,
150 },
151 })
152 defer b.Close()
154 bURL, _ := url.Parse(b.URL)
155 p := testGitHubProvider(bURL.Host,
156 options.GitHubOptions{
157 Org: "testorg1",
158 },
159 )
161 session := CreateAuthorizedSession()
162 err := p.getEmail(context.Background(), session)
163 assert.NoError(t, err)
164 assert.Equal(t, "michael.bland@gsa.gov", session.Email)
167func TestGitHubProvider_getEmailWithWriteAccessToPublicRepo(t *testing.T) {
168 b := testGitHubBackend(map[string][]string{
169 "/repo/oauth2-proxy/oauth2-proxy": {`{"permissions": {"pull": true, "push": true}, "private": false}`},
170 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
171 })
172 defer b.Close()
174 bURL, _ := url.Parse(b.URL)
175 p := testGitHubProvider(bURL.Host,
176 options.GitHubOptions{
177 Repo: "oauth2-proxy/oauth2-proxy",
178 Token: "token",
179 },
180 )
182 session := CreateAuthorizedSession()
183 err := p.getEmail(context.Background(), session)
184 assert.NoError(t, err)
185 assert.Equal(t, "michael.bland@gsa.gov", session.Email)
188func TestGitHubProvider_getEmailWithReadOnlyAccessToPrivateRepo(t *testing.T) {
189 b := testGitHubBackend(map[string][]string{
190 "/repo/oauth2-proxy/oauth2-proxy": {`{"permissions": {"pull": true, "push": false}, "private": true}`},
191 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
192 })
193 defer b.Close()
195 bURL, _ := url.Parse(b.URL)
196 p := testGitHubProvider(bURL.Host,
197 options.GitHubOptions{
198 Repo: "oauth2-proxy/oauth2-proxy",
199 Token: "token",
200 },
201 )
203 session := CreateAuthorizedSession()
204 err := p.getEmail(context.Background(), session)
205 assert.NoError(t, err)
206 assert.Equal(t, "michael.bland@gsa.gov", session.Email)
209func TestGitHubProvider_getEmailWithWriteAccessToPrivateRepo(t *testing.T) {
210 b := testGitHubBackend(map[string][]string{
211 "/repo/oauth2-proxy/oauth2-proxy": {`{"permissions": {"pull": true, "push": true}, "private": true}`},
212 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
213 })
214 defer b.Close()
216 bURL, _ := url.Parse(b.URL)
217 p := testGitHubProvider(bURL.Host,
218 options.GitHubOptions{
219 Repo: "oauth2-proxy/oauth2-proxy",
220 Token: "token",
221 },
222 )
224 session := CreateAuthorizedSession()
225 err := p.getEmail(context.Background(), session)
226 assert.NoError(t, err)
227 assert.Equal(t, "michael.bland@gsa.gov", session.Email)
230func TestGitHubProvider_getEmailWithNoAccessToPrivateRepo(t *testing.T) {
231 b := testGitHubBackend(map[string][]string{
232 "/repos/oauth2-proxy/oauth2-proxy": {`{}`},
233 })
234 defer b.Close()
236 bURL, _ := url.Parse(b.URL)
237 p := testGitHubProvider(bURL.Host,
238 options.GitHubOptions{
239 Repo: "oauth2-proxy/oauth2-proxy",
240 },
241 )
243 session := CreateAuthorizedSession()
244 err := p.getEmail(context.Background(), session)
245 assert.NoError(t, err)
246 assert.Empty(t, session.Email)
249func TestGitHubProvider_getEmailWithToken(t *testing.T) {
250 b := testGitHubBackend(map[string][]string{
251 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
252 })
253 defer b.Close()
255 bURL, _ := url.Parse(b.URL)
256 p := testGitHubProvider(bURL.Host,
257 options.GitHubOptions{
258 Repo: "oauth2-proxy/oauth2-proxy",
259 Token: "token",
260 },
261 )
263 session := CreateAuthorizedSession()
264 err := p.getEmail(context.Background(), session)
265 assert.NoError(t, err)
266 assert.Equal(t, "michael.bland@gsa.gov", session.Email)
269// Note that trying to trigger the "failed building request" case is not
270// practical, since the only way it can fail is if the URL fails to parse.
271func TestGitHubProvider_getEmailFailedRequest(t *testing.T) {
272 b := testGitHubBackend(map[string][]string{})
273 defer b.Close()
275 bURL, _ := url.Parse(b.URL)
276 p := testGitHubProvider(bURL.Host, options.GitHubOptions{})
278 // We'll trigger a request failure by using an unexpected access
279 // token. Alternatively, we could allow the parsing of the payload as
280 // JSON to fail.
281 session := &sessions.SessionState{AccessToken: "unexpected_access_token"}
282 err := p.getEmail(context.Background(), session)
283 assert.Error(t, err)
284 assert.Empty(t, session.Email)
287func TestGitHubProvider_getEmailNotPresentInPayload(t *testing.T) {
288 b := testGitHubBackend(map[string][]string{
289 "/user/emails": {`{"foo": "bar"}`},
290 })
291 defer b.Close()
293 bURL, _ := url.Parse(b.URL)
294 p := testGitHubProvider(bURL.Host, options.GitHubOptions{})
296 session := CreateAuthorizedSession()
297 err := p.getEmail(context.Background(), session)
298 assert.Error(t, err)
299 assert.Empty(t, session.Email)
302func TestGitHubProvider_getUser(t *testing.T) {
303 b := testGitHubBackend(map[string][]string{
304 "/user": {`{"email": "michael.bland@gsa.gov", "login": "mbland"}`},
305 })
306 defer b.Close()
308 bURL, _ := url.Parse(b.URL)
309 p := testGitHubProvider(bURL.Host, options.GitHubOptions{})
311 session := CreateAuthorizedSession()
312 err := p.getUser(context.Background(), session)
313 assert.NoError(t, err)
314 assert.Equal(t, "mbland", session.User)
317func TestGitHubProvider_getUserWithRepoAndToken(t *testing.T) {
318 b := testGitHubBackend(map[string][]string{
319 "/user": {`{"email": "michael.bland@gsa.gov", "login": "mbland"}`},
320 "/repos/oauth2-proxy/oauth2-proxy/collaborators/mbland": {""},
321 })
322 defer b.Close()
324 bURL, _ := url.Parse(b.URL)
325 p := testGitHubProvider(bURL.Host,
326 options.GitHubOptions{
327 Repo: "oauth2-proxy/oauth2-proxy",
328 Token: "token",
329 },
330 )
332 session := CreateAuthorizedSession()
333 err := p.getUser(context.Background(), session)
334 assert.NoError(t, err)
335 assert.Equal(t, "mbland", session.User)
338func TestGitHubProvider_getUserWithRepoAndTokenWithoutPushAccess(t *testing.T) {
339 b := testGitHubBackend(map[string][]string{})
340 defer b.Close()
342 bURL, _ := url.Parse(b.URL)
343 p := testGitHubProvider(bURL.Host,
344 options.GitHubOptions{
345 Repo: "oauth2-proxy/oauth2-proxy",
346 Token: "token",
347 },
348 )
350 session := CreateAuthorizedSession()
351 err := p.getUser(context.Background(), session)
352 assert.Error(t, err)
353 assert.Empty(t, session.User)
356func TestGitHubProvider_getEmailWithUsername(t *testing.T) {
357 b := testGitHubBackend(map[string][]string{
358 "/user": {`{"email": "michael.bland@gsa.gov", "login": "mbland"}`},
359 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
360 })
361 defer b.Close()
363 bURL, _ := url.Parse(b.URL)
364 p := testGitHubProvider(bURL.Host,
365 options.GitHubOptions{
366 Users: []string{"mbland", "octocat"},
367 },
368 )
370 session := CreateAuthorizedSession()
371 err := p.getEmail(context.Background(), session)
372 assert.NoError(t, err)
373 assert.Equal(t, "michael.bland@gsa.gov", session.Email)
376func TestGitHubProvider_getEmailWithNotAllowedUsername(t *testing.T) {
377 b := testGitHubBackend(map[string][]string{
378 "/user": {`{"email": "michael.bland@gsa.gov", "login": "mbland"}`},
379 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
380 })
381 defer b.Close()
383 bURL, _ := url.Parse(b.URL)
384 p := testGitHubProvider(bURL.Host,
385 options.GitHubOptions{
386 Users: []string{"octocat"},
387 },
388 )
390 session := CreateAuthorizedSession()
391 err := p.getEmail(context.Background(), session)
392 assert.Error(t, err)
393 assert.Empty(t, session.Email)
396func TestGitHubProvider_getEmailWithUsernameAndNotBelongToOrg(t *testing.T) {
397 b := testGitHubBackend(map[string][]string{
398 "/user": {`{"email": "michael.bland@gsa.gov", "login": "mbland"}`},
399 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
400 "/user/orgs": {
401 `[ {"login":"testorg"} ]`,
402 `[ ]`,
403 },
404 })
405 defer b.Close()
407 bURL, _ := url.Parse(b.URL)
408 p := testGitHubProvider(bURL.Host,
409 options.GitHubOptions{
410 Org: "not_belog_to",
411 Users: []string{"mbland"},
412 },
413 )
415 session := CreateAuthorizedSession()
416 err := p.getEmail(context.Background(), session)
417 assert.NoError(t, err)
418 assert.Equal(t, "michael.bland@gsa.gov", session.Email)
421func TestGitHubProvider_getEmailWithUsernameAndNoAccessToPrivateRepo(t *testing.T) {
422 b := testGitHubBackend(map[string][]string{
423 "/user": {`{"email": "michael.bland@gsa.gov", "login": "mbland"}`},
424 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
425 "/repo/oauth2-proxy/oauth2-proxy": {`{}`},
426 })
427 defer b.Close()
429 bURL, _ := url.Parse(b.URL)
430 p := testGitHubProvider(bURL.Host,
431 options.GitHubOptions{
432 Repo: "oauth2-proxy/oauth2-proxy",
433 Token: "token",
434 Users: []string{"mbland"},
435 },
436 )
438 session := CreateAuthorizedSession()
439 err := p.getEmail(context.Background(), session)
440 assert.NoError(t, err)
441 assert.Equal(t, "michael.bland@gsa.gov", session.Email)