Skip to content

Commit fd4954b

Browse files
authored
fix: Use membership endpoint to ensure user exists in team (#3129)
This was using the incorrect GitHub endpoint prior, which fetched a team by slug. Any user in a GitHub organization can view all teams, so this didn't block signups like intended. I've verified this API returns an error when the calling user is not a member of the team requested. Fixes #3105.
1 parent 471564d commit fd4954b

File tree

3 files changed

+22
-16
lines changed

3 files changed

+22
-16
lines changed

cli/server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -796,8 +796,8 @@ func configureGithubOAuth2(accessURL *url.URL, clientID, clientSecret string, al
796796
})
797797
return memberships, err
798798
},
799-
Team: func(ctx context.Context, client *http.Client, org, teamSlug string) (*github.Team, error) {
800-
team, _, err := github.NewClient(client).Teams.GetTeamBySlug(ctx, org, teamSlug)
799+
TeamMembership: func(ctx context.Context, client *http.Client, org, teamSlug, username string) (*github.Membership, error) {
800+
team, _, err := github.NewClient(client).Teams.GetTeamMembershipBySlug(ctx, org, teamSlug, username)
801801
return team, err
802802
},
803803
}, nil

coderd/userauth.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type GithubOAuth2Config struct {
2929
AuthenticatedUser func(ctx context.Context, client *http.Client) (*github.User, error)
3030
ListEmails func(ctx context.Context, client *http.Client) ([]*github.UserEmail, error)
3131
ListOrganizationMemberships func(ctx context.Context, client *http.Client) ([]*github.Membership, error)
32-
Team func(ctx context.Context, client *http.Client, org, team string) (*github.Team, error)
32+
TeamMembership func(ctx context.Context, client *http.Client, org, team, username string) (*github.Membership, error)
3333

3434
AllowSignups bool
3535
AllowOrganizations []string
@@ -72,17 +72,26 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
7272
return
7373
}
7474

75+
ghUser, err := api.GithubOAuth2Config.AuthenticatedUser(r.Context(), oauthClient)
76+
if err != nil {
77+
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
78+
Message: "Internal error fetching authenticated Github user.",
79+
Detail: err.Error(),
80+
})
81+
return
82+
}
83+
7584
// The default if no teams are specified is to allow all.
7685
if len(api.GithubOAuth2Config.AllowTeams) > 0 {
77-
var allowedTeam *github.Team
86+
var allowedTeam *github.Membership
7887
for _, allowTeam := range api.GithubOAuth2Config.AllowTeams {
7988
if allowTeam.Organization != *selectedMembership.Organization.Login {
8089
// This needs to continue because multiple organizations
8190
// could exist in the allow/team listings.
8291
continue
8392
}
8493

85-
allowedTeam, err = api.GithubOAuth2Config.Team(r.Context(), oauthClient, allowTeam.Organization, allowTeam.Slug)
94+
allowedTeam, err = api.GithubOAuth2Config.TeamMembership(r.Context(), oauthClient, allowTeam.Organization, allowTeam.Slug, *ghUser.Login)
8695
// The calling user may not have permission to the requested team!
8796
if err != nil {
8897
continue
@@ -151,14 +160,6 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
151160
// email to organization.
152161
organizationID = organizations[0].ID
153162
}
154-
ghUser, err := api.GithubOAuth2Config.AuthenticatedUser(r.Context(), oauthClient)
155-
if err != nil {
156-
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
157-
Message: "Internal error fetching authenticated Github user.",
158-
Detail: err.Error(),
159-
})
160-
return
161-
}
162163
var verifiedEmail *github.UserEmail
163164
for _, email := range emails {
164165
if !email.GetPrimary() || !email.GetVerified() {

coderd/userauth_test.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,12 @@ func TestUserOAuth2Github(t *testing.T) {
8888
},
8989
}}, nil
9090
},
91-
Team: func(ctx context.Context, client *http.Client, org, team string) (*github.Team, error) {
91+
AuthenticatedUser: func(ctx context.Context, client *http.Client) (*github.User, error) {
92+
return &github.User{
93+
Login: github.String("kyle"),
94+
}, nil
95+
},
96+
TeamMembership: func(ctx context.Context, client *http.Client, org, team, username string) (*github.Membership, error) {
9297
return nil, xerrors.New("no perms")
9398
},
9499
},
@@ -222,8 +227,8 @@ func TestUserOAuth2Github(t *testing.T) {
222227
},
223228
}}, nil
224229
},
225-
Team: func(ctx context.Context, client *http.Client, org, team string) (*github.Team, error) {
226-
return &github.Team{}, nil
230+
TeamMembership: func(ctx context.Context, client *http.Client, org, team, username string) (*github.Membership, error) {
231+
return &github.Membership{}, nil
227232
},
228233
AuthenticatedUser: func(ctx context.Context, client *http.Client) (*github.User, error) {
229234
return &github.User{

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy