mirror of
https://github.com/coder/coder.git
synced 2026-06-03 04:58:23 +00:00
8fefd91e4a
**Breaking Change:** Existing oauth apps might now use PKCE. If an unknown IdP type was being used, and it does not support PKCE, it will break. To fix, set the PKCE methods on the external auth to `none` ``` export CODER_EXTERNAL_AUTH_1_PKCE_METHODS=none ```
241 lines
8.6 KiB
Go
241 lines
8.6 KiB
Go
package externalauth
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/coder/coder/v2/coderd/promoauth"
|
|
"github.com/coder/coder/v2/codersdk"
|
|
)
|
|
|
|
func TestGitlabDefaults(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// The default cloud setup. Copying this here as hard coded
|
|
// values.
|
|
cloud := func() codersdk.ExternalAuthConfig {
|
|
return codersdk.ExternalAuthConfig{
|
|
Type: string(codersdk.EnhancedExternalAuthProviderGitLab),
|
|
ID: string(codersdk.EnhancedExternalAuthProviderGitLab),
|
|
AuthURL: "https://gitlab.com/oauth/authorize",
|
|
TokenURL: "https://gitlab.com/oauth/token",
|
|
ValidateURL: "https://gitlab.com/oauth/token/info",
|
|
RevokeURL: "https://gitlab.com/oauth/revoke",
|
|
DisplayName: "GitLab",
|
|
DisplayIcon: "/icon/gitlab.svg",
|
|
Regex: `^(https?://)?gitlab\.com(/.*)?$`,
|
|
Scopes: []string{"write_repository"},
|
|
CodeChallengeMethodsSupported: []string{string(promoauth.PKCEChallengeMethodSha256)},
|
|
}
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
input codersdk.ExternalAuthConfig
|
|
expected codersdk.ExternalAuthConfig
|
|
mutateExpected func(*codersdk.ExternalAuthConfig)
|
|
}{
|
|
// Cloud
|
|
{
|
|
name: "OnlyType",
|
|
input: codersdk.ExternalAuthConfig{
|
|
Type: string(codersdk.EnhancedExternalAuthProviderGitLab),
|
|
},
|
|
expected: cloud(),
|
|
},
|
|
{
|
|
// If someone was to manually configure the gitlab cli.
|
|
name: "CloudByConfig",
|
|
input: codersdk.ExternalAuthConfig{
|
|
Type: string(codersdk.EnhancedExternalAuthProviderGitLab),
|
|
AuthURL: "https://gitlab.com/oauth/authorize",
|
|
},
|
|
expected: cloud(),
|
|
},
|
|
{
|
|
// Changing some of the defaults of the cloud option
|
|
name: "CloudWithChanges",
|
|
input: codersdk.ExternalAuthConfig{
|
|
Type: string(codersdk.EnhancedExternalAuthProviderGitLab),
|
|
// Adding an extra query param intentionally to break simple
|
|
// string comparisons.
|
|
AuthURL: "https://gitlab.com/oauth/authorize?foo=bar",
|
|
DisplayName: "custom",
|
|
Regex: ".*",
|
|
},
|
|
expected: cloud(),
|
|
mutateExpected: func(config *codersdk.ExternalAuthConfig) {
|
|
config.AuthURL = "https://gitlab.com/oauth/authorize?foo=bar"
|
|
config.DisplayName = "custom"
|
|
config.Regex = ".*"
|
|
},
|
|
},
|
|
// Self-hosted
|
|
{
|
|
// Dynamically figures out the Validate, Token, and Regex fields.
|
|
name: "SelfHostedOnlyAuthURL",
|
|
input: codersdk.ExternalAuthConfig{
|
|
Type: string(codersdk.EnhancedExternalAuthProviderGitLab),
|
|
AuthURL: "https://gitlab.company.org/oauth/authorize?foo=bar",
|
|
},
|
|
expected: cloud(),
|
|
mutateExpected: func(config *codersdk.ExternalAuthConfig) {
|
|
config.AuthURL = "https://gitlab.company.org/oauth/authorize?foo=bar"
|
|
config.ValidateURL = "https://gitlab.company.org/oauth/token/info"
|
|
config.TokenURL = "https://gitlab.company.org/oauth/token"
|
|
config.RevokeURL = "https://gitlab.company.org/oauth/revoke"
|
|
config.Regex = `^(https?://)?gitlab\.company\.org(/.*)?$`
|
|
},
|
|
},
|
|
{
|
|
// Strange values
|
|
name: "RandomValues",
|
|
input: codersdk.ExternalAuthConfig{
|
|
Type: string(codersdk.EnhancedExternalAuthProviderGitLab),
|
|
AuthURL: "https://auth.com/auth",
|
|
ValidateURL: "https://validate.com/validate",
|
|
TokenURL: "https://token.com/token",
|
|
RevokeURL: "https://token.com/revoke",
|
|
Regex: "random",
|
|
CodeChallengeMethodsSupported: []string{"random"},
|
|
},
|
|
expected: cloud(),
|
|
mutateExpected: func(config *codersdk.ExternalAuthConfig) {
|
|
config.AuthURL = "https://auth.com/auth"
|
|
config.ValidateURL = "https://validate.com/validate"
|
|
config.TokenURL = "https://token.com/token"
|
|
config.RevokeURL = "https://token.com/revoke"
|
|
config.Regex = `random`
|
|
config.CodeChallengeMethodsSupported = []string{"random"}
|
|
},
|
|
},
|
|
}
|
|
for _, c := range tests {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
applyDefaultsToConfig(&c.input)
|
|
if c.mutateExpected != nil {
|
|
c.mutateExpected(&c.expected)
|
|
}
|
|
require.Equal(t, c.input, c.expected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_bitbucketServerConfigDefaults(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
bbType := string(codersdk.EnhancedExternalAuthProviderBitBucketServer)
|
|
tests := []struct {
|
|
name string
|
|
config *codersdk.ExternalAuthConfig
|
|
expected codersdk.ExternalAuthConfig
|
|
}{
|
|
{
|
|
// Very few fields are statically defined for Bitbucket Server.
|
|
name: "EmptyBitbucketServer",
|
|
config: &codersdk.ExternalAuthConfig{
|
|
Type: bbType,
|
|
},
|
|
expected: codersdk.ExternalAuthConfig{
|
|
Type: bbType,
|
|
ID: bbType,
|
|
DisplayName: "Bitbucket Server",
|
|
Scopes: []string{"PUBLIC_REPOS", "REPO_READ", "REPO_WRITE"},
|
|
DisplayIcon: "/icon/bitbucket.svg",
|
|
CodeChallengeMethodsSupported: []string{string(promoauth.PKCEChallengeMethodNone)},
|
|
},
|
|
},
|
|
{
|
|
// Only the AuthURL is required for defaults to work.
|
|
name: "AuthURL",
|
|
config: &codersdk.ExternalAuthConfig{
|
|
Type: bbType,
|
|
AuthURL: "https://bitbucket.example.com/login/oauth/authorize",
|
|
},
|
|
expected: codersdk.ExternalAuthConfig{
|
|
Type: bbType,
|
|
ID: bbType,
|
|
AuthURL: "https://bitbucket.example.com/login/oauth/authorize",
|
|
TokenURL: "https://bitbucket.example.com/rest/oauth2/latest/token",
|
|
ValidateURL: "https://bitbucket.example.com/rest/api/latest/inbox/pull-requests/count",
|
|
Scopes: []string{"PUBLIC_REPOS", "REPO_READ", "REPO_WRITE"},
|
|
Regex: `^(https?://)?bitbucket\.example\.com(/.*)?$`,
|
|
DisplayName: "Bitbucket Server",
|
|
DisplayIcon: "/icon/bitbucket.svg",
|
|
CodeChallengeMethodsSupported: []string{string(promoauth.PKCEChallengeMethodNone)},
|
|
},
|
|
},
|
|
{
|
|
// Ensure backwards compatibility. The type should update to "bitbucket-cloud",
|
|
// but the ID and other fields should remain the same.
|
|
name: "BitbucketLegacy",
|
|
config: &codersdk.ExternalAuthConfig{
|
|
Type: "bitbucket",
|
|
},
|
|
expected: codersdk.ExternalAuthConfig{
|
|
Type: string(codersdk.EnhancedExternalAuthProviderBitBucketCloud),
|
|
ID: "bitbucket", // Legacy ID remains unchanged
|
|
AuthURL: "https://bitbucket.org/site/oauth2/authorize",
|
|
TokenURL: "https://bitbucket.org/site/oauth2/access_token",
|
|
ValidateURL: "https://api.bitbucket.org/2.0/user",
|
|
DisplayName: "BitBucket",
|
|
DisplayIcon: "/icon/bitbucket.svg",
|
|
Regex: `^(https?://)?bitbucket\.org(/.*)?$`,
|
|
Scopes: []string{"account", "repository:write"},
|
|
CodeChallengeMethodsSupported: []string{string(promoauth.PKCEChallengeMethodNone)},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
applyDefaultsToConfig(tt.config)
|
|
require.Equal(t, tt.expected, *tt.config)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUntyped(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
input codersdk.ExternalAuthConfig
|
|
expected codersdk.ExternalAuthConfig
|
|
}{
|
|
{
|
|
// Unknown Type uses S256 by default.
|
|
name: "RandomValues",
|
|
input: codersdk.ExternalAuthConfig{
|
|
Type: "unknown",
|
|
AuthURL: "https://auth.com/auth",
|
|
ValidateURL: "https://validate.com/validate",
|
|
TokenURL: "https://token.com/token",
|
|
RevokeURL: "https://token.com/revoke",
|
|
Regex: "random",
|
|
},
|
|
expected: codersdk.ExternalAuthConfig{
|
|
ID: "unknown",
|
|
Type: "unknown",
|
|
DisplayName: "unknown",
|
|
DisplayIcon: "/emojis/1f511.png",
|
|
AuthURL: "https://auth.com/auth",
|
|
ValidateURL: "https://validate.com/validate",
|
|
TokenURL: "https://token.com/token",
|
|
RevokeURL: "https://token.com/revoke",
|
|
Regex: `random`,
|
|
CodeChallengeMethodsSupported: []string{string(promoauth.PKCEChallengeMethodSha256)},
|
|
},
|
|
},
|
|
}
|
|
for _, c := range tests {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
applyDefaultsToConfig(&c.input)
|
|
require.Equal(t, c.input, c.expected)
|
|
})
|
|
}
|
|
}
|