fix(coderd)!: add CODER_OIDC_IGNORE_USERINFO configuration option (#6922)

* add CODER_OIDC_IGNORE_USERINFO option
* chore: update docs for CODER_OIDC_IGNORE_USERINFO w.r.t ADFS
* fix!: codersdk: fix incorrectly named OIDC_GROUP_MAPPING -> CODER_OIDC_GROUP_MAPPING
This commit is contained in:
Cian Johnston
2023-04-05 09:07:43 +01:00
committed by GitHub
parent 929589ddfa
commit 9c4ccd76a0
13 changed files with 209 additions and 42 deletions
+1
View File
@@ -731,6 +731,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
UsernameField: cfg.OIDC.UsernameField.String(), UsernameField: cfg.OIDC.UsernameField.String(),
EmailField: cfg.OIDC.EmailField.String(), EmailField: cfg.OIDC.EmailField.String(),
AuthURLParams: cfg.OIDC.AuthURLParams.Value, AuthURLParams: cfg.OIDC.AuthURLParams.Value,
IgnoreUserInfo: cfg.OIDC.IgnoreUserInfo.Value(),
GroupField: cfg.OIDC.GroupField.String(), GroupField: cfg.OIDC.GroupField.String(),
GroupMapping: cfg.OIDC.GroupMapping.Value, GroupMapping: cfg.OIDC.GroupMapping.Value,
SignInText: cfg.OIDC.SignInText.String(), SignInText: cfg.OIDC.SignInText.String(),
+3
View File
@@ -1086,6 +1086,7 @@ func TestServer(t *testing.T) {
require.Equal(t, "preferred_username", deploymentConfig.Values.OIDC.UsernameField.Value()) require.Equal(t, "preferred_username", deploymentConfig.Values.OIDC.UsernameField.Value())
require.Equal(t, "email", deploymentConfig.Values.OIDC.EmailField.Value()) require.Equal(t, "email", deploymentConfig.Values.OIDC.EmailField.Value())
require.Equal(t, map[string]string{"access_type": "offline"}, deploymentConfig.Values.OIDC.AuthURLParams.Value) require.Equal(t, map[string]string{"access_type": "offline"}, deploymentConfig.Values.OIDC.AuthURLParams.Value)
require.False(t, deploymentConfig.Values.OIDC.IgnoreUserInfo.Value())
require.Empty(t, deploymentConfig.Values.OIDC.GroupField.Value()) require.Empty(t, deploymentConfig.Values.OIDC.GroupField.Value())
require.Empty(t, deploymentConfig.Values.OIDC.GroupMapping.Value) require.Empty(t, deploymentConfig.Values.OIDC.GroupMapping.Value)
require.Equal(t, "OpenID Connect", deploymentConfig.Values.OIDC.SignInText.Value()) require.Equal(t, "OpenID Connect", deploymentConfig.Values.OIDC.SignInText.Value())
@@ -1125,6 +1126,7 @@ func TestServer(t *testing.T) {
"--oidc-username-field", "not_preferred_username", "--oidc-username-field", "not_preferred_username",
"--oidc-email-field", "not_email", "--oidc-email-field", "not_email",
"--oidc-auth-url-params", `{"prompt":"consent"}`, "--oidc-auth-url-params", `{"prompt":"consent"}`,
"--oidc-ignore-userinfo",
"--oidc-group-field", "serious_business_unit", "--oidc-group-field", "serious_business_unit",
"--oidc-group-mapping", `{"serious_business_unit": "serious_business_unit"}`, "--oidc-group-mapping", `{"serious_business_unit": "serious_business_unit"}`,
"--oidc-sign-in-text", "Sign In With Coder", "--oidc-sign-in-text", "Sign In With Coder",
@@ -1169,6 +1171,7 @@ func TestServer(t *testing.T) {
require.True(t, deploymentConfig.Values.OIDC.IgnoreEmailVerified.Value()) require.True(t, deploymentConfig.Values.OIDC.IgnoreEmailVerified.Value())
require.Equal(t, "not_preferred_username", deploymentConfig.Values.OIDC.UsernameField.Value()) require.Equal(t, "not_preferred_username", deploymentConfig.Values.OIDC.UsernameField.Value())
require.Equal(t, "not_email", deploymentConfig.Values.OIDC.EmailField.Value()) require.Equal(t, "not_email", deploymentConfig.Values.OIDC.EmailField.Value())
require.True(t, deploymentConfig.Values.OIDC.IgnoreUserInfo.Value())
require.Equal(t, map[string]string{"prompt": "consent"}, deploymentConfig.Values.OIDC.AuthURLParams.Value) require.Equal(t, map[string]string{"prompt": "consent"}, deploymentConfig.Values.OIDC.AuthURLParams.Value)
require.Equal(t, "serious_business_unit", deploymentConfig.Values.OIDC.GroupField.Value()) require.Equal(t, "serious_business_unit", deploymentConfig.Values.OIDC.GroupField.Value())
require.Equal(t, map[string]string{"serious_business_unit": "serious_business_unit"}, deploymentConfig.Values.OIDC.GroupMapping.Value) require.Equal(t, map[string]string{"serious_business_unit": "serious_business_unit"}, deploymentConfig.Values.OIDC.GroupMapping.Value)
+5 -1
View File
@@ -280,13 +280,17 @@ can safely ignore these settings.
Change the OIDC default 'groups' claim field. By default, will be Change the OIDC default 'groups' claim field. By default, will be
'groups' if present in the oidc scopes argument. 'groups' if present in the oidc scopes argument.
--oidc-group-mapping struct[map[string]string], $OIDC_GROUP_MAPPING (default: {}) --oidc-group-mapping struct[map[string]string], $CODER_OIDC_GROUP_MAPPING (default: {})
A map of OIDC group IDs and the group in Coder it should map to. This A map of OIDC group IDs and the group in Coder it should map to. This
is useful for when OIDC providers only return group IDs. is useful for when OIDC providers only return group IDs.
--oidc-ignore-email-verified bool, $CODER_OIDC_IGNORE_EMAIL_VERIFIED --oidc-ignore-email-verified bool, $CODER_OIDC_IGNORE_EMAIL_VERIFIED
Ignore the email_verified claim from the upstream provider. Ignore the email_verified claim from the upstream provider.
--oidc-ignore-userinfo bool, $CODER_OIDC_IGNORE_USERINFO (default: false)
Ignore the userinfo endpoint and only use the ID token for user
information.
--oidc-issuer-url string, $CODER_OIDC_ISSUER_URL --oidc-issuer-url string, $CODER_OIDC_ISSUER_URL
Issuer URL to use for Login with OIDC. Issuer URL to use for Login with OIDC.
+3
View File
@@ -7553,6 +7553,9 @@ const docTemplate = `{
"ignore_email_verified": { "ignore_email_verified": {
"type": "boolean" "type": "boolean"
}, },
"ignore_user_info": {
"type": "boolean"
},
"issuer_url": { "issuer_url": {
"type": "string" "type": "string"
}, },
+3
View File
@@ -6767,6 +6767,9 @@
"ignore_email_verified": { "ignore_email_verified": {
"type": "boolean" "type": "boolean"
}, },
"ignore_user_info": {
"type": "boolean"
},
"issuer_url": { "issuer_url": {
"type": "string" "type": "string"
}, },
+91 -33
View File
@@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/mail" "net/mail"
"sort"
"strconv" "strconv"
"strings" "strings"
@@ -483,6 +484,11 @@ type OIDCConfig struct {
// AuthURLParams are additional parameters to be passed to the OIDC provider // AuthURLParams are additional parameters to be passed to the OIDC provider
// when requesting an access token. // when requesting an access token.
AuthURLParams map[string]string AuthURLParams map[string]string
// IgnoreUserInfo causes Coder to only use claims from the ID token to
// process OIDC logins. This is useful if the OIDC provider does not
// support the userinfo endpoint, or if the userinfo endpoint causes
// undesirable behavior.
IgnoreUserInfo bool
// GroupField selects the claim field to be used as the created user's // GroupField selects the claim field to be used as the created user's
// groups. If the group field is the empty string, then no group updates // groups. If the group field is the empty string, then no group updates
// will ever come from the OIDC provider. // will ever come from the OIDC provider.
@@ -551,46 +557,62 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
return return
} }
api.Logger.Debug(ctx, "got oidc claims",
slog.F("source", "id_token"),
slog.F("claim_fields", claimFields(claims)),
slog.F("blank", blankFields(claims)),
)
// Not all claims are necessarily embedded in the `id_token`. // Not all claims are necessarily embedded in the `id_token`.
// In GitLab, the username is left empty and must be fetched in UserInfo. // In GitLab, the username is left empty and must be fetched in UserInfo.
// //
// The OIDC specification says claims can be in either place, so we fetch // The OIDC specification says claims can be in either place, so we fetch
// user info and merge the two claim sets to be sure we have all of // user info if required and merge the two claim sets to be sure we have
// the correct data. // all of the correct data.
userInfo, err := api.OIDCConfig.Provider.UserInfo(ctx, oauth2.StaticTokenSource(state.Token)) //
if err == nil { // Some providers (e.g. ADFS) do not support custom OIDC claims in the
userInfoClaims := map[string]interface{}{} // UserInfo endpoint, so we allow users to disable it and only rely on the
err = userInfo.Claims(&userInfoClaims) // ID token.
if err != nil { if !api.OIDCConfig.IgnoreUserInfo {
userInfo, err := api.OIDCConfig.Provider.UserInfo(ctx, oauth2.StaticTokenSource(state.Token))
if err == nil {
userInfoClaims := map[string]interface{}{}
err = userInfo.Claims(&userInfoClaims)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Failed to unmarshal user info claims.",
Detail: err.Error(),
})
return
}
api.Logger.Debug(ctx, "got oidc claims",
slog.F("source", "userinfo"),
slog.F("claim_fields", claimFields(userInfoClaims)),
slog.F("blank", blankFields(userInfoClaims)),
)
// Merge the claims from the ID token and the UserInfo endpoint.
// Information from UserInfo takes precedence.
claims = mergeClaims(claims, userInfoClaims)
// Log all of the field names after merging.
api.Logger.Debug(ctx, "got oidc claims",
slog.F("source", "merged"),
slog.F("claim_fields", claimFields(claims)),
slog.F("blank", blankFields(claims)),
)
} else if !strings.Contains(err.Error(), "user info endpoint is not supported by this provider") {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Failed to unmarshal user info claims.", Message: "Failed to obtain user information claims.",
Detail: err.Error(), Detail: "The attempt to fetch claims via the UserInfo endpoint failed: " + err.Error(),
}) })
return return
} else {
// The OIDC provider does not support the UserInfo endpoint.
// This is not an error, but we should log it as it may mean
// that some claims are missing.
api.Logger.Warn(ctx, "OIDC provider does not support the user info endpoint, ensure that all required claims are present in the id_token")
} }
for k, v := range userInfoClaims {
claims[k] = v
}
} else if !strings.Contains(err.Error(), "user info endpoint is not supported by this provider") {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Failed to obtain user information claims.",
Detail: "The OIDC provider returned no claims as part of the `id_token`. The attempt to fetch claims via the UserInfo endpoint failed: " + err.Error(),
})
return
}
// Log all of the field names returned in the ID token claims, and the
// userinfo returned from the provider.
{
fields := make([]string, 0, len(claims))
for f := range claims {
fields = append(fields, f)
}
api.Logger.Debug(ctx, "got oidc claims",
slog.F("user_info", userInfo),
slog.F("claim_fields", fields),
)
} }
usernameRaw, ok := claims[api.OIDCConfig.UsernameField] usernameRaw, ok := claims[api.OIDCConfig.UsernameField]
@@ -657,7 +679,7 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
group, ok := groupInterface.(string) group, ok := groupInterface.(string)
if !ok { if !ok {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Invalid group type. Expected string, got: %t", emailRaw), Message: fmt.Sprintf("Invalid group type. Expected string, got: %T", groupInterface),
}) })
return return
} }
@@ -761,6 +783,42 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
http.Redirect(rw, r, redirect, http.StatusTemporaryRedirect) http.Redirect(rw, r, redirect, http.StatusTemporaryRedirect)
} }
// claimFields returns the sorted list of fields in the claims map.
func claimFields(claims map[string]interface{}) []string {
fields := []string{}
for field := range claims {
fields = append(fields, field)
}
sort.Strings(fields)
return fields
}
// blankFields returns the list of fields in the claims map that are
// an empty string.
func blankFields(claims map[string]interface{}) []string {
fields := make([]string, 0)
for field, value := range claims {
if valueStr, ok := value.(string); ok && valueStr == "" {
fields = append(fields, field)
}
}
sort.Strings(fields)
return fields
}
// mergeClaims merges the claims from a and b and returns the merged set.
// claims from b take precedence over claims from a.
func mergeClaims(a, b map[string]interface{}) map[string]interface{} {
c := make(map[string]interface{})
for k, v := range a {
c[k] = v
}
for k, v := range b {
c[k] = v
}
return c
}
type oauthLoginParams struct { type oauthLoginParams struct {
User database.User User database.User
Link database.UserLink Link database.UserLink
+44
View File
@@ -501,6 +501,7 @@ func TestUserOIDC(t *testing.T) {
AvatarURL string AvatarURL string
StatusCode int StatusCode int
IgnoreEmailVerified bool IgnoreEmailVerified bool
IgnoreUserInfo bool
}{{ }{{
Name: "EmailOnly", Name: "EmailOnly",
IDTokenClaims: jwt.MapClaims{ IDTokenClaims: jwt.MapClaims{
@@ -643,6 +644,48 @@ func TestUserOIDC(t *testing.T) {
}, },
AllowSignups: true, AllowSignups: true,
StatusCode: http.StatusTemporaryRedirect, StatusCode: http.StatusTemporaryRedirect,
}, {
Name: "UserInfoOverridesIDTokenClaims",
IDTokenClaims: jwt.MapClaims{
"email": "internaluser@internal.domain",
"email_verified": false,
},
UserInfoClaims: jwt.MapClaims{
"email": "externaluser@external.domain",
"email_verified": true,
"preferred_username": "user",
},
Username: "user",
AllowSignups: true,
IgnoreEmailVerified: false,
StatusCode: http.StatusTemporaryRedirect,
}, {
Name: "InvalidUserInfo",
IDTokenClaims: jwt.MapClaims{
"email": "internaluser@internal.domain",
"email_verified": false,
},
UserInfoClaims: jwt.MapClaims{
"email": 1,
},
AllowSignups: true,
IgnoreEmailVerified: false,
StatusCode: http.StatusInternalServerError,
}, {
Name: "IgnoreUserInfo",
IDTokenClaims: jwt.MapClaims{
"email": "user@internal.domain",
"email_verified": true,
"preferred_username": "user",
},
UserInfoClaims: jwt.MapClaims{
"email": "user.mcname@external.domain",
"preferred_username": "Mr. User McName",
},
Username: "user",
IgnoreUserInfo: true,
AllowSignups: true,
StatusCode: http.StatusTemporaryRedirect,
}} { }} {
tc := tc tc := tc
t.Run(tc.Name, func(t *testing.T) { t.Run(tc.Name, func(t *testing.T) {
@@ -654,6 +697,7 @@ func TestUserOIDC(t *testing.T) {
config.AllowSignups = tc.AllowSignups config.AllowSignups = tc.AllowSignups
config.EmailDomain = tc.EmailDomain config.EmailDomain = tc.EmailDomain
config.IgnoreEmailVerified = tc.IgnoreEmailVerified config.IgnoreEmailVerified = tc.IgnoreEmailVerified
config.IgnoreUserInfo = tc.IgnoreUserInfo
client := coderdtest.New(t, &coderdtest.Options{ client := coderdtest.New(t, &coderdtest.Options{
Auditor: auditor, Auditor: auditor,
+12 -1
View File
@@ -258,6 +258,7 @@ type OIDCConfig struct {
UsernameField clibase.String `json:"username_field" typescript:",notnull"` UsernameField clibase.String `json:"username_field" typescript:",notnull"`
EmailField clibase.String `json:"email_field" typescript:",notnull"` EmailField clibase.String `json:"email_field" typescript:",notnull"`
AuthURLParams clibase.Struct[map[string]string] `json:"auth_url_params" typescript:",notnull"` AuthURLParams clibase.Struct[map[string]string] `json:"auth_url_params" typescript:",notnull"`
IgnoreUserInfo clibase.Bool `json:"ignore_user_info" typescript:",notnull"`
GroupField clibase.String `json:"groups_field" typescript:",notnull"` GroupField clibase.String `json:"groups_field" typescript:",notnull"`
GroupMapping clibase.Struct[map[string]string] `json:"group_mapping" typescript:",notnull"` GroupMapping clibase.Struct[map[string]string] `json:"group_mapping" typescript:",notnull"`
SignInText clibase.String `json:"sign_in_text" typescript:",notnull"` SignInText clibase.String `json:"sign_in_text" typescript:",notnull"`
@@ -882,6 +883,16 @@ when required by your organization's security policy.`,
Group: &deploymentGroupOIDC, Group: &deploymentGroupOIDC,
YAML: "authURLParams", YAML: "authURLParams",
}, },
{
Name: "OIDC Ignore UserInfo",
Description: "Ignore the userinfo endpoint and only use the ID token for user information.",
Flag: "oidc-ignore-userinfo",
Env: "CODER_OIDC_IGNORE_USERINFO",
Default: "false",
Value: &c.OIDC.IgnoreUserInfo,
Group: &deploymentGroupOIDC,
YAML: "ignoreUserInfo",
},
{ {
Name: "OIDC Group Field", Name: "OIDC Group Field",
Description: "Change the OIDC default 'groups' claim field. By default, will be 'groups' if present in the oidc scopes argument.", Description: "Change the OIDC default 'groups' claim field. By default, will be 'groups' if present in the oidc scopes argument.",
@@ -901,7 +912,7 @@ when required by your organization's security policy.`,
Name: "OIDC Group Mapping", Name: "OIDC Group Mapping",
Description: "A map of OIDC group IDs and the group in Coder it should map to. This is useful for when OIDC providers only return group IDs.", Description: "A map of OIDC group IDs and the group in Coder it should map to. This is useful for when OIDC providers only return group IDs.",
Flag: "oidc-group-mapping", Flag: "oidc-group-mapping",
Env: "OIDC_GROUP_MAPPING", Env: "CODER_OIDC_GROUP_MAPPING",
Default: "{}", Default: "{}",
Value: &c.OIDC.GroupMapping, Value: &c.OIDC.GroupMapping,
Group: &deploymentGroupOIDC, Group: &deploymentGroupOIDC,
+30 -6
View File
@@ -144,6 +144,10 @@ while signing in via OIDC as a new user. Coder will log the claim fields
returned by the upstream identity provider in a message containing the returned by the upstream identity provider in a message containing the
string `got oidc claims`, as well as the user info returned. string `got oidc claims`, as well as the user info returned.
> **Note:** If you need to ensure that Coder only uses information from
> the ID token and does not hit the UserInfo endpoint, you can set the
> configuration option `CODER_OIDC_IGNORE_USERINFO=true`.
### Email Addresses ### Email Addresses
By default, Coder will look for the OIDC claim named `email` and use that By default, Coder will look for the OIDC claim named `email` and use that
@@ -262,17 +266,37 @@ Below are some details specific to individual OIDC providers.
steps as described [here.](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/development/msal/adfs-msal-web-app-web-api#app-registration-in-ad-fs) steps as described [here.](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/development/msal/adfs-msal-web-app-web-api#app-registration-in-ad-fs)
- **Server Application**: Note the Client ID. - **Server Application**: Note the Client ID.
- **Configure Application Credentials**: Note the Client Secret. - **Configure Application Credentials**: Note the Client Secret.
- **Configure Web API**: Ensure the Client ID is set as the relying party identifier. - **Configure Web API**: Set the Client ID as the relying party identifier.
- **Application Permissions**: Allow access to the claims `openid`, `email`, and `profile`. - **Application Permissions**: Allow access to the claims `openid`, `email`, `profile`, and `allatclaims`.
1. Visit your ADFS server's `/.well-known/openid-configuration` URL and note 1. Visit your ADFS server's `/.well-known/openid-configuration` URL and note
the value for `issuer`. the value for `issuer`.
> **Note:** This is usually of the form `https://adfs.corp/adfs/.well-known/openid-configuration` > **Note:** This is usually of the form `https://adfs.corp/adfs/.well-known/openid-configuration`
1. In Coder's configuration file (or Helm values as appropriate), set the following 1. In Coder's configuration file (or Helm values as appropriate), set the following
environment variables or their corresponding CLI arguments: environment variables or their corresponding CLI arguments:
- `CODER_OIDC_ISSUER_URL`: the `issuer` value from the previous step. - `CODER_OIDC_ISSUER_URL`: the `issuer` value from the previous step.
- `CODER_OIDC_CLIENT_ID`: the Client ID from step 1. - `CODER_OIDC_CLIENT_ID`: the Client ID from step 1.
- `CODER_OIDC_CLIENT_SECRET`: the Client Secret from step 1. - `CODER_OIDC_CLIENT_SECRET`: the Client Secret from step 1.
- `CODER_OIDC_AUTH_URL_PARAMS`: set to `{"resource":"urn:microsoft:userinfo"}` ([see here](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios#:~:text=scope%E2%80%AFopenid.-,resource,-optional)). OIDC logins will fail if this is not set. - `CODER_OIDC_AUTH_URL_PARAMS`: set to
1. Ensure that Coder has the required OIDC claims by performing either of the below:
- Configure your federation server to reuturn both the `email` and `preferred_username` fields by [creating a custom claim rule](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-rule-to-send-ldap-attributes-as-claims), or ```console
- Set `CODER_OIDC_EMAIL_FIELD="upn"`. This will use the User Principal Name as the user email, which is [guaranteed to be unique in an Active Directory Forest](https://learn.microsoft.com/en-us/windows/win32/ad/naming-properties#upn-format). {"resource":"$CLIENT_ID"}
```
where `$CLIENT_ID` is the Client ID from step 1 ([see here](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios#:~:text=scope%E2%80%AFopenid.-,resource,-optional)).
This is required for the upstream OIDC provider to return the requested claims.
- `CODER_OIDC_IGNORE_USERINFO`: Set to `true`.
1. Configure [Issuance Transform Rules](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-rule-to-send-ldap-attributes-as-claims)
on your federation server to send the following claims:
- `preferred_username`: You can use e.g. "Display Name" as required.
- `email`: You can use e.g. the LDAP attribute "E-Mail-Addresses" as required.
- `email_verified`: Create a custom claim rule:
```console
=> issue(Type = "email_verified", Value = "true")
```
- (Optional) If using Group Sync, send the required groups in the configured groups claim field. See [here](https://stackoverflow.com/a/55570286) for an example.
+1
View File
@@ -251,6 +251,7 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \
"user": {} "user": {}
}, },
"ignore_email_verified": true, "ignore_email_verified": true,
"ignore_user_info": true,
"issuer_url": "string", "issuer_url": "string",
"scopes": ["string"], "scopes": ["string"],
"sign_in_text": "string", "sign_in_text": "string",
+4
View File
@@ -1877,6 +1877,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
"user": {} "user": {}
}, },
"ignore_email_verified": true, "ignore_email_verified": true,
"ignore_user_info": true,
"issuer_url": "string", "issuer_url": "string",
"scopes": ["string"], "scopes": ["string"],
"sign_in_text": "string", "sign_in_text": "string",
@@ -2224,6 +2225,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
"user": {} "user": {}
}, },
"ignore_email_verified": true, "ignore_email_verified": true,
"ignore_user_info": true,
"issuer_url": "string", "issuer_url": "string",
"scopes": ["string"], "scopes": ["string"],
"sign_in_text": "string", "sign_in_text": "string",
@@ -2890,6 +2892,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
"user": {} "user": {}
}, },
"ignore_email_verified": true, "ignore_email_verified": true,
"ignore_user_info": true,
"issuer_url": "string", "issuer_url": "string",
"scopes": ["string"], "scopes": ["string"],
"sign_in_text": "string", "sign_in_text": "string",
@@ -2911,6 +2914,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
| `groups_field` | string | false | | | | `groups_field` | string | false | | |
| `icon_url` | [clibase.URL](#clibaseurl) | false | | | | `icon_url` | [clibase.URL](#clibaseurl) | false | | |
| `ignore_email_verified` | boolean | false | | | | `ignore_email_verified` | boolean | false | | |
| `ignore_user_info` | boolean | false | | |
| `issuer_url` | string | false | | | | `issuer_url` | string | false | | |
| `scopes` | array of string | false | | | | `scopes` | array of string | false | | |
| `sign_in_text` | string | false | | | | `sign_in_text` | string | false | | |
+11 -1
View File
@@ -361,7 +361,7 @@ Change the OIDC default 'groups' claim field. By default, will be 'groups' if pr
| | | | | |
| ----------- | -------------------------------------- | | ----------- | -------------------------------------- |
| Type | <code>struct[map[string]string]</code> | | Type | <code>struct[map[string]string]</code> |
| Environment | <code>$OIDC_GROUP_MAPPING</code> | | Environment | <code>$CODER_OIDC_GROUP_MAPPING</code> |
| Default | <code>{}</code> | | Default | <code>{}</code> |
A map of OIDC group IDs and the group in Coder it should map to. This is useful for when OIDC providers only return group IDs. A map of OIDC group IDs and the group in Coder it should map to. This is useful for when OIDC providers only return group IDs.
@@ -384,6 +384,16 @@ URL pointing to the icon to use on the OepnID Connect login button.
Ignore the email_verified claim from the upstream provider. Ignore the email_verified claim from the upstream provider.
### --oidc-ignore-userinfo
| | |
| ----------- | ---------------------------------------- |
| Type | <code>bool</code> |
| Environment | <code>$CODER_OIDC_IGNORE_USERINFO</code> |
| Default | <code>false</code> |
Ignore the userinfo endpoint and only use the ID token for user information.
### --oidc-issuer-url ### --oidc-issuer-url
| | | | | |
+1
View File
@@ -531,6 +531,7 @@ export interface OIDCConfig {
// Named type "github.com/coder/coder/cli/clibase.Struct[map[string]string]" unknown, using "any" // Named type "github.com/coder/coder/cli/clibase.Struct[map[string]string]" unknown, using "any"
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type
readonly auth_url_params: any readonly auth_url_params: any
readonly ignore_user_info: boolean
readonly groups_field: string readonly groups_field: string
// Named type "github.com/coder/coder/cli/clibase.Struct[map[string]string]" unknown, using "any" // Named type "github.com/coder/coder/cli/clibase.Struct[map[string]string]" unknown, using "any"
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type