@@ -162,6 +162,7 @@ type (
162162 PasswordRequirements PasswordRequirements `toml:"password_requirements" json:"password_requirements"`
163163 SigningKeysPath string `toml:"signing_keys_path" json:"signing_keys_path"`
164164 SigningKeys []JWK `toml:"-" json:"-"`
165+ Passkey * passkey `toml:"passkey" json:"passkey"`
165166
166167 RateLimit rateLimit `toml:"rate_limit" json:"rate_limit"`
167168 Captcha * captcha `toml:"captcha" json:"captcha"`
@@ -378,6 +379,13 @@ type (
378379 Ethereum ethereum `toml:"ethereum" json:"ethereum"`
379380 }
380381
382+ passkey struct {
383+ Enabled bool `toml:"enabled" json:"enabled"`
384+ RpDisplayName string `toml:"rp_display_name" json:"rp_display_name"`
385+ RpId string `toml:"rp_id" json:"rp_id"`
386+ RpOrigins []string `toml:"rp_origins" json:"rp_origins"`
387+ }
388+
381389 OAuthServer struct {
382390 Enabled bool `toml:"enabled" json:"enabled"`
383391 AllowDynamicRegistration bool `toml:"allow_dynamic_registration" json:"allow_dynamic_registration"`
@@ -407,6 +415,9 @@ func (a *auth) ToUpdateAuthConfigBody() v1API.UpdateAuthConfigBody {
407415 if a .Captcha != nil {
408416 a .Captcha .toAuthConfigBody (& body )
409417 }
418+ if a .Passkey != nil {
419+ a .Passkey .toAuthConfigBody (& body )
420+ }
410421 a .Hook .toAuthConfigBody (& body )
411422 a .MFA .toAuthConfigBody (& body )
412423 a .Sessions .toAuthConfigBody (& body )
@@ -430,6 +441,17 @@ func (a *auth) FromRemoteAuthConfig(remoteConfig v1API.AuthConfigResponse) {
430441 a .MinimumPasswordLength = cast .IntToUint (ValOrDefault (remoteConfig .PasswordMinLength , 0 ))
431442 prc := ValOrDefault (remoteConfig .PasswordRequiredCharacters , "" )
432443 a .PasswordRequirements = NewPasswordRequirement (v1API .UpdateAuthConfigBodyPasswordRequiredCharacters (prc ))
444+ passkeyDisplayName := ValOrDefault (remoteConfig .WebauthnRpDisplayName , "" )
445+ passkeyId := ValOrDefault (remoteConfig .WebauthnRpId , "" )
446+ passkeyOrigins := ValOrDefault (remoteConfig .WebauthnRpOrigins , "" )
447+ if remoteConfig .PasskeyEnabled || passkeyDisplayName != "" || passkeyId != "" || passkeyOrigins != "" {
448+ if a .Passkey == nil {
449+ a .Passkey = & passkey {}
450+ }
451+ a .Passkey .fromAuthConfig (remoteConfig )
452+ } else {
453+ a .Passkey = nil
454+ }
433455 a .RateLimit .fromAuthConfig (remoteConfig )
434456 if s := a .Email .Smtp ; s != nil && s .Enabled {
435457 a .RateLimit .EmailSent = cast .IntToUint (ValOrDefault (remoteConfig .RateLimitEmailSent , 0 ))
@@ -489,6 +511,20 @@ func (c *captcha) fromAuthConfig(remoteConfig v1API.AuthConfigResponse) {
489511 c .Enabled = ValOrDefault (remoteConfig .SecurityCaptchaEnabled , false )
490512}
491513
514+ func (p passkey ) toAuthConfigBody (body * v1API.UpdateAuthConfigBody ) {
515+ body .PasskeyEnabled = cast .Ptr (p .Enabled )
516+ body .WebauthnRpDisplayName = nullable .NewNullableWithValue (p .RpDisplayName )
517+ body .WebauthnRpId = nullable .NewNullableWithValue (p .RpId )
518+ body .WebauthnRpOrigins = nullable .NewNullableWithValue (strings .Join (p .RpOrigins , "," ))
519+ }
520+
521+ func (p * passkey ) fromAuthConfig (remoteConfig v1API.AuthConfigResponse ) {
522+ p .Enabled = remoteConfig .PasskeyEnabled
523+ p .RpDisplayName = ValOrDefault (remoteConfig .WebauthnRpDisplayName , "" )
524+ p .RpId = ValOrDefault (remoteConfig .WebauthnRpId , "" )
525+ p .RpOrigins = strToArr (ValOrDefault (remoteConfig .WebauthnRpOrigins , "" ))
526+ }
527+
492528func (h hook ) toAuthConfigBody (body * v1API.UpdateAuthConfigBody ) {
493529 // When local config is not set, we assume platform defaults should not change
494530 if hook := h .BeforeUserCreated ; hook != nil {
0 commit comments