fix: allow orgs with default github provider (cherry-pick #16755) (#16784)

Cherry-picked fix: allow orgs with default github provider (#16755)

This PR fixes 2 bugs:

## Problem 1

The server would fail to start when the default github provider was
configured and the flag `--oauth2-github-allowed-orgs` was set. The
error was

```
error: configure github oauth2: allow everyone and allowed orgs cannot be used together
```

This PR fixes it by enabling "allow everone" with the default provider
only if "allowed orgs" isn't set.

## Problem 2

The default github provider uses the device flow to authorize users, and
that's handled differently by our web UI than the standard oauth flow.
In particular, the web UI only handles JSON responses rather than HTTP
redirects. There were 2 code paths that returned redirects, and the PR
changes them to return JSON messages instead if the device flow is
configured.

Co-authored-by: Hugo Dutka <hugo@coder.com>
This commit is contained in:
gcp-cherry-pick-bot[bot]
2025-03-03 17:49:35 -06:00
committed by GitHub
parent 99a5d72a8d
commit 6da3c9d48c
3 changed files with 35 additions and 4 deletions

View File

@ -1911,8 +1911,10 @@ func getGithubOAuth2ConfigParams(ctx context.Context, db database.Store, vals *c
}
params.clientID = GithubOAuth2DefaultProviderClientID
params.allowEveryone = GithubOAuth2DefaultProviderAllowEveryone
params.deviceFlow = GithubOAuth2DefaultProviderDeviceFlow
if len(params.allowOrgs) == 0 {
params.allowEveryone = GithubOAuth2DefaultProviderAllowEveryone
}
return &params, nil
}

View File

@ -314,6 +314,7 @@ func TestServer(t *testing.T) {
githubDefaultProviderEnabled string
githubClientID string
githubClientSecret string
allowedOrg string
expectGithubEnabled bool
expectGithubDefaultProviderConfigured bool
createUserPreStart bool
@ -355,7 +356,9 @@ func TestServer(t *testing.T) {
if tc.githubDefaultProviderEnabled != "" {
args = append(args, fmt.Sprintf("--oauth2-github-default-provider-enable=%s", tc.githubDefaultProviderEnabled))
}
if tc.allowedOrg != "" {
args = append(args, fmt.Sprintf("--oauth2-github-allowed-orgs=%s", tc.allowedOrg))
}
inv, cfg := clitest.New(t, args...)
errChan := make(chan error, 1)
go func() {
@ -439,6 +442,12 @@ func TestServer(t *testing.T) {
expectGithubEnabled: true,
expectGithubDefaultProviderConfigured: false,
},
{
name: "AllowedOrg",
allowedOrg: "coder",
expectGithubEnabled: true,
expectGithubDefaultProviderConfigured: true,
},
} {
tc := tc
t.Run(tc.name, func(t *testing.T) {

View File

@ -922,7 +922,17 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
}
}
if len(selectedMemberships) == 0 {
httpmw.CustomRedirectToLogin(rw, r, redirect, "You aren't a member of the authorized Github organizations!", http.StatusUnauthorized)
status := http.StatusUnauthorized
msg := "You aren't a member of the authorized Github organizations!"
if api.GithubOAuth2Config.DeviceFlowEnabled {
// In the device flow, the error is rendered client-side.
httpapi.Write(ctx, rw, status, codersdk.Response{
Message: "Unauthorized",
Detail: msg,
})
} else {
httpmw.CustomRedirectToLogin(rw, r, redirect, msg, status)
}
return
}
}
@ -959,7 +969,17 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
}
}
if allowedTeam == nil {
httpmw.CustomRedirectToLogin(rw, r, redirect, fmt.Sprintf("You aren't a member of an authorized team in the %v Github organization(s)!", organizationNames), http.StatusUnauthorized)
msg := fmt.Sprintf("You aren't a member of an authorized team in the %v Github organization(s)!", organizationNames)
status := http.StatusUnauthorized
if api.GithubOAuth2Config.DeviceFlowEnabled {
// In the device flow, the error is rendered client-side.
httpapi.Write(ctx, rw, status, codersdk.Response{
Message: "Unauthorized",
Detail: msg,
})
} else {
httpmw.CustomRedirectToLogin(rw, r, redirect, msg, status)
}
return
}
}