mirror of
https://github.com/coder/coder.git
synced 2026-10-16 06:37:58 +08:00
feat: add redirect URL override for external auth (#28082)
This commit is contained in:
@@ -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":
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
Generated
+5
-1
@@ -20739,6 +20739,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"
|
||||
@@ -22434,7 +22438,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"
|
||||
|
||||
Generated
+5
-1
@@ -18861,6 +18861,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"
|
||||
@@ -20488,7 +20492,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"
|
||||
|
||||
@@ -912,7 +912,7 @@ 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 {
|
||||
@@ -921,6 +921,8 @@ func ConvertConfig(logger slog.Logger, instrument *promoauth.Factory, entries []
|
||||
// apply their client secret and ID, and have the UI appear nicely.
|
||||
applyDefaultsToConfig(&entry)
|
||||
|
||||
logger := logger.Named("externalauth").With(slog.F("provider_id", entry.ID), slog.F("provider_type", entry.Type))
|
||||
|
||||
valid := codersdk.NameValid(entry.ID)
|
||||
if valid != nil {
|
||||
return nil, xerrors.Errorf("external auth provider %q doesn't have a valid id: %w", entry.ID, valid)
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{{
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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",
|
||||
|
||||
Vendored
+1
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Generated
+1
@@ -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": [
|
||||
|
||||
Generated
+23
-18
@@ -6096,6 +6096,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": [
|
||||
@@ -6723,6 +6724,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": [
|
||||
@@ -7724,6 +7726,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": [
|
||||
@@ -7737,23 +7740,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|||
|
||||
@@ -9615,7 +9619,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 | | |
|
||||
@@ -19348,6 +19352,7 @@ None
|
||||
"mcp_tool_deny_regex": "string",
|
||||
"mcp_url": "string",
|
||||
"no_refresh": true,
|
||||
"redirect_url": "string",
|
||||
"regex": "string",
|
||||
"revoke_url": "string",
|
||||
"scopes": [
|
||||
|
||||
Generated
+7
-1
@@ -5069,6 +5069,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;
|
||||
@@ -6799,7 +6805,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;
|
||||
|
||||
+1
@@ -17,6 +17,7 @@ const meta: Meta<typeof ExternalAuthSettingsPageView> = {
|
||||
auth_url: "",
|
||||
token_url: "",
|
||||
validate_url: "",
|
||||
redirect_url: "",
|
||||
revoke_url: "",
|
||||
app_install_url: "https://github.com/apps/coder/installations/new",
|
||||
app_installations_url: "",
|
||||
|
||||
Reference in New Issue
Block a user