git.iko.soy/typeable/oauth2-proxy
on master help sign in
Feature: Add GitHub groups (orgs/teams) support (#2196)

* Add GitHub groups (orgs/teams) support * align code of getTeams with getOrgs to support Github Enterprise Server instances with different domain * add documentation * add missing import after rebase * add nightly build and push (#2297) * add nightly build and push * add date based nightly build tags * only keep single multiarch image build and push * add changelog * add images to internal docs static files * add docu for nightly builds * remove unnecessary spaces * update nightly repository * Issue 978: Fix Custom cookie name breaks redis for session (#1949) * Issue 978: Fix Custom cookie name breaks redis for session (see https://github.com/oauth2-proxy/oauth2-proxy/issues/978) * Issue 978: Fix Custom cookie name breaks redis for session (see https://github.com/oauth2-proxy/oauth2-proxy/issues/978) * Update CHANGELOG.md * Issue 978: Fix Custom cookie name breaks redis for session * Issue 978: Fix Custom cookie name breaks redis for session * Issue 978: Fix Custom cookie name breaks redis for session * Issue 978: Fix Custom cookie name breaks redis for session * Issue 978: Fix Custom cookie name breaks redis for session * Issue 978: Fix Custom cookie name breaks redis for session * Update CHANGELOG.md --------- Co-authored-by: Nuno Borges <Nuno.Borges@ctw.bmwgroup.com> Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * Support http.AllowQuerySemicolons (#2248) * Support http.AllowQuerySemicolons * Docs * Make it clear we are overriding the handler * Update documentation for allow-query-semicolons * Fix changelog format * Fix formatting --------- Co-authored-by: MickMake <github@mickmake.com> * Add GitHub groups (orgs/teams) support * align code of getTeams with getOrgs to support Github Enterprise Server instances with different domain * add documentation * fix changelog & documentation * fix missing import --------- Co-authored-by: Tobias Mayer <github@tobiasm.de> Co-authored-by: Nuno Miguel Micaelo Borges <miguelborges99@gmail.com> Co-authored-by: Nuno Borges <Nuno.Borges@ctw.bmwgroup.com> Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> Co-authored-by: Tim White <tim.white@su.org.au> Co-authored-by: MickMake <github@mickmake.com>

commit52ad31752d0d0b38673d419e56ddfc4cb2f56857 authorJan Larwig <jan@larwig.com> dateMon 18 Dec 2023, 11:03 (3 years ago) parent53ae4c8
6 files changed+214−186
CHANGELOG.md+2−1 docs/docs/configuration/providers/github.md+1−1 docs/versioned_docs/version-7.5.x/configuration/auth.md+1−1 providers/github.go+200−173 providers/github_test.go+7−7 providers/providers_test.go+3−3
CHANGELOG.md+2−1
@@ -19,7 +19,8 @@
1919- [#1949](https://github.com/oauth2-proxy/oauth2-proxy/pull/1949) Allow cookie names with dots in redis sessions (@miguelborges99)
2020- [#2297](https://github.com/oauth2-proxy/oauth2-proxy/pull/2297) Add nightly build and push (@tuunit)
2121- [#2299](https://github.com/oauth2-proxy/oauth2-proxy/pull/2299) bugfix: OIDCConfig based providers are not respecting flags and configs (@tuunit)
22−- [#2248](https://github.com/oauth2-proxy/oauth2-proxy/pull/2248) Added support for semicolons in query strings.
22+- [#2248](https://github.com/oauth2-proxy/oauth2-proxy/pull/2248) Added support for semicolons in query strings. (@timwsuqld)
23+- [#2196](https://github.com/oauth2-proxy/oauth2-proxy/pull/2196) Add GitHub groups (orgs/teams) support. Including `X-Forwarded-Groups` header (@tuunit)
2324
2425# V7.5.1
2526
docs/docs/configuration/providers/github.md+1−1
@@ -7,7 +7,7 @@ title: GitHub
772. Under `Authorization callback URL` enter the correct url ie `https://internal.yourcompany.com/oauth2/callback`
88
99The GitHub auth provider supports two additional ways to restrict authentication to either organization and optional
10−team level access, or to collaborators of a repository. Restricting by these options is normally accompanied with `--email-domain=*`
10+team level access, or to collaborators of a repository. Restricting by these options is normally accompanied with `--email-domain=*`. Additionally, all the organizations and teams a user belongs to are set as part of the `X-Forwarded-Groups` header. e.g. `org1:team1,org1:team2,org2:team1`
1111
1212NOTE: When `--github-user` is set, the specified users are allowed to log in even if they do not belong to the specified
1313org and team or collaborators.
docs/versioned_docs/version-7.5.x/configuration/auth.md+1−1
@@ -147,7 +147,7 @@ Note: When using the ADFS Auth provider with nginx and the cookie session store
1471471. Create a new project: https://github.com/settings/developers
1481482. Under `Authorization callback URL` enter the correct url ie `https://internal.yourcompany.com/oauth2/callback`
149149
150−The GitHub auth provider supports two additional ways to restrict authentication to either organization and optional team level access, or to collaborators of a repository. Restricting by these options is normally accompanied with `--email-domain=*`
150+The GitHub auth provider supports two additional ways to restrict authentication to either organization and optional team level access, or to collaborators of a repository. Restricting by these options is normally accompanied with `--email-domain=*`. Additionally, all the organizations and teams a user belongs to are set as part of the `X-Forwarded-Groups` header. e.g. `org1:team1,org1:team2,org2:team1`
151151
152152NOTE: When `--github-user` is set, the specified users are allowed to login even if they do not belong to the specified org and team or collaborators.
153153
providers/github.go+200−173
@@ -15,6 +15,7 @@ import (
1515 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
1616 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
1717 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests"
18+ "golang.org/x/exp/maps"
1819)
1920
2021// GitHubProvider represents an GitHub based Identity Provider
@@ -31,7 +32,8 @@ var _ Provider = (*GitHubProvider)(nil)
3132
3233const (
3334 githubProviderName = "GitHub"
34− githubDefaultScope = "user:email"
35+ githubDefaultScope = "user:email read:org"
36+ orgTeamSeparator = ":"
3537)
3638
3739var (
@@ -114,9 +116,6 @@ func (p *GitHubProvider) makeGitHubAPIEndpoint(endpoint string, params *url.Valu
114116func (p *GitHubProvider) setOrgTeam(org, team string) {
115117 p.Org = org
116118 p.Team = team
117− if org != "" || team != "" {
118− p.Scope += " read:org"
119− }
120119}
121120
122121// setRepo configures the target repository and optional token to use
@@ -132,10 +131,19 @@ func (p *GitHubProvider) setUsers(users []string) {
132131
133132// EnrichSession updates the User & Email after the initial Redeem
134133func (p *GitHubProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error {
135− err := p.getEmail(ctx, s)
136− if err != nil {
134+ // Construct user info JSON from multiple GitHub API endpoints to have a more detailed session state
135+ if err := p.getOrgAndTeam(ctx, s); err != nil {
137136 return err
138137 }
138+
139+ if err := p.checkRestrictions(ctx, s); err != nil {
140+ return err
141+ }
142+
143+ if err := p.getEmail(ctx, s); err != nil {
144+ return err
145+ }
146+
139147 return p.getUser(ctx, s)
140148}
141149
@@ -144,170 +152,75 @@ func (p *GitHubProvider) ValidateSession(ctx context.Context, s *sessions.Sessio
144152 return validateToken(ctx, p, s.AccessToken, makeGitHubHeader(s.AccessToken))
145153}
146154
147−func (p *GitHubProvider) hasOrg(ctx context.Context, accessToken string) (bool, error) {
155+func (p *GitHubProvider) hasOrg(ctx context.Context, s *sessions.SessionState) error {
148156 // https://developer.github.com/v3/orgs/#list-your-organizations
157+ var orgs []string
149158
150− var orgs []struct {
151− Login string `json:"login"`
152− }
153−
154− type orgsPage []struct {
155− Login string `json:"login"`
156− }
157−
158− pn := 1
159− for {
160− params := url.Values{
161− "per_page": {"100"},
162− "page": {strconv.Itoa(pn)},
163− }
164−
165− endpoint := p.makeGitHubAPIEndpoint("/user/orgs", &params)
166−
167− var op orgsPage
168− err := requests.New(endpoint.String()).
169− WithContext(ctx).
170− WithHeaders(makeGitHubHeader(accessToken)).
171− Do().
172− UnmarshalInto(&op)
173− if err != nil {
174− return false, err
175− }
176−
177− if len(op) == 0 {
178− break
159+ for _, group := range s.Groups {
160+ if !strings.Contains(group, ":") {
161+ orgs = append(orgs, group)
179162 }
180−
181− orgs = append(orgs, op...)
182− pn++
183163 }
184164
185165 presentOrgs := make([]string, 0, len(orgs))
186166 for _, org := range orgs {
187− if p.Org == org.Login {
188− logger.Printf("Found Github Organization: %q", org.Login)
189− return true, nil
167+ if p.Org == org {
168+ logger.Printf("Found Github Organization:%q", org)
169+ return nil
190170 }
191− presentOrgs = append(presentOrgs, org.Login)
171+ presentOrgs = append(presentOrgs, org)
192172 }
193173
194174 logger.Printf("Missing Organization:%q in %v", p.Org, presentOrgs)
195− return false, nil
175+ return errors.New("user is missing required organization")
196176}
197177
198−func (p *GitHubProvider) hasOrgAndTeam(ctx context.Context, accessToken string) (bool, error) {
199− // https://developer.github.com/v3/orgs/teams/#list-user-teams
200−
201− var teams []struct {
202− Name string `json:"name"`
203− Slug string `json:"slug"`
204− Org struct {
205− Login string `json:"login"`
206− } `json:"organization"`
207− }
208−
209− type teamsPage []struct {
210− Name string `json:"name"`
211− Slug string `json:"slug"`
212− Org struct {
213− Login string `json:"login"`
214− } `json:"organization"`
178+func (p *GitHubProvider) hasOrgAndTeam(ctx context.Context, s *sessions.SessionState) error {
179+ type orgTeam struct {
180+ Org string `json:"org"`
181+ Team string `json:"team"`
215182 }
216183
217− pn := 1
218− last := 0
219− for {
220− params := url.Values{
221− "per_page": {"100"},
222− "page": {strconv.Itoa(pn)},
223− }
224−
225− endpoint := p.makeGitHubAPIEndpoint("/user/teams", &params)
184+ var presentOrgTeams []orgTeam
226185
227− // bodyclose cannot detect that the body is being closed later in requests.Into,
228− // so have to skip the linting for the next line.
229− // nolint:bodyclose
230− result := requests.New(endpoint.String()).
231− WithContext(ctx).
232− WithHeaders(makeGitHubHeader(accessToken)).
233− Do()
234− if result.Error() != nil {
235− return false, result.Error()
236− }
237−
238− if last == 0 {
239− // link header may not be obtained
240− // When paging is not required and all data can be retrieved with a single call
241−
242− // Conditions for obtaining the link header.
243− // 1. When paging is required (Example: When the data size is 100 and the page size is 99 or less)
244− // 2. When it exceeds the paging frame (Example: When there is only 10 records but the second page is called with a page size of 100)
245−
246− // link header at not last page
247− // <https://api.github.com/user/teams?page=1&per_page=100>; rel="prev", <https://api.github.com/user/teams?page=1&per_page=100>; rel="last", <https://api.github.com/user/teams?page=1&per_page=100>; rel="first"
248− // link header at last page (doesn't exist last info)
249− // <https://api.github.com/user/teams?page=3&per_page=10>; rel="prev", <https://api.github.com/user/teams?page=1&per_page=10>; rel="first"
250−
251− link := result.Headers().Get("Link")
252− rep1 := regexp.MustCompile(`(?s).*\<https://api.github.com/user/teams\?page=(.)&per_page=[0-9]+\>; rel="last".*`)
253− i, converr := strconv.Atoi(rep1.ReplaceAllString(link, "$1"))
254−
255− // If the last page cannot be taken from the link in the http header, the last variable remains zero
256− if converr == nil {
257− last = i
258− }
186+ for _, group := range s.Groups {
187+ if strings.Contains(group, orgTeamSeparator) {
188+ ot := strings.Split(group, orgTeamSeparator)
189+ presentOrgTeams = append(presentOrgTeams, orgTeam{ot[0], ot[1]})
259190 }
260−
261− var tp teamsPage
262− if err := result.UnmarshalInto(&tp); err != nil {
263− return false, err
264− }
265− if len(tp) == 0 {
266− break
267− }
268−
269− teams = append(teams, tp...)
270−
271− if pn == last {
272− break
273− }
274− if last == 0 {
275− break
276− }
277−
278− pn++
279191 }
280192
281193 var hasOrg bool
194+
282195 presentOrgs := make(map[string]bool)
283196 var presentTeams []string
284− for _, team := range teams {
285− presentOrgs[team.Org.Login] = true
286− if p.Org == team.Org.Login {
197+
198+ for _, ot := range presentOrgTeams {
199+ presentOrgs[ot.Org] = true
200+
201+ if strings.EqualFold(p.Org, ot.Org) {
287202 hasOrg = true
288− ts := strings.Split(p.Team, ",")
289− for _, t := range ts {
290− if t == team.Slug {
291− logger.Printf("Found Github Organization:%q Team:%q (Name:%q)", team.Org.Login, team.Slug, team.Name)
292− return true, nil
203+ teams := strings.Split(p.Team, ",")
204+ for _, team := range teams {
205+ if strings.EqualFold(strings.TrimSpace(team), ot.Team) {
206+ logger.Printf("Found Github Organization/Team:%q/%q", ot.Org, ot.Team)
207+ return nil
293208 }
294209 }
295− presentTeams = append(presentTeams, team.Slug)
210+ presentTeams = append(presentTeams, ot.Team)
296211 }
297212 }
213+
298214 if hasOrg {
299215 logger.Printf("Missing Team:%q from Org:%q in teams: %v", p.Team, p.Org, presentTeams)
300− } else {
301− var allOrgs []string
302− for org := range presentOrgs {
303− allOrgs = append(allOrgs, org)
304− }
305− logger.Printf("Missing Organization:%q in %#v", p.Org, allOrgs)
216+ return errors.New("user is missing required team")
306217 }
307− return false, nil
218+
219+ logger.Printf("Missing Organization:%q in %#v", p.Org, maps.Keys(presentOrgs))
220+ return errors.New("user is missing required organization")
308221}
309222
310−func (p *GitHubProvider) hasRepo(ctx context.Context, accessToken string) (bool, error) {
223+func (p *GitHubProvider) hasRepoAccess(ctx context.Context, accessToken string) error {
311224 // https://developer.github.com/v3/repos/#get-a-repository
312225
313226 type permissions struct {
@@ -328,13 +241,18 @@ func (p *GitHubProvider) hasRepo(ctx context.Context, accessToken string) (bool,
328241 WithHeaders(makeGitHubHeader(accessToken)).
329242 Do().
330243 UnmarshalInto(&repo)
244+
331245 if err != nil {
332− return false, err
246+ return err
333247 }
334248
335249 // Every user can implicitly pull from a public repo, so only grant access
336250 // if they have push access or the repo is private and they can pull
337− return repo.Permissions.Push || (repo.Private && repo.Permissions.Pull), nil
251+ if repo.Permissions.Push || (repo.Private && repo.Permissions.Pull) {
252+ return nil
253+ }
254+
255+ return errors.New("user doesn't have repository access")
338256}
339257
340258func (p *GitHubProvider) hasUser(ctx context.Context, accessToken string) (bool, error) {
@@ -393,39 +311,8 @@ func (p *GitHubProvider) getEmail(ctx context.Context, s *sessions.SessionState)
393311 Verified bool `json:"verified"`
394312 }
395313
396− // If usernames are set, check that first
397− verifiedUser := false
398− if len(p.Users) > 0 {
399− var err error
400− verifiedUser, err = p.hasUser(ctx, s.AccessToken)
401− if err != nil {
402− return err
403− }
404− // org and repository options are not configured
405− if !verifiedUser && p.Org == "" && p.Repo == "" {
406− return errors.New("missing github user")
407− }
408− }
409− // If a user is verified by username options, skip the following restrictions
410− if !verifiedUser {
411− if p.Org != "" {
412− if p.Team != "" {
413− if ok, err := p.hasOrgAndTeam(ctx, s.AccessToken); err != nil || !ok {
414− return err
415− }
416− } else {
417− if ok, err := p.hasOrg(ctx, s.AccessToken); err != nil || !ok {
418− return err
419− }
420− }
421− } else if p.Repo != "" && p.Token == "" { // If we have a token we'll do the collaborator check in GetUserName
422− if ok, err := p.hasRepo(ctx, s.AccessToken); err != nil || !ok {
423− return err
424− }
425− }
426− }
427−
428314 endpoint := p.makeGitHubAPIEndpoint("/user/emails", nil)
315+
429316 err := requests.New(endpoint.String()).
430317 WithContext(ctx).
431318 WithHeaders(makeGitHubHeader(s.AccessToken)).
@@ -476,7 +363,6 @@ func (p *GitHubProvider) getUser(ctx context.Context, s *sessions.SessionState)
476363 return nil
477364}
478365
479−// isVerifiedUser
480366func (p *GitHubProvider) isVerifiedUser(username string) bool {
481367 for _, u := range p.Users {
482368 if username == u {
@@ -485,3 +371,144 @@ func (p *GitHubProvider) isVerifiedUser(username string) bool {
485371 }
486372 return false
487373}
374+
375+func (p *GitHubProvider) checkRestrictions(ctx context.Context, s *sessions.SessionState) error {
376+ // If a user is verified by username options, skip the following restrictions
377+ if ok, err := p.checkUserRestriction(ctx, s); err != nil || ok {
378+ return err
379+ }
380+
381+ if err := p.hasOrgAndTeamAccess(ctx, s); err != nil {
382+ return err
383+ }
384+
385+ if p.Org == "" && p.Repo != "" && p.Token == "" {
386+ // If we have a token we'll do the collaborator check in GetUserName
387+ return p.hasRepoAccess(ctx, s.AccessToken)
388+ }
389+
390+ return nil
391+}
392+
393+func (p *GitHubProvider) checkUserRestriction(ctx context.Context, s *sessions.SessionState) (bool, error) {
394+ if len(p.Users) == 0 {
395+ return false, nil
396+ }
397+
398+ verifiedUser, err := p.hasUser(ctx, s.AccessToken)
399+ if err != nil {
400+ return verifiedUser, err
401+ }
402+
403+ // org and repository options are not configured
404+ if !verifiedUser && p.Org == "" && p.Repo == "" {
405+ return false, errors.New("missing github user")
406+ }
407+
408+ return verifiedUser, nil
409+}
410+
411+func (p *GitHubProvider) hasOrgAndTeamAccess(ctx context.Context, s *sessions.SessionState) error {
412+ if p.Org != "" && p.Team != "" {
413+ return p.hasOrgAndTeam(ctx, s)
414+ }
415+
416+ if p.Org != "" {
417+ return p.hasOrg(ctx, s)
418+ }
419+
420+ return nil
421+}
422+
423+func (p *GitHubProvider) getOrgAndTeam(ctx context.Context, s *sessions.SessionState) error {
424+ err := p.getOrgs(ctx, s)
425+ if err != nil {
426+ return err
427+ }
428+
429+ return p.getTeams(ctx, s)
430+}
431+
432+func (p *GitHubProvider) getOrgs(ctx context.Context, s *sessions.SessionState) error {
433+ // https://docs.github.com/en/rest/orgs/orgs#list-organizations-for-the-authenticated-user
434+
435+ type Organization struct {
436+ Login string `json:"login"`
437+ }
438+
439+ pn := 1
440+ for {
441+ params := url.Values{
442+ "per_page": {"100"},
443+ "page": {strconv.Itoa(pn)},
444+ }
445+
446+ endpoint := p.makeGitHubAPIEndpoint("/user/orgs", &params)
447+
448+ var orgs []Organization
449+ err := requests.New(endpoint.String()).
450+ WithContext(ctx).
451+ WithHeaders(makeGitHubHeader(s.AccessToken)).
452+ Do().
453+ UnmarshalInto(&orgs)
454+ if err != nil {
455+ return err
456+ }
457+
458+ if len(orgs) == 0 {
459+ break
460+ }
461+
462+ for _, org := range orgs {
463+ logger.Printf("Member of Github Organization:%q", org.Login)
464+ s.Groups = append(s.Groups, org.Login)
465+ }
466+ pn++
467+ }
468+
469+ return nil
470+}
471+
472+func (p *GitHubProvider) getTeams(ctx context.Context, s *sessions.SessionState) error {
473+ // https://docs.github.com/en/rest/teams/teams?#list-user-teams
474+ type Team struct {
475+ Name string `json:"name"`
476+ Slug string `json:"slug"`
477+ Org struct {
478+ Login string `json:"login"`
479+ } `json:"organization"`
480+ }
481+
482+ pn := 1
483+ for {
484+ params := url.Values{
485+ "per_page": {"100"},
486+ "page": {strconv.Itoa(pn)},
487+ }
488+
489+ endpoint := p.makeGitHubAPIEndpoint("/user/teams", &params)
490+
491+ var teams []Team
492+ err := requests.New(endpoint.String()).
493+ WithContext(ctx).
494+ WithHeaders(makeGitHubHeader(s.AccessToken)).
495+ Do().
496+ UnmarshalInto(&teams)
497+ if err != nil {
498+ return err
499+ }
500+
501+ if len(teams) == 0 {
502+ break
503+ }
504+
505+ for _, team := range teams {
506+ logger.Printf("Member of Github Organization/Team:%q/%q", team.Org.Login, team.Slug)
507+ s.Groups = append(s.Groups, team.Org.Login+orgTeamSeparator+team.Slug)
508+ }
509+
510+ pn++
511+ }
512+
513+ return nil
514+}
providers/github_test.go+7−7
@@ -82,8 +82,8 @@ func TestNewGitHubProvider(t *testing.T) {
8282 g.Expect(providerData.LoginURL.String()).To(Equal(githubDefaultLoginURL.String()))
8383 g.Expect(providerData.RedeemURL.String()).To(Equal(githubDefaultRedeemURL.String()))
8484 g.Expect(providerData.ProfileURL.String()).To(Equal(""))
85− g.Expect(providerData.ValidateURL.String()).To(Equal(githubDefaultValidateURL.String()))
86− g.Expect(providerData.Scope).To(Equal("user:email"))
85+ g.Expect(providerData.ValidateURL.String()).To(Equal("https://api.github.com/"))
86+ g.Expect(providerData.Scope).To(Equal("user:email read:org"))
8787}
8888
8989func TestGitHubProviderOverrides(t *testing.T) {
@@ -231,7 +231,7 @@ func TestGitHubProvider_getEmailWithWriteAccessToPrivateRepo(t *testing.T) {
231231 assert.Equal(t, "michael.bland@gsa.gov", session.Email)
232232}
233233
234−func TestGitHubProvider_getEmailWithNoAccessToPrivateRepo(t *testing.T) {
234+func TestGitHubProvider_checkRestrictionsWithNoAccessToPrivateRepo(t *testing.T) {
235235 b := testGitHubBackend(map[string][]string{
236236 "/repos/oauth2-proxy/oauth2-proxy": {`{}`},
237237 })
@@ -245,8 +245,8 @@ func TestGitHubProvider_getEmailWithNoAccessToPrivateRepo(t *testing.T) {
245245 )
246246
247247 session := CreateAuthorizedSession()
248− err := p.getEmail(context.Background(), session)
249− assert.NoError(t, err)
248+ err := p.checkRestrictions(context.Background(), session)
249+ assert.Error(t, err)
250250 assert.Empty(t, session.Email)
251251}
252252
@@ -377,7 +377,7 @@ func TestGitHubProvider_getEmailWithUsername(t *testing.T) {
377377 assert.Equal(t, "michael.bland@gsa.gov", session.Email)
378378}
379379
380−func TestGitHubProvider_getEmailWithNotAllowedUsername(t *testing.T) {
380+func TestGitHubProvider_checkRestrictionsWithNotAllowedUsername(t *testing.T) {
381381 b := testGitHubBackend(map[string][]string{
382382 "/user": {`{"email": "michael.bland@gsa.gov", "login": "mbland"}`},
383383 "/user/emails": {`[ {"email": "michael.bland@gsa.gov", "verified": true, "primary": true} ]`},
@@ -392,7 +392,7 @@ func TestGitHubProvider_getEmailWithNotAllowedUsername(t *testing.T) {
392392 )
393393
394394 session := CreateAuthorizedSession()
395− err := p.getEmail(context.Background(), session)
395+ err := p.checkRestrictions(context.Background(), session)
396396 assert.Error(t, err)
397397 assert.Empty(t, session.Email)
398398}
providers/providers_test.go+3−3
@@ -153,13 +153,13 @@ func TestScope(t *testing.T) {
153153 name: "github: with no scope provided",
154154 configuredType: "github",
155155 configuredScope: "",
156− expectedScope: "user:email",
156+ expectedScope: "user:email read:org",
157157 },
158158 {
159159 name: "github: with a configured scope provided",
160160 configuredType: "github",
161− configuredScope: "user:email org:read",
162− expectedScope: "user:email org:read",
161+ configuredScope: "read:user read:org",
162+ expectedScope: "read:user read:org",
163163 },
164164 }
165165