Skip to content

Commit 7a12639

Browse files
authored
fix(auth): propagate passkey config to env (#5401)
1 parent dfc9d1e commit 7a12639

4 files changed

Lines changed: 61 additions & 14 deletions

File tree

apps/cli-go/internal/start/start.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,7 @@ EOF
747747
)
748748
}
749749

750+
env = appendGotruePasskeyEnv(env)
750751
env = appendGotrueExternalProviderEnv(env)
751752
env = append(env,
752753
fmt.Sprintf("GOTRUE_EXTERNAL_WEB3_SOLANA_ENABLED=%v", utils.Config.Auth.Web3.Solana.Enabled),
@@ -1354,6 +1355,24 @@ func buildGotrueEnv(dbConfig pgconn.Config) []string {
13541355
}
13551356
}
13561357

1358+
// appendGotruePasskeyEnv wires the Auth container with passkey/WebAuthn
1359+
// settings from the [auth.passkey] and [auth.webauthn] config sections. Both
1360+
// sections are optional (nil when unset), so each block is guarded.
1361+
func appendGotruePasskeyEnv(env []string) []string {
1362+
if utils.Config.Auth.Passkey != nil {
1363+
env = append(env, fmt.Sprintf("GOTRUE_PASSKEY_ENABLED=%v", utils.Config.Auth.Passkey.Enabled))
1364+
}
1365+
if w := utils.Config.Auth.Webauthn; w != nil {
1366+
env = append(
1367+
env,
1368+
"GOTRUE_WEBAUTHN_RP_ID="+w.RpId,
1369+
"GOTRUE_WEBAUTHN_RP_DISPLAY_NAME="+w.RpDisplayName,
1370+
"GOTRUE_WEBAUTHN_RP_ORIGINS="+strings.Join(w.RpOrigins, ","),
1371+
)
1372+
}
1373+
return env
1374+
}
1375+
13571376
func appendGotrueExternalProviderEnv(env []string) []string {
13581377
for name, config := range utils.Config.Auth.External {
13591378
redirectUri := config.RedirectUri

apps/cli-go/internal/start/start_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,34 @@ func TestBuildGotrueEnv(t *testing.T) {
353353
assert.Equal(t, "http://127.0.0.1:54321/auth/v1/verify", env["GOTRUE_MAILER_URLPATHS_INVITE"])
354354
assert.Equal(t, "https://example.com/custom/callback", env["GOTRUE_EXTERNAL_AZURE_REDIRECT_URI"])
355355
})
356+
357+
t.Run("wires passkey and webauthn settings", func(t *testing.T) {
358+
utils.Config = config.NewConfig()
359+
utils.Config.Auth.Passkey = &config.Passkey{Enabled: true}
360+
utils.Config.Auth.Webauthn = &config.Webauthn{
361+
RpDisplayName: "Supabase",
362+
RpId: "localhost",
363+
RpOrigins: []string{"http://127.0.0.1:5173", "http://localhost:5173"},
364+
}
365+
366+
env := envToMap(appendGotruePasskeyEnv(buildGotrueEnv(pgconn.Config{})))
367+
368+
assert.Equal(t, "true", env["GOTRUE_PASSKEY_ENABLED"])
369+
assert.Equal(t, "localhost", env["GOTRUE_WEBAUTHN_RP_ID"])
370+
assert.Equal(t, "Supabase", env["GOTRUE_WEBAUTHN_RP_DISPLAY_NAME"])
371+
assert.Equal(t, "http://127.0.0.1:5173,http://localhost:5173", env["GOTRUE_WEBAUTHN_RP_ORIGINS"])
372+
})
373+
374+
t.Run("omits passkey and webauthn env when sections are unset", func(t *testing.T) {
375+
utils.Config = config.NewConfig()
376+
377+
env := envToMap(appendGotruePasskeyEnv(buildGotrueEnv(pgconn.Config{})))
378+
379+
_, hasPasskey := env["GOTRUE_PASSKEY_ENABLED"]
380+
_, hasRpId := env["GOTRUE_WEBAUTHN_RP_ID"]
381+
assert.False(t, hasPasskey)
382+
assert.False(t, hasRpId)
383+
})
356384
}
357385

