Skip to content

feat: Allow multiple OIDC domains #5210

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
revert plural
  • Loading branch information
Daniel Carrion committed Dec 2, 2022
commit 193c000819ceb6bacafc18d70dc6ea45cd5cef8c
2 changes: 1 addition & 1 deletion cli/deployment/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ func newConfig() *codersdk.DeploymentConfig {
Flag: "oidc-client-secret",
Secret: true,
},
EmailDomains: &codersdk.DeploymentConfigField[[]string]{
EmailDomain: &codersdk.DeploymentConfigField[[]string]{
Name: "OIDC Email Domain",
Usage: "Email domains that clients logging in with OIDC must match.",
Flag: "oidc-email-domain",
Expand Down
4 changes: 2 additions & 2 deletions cli/deployment/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func TestConfig(t *testing.T) {
Env: map[string]string{},
Valid: func(config *codersdk.DeploymentConfig) {
require.Empty(t, config.OIDC.IssuerURL.Value)
require.Empty(t, config.OIDC.EmailDomains.Value)
require.Empty(t, config.OIDC.EmailDomain.Value)
require.Empty(t, config.OIDC.ClientID.Value)
require.Empty(t, config.OIDC.ClientSecret.Value)
require.True(t, config.OIDC.AllowSignups.Value)
Expand All @@ -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.EmailDomains.Value, []string{"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)
Expand Down
2 changes: 1 addition & 1 deletion cli/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
Verifier: oidcProvider.Verifier(&oidc.Config{
ClientID: cfg.OIDC.ClientID.Value,
}),
EmailDomains: cfg.OIDC.EmailDomains.Value,
EmailDomain: cfg.OIDC.EmailDomain.Value,
AllowSignups: cfg.OIDC.AllowSignups.Value,
}
}
Expand Down
2 changes: 1 addition & 1 deletion cli/testdata/coder_server_--help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Flags:
Consumes $CODER_OIDC_CLIENT_SECRET
--oidc-email-domain strings Email domains that clients logging in
with OIDC must match.
Consumes $CODER_OIDC_EMAIL_DOMAINS
Consumes $CODER_OIDC_EMAIL_DOMAIN
--oidc-ignore-email-verified Ignore the email_verified claim from the
upstream provider.
Consumes $CODER_OIDC_IGNORE_EMAIL_VERIFIED
Expand Down
8 changes: 4 additions & 4 deletions coderd/userauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ type OIDCConfig struct {

Verifier *oidc.IDTokenVerifier
// EmailDomains are the domains to enforce when a user authenticates.
EmailDomains []string
EmailDomain []string
AllowSignups bool
// IgnoreEmailVerified allows ignoring the email_verified claim
// from an upstream OIDC provider. See #5065 for context.
Expand Down Expand Up @@ -291,17 +291,17 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
}
// Check if one or comma delimited list of allowed domains is provided.
// If a suffix matches, break and continue, otherwise error.
if len(api.OIDCConfig.EmailDomains) > 0 {
if len(api.OIDCConfig.EmailDomain) > 0 {
ok = false
for _, domain := range api.OIDCConfig.EmailDomains {
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 in domains %q !", email, api.OIDCConfig.EmailDomains),
Message: fmt.Sprintf("Your email %q is not in domains %q !", email, api.OIDCConfig.EmailDomain),
})
return
}
Expand Down
8 changes: 4 additions & 4 deletions coderd/userauth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ func TestUserOIDC(t *testing.T) {
Name string
Claims jwt.MapClaims
AllowSignups bool
EmailDomains []string
EmailDomain []string
Username string
AvatarURL string
StatusCode int
Expand Down Expand Up @@ -528,7 +528,7 @@ func TestUserOIDC(t *testing.T) {
"email_verified": true,
},
AllowSignups: true,
EmailDomains: []string{
EmailDomain: []string{
"coder.com",
},
StatusCode: http.StatusForbidden,
Expand All @@ -539,7 +539,7 @@ func TestUserOIDC(t *testing.T) {
"email_verified": true,
},
AllowSignups: true,
EmailDomains: []string{
EmailDomain: []string{
"kwc.io",
},
StatusCode: http.StatusTemporaryRedirect,
Expand Down Expand Up @@ -615,7 +615,7 @@ func TestUserOIDC(t *testing.T) {

config := conf.OIDCConfig()
config.AllowSignups = tc.AllowSignups
config.EmailDomains = tc.EmailDomains
config.EmailDomain = tc.EmailDomain
config.IgnoreEmailVerified = tc.IgnoreEmailVerified

client := coderdtest.New(t, &coderdtest.Options{
Expand Down
2 changes: 1 addition & 1 deletion codersdk/deploymentconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
EmailDomains *DeploymentConfigField[[]string] `json:"email_domains" 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"`
Expand Down
2 changes: 1 addition & 1 deletion site/src/api/typesGenerated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ export interface OIDCConfig {
readonly allow_signups: DeploymentConfigField<boolean>
readonly client_id: DeploymentConfigField<string>
readonly client_secret: DeploymentConfigField<string>
readonly email_domains: DeploymentConfigField<string[]>
readonly email_domain: DeploymentConfigField<string[]>
readonly issuer_url: DeploymentConfigField<string>
readonly scopes: DeploymentConfigField<string[]>
readonly ignore_email_verified: DeploymentConfigField<boolean>
Expand Down
2 changes: 1 addition & 1 deletion site/src/pages/DeploySettingsPage/UserAuthSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const UserAuthSettingsPage: React.FC = () => {
options={{
client_id: deploymentConfig.oidc.client_id,
allow_signups: deploymentConfig.oidc.allow_signups,
email_domains: deploymentConfig.oidc.email_domains,
email_domain: deploymentConfig.oidc.email_domain,
issuer_url: deploymentConfig.oidc.issuer_url,
scopes: deploymentConfig.oidc.scopes,
}}
Expand Down