diff --git a/cli/deployment/config.go b/cli/deployment/config.go index 97177d235996c..aaa64d2bea963 100644 --- a/cli/deployment/config.go +++ b/cli/deployment/config.go @@ -248,6 +248,12 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "oidc-ignore-email-verified", Default: false, }, + UsernameField: &codersdk.DeploymentConfigField[string]{ + Name: "OIDC Username Field", + Usage: "OIDC claim field to use as the username.", + Flag: "oidc-username-field", + Default: "preferred_username", + }, }, Telemetry: &codersdk.TelemetryConfig{ diff --git a/cli/server.go b/cli/server.go index 740782779ab19..e04ffc4283cb7 100644 --- a/cli/server.go +++ b/cli/server.go @@ -526,8 +526,9 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co Verifier: oidcProvider.Verifier(&oidc.Config{ ClientID: cfg.OIDC.ClientID.Value, }), - EmailDomain: cfg.OIDC.EmailDomain.Value, - AllowSignups: cfg.OIDC.AllowSignups.Value, + EmailDomain: cfg.OIDC.EmailDomain.Value, + AllowSignups: cfg.OIDC.AllowSignups.Value, + UsernameField: cfg.OIDC.UsernameField.Value, } } diff --git a/cli/testdata/coder_server_--help.golden b/cli/testdata/coder_server_--help.golden index 43b97ccb2189b..fa7cc9eeba05f 100644 --- a/cli/testdata/coder_server_--help.golden +++ b/cli/testdata/coder_server_--help.golden @@ -112,6 +112,9 @@ Flags: OIDC. Consumes $CODER_OIDC_SCOPES (default [openid,profile,email]) + --oidc-username-field string OIDC claim field to use as the username. + Consumes $CODER_OIDC_USERNAME_FIELD + (default "preferred_username") --postgres-url string URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 9b45d84e515da..ebd1a8a8e4498 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -1975,6 +1975,9 @@ const docTemplate = `{ }, "scopes": { "$ref": "#/definitions/codersdk.DeploymentConfigField-array_string" + }, + "username_field": { + "$ref": "#/definitions/codersdk.DeploymentConfigField-string" } } }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 8474aebfee1cd..3b3514852255e 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -1795,6 +1795,9 @@ }, "scopes": { "$ref": "#/definitions/codersdk.DeploymentConfigField-array_string" + }, + "username_field": { + "$ref": "#/definitions/codersdk.DeploymentConfigField-string" } } }, diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index 7da86ad83d6f6..34b44ab883dad 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -880,6 +880,7 @@ func (o *OIDCConfig) OIDCConfig() *coderd.OIDCConfig { }, &oidc.Config{ SkipClientIDCheck: true, }), + UsernameField: "preferred_username", } } diff --git a/coderd/userauth.go b/coderd/userauth.go index 1197aa8d2cea6..5a23b86c8de71 100644 --- a/coderd/userauth.go +++ b/coderd/userauth.go @@ -198,6 +198,9 @@ type OIDCConfig struct { // IgnoreEmailVerified allows ignoring the email_verified claim // from an upstream OIDC provider. See #5065 for context. IgnoreEmailVerified bool + // UsernameField selects the claim field to be used as the created user's + // username. + UsernameField string } func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) { @@ -236,7 +239,7 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) { }) return } - usernameRaw, ok := claims["preferred_username"] + usernameRaw, ok := claims[api.OIDCConfig.UsernameField] var username string if ok { username, _ = usernameRaw.(string) diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index 7a336595f91e4..8d12426292241 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -99,6 +99,7 @@ type OIDCConfig struct { IssuerURL *DeploymentConfigField[string] `json:"issuer_url" typescript:",notnull"` Scopes *DeploymentConfigField[[]string] `json:"scopes" typescript:",notnull"` IgnoreEmailVerified *DeploymentConfigField[bool] `json:"ignore_email_verified" typescript:",notnull"` + UsernameField *DeploymentConfigField[string] `json:"username_field" typescript:",notnull"` } type TelemetryConfig struct { diff --git a/docs/api/general.md b/docs/api/general.md index f8293d32c8709..d9355f7f1c505 100644 --- a/docs/api/general.md +++ b/docs/api/general.md @@ -535,6 +535,17 @@ curl -X GET http://coder-server:8080/api/v2/config/deployment \ "shorthand": "string", "usage": "string", "value": "string" + }, + "username_field": { + "default": "string", + "enterprise": true, + "flag": "string", + "hidden": true, + "name": "string", + "secret": true, + "shorthand": "string", + "usage": "string", + "value": "string" } }, "pg_connection_url": { diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 511cd2402aede..478403c1fc166 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -1119,6 +1119,17 @@ CreateParameterRequest is a structure used to create a new parameter value for a "shorthand": "string", "usage": "string", "value": "string" + }, + "username_field": { + "default": "string", + "enterprise": true, + "flag": "string", + "hidden": true, + "name": "string", + "secret": true, + "shorthand": "string", + "usage": "string", + "value": "string" } }, "pg_connection_url": { @@ -2072,6 +2083,17 @@ CreateParameterRequest is a structure used to create a new parameter value for a "shorthand": "string", "usage": "string", "value": "string" + }, + "username_field": { + "default": "string", + "enterprise": true, + "flag": "string", + "hidden": true, + "name": "string", + "secret": true, + "shorthand": "string", + "usage": "string", + "value": "string" } } ``` @@ -2087,6 +2109,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a | `ignore_email_verified` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | | | `issuer_url` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | | | `scopes` | [codersdk.DeploymentConfigField-array_string](#codersdkdeploymentconfigfield-array_string) | false | | | +| `username_field` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | | ## codersdk.Parameter diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index eaea70ca0ff95..72669b8f01fab 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -452,6 +452,7 @@ export interface OIDCConfig { readonly issuer_url: DeploymentConfigField readonly scopes: DeploymentConfigField readonly ignore_email_verified: DeploymentConfigField + readonly username_field: DeploymentConfigField } // From codersdk/organizations.go