diff --git a/cli/server.go b/cli/server.go index 1b1bc49f9ce..0efed00a375 100644 --- a/cli/server.go +++ b/cli/server.go @@ -974,6 +974,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd. } options.ExternalAuthConfigs, err = externalauth.ConvertConfig( + ctx, logger, oauthInstrument, mergedExternalAuthProviders, @@ -3123,6 +3124,8 @@ func parseExternalAuthProvidersFromEnv(prefix string, environ []string) ([]coder provider.RevokeURL = v.Value case "VALIDATE_URL": provider.ValidateURL = v.Value + case "REDIRECT_URL": + provider.RedirectURL = v.Value case "REGEX": provider.Regex = v.Value case "DEVICE_FLOW": diff --git a/cli/server_test.go b/cli/server_test.go index f239eec278d..2458f033f4c 100644 --- a/cli/server_test.go +++ b/cli/server_test.go @@ -81,6 +81,7 @@ func TestReadExternalAuthProvidersFromEnv(t *testing.T) { "CODER_EXTERNAL_AUTH_1_CLIENT_SECRET=hunter12", "CODER_EXTERNAL_AUTH_1_TOKEN_URL=google.com", "CODER_EXTERNAL_AUTH_1_VALIDATE_URL=bing.com", + "CODER_EXTERNAL_AUTH_1_REDIRECT_URL=coder.com", "CODER_EXTERNAL_AUTH_1_REVOKE_URL=revoke.url", "CODER_EXTERNAL_AUTH_1_SCOPES=repo:read repo:write", "CODER_EXTERNAL_AUTH_1_NO_REFRESH=true", @@ -101,6 +102,7 @@ func TestReadExternalAuthProvidersFromEnv(t *testing.T) { assert.Equal(t, "hunter12", providers[1].ClientSecret) assert.Equal(t, "google.com", providers[1].TokenURL) assert.Equal(t, "bing.com", providers[1].ValidateURL) + assert.Equal(t, "coder.com", providers[1].RedirectURL) assert.Equal(t, "revoke.url", providers[1].RevokeURL) assert.Equal(t, []string{"repo:read", "repo:write"}, providers[1].Scopes) assert.Equal(t, true, providers[1].NoRefresh) @@ -193,6 +195,7 @@ func TestReadGitAuthProvidersFromEnv(t *testing.T) { "CODER_GITAUTH_1_CLIENT_SECRET=hunter12", "CODER_GITAUTH_1_TOKEN_URL=google.com", "CODER_GITAUTH_1_VALIDATE_URL=bing.com", + "CODER_GITAUTH_1_REDIRECT_URL=coder.com", "CODER_GITAUTH_1_SCOPES=repo:read repo:write", "CODER_GITAUTH_1_NO_REFRESH=true", }) @@ -209,6 +212,7 @@ func TestReadGitAuthProvidersFromEnv(t *testing.T) { assert.Equal(t, "hunter12", providers[1].ClientSecret) assert.Equal(t, "google.com", providers[1].TokenURL) assert.Equal(t, "bing.com", providers[1].ValidateURL) + assert.Equal(t, "coder.com", providers[1].RedirectURL) assert.Equal(t, []string{"repo:read", "repo:write"}, providers[1].Scopes) assert.Equal(t, true, providers[1].NoRefresh) }) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index f3dd16d01d0..26ad75ed1e8 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -20606,6 +20606,10 @@ const docTemplate = `{ "no_refresh": { "type": "boolean" }, + "redirect_url": { + "description": "RedirectURL is optional, defaulting to 'ACCESS_URL'. Only useful in niche\nsituations where the OAuth callback domain is different from the ACCESS_URL\ndomain. The path component is ignored.", + "type": "string" + }, "regex": { "description": "Regex allows API requesters to match an auth config by\na string (e.g. coder.com) instead of by it's type.\n\nGit clone makes use of this by parsing the URL from:\n'Username for \"https://github.com\":'\nAnd sending it to the Coder server to match against the Regex.", "type": "string" @@ -22301,7 +22305,7 @@ const docTemplate = `{ } }, "redirect_url": { - "description": "RedirectURL is optional, defaulting to 'ACCESS_URL'. Only useful in niche\nsituations where the OIDC callback domain is different from the ACCESS_URL\ndomain.", + "description": "RedirectURL is optional, defaulting to 'ACCESS_URL'. Only useful in niche\nsituations where the OIDC callback domain is different from the ACCESS_URL\ndomain. The path component is ignored.", "allOf": [ { "$ref": "#/definitions/serpent.URL" diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index e0aa90bda21..8d201ac70c2 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -18736,6 +18736,10 @@ "no_refresh": { "type": "boolean" }, + "redirect_url": { + "description": "RedirectURL is optional, defaulting to 'ACCESS_URL'. Only useful in niche\nsituations where the OAuth callback domain is different from the ACCESS_URL\ndomain. The path component is ignored.", + "type": "string" + }, "regex": { "description": "Regex allows API requesters to match an auth config by\na string (e.g. coder.com) instead of by it's type.\n\nGit clone makes use of this by parsing the URL from:\n'Username for \"https://github.com\":'\nAnd sending it to the Coder server to match against the Regex.", "type": "string" @@ -20363,7 +20367,7 @@ } }, "redirect_url": { - "description": "RedirectURL is optional, defaulting to 'ACCESS_URL'. Only useful in niche\nsituations where the OIDC callback domain is different from the ACCESS_URL\ndomain.", + "description": "RedirectURL is optional, defaulting to 'ACCESS_URL'. Only useful in niche\nsituations where the OIDC callback domain is different from the ACCESS_URL\ndomain. The path component is ignored.", "allOf": [ { "$ref": "#/definitions/serpent.URL" diff --git a/coderd/externalauth/externalauth.go b/coderd/externalauth/externalauth.go index ff275f3f753..98a84118589 100644 --- a/coderd/externalauth/externalauth.go +++ b/coderd/externalauth/externalauth.go @@ -912,10 +912,12 @@ func (c *DeviceAuth) formatDeviceCodeURL() (string, error) { // ConvertConfig converts the SDK configuration entry format // to the parsed and ready-to-consume in coderd provider type. -func ConvertConfig(logger slog.Logger, instrument *promoauth.Factory, entries []codersdk.ExternalAuthConfig, accessURL *url.URL) ([]*Config, error) { +func ConvertConfig(ctx context.Context, logger slog.Logger, instrument *promoauth.Factory, entries []codersdk.ExternalAuthConfig, accessURL *url.URL) ([]*Config, error) { ids := map[string]struct{}{} configs := []*Config{} for _, entry := range entries { + logger := logger.Named("externalauth").With(slog.F("provider_id", entry.ID), slog.F("provider_type", entry.Type)) + // Applies defaults to the config entry. // This allows users to very simply state that they type is "GitHub", // apply their client secret and ID, and have the UI appear nicely. @@ -938,9 +940,18 @@ func ConvertConfig(logger slog.Logger, instrument *promoauth.Factory, entries [] } ids[entry.ID] = struct{}{} - authRedirect, err := accessURL.Parse(fmt.Sprintf("/external-auth/%s/callback", entry.ID)) + baseRedirectURL := accessURL + if entry.RedirectURL != "" { + var err error + baseRedirectURL, err = url.Parse(entry.RedirectURL) + if err != nil { + return nil, xerrors.Errorf("parse redirect url override for external auth provider %q: %w", entry.ID, err) + } + logger.Warn(ctx, "custom redirect URL used instead of 'access_url', ensure this matches the value configured in your provider") + } + authRedirect, err := baseRedirectURL.Parse(fmt.Sprintf("/external-auth/%s/callback", entry.ID)) if err != nil { - return nil, xerrors.Errorf("parse external auth callback url: %w", err) + return nil, xerrors.Errorf("parse callback url for external auth provider %q: %w", entry.ID, err) } var regex *regexp.Regexp @@ -996,7 +1007,7 @@ func ConvertConfig(logger slog.Logger, instrument *promoauth.Factory, entries [] cfg := &Config{ InstrumentedOAuth2Config: instrumented, - Logger: logger.Named("externalauth").With(slog.F("provider_id", entry.ID), slog.F("provider_type", entry.Type)), + Logger: logger, ID: entry.ID, ClientID: entry.ClientID, ClientSecret: entry.ClientSecret, @@ -1092,6 +1103,9 @@ func copyDefaultSettings(config *codersdk.ExternalAuthConfig, defaults codersdk. if config.ValidateURL == "" { config.ValidateURL = defaults.ValidateURL } + if config.RedirectURL == "" { + config.RedirectURL = defaults.RedirectURL + } if config.RevokeURL == "" { config.RevokeURL = defaults.RevokeURL } diff --git a/coderd/externalauth/externalauth_test.go b/coderd/externalauth/externalauth_test.go index f29d1a3af61..75519614210 100644 --- a/coderd/externalauth/externalauth_test.go +++ b/coderd/externalauth/externalauth_test.go @@ -1076,7 +1076,7 @@ func TestRefreshTokenWithScopes(t *testing.T) { newConfig := func(t *testing.T, scopes []string) *externalauth.Config { t.Helper() instrument := promoauth.NewFactory(prometheus.NewRegistry()) - configs, err := externalauth.ConvertConfig(testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ + configs, err := externalauth.ConvertConfig(context.Background(), testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ ID: "test", Type: codersdk.EnhancedExternalAuthProviderAzureDevopsEntra.String(), ClientID: "id", @@ -1203,7 +1203,7 @@ func TestValidateToken(t *testing.T) { logs := &bytes.Buffer{} logger := slog.Make(slogjson.Sink(logs)).Leveled(slog.LevelDebug) // ConvertConfig wires the named logger as production does. - configs, err := externalauth.ConvertConfig(logger, f, []codersdk.ExternalAuthConfig{{ + configs, err := externalauth.ConvertConfig(context.Background(), logger, f, []codersdk.ExternalAuthConfig{{ ID: providerName, Type: codersdk.EnhancedExternalAuthProviderGitHub.String(), ClientID: "id", @@ -1608,7 +1608,7 @@ func TestExchangeWithClientSecret(t *testing.T) { instrument := promoauth.NewFactory(prometheus.NewRegistry()) // This ensures a provider that requires the custom // client secret exchange works. - configs, err := externalauth.ConvertConfig(testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ + configs, err := externalauth.ConvertConfig(context.Background(), testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ // JFrog just happens to require this custom type. Type: codersdk.EnhancedExternalAuthProviderJFrog.String(), @@ -1740,7 +1740,7 @@ func TestConvertYAML(t *testing.T) { }} { t.Run(tc.Name, func(t *testing.T) { t.Parallel() - output, err := externalauth.ConvertConfig(testutil.Logger(t), instrument, tc.Input, &url.URL{}) + output, err := externalauth.ConvertConfig(context.Background(), testutil.Logger(t), instrument, tc.Input, &url.URL{}) if tc.Error != "" { require.Error(t, err) require.Contains(t, err.Error(), tc.Error) @@ -1752,21 +1752,22 @@ func TestConvertYAML(t *testing.T) { t.Run("CustomScopesAndEndpoint", func(t *testing.T) { t.Parallel() - config, err := externalauth.ConvertConfig(testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ + config, err := externalauth.ConvertConfig(context.Background(), testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ Type: string(codersdk.EnhancedExternalAuthProviderGitLab), ClientID: "id", ClientSecret: "secret", AuthURL: "https://auth.com", TokenURL: "https://token.com", + RedirectURL: "https://redirect.com", Scopes: []string{"read"}, - }}, &url.URL{}) + }}, &url.URL{Scheme: "https", Host: "default.com"}) require.NoError(t, err) - require.Equal(t, "https://auth.com?client_id=id&redirect_uri=%2Fexternal-auth%2Fgitlab%2Fcallback&response_type=code&scope=read", config[0].AuthCodeURL("")) + require.Equal(t, "https://auth.com?client_id=id&redirect_uri=https%3A%2F%2Fredirect.com%2Fexternal-auth%2Fgitlab%2Fcallback&response_type=code&scope=read", config[0].AuthCodeURL("")) }) t.Run("RevokeTimeoutSet", func(t *testing.T) { t.Parallel() - configs, err := externalauth.ConvertConfig(testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ + configs, err := externalauth.ConvertConfig(context.Background(), testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ Type: string(codersdk.EnhancedExternalAuthProviderGitLab), ClientID: "id", ClientSecret: "secret", @@ -1777,7 +1778,7 @@ func TestConvertYAML(t *testing.T) { t.Run("SelfHostedGitLabAPIBaseURL", func(t *testing.T) { t.Parallel() - configs, err := externalauth.ConvertConfig(testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ + configs, err := externalauth.ConvertConfig(context.Background(), testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ Type: string(codersdk.EnhancedExternalAuthProviderGitLab), ClientID: "id", ClientSecret: "secret", @@ -1956,6 +1957,7 @@ func TestApplyDefaultsToConfig_CaseInsensitive(t *testing.T) { t.Run(tc.Name, func(t *testing.T) { t.Parallel() configs, err := externalauth.ConvertConfig( + context.Background(), testutil.Logger(t), instrument, []codersdk.ExternalAuthConfig{{ diff --git a/codersdk/deployment.go b/codersdk/deployment.go index 14eca1624ec..e8f127fb8d2 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -1016,7 +1016,7 @@ type OIDCConfig struct { // RedirectURL is optional, defaulting to 'ACCESS_URL'. Only useful in niche // situations where the OIDC callback domain is different from the ACCESS_URL - // domain. + // domain. The path component is ignored. RedirectURL serpent.URL `json:"redirect_url" typescript:",notnull"` AutoRepairLinks serpent.Bool `json:"auto_repair_links" typescript:",notnull"` @@ -1170,10 +1170,14 @@ type ExternalAuthConfig struct { ClientSecret string `json:"-" yaml:"client_secret"` // ID is a unique identifier for the auth config. // It defaults to `type` when not provided. - ID string `json:"id" yaml:"id"` - AuthURL string `json:"auth_url" yaml:"auth_url"` - TokenURL string `json:"token_url" yaml:"token_url"` - ValidateURL string `json:"validate_url" yaml:"validate_url"` + ID string `json:"id" yaml:"id"` + AuthURL string `json:"auth_url" yaml:"auth_url"` + TokenURL string `json:"token_url" yaml:"token_url"` + ValidateURL string `json:"validate_url" yaml:"validate_url"` + // RedirectURL is optional, defaulting to 'ACCESS_URL'. Only useful in niche + // situations where the OAuth callback domain is different from the ACCESS_URL + // domain. The path component is ignored. + RedirectURL string `json:"redirect_url" yaml:"redirect_url"` RevokeURL string `json:"revoke_url" yaml:"revoke_url"` AppInstallURL string `json:"app_install_url" yaml:"app_install_url"` AppInstallationsURL string `json:"app_installations_url" yaml:"app_installations_url"` diff --git a/codersdk/deployment_test.go b/codersdk/deployment_test.go index de3395aac84..5d366ee88e3 100644 --- a/codersdk/deployment_test.go +++ b/codersdk/deployment_test.go @@ -1006,6 +1006,7 @@ func TestExternalAuthYAMLConfig(t *testing.T) { ID: "id", AuthURL: "https://example.com/auth", TokenURL: "https://example.com/token", + RedirectURL: "https://example.com/redirect", ValidateURL: "https://example.com/validate", RevokeURL: "https://example.com/revoke", AppInstallURL: "https://example.com/install", diff --git a/codersdk/testdata/githubcfg.yaml b/codersdk/testdata/githubcfg.yaml index 86bfaf4eb1d..5cfe95ac50f 100644 --- a/codersdk/testdata/githubcfg.yaml +++ b/codersdk/testdata/githubcfg.yaml @@ -6,6 +6,7 @@ externalAuthProviders: auth_url: https://example.com/auth token_url: https://example.com/token validate_url: https://example.com/validate + redirect_url: https://example.com/redirect revoke_url: https://example.com/revoke app_install_url: https://example.com/install app_installations_url: https://example.com/installations diff --git a/docs/admin/external-auth/index.md b/docs/admin/external-auth/index.md index bb271a82f15..ffcec0cc3e2 100644 --- a/docs/admin/external-auth/index.md +++ b/docs/admin/external-auth/index.md @@ -43,6 +43,27 @@ Set it with a value that helps you identify the provider. For example, if you use `CODER_EXTERNAL_AUTH_0_ID="primary-github"` for your GitHub provider, configure your callback URL as `https://example.com/external-auth/primary-github/callback`. +By default, the redirect URL is built from the access URL Coder is configured +with. You can override the base URL with: + +```dotenv +CODER_EXTERNAL_AUTH_0_REDIRECT_URL=https://my.tld +``` + +This would change the callback in the above example to +`https://my.tld/external-auth/primary-github/callback` (any path component on +the redirect URL is ignored). + +Using this setting can break OAuth, so use with caution. The override is +intended to be used when the access URL is internal and either: + +- Users access Coder via some other URL that proxies to the internal one. +- The redirect URL redirects to the internal access URL (this can be used to + work around providers that require public domains for the callback). + +Ultimately, the user must end up on the same domain they were on when the +authentication flow was initiated. + ### Add an authentication button to the workspace template Add the following code to any template to add a button to the workspace setup page which will allow you to authenticate with your provider: diff --git a/docs/reference/api/general.md b/docs/reference/api/general.md index 6b708bca408..982b5064099 100644 --- a/docs/reference/api/general.md +++ b/docs/reference/api/general.md @@ -351,6 +351,7 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \ "mcp_tool_deny_regex": "string", "mcp_url": "string", "no_refresh": true, + "redirect_url": "string", "regex": "string", "revoke_url": "string", "scopes": [ diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index 1e6dbe6e0ef..26613097bc1 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -6044,6 +6044,7 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o "mcp_tool_deny_regex": "string", "mcp_url": "string", "no_refresh": true, + "redirect_url": "string", "regex": "string", "revoke_url": "string", "scopes": [ @@ -6671,6 +6672,7 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o "mcp_tool_deny_regex": "string", "mcp_url": "string", "no_refresh": true, + "redirect_url": "string", "regex": "string", "revoke_url": "string", "scopes": [ @@ -7672,6 +7674,7 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o "mcp_tool_deny_regex": "string", "mcp_url": "string", "no_refresh": true, + "redirect_url": "string", "regex": "string", "revoke_url": "string", "scopes": [ @@ -7685,23 +7688,24 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o ### Properties -| Name | Type | Required | Restrictions | Description | -|------------------------------------|-----------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `api_base_url` | string | false | | Api base URL is the base URL for provider REST API calls (e.g., "https://api.github.com" for GitHub). Derived from defaults when not explicitly configured. | -| `app_install_url` | string | false | | | -| `app_installations_url` | string | false | | | -| `auth_url` | string | false | | | -| `client_id` | string | false | | | -| `code_challenge_methods_supported` | array of string | false | | Code challenge methods supported lists the PKCE code challenge methods The only one supported by Coder is "S256". | -| `device_code_url` | string | false | | | -| `device_flow` | boolean | false | | | -| `display_icon` | string | false | | Display icon is a URL to an icon to display in the UI. | -| `display_name` | string | false | | Display name is shown in the UI to identify the auth config. | -| `id` | string | false | | ID is a unique identifier for the auth config. It defaults to `type` when not provided. | -| `mcp_tool_allow_regex` | string | false | | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release. | -| `mcp_tool_deny_regex` | string | false | | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release. | -| `mcp_url` | string | false | | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release. | -| `no_refresh` | boolean | false | | | +| Name | Type | Required | Restrictions | Description | +|------------------------------------|-----------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `api_base_url` | string | false | | Api base URL is the base URL for provider REST API calls (e.g., "https://api.github.com" for GitHub). Derived from defaults when not explicitly configured. | +| `app_install_url` | string | false | | | +| `app_installations_url` | string | false | | | +| `auth_url` | string | false | | | +| `client_id` | string | false | | | +| `code_challenge_methods_supported` | array of string | false | | Code challenge methods supported lists the PKCE code challenge methods The only one supported by Coder is "S256". | +| `device_code_url` | string | false | | | +| `device_flow` | boolean | false | | | +| `display_icon` | string | false | | Display icon is a URL to an icon to display in the UI. | +| `display_name` | string | false | | Display name is shown in the UI to identify the auth config. | +| `id` | string | false | | ID is a unique identifier for the auth config. It defaults to `type` when not provided. | +| `mcp_tool_allow_regex` | string | false | | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release. | +| `mcp_tool_deny_regex` | string | false | | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release. | +| `mcp_url` | string | false | | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release. | +| `no_refresh` | boolean | false | | | +| `redirect_url` | string | false | | Redirect URL is optional, defaulting to 'ACCESS_URL'. Only useful in niche situations where the OAuth callback domain is different from the ACCESS_URL domain. The path component is ignored. | |`regex`|string|false||Regex allows API requesters to match an auth config by a string (e.g. coder.com) instead of by it's type. Git clone makes use of this by parsing the URL from: 'Username for "https://github.com":' And sending it to the Coder server to match against the Regex.| |`revoke_url`|string|false||| @@ -9563,7 +9567,7 @@ Only certain features set these fields: - FeatureManagedAgentLimit - FeatureAgen | `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. | +| `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. The path component is ignored. | | `scopes` | array of string | false | | | | `sign_in_text` | string | false | | | | `signups_disabled_text` | string | false | | | @@ -19273,6 +19277,7 @@ None "mcp_tool_deny_regex": "string", "mcp_url": "string", "no_refresh": true, + "redirect_url": "string", "regex": "string", "revoke_url": "string", "scopes": [ diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 0222095336d..c5238d13e25 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -5034,6 +5034,12 @@ export interface ExternalAuthConfig { readonly auth_url: string; readonly token_url: string; readonly validate_url: string; + /** + * RedirectURL is optional, defaulting to 'ACCESS_URL'. Only useful in niche + * situations where the OAuth callback domain is different from the ACCESS_URL + * domain. The path component is ignored. + */ + readonly redirect_url: string; readonly revoke_url: string; readonly app_install_url: string; readonly app_installations_url: string; @@ -6758,7 +6764,7 @@ export interface OIDCConfig { /** * RedirectURL is optional, defaulting to 'ACCESS_URL'. Only useful in niche * situations where the OIDC callback domain is different from the ACCESS_URL - * domain. + * domain. The path component is ignored. */ readonly redirect_url: string; readonly auto_repair_links: boolean; diff --git a/site/src/pages/DeploymentSettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.stories.tsx b/site/src/pages/DeploymentSettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.stories.tsx index 94d0ecc0240..339a0a59974 100644 --- a/site/src/pages/DeploymentSettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.stories.tsx +++ b/site/src/pages/DeploymentSettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPageView.stories.tsx @@ -17,6 +17,7 @@ const meta: Meta = { auth_url: "", token_url: "", validate_url: "", + redirect_url: "", revoke_url: "", app_install_url: "https://github.com/apps/coder/installations/new", app_installations_url: "",