Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
af12479
refactor: encode auth external url explicitly
jgoux Apr 16, 2026
ad91e03
Merge branch 'develop' into refactor--encode-auth-external-url-explic…
jgoux Apr 21, 2026
3c14581
chore(deps): upgrade pg-delta to alpha.17 (#5110)
avallete Apr 22, 2026
0b0bbea
chore(deps): bump the actions-major group across 1 directory with 4 u…
dependabot[bot] Apr 22, 2026
baa87c5
fix(docker): bump the docker-minor group across 1 directory with 6 up…
dependabot[bot] Apr 22, 2026
aaa105d
chore(workflows): enable install scripts for supabase package in Yarn…
avallete Apr 22, 2026
6912c74
feat: --diff-engine flag on db pull
jgoux Apr 22, 2026
dc2496b
fix(docker): bump the docker-minor group in /pkg/config/templates wit…
dependabot[bot] Apr 23, 2026
dafd114
feat: exposing new api keys to functions (#4946)
kallebysantos Apr 23, 2026
faa0d0e
chore: upgrade pg-delta to alpha.20 in multiple templates
avallete Apr 24, 2026
445223e
fix: remove version comparison check for storage image updates (#5118)
avallete Apr 24, 2026
a36f733
fix: improve error handling and output formatting in pg-delta apply p…
avallete Apr 24, 2026
de1c5ef
fix(start): guard db_logs vector transform against null regex capture…
rebasecase Apr 25, 2026
703fcc6
Update Dockerfile for Studio image 2026-04-27
joshenlim Apr 27, 2026
85a93a6
chore: resync develop with main (#5123)
avallete Apr 27, 2026
e31315d
Revert "Update Dockerfile for Studio image 2026-04-27" (#5132)
avallete Apr 27, 2026
51d559f
Revert "Revert "Update Dockerfile for Studio image 2026-04-27"" (#5134)
avallete Apr 27, 2026
03d3544
fix(windows): json unmarshal errors in telemetry and pg-delta declara…
avallete Apr 27, 2026
47586ce
Merge branch 'develop' into refactor--encode-auth-external-url-explic…
avallete Apr 28, 2026
2b6b5e1
Merge branch 'develop' into refactor--encode-auth-external-url-explic…
avallete Apr 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/db/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ func initAuthJob(host string) utils.DockerJob {
return utils.DockerJob{
Image: utils.Config.Auth.Image,
Env: []string{
"API_EXTERNAL_URL=" + utils.Config.Api.ExternalUrl,
"API_EXTERNAL_URL=" + utils.Config.AuthExternalURL(),
"GOTRUE_LOG_LEVEL=error",
"GOTRUE_DB_DRIVER=postgres",
fmt.Sprintf("GOTRUE_DB_DATABASE_URL=postgresql://supabase_auth_admin:%s@%s:5432/postgres", utils.Config.Db.Password, host),
Expand Down
188 changes: 96 additions & 92 deletions internal/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,78 +573,7 @@ EOF

// Start GoTrue.
if utils.Config.Auth.Enabled && !isContainerExcluded(utils.Config.Auth.Image, excluded) {
var testOTP bytes.Buffer
if len(utils.Config.Auth.Sms.TestOTP) > 0 {
formatMapForEnvConfig(utils.Config.Auth.Sms.TestOTP, &testOTP)
}

env := []string{
"API_EXTERNAL_URL=" + utils.Config.Api.ExternalUrl,

"GOTRUE_API_HOST=0.0.0.0",
"GOTRUE_API_PORT=9999",

"GOTRUE_DB_DRIVER=postgres",
fmt.Sprintf("GOTRUE_DB_DATABASE_URL=postgresql://supabase_auth_admin:%s@%s:%d/%s", dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database),

"GOTRUE_SITE_URL=" + utils.Config.Auth.SiteUrl,
"GOTRUE_URI_ALLOW_LIST=" + strings.Join(utils.Config.Auth.AdditionalRedirectUrls, ","),
fmt.Sprintf("GOTRUE_DISABLE_SIGNUP=%v", !utils.Config.Auth.EnableSignup),

"GOTRUE_JWT_ADMIN_ROLES=service_role",
"GOTRUE_JWT_AUD=authenticated",
"GOTRUE_JWT_DEFAULT_GROUP_NAME=authenticated",
fmt.Sprintf("GOTRUE_JWT_EXP=%v", utils.Config.Auth.JwtExpiry),
"GOTRUE_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value,
"GOTRUE_JWT_ISSUER=" + utils.Config.Auth.JwtIssuer,

fmt.Sprintf("GOTRUE_EXTERNAL_EMAIL_ENABLED=%v", utils.Config.Auth.Email.EnableSignup),
fmt.Sprintf("GOTRUE_MAILER_SECURE_EMAIL_CHANGE_ENABLED=%v", utils.Config.Auth.Email.DoubleConfirmChanges),
fmt.Sprintf("GOTRUE_MAILER_AUTOCONFIRM=%v", !utils.Config.Auth.Email.EnableConfirmations),
fmt.Sprintf("GOTRUE_MAILER_OTP_LENGTH=%v", utils.Config.Auth.Email.OtpLength),
fmt.Sprintf("GOTRUE_MAILER_OTP_EXP=%v", utils.Config.Auth.Email.OtpExpiry),
"GOTRUE_MAILER_TEMPLATE_RELOADING_ENABLED=true",

fmt.Sprintf("GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED=%v", utils.Config.Auth.EnableAnonymousSignIns),

fmt.Sprintf("GOTRUE_SMTP_MAX_FREQUENCY=%v", utils.Config.Auth.Email.MaxFrequency),

fmt.Sprintf("GOTRUE_MAILER_URLPATHS_INVITE=%s/verify", utils.Config.Auth.JwtIssuer),
fmt.Sprintf("GOTRUE_MAILER_URLPATHS_CONFIRMATION=%s/verify", utils.Config.Auth.JwtIssuer),
fmt.Sprintf("GOTRUE_MAILER_URLPATHS_RECOVERY=%s/verify", utils.Config.Auth.JwtIssuer),
fmt.Sprintf("GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE=%s/verify", utils.Config.Auth.JwtIssuer),
"GOTRUE_RATE_LIMIT_EMAIL_SENT=360000",

fmt.Sprintf("GOTRUE_EXTERNAL_PHONE_ENABLED=%v", utils.Config.Auth.Sms.EnableSignup),
fmt.Sprintf("GOTRUE_SMS_AUTOCONFIRM=%v", !utils.Config.Auth.Sms.EnableConfirmations),
fmt.Sprintf("GOTRUE_SMS_MAX_FREQUENCY=%v", utils.Config.Auth.Sms.MaxFrequency),
"GOTRUE_SMS_OTP_EXP=6000",
"GOTRUE_SMS_OTP_LENGTH=6",
fmt.Sprintf("GOTRUE_SMS_TEMPLATE=%v", utils.Config.Auth.Sms.Template),
"GOTRUE_SMS_TEST_OTP=" + testOTP.String(),

fmt.Sprintf("GOTRUE_PASSWORD_MIN_LENGTH=%v", utils.Config.Auth.MinimumPasswordLength),
fmt.Sprintf("GOTRUE_PASSWORD_REQUIRED_CHARACTERS=%v", utils.Config.Auth.PasswordRequirements.ToChar()),
fmt.Sprintf("GOTRUE_SECURITY_REFRESH_TOKEN_ROTATION_ENABLED=%v", utils.Config.Auth.EnableRefreshTokenRotation),
fmt.Sprintf("GOTRUE_SECURITY_REFRESH_TOKEN_REUSE_INTERVAL=%v", utils.Config.Auth.RefreshTokenReuseInterval),
fmt.Sprintf("GOTRUE_SECURITY_MANUAL_LINKING_ENABLED=%v", utils.Config.Auth.EnableManualLinking),
fmt.Sprintf("GOTRUE_SECURITY_UPDATE_PASSWORD_REQUIRE_REAUTHENTICATION=%v", utils.Config.Auth.Email.SecurePasswordChange),
fmt.Sprintf("GOTRUE_MFA_PHONE_ENROLL_ENABLED=%v", utils.Config.Auth.MFA.Phone.EnrollEnabled),
fmt.Sprintf("GOTRUE_MFA_PHONE_VERIFY_ENABLED=%v", utils.Config.Auth.MFA.Phone.VerifyEnabled),
fmt.Sprintf("GOTRUE_MFA_TOTP_ENROLL_ENABLED=%v", utils.Config.Auth.MFA.TOTP.EnrollEnabled),
fmt.Sprintf("GOTRUE_MFA_TOTP_VERIFY_ENABLED=%v", utils.Config.Auth.MFA.TOTP.VerifyEnabled),
fmt.Sprintf("GOTRUE_MFA_WEB_AUTHN_ENROLL_ENABLED=%v", utils.Config.Auth.MFA.WebAuthn.EnrollEnabled),
fmt.Sprintf("GOTRUE_MFA_WEB_AUTHN_VERIFY_ENABLED=%v", utils.Config.Auth.MFA.WebAuthn.VerifyEnabled),
fmt.Sprintf("GOTRUE_MFA_MAX_ENROLLED_FACTORS=%v", utils.Config.Auth.MFA.MaxEnrolledFactors),

// Add rate limit configurations
fmt.Sprintf("GOTRUE_RATE_LIMIT_ANONYMOUS_USERS=%v", utils.Config.Auth.RateLimit.AnonymousUsers),
fmt.Sprintf("GOTRUE_RATE_LIMIT_TOKEN_REFRESH=%v", utils.Config.Auth.RateLimit.TokenRefresh),
fmt.Sprintf("GOTRUE_RATE_LIMIT_OTP=%v", utils.Config.Auth.RateLimit.SignInSignUps),
fmt.Sprintf("GOTRUE_RATE_LIMIT_VERIFY=%v", utils.Config.Auth.RateLimit.TokenVerifications),
fmt.Sprintf("GOTRUE_RATE_LIMIT_SMS_SENT=%v", utils.Config.Auth.RateLimit.SmsSent),
fmt.Sprintf("GOTRUE_RATE_LIMIT_WEB3=%v", utils.Config.Auth.RateLimit.Web3),
}
env := buildGotrueEnv(dbConfig)

// Serialise default or custom signing keys
if keys, err := json.Marshal(utils.Config.Auth.SigningKeys); err == nil {
Expand Down Expand Up @@ -817,26 +746,7 @@ EOF
)
}

for name, config := range utils.Config.Auth.External {
env = append(
env,
fmt.Sprintf("GOTRUE_EXTERNAL_%s_ENABLED=%v", strings.ToUpper(name), config.Enabled),
fmt.Sprintf("GOTRUE_EXTERNAL_%s_CLIENT_ID=%s", strings.ToUpper(name), config.ClientId),
fmt.Sprintf("GOTRUE_EXTERNAL_%s_SECRET=%s", strings.ToUpper(name), config.Secret.Value),
fmt.Sprintf("GOTRUE_EXTERNAL_%s_SKIP_NONCE_CHECK=%t", strings.ToUpper(name), config.SkipNonceCheck),
fmt.Sprintf("GOTRUE_EXTERNAL_%s_EMAIL_OPTIONAL=%t", strings.ToUpper(name), config.EmailOptional),
)

redirectUri := config.RedirectUri
if redirectUri == "" {
redirectUri = utils.Config.Auth.JwtIssuer + "/callback"
}
env = append(env, fmt.Sprintf("GOTRUE_EXTERNAL_%s_REDIRECT_URI=%s", strings.ToUpper(name), redirectUri))

if config.Url != "" {
env = append(env, fmt.Sprintf("GOTRUE_EXTERNAL_%s_URL=%s", strings.ToUpper(name), config.Url))
}
}
env = appendGotrueExternalProviderEnv(env)
env = append(env,
fmt.Sprintf("GOTRUE_EXTERNAL_WEB3_SOLANA_ENABLED=%v", utils.Config.Auth.Web3.Solana.Enabled),
fmt.Sprintf("GOTRUE_EXTERNAL_WEB3_ETHEREUM_ENABLED=%v", utils.Config.Auth.Web3.Ethereum.Enabled),
Expand Down Expand Up @@ -1368,6 +1278,100 @@ func formatMapForEnvConfig(input map[string]string, output *bytes.Buffer) {
}
}

func buildGotrueEnv(dbConfig pgconn.Config) []string {
var testOTP bytes.Buffer
if len(utils.Config.Auth.Sms.TestOTP) > 0 {
formatMapForEnvConfig(utils.Config.Auth.Sms.TestOTP, &testOTP)
}

return []string{
"API_EXTERNAL_URL=" + utils.Config.AuthExternalURL(),

"GOTRUE_API_HOST=0.0.0.0",
"GOTRUE_API_PORT=9999",

"GOTRUE_DB_DRIVER=postgres",
fmt.Sprintf("GOTRUE_DB_DATABASE_URL=postgresql://supabase_auth_admin:%s@%s:%d/%s", dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database),

"GOTRUE_SITE_URL=" + utils.Config.Auth.SiteUrl,
"GOTRUE_URI_ALLOW_LIST=" + strings.Join(utils.Config.Auth.AdditionalRedirectUrls, ","),
fmt.Sprintf("GOTRUE_DISABLE_SIGNUP=%v", !utils.Config.Auth.EnableSignup),

"GOTRUE_JWT_ADMIN_ROLES=service_role",
"GOTRUE_JWT_AUD=authenticated",
"GOTRUE_JWT_DEFAULT_GROUP_NAME=authenticated",
fmt.Sprintf("GOTRUE_JWT_EXP=%v", utils.Config.Auth.JwtExpiry),
"GOTRUE_JWT_SECRET=" + utils.Config.Auth.JwtSecret.Value,
"GOTRUE_JWT_ISSUER=" + utils.Config.Auth.JwtIssuer,

fmt.Sprintf("GOTRUE_EXTERNAL_EMAIL_ENABLED=%v", utils.Config.Auth.Email.EnableSignup),
fmt.Sprintf("GOTRUE_MAILER_SECURE_EMAIL_CHANGE_ENABLED=%v", utils.Config.Auth.Email.DoubleConfirmChanges),
fmt.Sprintf("GOTRUE_MAILER_AUTOCONFIRM=%v", !utils.Config.Auth.Email.EnableConfirmations),
fmt.Sprintf("GOTRUE_MAILER_OTP_LENGTH=%v", utils.Config.Auth.Email.OtpLength),
fmt.Sprintf("GOTRUE_MAILER_OTP_EXP=%v", utils.Config.Auth.Email.OtpExpiry),
"GOTRUE_MAILER_TEMPLATE_RELOADING_ENABLED=true",

fmt.Sprintf("GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED=%v", utils.Config.Auth.EnableAnonymousSignIns),

fmt.Sprintf("GOTRUE_SMTP_MAX_FREQUENCY=%v", utils.Config.Auth.Email.MaxFrequency),

"GOTRUE_MAILER_URLPATHS_INVITE=/verify",
"GOTRUE_MAILER_URLPATHS_CONFIRMATION=/verify",
"GOTRUE_MAILER_URLPATHS_RECOVERY=/verify",
"GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE=/verify",
"GOTRUE_RATE_LIMIT_EMAIL_SENT=360000",

fmt.Sprintf("GOTRUE_EXTERNAL_PHONE_ENABLED=%v", utils.Config.Auth.Sms.EnableSignup),
fmt.Sprintf("GOTRUE_SMS_AUTOCONFIRM=%v", !utils.Config.Auth.Sms.EnableConfirmations),
fmt.Sprintf("GOTRUE_SMS_MAX_FREQUENCY=%v", utils.Config.Auth.Sms.MaxFrequency),
"GOTRUE_SMS_OTP_EXP=6000",
"GOTRUE_SMS_OTP_LENGTH=6",
fmt.Sprintf("GOTRUE_SMS_TEMPLATE=%v", utils.Config.Auth.Sms.Template),
"GOTRUE_SMS_TEST_OTP=" + testOTP.String(),

fmt.Sprintf("GOTRUE_PASSWORD_MIN_LENGTH=%v", utils.Config.Auth.MinimumPasswordLength),
fmt.Sprintf("GOTRUE_PASSWORD_REQUIRED_CHARACTERS=%v", utils.Config.Auth.PasswordRequirements.ToChar()),
fmt.Sprintf("GOTRUE_SECURITY_REFRESH_TOKEN_ROTATION_ENABLED=%v", utils.Config.Auth.EnableRefreshTokenRotation),
fmt.Sprintf("GOTRUE_SECURITY_REFRESH_TOKEN_REUSE_INTERVAL=%v", utils.Config.Auth.RefreshTokenReuseInterval),
fmt.Sprintf("GOTRUE_SECURITY_MANUAL_LINKING_ENABLED=%v", utils.Config.Auth.EnableManualLinking),
fmt.Sprintf("GOTRUE_SECURITY_UPDATE_PASSWORD_REQUIRE_REAUTHENTICATION=%v", utils.Config.Auth.Email.SecurePasswordChange),
fmt.Sprintf("GOTRUE_MFA_PHONE_ENROLL_ENABLED=%v", utils.Config.Auth.MFA.Phone.EnrollEnabled),
fmt.Sprintf("GOTRUE_MFA_PHONE_VERIFY_ENABLED=%v", utils.Config.Auth.MFA.Phone.VerifyEnabled),
fmt.Sprintf("GOTRUE_MFA_TOTP_ENROLL_ENABLED=%v", utils.Config.Auth.MFA.TOTP.EnrollEnabled),
fmt.Sprintf("GOTRUE_MFA_TOTP_VERIFY_ENABLED=%v", utils.Config.Auth.MFA.TOTP.VerifyEnabled),
fmt.Sprintf("GOTRUE_MFA_WEB_AUTHN_ENROLL_ENABLED=%v", utils.Config.Auth.MFA.WebAuthn.EnrollEnabled),
fmt.Sprintf("GOTRUE_MFA_WEB_AUTHN_VERIFY_ENABLED=%v", utils.Config.Auth.MFA.WebAuthn.VerifyEnabled),
fmt.Sprintf("GOTRUE_MFA_MAX_ENROLLED_FACTORS=%v", utils.Config.Auth.MFA.MaxEnrolledFactors),

fmt.Sprintf("GOTRUE_RATE_LIMIT_ANONYMOUS_USERS=%v", utils.Config.Auth.RateLimit.AnonymousUsers),
fmt.Sprintf("GOTRUE_RATE_LIMIT_TOKEN_REFRESH=%v", utils.Config.Auth.RateLimit.TokenRefresh),
fmt.Sprintf("GOTRUE_RATE_LIMIT_OTP=%v", utils.Config.Auth.RateLimit.SignInSignUps),
fmt.Sprintf("GOTRUE_RATE_LIMIT_VERIFY=%v", utils.Config.Auth.RateLimit.TokenVerifications),
fmt.Sprintf("GOTRUE_RATE_LIMIT_SMS_SENT=%v", utils.Config.Auth.RateLimit.SmsSent),
fmt.Sprintf("GOTRUE_RATE_LIMIT_WEB3=%v", utils.Config.Auth.RateLimit.Web3),
}
}

func appendGotrueExternalProviderEnv(env []string) []string {
for name, config := range utils.Config.Auth.External {
env = append(
env,
fmt.Sprintf("GOTRUE_EXTERNAL_%s_ENABLED=%v", strings.ToUpper(name), config.Enabled),
fmt.Sprintf("GOTRUE_EXTERNAL_%s_CLIENT_ID=%s", strings.ToUpper(name), config.ClientId),
fmt.Sprintf("GOTRUE_EXTERNAL_%s_SECRET=%s", strings.ToUpper(name), config.Secret.Value),
fmt.Sprintf("GOTRUE_EXTERNAL_%s_SKIP_NONCE_CHECK=%t", strings.ToUpper(name), config.SkipNonceCheck),
fmt.Sprintf("GOTRUE_EXTERNAL_%s_EMAIL_OPTIONAL=%t", strings.ToUpper(name), config.EmailOptional),
)
if config.RedirectUri != "" {
env = append(env, fmt.Sprintf("GOTRUE_EXTERNAL_%s_REDIRECT_URI=%s", strings.ToUpper(name), config.RedirectUri))
}
if config.Url != "" {
env = append(env, fmt.Sprintf("GOTRUE_EXTERNAL_%s_URL=%s", strings.ToUpper(name), config.Url))
}
}
return env
}

func printSecurityNotice() {
fmt.Fprintln(os.Stderr, utils.Yellow("Local dev security notice"))
fmt.Fprintln(os.Stderr, "All services bind to 0.0.0.0 (network-accessible, not just localhost)")
Expand Down
65 changes: 65 additions & 0 deletions internal/start/start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"net/http"
"regexp"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -300,6 +301,59 @@ func TestDatabaseStart(t *testing.T) {
})
}

func TestBuildGotrueEnv(t *testing.T) {
original := utils.Config
t.Cleanup(func() {
utils.Config = original
})

t.Run("uses auth scoped external url and relative mailer paths", func(t *testing.T) {
utils.Config = config.NewConfig()
utils.Config.Api.ExternalUrl = "http://127.0.0.1:54321"
utils.Config.Auth.ExternalUrl = "http://127.0.0.1:54321/auth/v1"
utils.Config.Auth.JwtIssuer = utils.Config.Auth.ExternalUrl
utils.Config.Auth.SiteUrl = "http://127.0.0.1:3000"
provider := utils.Config.Auth.External["github"]
provider.Enabled = true
provider.ClientId = "client-id"
provider.Secret.Value = "secret"
utils.Config.Auth.External["github"] = provider

env := envToMap(appendGotrueExternalProviderEnv(buildGotrueEnv(pgconn.Config{
Host: "db",
Port: 5432,
Database: "postgres",
Password: "postgres",
})))

assert.Equal(t, "http://127.0.0.1:54321/auth/v1", env["API_EXTERNAL_URL"])
assert.Equal(t, "http://127.0.0.1:54321/auth/v1", env["GOTRUE_JWT_ISSUER"])
assert.Equal(t, "/verify", env["GOTRUE_MAILER_URLPATHS_INVITE"])
assert.Equal(t, "/verify", env["GOTRUE_MAILER_URLPATHS_CONFIRMATION"])
assert.Equal(t, "/verify", env["GOTRUE_MAILER_URLPATHS_RECOVERY"])
assert.Equal(t, "/verify", env["GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE"])
assert.NotContains(t, env, "GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI")
})

t.Run("preserves explicit provider redirect override", func(t *testing.T) {
utils.Config = config.NewConfig()
utils.Config.Api.ExternalUrl = "http://127.0.0.1:54321"
utils.Config.Auth.ExternalUrl = "http://127.0.0.1:54321/auth/v1"
utils.Config.Auth.JwtIssuer = "https://issuer.example.com/auth/v1"
utils.Config.Auth.SiteUrl = "http://127.0.0.1:3000"
provider := utils.Config.Auth.External["azure"]
provider.Enabled = true
provider.RedirectUri = "https://example.com/custom/callback"
utils.Config.Auth.External["azure"] = provider

env := envToMap(appendGotrueExternalProviderEnv(buildGotrueEnv(pgconn.Config{})))

assert.Equal(t, "http://127.0.0.1:54321/auth/v1", env["API_EXTERNAL_URL"])
assert.Equal(t, "https://issuer.example.com/auth/v1", env["GOTRUE_JWT_ISSUER"])
assert.Equal(t, "https://example.com/custom/callback", env["GOTRUE_EXTERNAL_AZURE_REDIRECT_URI"])
})
}

func TestFormatMapForEnvConfig(t *testing.T) {
t.Run("It produces the correct format and removes the trailing comma", func(t *testing.T) {
testcases := []struct {
Expand Down Expand Up @@ -347,3 +401,14 @@ func TestFormatMapForEnvConfig(t *testing.T) {
}
})
}

func envToMap(env []string) map[string]string {
result := make(map[string]string, len(env))
for _, item := range env {
key, value, ok := strings.Cut(item, "=")
if ok {
result[key] = value
}
}
return result
}
8 changes: 4 additions & 4 deletions internal/start/templates/kong.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ _format_version: "1.1"
services:
# Tenant project endpoints
- name: auth-v1-open
_comment: "GoTrue: /auth/v1/verify* -> http://auth:9999/verify*"
_comment: "GoTrue external /auth/v1/verify* -> internal root /verify*"
url: http://{{ .GotrueId }}:9999/verify
routes:
- name: auth-v1-open
Expand All @@ -12,7 +12,7 @@ services:
plugins:
- name: cors
- name: auth-v1-open-callback
_comment: "GoTrue: /auth/v1/callback* -> http://auth:9999/callback*"
_comment: "GoTrue external /auth/v1/callback* -> internal root /callback*"
url: http://{{ .GotrueId }}:9999/callback
routes:
- name: auth-v1-open-callback
Expand All @@ -22,7 +22,7 @@ services:
plugins:
- name: cors
- name: auth-v1-open-authorize
_comment: "GoTrue: /auth/v1/authorize* -> http://auth:9999/authorize*"
_comment: "GoTrue external /auth/v1/authorize* -> internal root /authorize*"
url: http://{{ .GotrueId }}:9999/authorize
routes:
- name: auth-v1-open-authorize
Expand All @@ -32,7 +32,7 @@ services:
plugins:
- name: cors
- name: auth-v1
_comment: "GoTrue: /auth/v1/* -> http://auth:9999/*"
_comment: "GoTrue external /auth/v1/* -> internal root /*"
url: http://{{ .GotrueId }}:9999/
routes:
- name: auth-v1-all
Expand Down
8 changes: 8 additions & 0 deletions pkg/config/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ type (
Image string `toml:"-" json:"-"`

SiteUrl string `toml:"site_url" json:"site_url"`
ExternalUrl string `toml:"external_url" json:"external_url"`
AdditionalRedirectUrls []string `toml:"additional_redirect_urls" json:"additional_redirect_urls"`
JwtExpiry uint `toml:"jwt_expiry" json:"jwt_expiry"`
JwtIssuer string `toml:"jwt_issuer" json:"jwt_issuer"`
Expand Down Expand Up @@ -397,6 +398,13 @@ type (
}
)

func (a auth) GetExternalURL(apiExternalURL string) string {
if len(a.ExternalUrl) > 0 {
return a.ExternalUrl
}
return strings.TrimRight(apiExternalURL, "/") + "/auth/v1"
}

func (a *auth) ToUpdateAuthConfigBody() v1API.UpdateAuthConfigBody {
body := v1API.UpdateAuthConfigBody{
SiteUrl: nullable.NewNullableWithValue(a.SiteUrl),
Expand Down
9 changes: 8 additions & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,10 @@ func NewConfig(editors ...ConfigEditor) config {
return initial
}

func (c *config) AuthExternalURL() string {
return c.Auth.GetExternalURL(c.Api.ExternalUrl)
}

var (
//go:embed templates/certs/kong.local.crt
kongCert []byte
Expand Down Expand Up @@ -632,9 +636,12 @@ func (c *config) Load(path string, fsys fs.FS, overrides ...ConfigEditor) error
}
c.Api.ExternalUrl = apiUrl.String()
}
if len(c.Auth.ExternalUrl) == 0 {
c.Auth.ExternalUrl = c.AuthExternalURL()
}
// Set default JWT issuer if not configured
if len(c.Auth.JwtIssuer) == 0 {
c.Auth.JwtIssuer = c.Api.ExternalUrl + "/auth/v1"
c.Auth.JwtIssuer = c.Auth.ExternalUrl
}
// Update image versions
switch c.Db.MajorVersion {
Expand Down
Loading
Loading