diff --git a/cli/deployment/config.go b/cli/deployment/config.go index 9e1c92163192e..decaaaf01ce72 100644 --- a/cli/deployment/config.go +++ b/cli/deployment/config.go @@ -215,9 +215,9 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "oidc-client-secret", Secret: true, }, - EmailDomain: &codersdk.DeploymentConfigField[string]{ + EmailDomain: &codersdk.DeploymentConfigField[[]string]{ Name: "OIDC Email Domain", - Usage: "Email domain that clients logging in with OIDC must match.", + Usage: "Email domains that clients logging in with OIDC must match.", Flag: "oidc-email-domain", }, IssuerURL: &codersdk.DeploymentConfigField[string]{ diff --git a/cli/deployment/config_test.go b/cli/deployment/config_test.go index ca1ad0eeabe1e..48a2249258944 100644 --- a/cli/deployment/config_test.go +++ b/cli/deployment/config_test.go @@ -147,7 +147,7 @@ func TestConfig(t *testing.T) { }, Valid: func(config *codersdk.DeploymentConfig) { require.Equal(t, config.OIDC.IssuerURL.Value, "https://accounts.google.com") - require.Equal(t, config.OIDC.EmailDomain.Value, "coder.com") + require.Equal(t, config.OIDC.EmailDomain.Value, []string{"coder.com"}) require.Equal(t, config.OIDC.ClientID.Value, "client") require.Equal(t, config.OIDC.ClientSecret.Value, "secret") require.False(t, config.OIDC.AllowSignups.Value) diff --git a/cli/testdata/coder_server_--help.golden b/cli/testdata/coder_server_--help.golden index 1351da7c89915..2c63bb7be89d4 100644 --- a/cli/testdata/coder_server_--help.golden +++ b/cli/testdata/coder_server_--help.golden @@ -95,8 +95,8 @@ Flags: Consumes $CODER_OIDC_CLIENT_ID --oidc-client-secret string Client secret to use for Login with OIDC. Consumes $CODER_OIDC_CLIENT_SECRET - --oidc-email-domain string Email domain that clients logging in with - OIDC must match. + --oidc-email-domain strings Email domains that clients logging in + with OIDC must match. Consumes $CODER_OIDC_EMAIL_DOMAIN --oidc-ignore-email-verified Ignore the email_verified claim from the upstream provider. diff --git a/coderd/userauth.go b/coderd/userauth.go index add41cf291650..1197aa8d2cea6 100644 --- a/coderd/userauth.go +++ b/coderd/userauth.go @@ -192,8 +192,8 @@ type OIDCConfig struct { httpmw.OAuth2Config Verifier *oidc.IDTokenVerifier - // EmailDomain is the domain to enforce when a user authenticates. - EmailDomain string + // EmailDomains are the domains to enforce when a user authenticates. + EmailDomain []string AllowSignups bool // IgnoreEmailVerified allows ignoring the email_verified claim // from an upstream OIDC provider. See #5065 for context. @@ -289,10 +289,17 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) { } username = httpapi.UsernameFrom(username) } - if api.OIDCConfig.EmailDomain != "" { - if !strings.HasSuffix(strings.ToLower(email), strings.ToLower(api.OIDCConfig.EmailDomain)) { + if len(api.OIDCConfig.EmailDomain) > 0 { + ok = false + for _, domain := range api.OIDCConfig.EmailDomain { + if strings.HasSuffix(strings.ToLower(email), strings.ToLower(domain)) { + ok = true + break + } + } + if !ok { httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{ - Message: fmt.Sprintf("Your email %q is not a part of the %q domain!", email, api.OIDCConfig.EmailDomain), + Message: fmt.Sprintf("Your email %q is not in domains %q !", email, api.OIDCConfig.EmailDomain), }) return } diff --git a/coderd/userauth_test.go b/coderd/userauth_test.go index 8727bedae3d91..6bfe3e193370b 100644 --- a/coderd/userauth_test.go +++ b/coderd/userauth_test.go @@ -482,7 +482,7 @@ func TestUserOIDC(t *testing.T) { Name string Claims jwt.MapClaims AllowSignups bool - EmailDomain string + EmailDomain []string Username string AvatarURL string StatusCode int @@ -528,8 +528,10 @@ func TestUserOIDC(t *testing.T) { "email_verified": true, }, AllowSignups: true, - EmailDomain: "coder.com", - StatusCode: http.StatusForbidden, + EmailDomain: []string{ + "coder.com", + }, + StatusCode: http.StatusForbidden, }, { Name: "EmailDomainCaseInsensitive", Claims: jwt.MapClaims{ @@ -537,8 +539,10 @@ func TestUserOIDC(t *testing.T) { "email_verified": true, }, AllowSignups: true, - EmailDomain: "kwc.io", - StatusCode: http.StatusTemporaryRedirect, + EmailDomain: []string{ + "kwc.io", + }, + StatusCode: http.StatusTemporaryRedirect, }, { Name: "EmptyClaims", Claims: jwt.MapClaims{}, diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index 74e0b58b91bea..218f45cd8541d 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -90,7 +90,7 @@ type OIDCConfig struct { AllowSignups *DeploymentConfigField[bool] `json:"allow_signups" typescript:",notnull"` ClientID *DeploymentConfigField[string] `json:"client_id" typescript:",notnull"` ClientSecret *DeploymentConfigField[string] `json:"client_secret" typescript:",notnull"` - EmailDomain *DeploymentConfigField[string] `json:"email_domain" typescript:",notnull"` + EmailDomain *DeploymentConfigField[[]string] `json:"email_domain" typescript:",notnull"` IssuerURL *DeploymentConfigField[string] `json:"issuer_url" typescript:",notnull"` Scopes *DeploymentConfigField[[]string] `json:"scopes" typescript:",notnull"` IgnoreEmailVerified *DeploymentConfigField[bool] `json:"ignore_email_verified" typescript:",notnull"` diff --git a/docs/admin/auth.md b/docs/admin/auth.md index ebef1d0af7b41..99a0f0b57b08c 100644 --- a/docs/admin/auth.md +++ b/docs/admin/auth.md @@ -63,7 +63,7 @@ Navigate to your Coder host and run the following command to start up the Coder server: ```console -coder server --oidc-issuer-url="https://accounts.google.com" --oidc-email-domain="your-domain" --oidc-client-id="533...ent.com" --oidc-client-secret="G0CSP...7qSM" +coder server --oidc-issuer-url="https://accounts.google.com" --oidc-email-domain="your-domain-1,your-domain-2" --oidc-client-id="533...ent.com" --oidc-client-secret="G0CSP...7qSM" ``` Alternatively, if you are running Coder as a system service, you can achieve the @@ -72,7 +72,7 @@ to the `/etc/coder.d/coder.env` file: ```console CODER_OIDC_ISSUER_URL="https://accounts.google.com" -CODER_OIDC_EMAIL_DOMAIN="your-domain" +CODER_OIDC_EMAIL_DOMAIN="your-domain-1,your-domain-2" CODER_OIDC_CLIENT_ID="533...ent.com" CODER_OIDC_CLIENT_SECRET="G0CSP...7qSM" ``` diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index df75f2080b1c4..00d0bed803ede 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -439,7 +439,7 @@ export interface OIDCConfig { readonly allow_signups: DeploymentConfigField readonly client_id: DeploymentConfigField readonly client_secret: DeploymentConfigField - readonly email_domain: DeploymentConfigField + readonly email_domain: DeploymentConfigField readonly issuer_url: DeploymentConfigField readonly scopes: DeploymentConfigField readonly ignore_email_verified: DeploymentConfigField