Revert "fix(coderd): explain default GitHub app org visibility on login rejection" (#27388)

This commit is contained in:
Atif Ali
2026-07-21 16:17:27 +00:00
committed by GitHub
parent 48e9bb3391
commit 2b2a5c963a
4 changed files with 2 additions and 101 deletions
-27
View File
@@ -772,20 +772,6 @@ type GithubOAuth2Config struct {
DefaultProviderConfigured bool
}
const (
// GithubOAuth2DefaultProviderInstallURL is where admins install the
// default Coder GitHub app so it can see organization and team
// memberships.
GithubOAuth2DefaultProviderInstallURL = "https://github.com/apps/coder/installations/select_target"
// githubOAuth2DefaultProviderRemediation explains why the default GitHub
// app can fail org and team membership checks, and how to fix it. It is
// appended to login rejection messages and mirrored by the server startup
// warning and the GitHub auth docs, so keep those in sync.
githubOAuth2DefaultProviderRemediation = "The default GitHub OAuth provider can only see organizations and teams that have installed the Coder GitHub app. " +
"Install it from " + GithubOAuth2DefaultProviderInstallURL + " for each authorized organization, or configure a custom GitHub OAuth app."
)
func (*GithubOAuth2Config) PKCESupported() []promoauth.Oauth2PKCEChallengeMethod {
return []promoauth.Oauth2PKCEChallengeMethod{promoauth.PKCEChallengeMethodSha256}
}
@@ -945,13 +931,6 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
if len(selectedMemberships) == 0 {
status := http.StatusUnauthorized
msg := "You aren't a member of the authorized Github organizations!"
if api.GithubOAuth2Config.DefaultProviderConfigured {
// The default provider is a GitHub App, so it can only report
// memberships in organizations that have installed it. Without
// this hint, users in an allowed organization see a confusing
// rejection with no way to discover the missing installation.
msg += " " + githubOAuth2DefaultProviderRemediation
}
if api.GithubOAuth2Config.DeviceFlowEnabled {
// In the device flow, the error is rendered client-side.
httpapi.Write(ctx, rw, status, codersdk.Response{
@@ -998,12 +977,6 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
}
if allowedTeam == nil {
msg := fmt.Sprintf("You aren't a member of an authorized team in the %v Github organization(s)!", organizationNames)
if api.GithubOAuth2Config.DefaultProviderConfigured {
// Team visibility has the same limitation as org visibility:
// the default GitHub App cannot see teams in organizations
// where it isn't installed.
msg += " " + githubOAuth2DefaultProviderRemediation
}
status := http.StatusUnauthorized
if api.GithubOAuth2Config.DeviceFlowEnabled {
// In the device flow, the error is rendered client-side.
-57
View File
@@ -221,63 +221,6 @@ func TestUserOAuth2Github(t *testing.T) {
resp := oauth2Callback(t, client)
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
location, err := resp.Location()
require.NoError(t, err)
require.NotContains(t, location.Query().Get("message"), "Coder GitHub app")
})
t.Run("NotInAllowedOrganizationDefaultProvider", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{
GithubOAuth2Config: &coderd.GithubOAuth2Config{
OAuth2Config: &testutil.OAuth2Config{},
DefaultProviderConfigured: true,
AllowOrganizations: []string{"coder"},
ListOrganizationMemberships: func(ctx context.Context, client *http.Client) ([]*github.Membership, error) {
// The default provider is a GitHub App, so it reports no
// memberships for organizations it isn't installed in.
return []*github.Membership{}, nil
},
},
})
resp := oauth2Callback(t, client)
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
// The error must tell the user how to fix the likely cause: the Coder
// GitHub app isn't installed in the allowed organization.
location, err := resp.Location()
require.NoError(t, err)
require.Contains(t, location.Query().Get("message"), "Coder GitHub app")
require.Contains(t, location.Query().Get("message"), "https://github.com/apps/coder")
})
t.Run("NotInAllowedOrganizationDefaultProviderDeviceFlow", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{
GithubOAuth2Config: &coderd.GithubOAuth2Config{
OAuth2Config: &testutil.OAuth2Config{},
DefaultProviderConfigured: true,
AllowOrganizations: []string{"coder"},
ListOrganizationMemberships: func(ctx context.Context, client *http.Client) ([]*github.Membership, error) {
return []*github.Membership{}, nil
},
DeviceFlowEnabled: true,
ExchangeDeviceCode: func(_ context.Context, _ string) (*oauth2.Token, error) {
return &oauth2.Token{
AccessToken: "access_token",
RefreshToken: "refresh_token",
Expiry: time.Now().Add(time.Hour),
}, nil
},
},
})
resp := oauth2Callback(t, client)
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
// In the device flow the error is rendered client-side, so the hint
// must arrive in the response body Detail rather than the redirect.
var apiErr codersdk.Response
require.NoError(t, json.NewDecoder(resp.Body).Decode(&apiErr))
require.Contains(t, apiErr.Detail, "Coder GitHub app")
require.Contains(t, apiErr.Detail, "https://github.com/apps/coder")
})
t.Run("NotInAllowedTeam", func(t *testing.T) {
t.Parallel()