mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: support multiple OIDC redirect URIs (#25408)
This PR adds a new opt-in setting, `CODER_OIDC_REDIRECT_ALLOWED_HOSTS`, that lets a single Coder deployment complete OIDC login on more than one hostname. When the allowlist is non-empty, Coder picks the OIDC `redirect_uri` based on the incoming request's Host header (validated against the list) instead of always using the static URL derived from `CODER_ACCESS_URL`. When unset, the (default) behavior is identical to today. The motivation is that a single Coder deployment is frequently reachable via multiple hostnames - for example, an internal hostname for users on a corporate VPN and a different hostname routed through a zero-trust gateway for users off-VPN - but OIDC login today only works on whichever single hostname `CODER_ACCESS_URL` points to, because the `redirect_uri` sent to the IdP is fixed at server startup. Users who reach the deployment on any other valid hostname can see the login page but fail the OIDC callback, since the IdP redirects them back to a hostname they can't reach (or whose cookies they don't have).
This commit is contained in:
Generated
+3
@@ -464,6 +464,9 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \
|
||||
"organization_assign_default": true,
|
||||
"organization_field": "string",
|
||||
"organization_mapping": {},
|
||||
"redirect_allowed_hosts": [
|
||||
"string"
|
||||
],
|
||||
"redirect_url": {
|
||||
"forceQuery": true,
|
||||
"fragment": "string",
|
||||
|
||||
Generated
+45
-35
@@ -5846,6 +5846,9 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
|
||||
"organization_assign_default": true,
|
||||
"organization_field": "string",
|
||||
"organization_mapping": {},
|
||||
"redirect_allowed_hosts": [
|
||||
"string"
|
||||
],
|
||||
"redirect_url": {
|
||||
"forceQuery": true,
|
||||
"fragment": "string",
|
||||
@@ -6452,6 +6455,9 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
|
||||
"organization_assign_default": true,
|
||||
"organization_field": "string",
|
||||
"organization_mapping": {},
|
||||
"redirect_allowed_hosts": [
|
||||
"string"
|
||||
],
|
||||
"redirect_url": {
|
||||
"forceQuery": true,
|
||||
"fragment": "string",
|
||||
@@ -8935,6 +8941,9 @@ Only certain features set these fields: - FeatureManagedAgentLimit|
|
||||
"organization_assign_default": true,
|
||||
"organization_field": "string",
|
||||
"organization_mapping": {},
|
||||
"redirect_allowed_hosts": [
|
||||
"string"
|
||||
],
|
||||
"redirect_url": {
|
||||
"forceQuery": true,
|
||||
"fragment": "string",
|
||||
@@ -8966,41 +8975,42 @@ Only certain features set these fields: - FeatureManagedAgentLimit|
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|--------------------------------------|----------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `allow_signups` | boolean | false | | |
|
||||
| `auth_url_params` | object | false | | |
|
||||
| `auto_repair_links` | boolean | false | | |
|
||||
| `client_cert_file` | string | false | | |
|
||||
| `client_id` | string | false | | |
|
||||
| `client_key_file` | string | false | | Client key file & ClientCertFile are used in place of ClientSecret for PKI auth. |
|
||||
| `client_secret` | string | false | | |
|
||||
| `email_domain` | array of string | false | | |
|
||||
| `email_fallback` | boolean | false | | Email fallback allows OIDC logins to fall back to email-based matching when the `linked_id` (issuer+subject) does not match an existing user link. INSECURE: weakens the linked_id check. It exists for IdP brokers that do not issue a stable `sub` for the same user across connections. |
|
||||
| `email_field` | string | false | | |
|
||||
| `group_allow_list` | array of string | false | | |
|
||||
| `group_auto_create` | boolean | false | | |
|
||||
| `group_mapping` | object | false | | |
|
||||
| `group_regex_filter` | [serpent.Regexp](#serpentregexp) | false | | |
|
||||
| `groups_field` | string | false | | |
|
||||
| `icon_url` | [serpent.URL](#serpenturl) | false | | |
|
||||
| `ignore_email_verified` | boolean | false | | |
|
||||
| `ignore_user_info` | boolean | false | | Ignore user info & UserInfoFromAccessToken are mutually exclusive. Only 1 can be set to true. Ideally this would be an enum with 3 states, ['none', 'userinfo', 'access_token']. However, for backward compatibility, `ignore_user_info` must remain. And `access_token` is a niche, non-spec compliant edge case. So it's use is rare, and should not be advised. |
|
||||
| `issuer_url` | string | false | | |
|
||||
| `name_field` | string | false | | |
|
||||
| `organization_assign_default` | boolean | false | | |
|
||||
| `organization_field` | string | false | | |
|
||||
| `organization_mapping` | object | false | | |
|
||||
| `redirect_url` | [serpent.URL](#serpenturl) | false | | Redirect URL is optional, defaulting to 'ACCESS_URL'. Only useful in niche situations where the OIDC callback domain is different from the ACCESS_URL domain. |
|
||||
| `scopes` | array of string | false | | |
|
||||
| `sign_in_text` | string | false | | |
|
||||
| `signups_disabled_text` | string | false | | |
|
||||
| `skip_issuer_checks` | boolean | false | | |
|
||||
| `source_user_info_from_access_token` | boolean | false | | Source user info from access token as mentioned above is an edge case. This allows sourcing the user_info from the access token itself instead of a user_info endpoint. This assumes the access token is a valid JWT with a set of claims to be merged with the id_token. |
|
||||
| `user_role_field` | string | false | | |
|
||||
| `user_role_mapping` | object | false | | |
|
||||
| `user_roles_default` | array of string | false | | |
|
||||
| `username_field` | string | false | | |
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|--------------------------------------|----------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `allow_signups` | boolean | false | | |
|
||||
| `auth_url_params` | object | false | | |
|
||||
| `auto_repair_links` | boolean | false | | |
|
||||
| `client_cert_file` | string | false | | |
|
||||
| `client_id` | string | false | | |
|
||||
| `client_key_file` | string | false | | Client key file & ClientCertFile are used in place of ClientSecret for PKI auth. |
|
||||
| `client_secret` | string | false | | |
|
||||
| `email_domain` | array of string | false | | |
|
||||
| `email_fallback` | boolean | false | | Email fallback allows OIDC logins to fall back to email-based matching when the `linked_id` (issuer+subject) does not match an existing user link. INSECURE: weakens the linked_id check. It exists for IdP brokers that do not issue a stable `sub` for the same user across connections. |
|
||||
| `email_field` | string | false | | |
|
||||
| `group_allow_list` | array of string | false | | |
|
||||
| `group_auto_create` | boolean | false | | |
|
||||
| `group_mapping` | object | false | | |
|
||||
| `group_regex_filter` | [serpent.Regexp](#serpentregexp) | false | | |
|
||||
| `groups_field` | string | false | | |
|
||||
| `icon_url` | [serpent.URL](#serpenturl) | false | | |
|
||||
| `ignore_email_verified` | boolean | false | | |
|
||||
| `ignore_user_info` | boolean | false | | Ignore user info & UserInfoFromAccessToken are mutually exclusive. Only 1 can be set to true. Ideally this would be an enum with 3 states, ['none', 'userinfo', 'access_token']. However, for backward compatibility, `ignore_user_info` must remain. And `access_token` is a niche, non-spec compliant edge case. So it's use is rare, and should not be advised. |
|
||||
| `issuer_url` | string | false | | |
|
||||
| `name_field` | string | false | | |
|
||||
| `organization_assign_default` | boolean | false | | |
|
||||
| `organization_field` | string | false | | |
|
||||
| `organization_mapping` | object | false | | |
|
||||
| `redirect_allowed_hosts` | array of string | false | | Redirect allowed hosts is an allowlist of hostnames that may be used as the host of the OIDC redirect_uri. When non-empty, the redirect_uri is constructed from the incoming request's Host header (validated against this list) instead of from AccessURL. Every listed host must also be registered as a valid redirect URI in the OIDC provider. This setting is mutually exclusive with RedirectURL: if RedirectURL is set, this allowlist is ignored. |
|
||||
| `redirect_url` | [serpent.URL](#serpenturl) | false | | Redirect URL is optional, defaulting to 'ACCESS_URL'. Only useful in niche situations where the OIDC callback domain is different from the ACCESS_URL domain. |
|
||||
| `scopes` | array of string | false | | |
|
||||
| `sign_in_text` | string | false | | |
|
||||
| `signups_disabled_text` | string | false | | |
|
||||
| `skip_issuer_checks` | boolean | false | | |
|
||||
| `source_user_info_from_access_token` | boolean | false | | Source user info from access token as mentioned above is an edge case. This allows sourcing the user_info from the access token itself instead of a user_info endpoint. This assumes the access token is a valid JWT with a set of claims to be merged with the id_token. |
|
||||
| `user_role_field` | string | false | | |
|
||||
| `user_role_mapping` | object | false | | |
|
||||
| `user_roles_default` | array of string | false | | |
|
||||
| `username_field` | string | false | | |
|
||||
|
||||
## codersdk.OptionType
|
||||
|
||||
|
||||
Reference in New Issue
Block a user