feat: Allow multiple OIDC domains (#5210)

Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
This commit is contained in:
Daniel Carrion
2022-12-05 20:20:53 +02:00
committed by GitHub
co-authored by Mathias Fredriksson
parent 02bb052d09
commit 061635c36d
8 changed files with 30 additions and 19 deletions
+2 -2
View File
@@ -216,9 +216,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]{
+1 -1
View File
@@ -154,7 +154,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)
+2 -2
View File
@@ -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.
+12 -5
View File
@@ -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
}
+9 -5
View File
@@ -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{},
+1 -1
View File
@@ -91,7 +91,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"`
+2 -2
View File
@@ -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"
```
+1 -1
View File
@@ -442,7 +442,7 @@ export interface OIDCConfig {
readonly allow_signups: DeploymentConfigField<boolean>
readonly client_id: DeploymentConfigField<string>
readonly client_secret: DeploymentConfigField<string>
readonly email_domain: DeploymentConfigField<string>
readonly email_domain: DeploymentConfigField<string[]>
readonly issuer_url: DeploymentConfigField<string>
readonly scopes: DeploymentConfigField<string[]>
readonly ignore_email_verified: DeploymentConfigField<boolean>