358386
func TestFormatMapForEnvConfig(t *testing.T) {

apps/cli-go/pkg/config/auth.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ type (
163163
PasswordRequirements PasswordRequirements `toml:"password_requirements" json:"password_requirements"`
164164
SigningKeysPath string `toml:"signing_keys_path" json:"signing_keys_path"`
165165
SigningKeys []JWK `toml:"-" json:"-"`
166-
Passkey *passkey `toml:"passkey" json:"passkey"`
167-
Webauthn *webauthn `toml:"webauthn" json:"webauthn"`
166+
Passkey *Passkey `toml:"passkey" json:"passkey"`
167+
Webauthn *Webauthn `toml:"webauthn" json:"webauthn"`
168168

169169
RateLimit rateLimit `toml:"rate_limit" json:"rate_limit"`
170170
Captcha *captcha `toml:"captcha" json:"captcha"`
@@ -381,11 +381,11 @@ type (
381381
Ethereum ethereum `toml:"ethereum" json:"ethereum"`
382382
}
383383

384-
passkey struct {
384+
Passkey struct {
385385
Enabled bool `toml:"enabled" json:"enabled"`
386386
}
387387

388-
webauthn struct {
388+
Webauthn struct {
389389
RpDisplayName string `toml:"rp_display_name" json:"rp_display_name"`
390390
RpId string `toml:"rp_id" json:"rp_id"`
391391
RpOrigins []string `toml:"rp_origins" json:"rp_origins"`
@@ -517,25 +517,25 @@ func (c *captcha) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
517517
c.Enabled = ValOrDefault(remoteConfig.SecurityCaptchaEnabled, false)
518518
}
519519

520-
func (p passkey) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
520+
func (p Passkey) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
521521
body.PasskeyEnabled = cast.Ptr(p.Enabled)
522522
}
523523

524-
func (p *passkey) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
524+
func (p *Passkey) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
525525
// When local config is not set, we assume platform defaults should not change
526526
if p == nil {
527527
return
528528
}
529529
p.Enabled = remoteConfig.PasskeyEnabled
530530
}
531531

532-
func (w webauthn) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
532+
func (w Webauthn) toAuthConfigBody(body *v1API.UpdateAuthConfigBody) {
533533
body.WebauthnRpDisplayName = nullable.NewNullableWithValue(w.RpDisplayName)
534534
body.WebauthnRpId = nullable.NewNullableWithValue(w.RpId)
535535
body.WebauthnRpOrigins = nullable.NewNullableWithValue(strings.Join(w.RpOrigins, ","))
536536
}
537537

538-
func (w *webauthn) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
538+
func (w *Webauthn) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
539539
// When local config is not set, we assume platform defaults should not change
540540
if w == nil {
541541
return

apps/cli-go/pkg/config/auth_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ func TestCaptchaDiff(t *testing.T) {
215215
func TestPasskeyConfigMapping(t *testing.T) {
216216
t.Run("serializes passkey config to update body", func(t *testing.T) {
217217
c := newWithDefaults()
218-
c.Passkey = &passkey{Enabled: true}
219-
c.Webauthn = &webauthn{
218+
c.Passkey = &Passkey{Enabled: true}
219+
c.Webauthn = &Webauthn{
220220
RpDisplayName: "Supabase CLI",
221221
RpId: "localhost",
222222
RpOrigins: []string{
@@ -237,7 +237,7 @@ func TestPasskeyConfigMapping(t *testing.T) {
237237

238238
t.Run("does not serialize rp fields when webauthn is undefined", func(t *testing.T) {
239239
c := newWithDefaults()
240-
c.Passkey = &passkey{Enabled: false}
240+
c.Passkey = &Passkey{Enabled: false}
241241
// Run test
242242
body := c.ToUpdateAuthConfigBody()
243243
// Check result
@@ -254,7 +254,7 @@ func TestPasskeyConfigMapping(t *testing.T) {
254254

255255
t.Run("serializes webauthn fields independently of passkey", func(t *testing.T) {
256256
c := newWithDefaults()
257-
c.Webauthn = &webauthn{
257+
c.Webauthn = &Webauthn{
258258
RpDisplayName: "Supabase CLI",
259259
RpId: "localhost",
260260
RpOrigins: []string{"http://127.0.0.1:3000"},
@@ -270,8 +270,8 @@ func TestPasskeyConfigMapping(t *testing.T) {
270270

271271
t.Run("hydrates passkey and webauthn config from remote", func(t *testing.T) {
272272
c := newWithDefaults()
273-
c.Passkey = &passkey{Enabled: true}
274-
c.Webauthn = &webauthn{}
273+
c.Passkey = &Passkey{Enabled: true}
274+
c.Webauthn = &Webauthn{}
275275
// Run test
276276
c.FromRemoteAuthConfig(v1API.AuthConfigResponse{
277277
PasskeyEnabled: true,

0 commit comments

Comments
 (0)