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

+2-2
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

+12-11
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

+8-3
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)