From 2733fc040cc43269889f5e11fd64c1fdb2e09ebd Mon Sep 17 00:00:00 2001 From: James Elliott Date: Sat, 15 Apr 2023 02:04:42 +1000 Subject: [PATCH] refactor: webauthn naming (#5243) Signed-off-by: James Elliott --- api/openapi.yml | 28 +++--- config.template.yml | 8 +- internal/commands/storage_run.go | 14 +-- internal/configuration/config.template.yml | 8 +- .../configuration/schema/configuration.go | 2 +- internal/configuration/schema/webauthn.go | 8 +- .../configuration/validator/configuration.go | 4 +- .../validator/configuration_test.go | 6 +- internal/configuration/validator/const.go | 10 +- internal/configuration/validator/webauthn.go | 28 +++--- .../configuration/validator/webauthn_test.go | 62 ++++++------ internal/handlers/const.go | 4 +- .../handlers/handler_configuration_test.go | 14 +-- .../handlers/handler_register_webauthn.go | 58 +++++------ internal/handlers/handler_sign_webauthn.go | 56 +++++------ internal/handlers/types.go | 4 +- internal/handlers/webauthn.go | 14 +-- internal/handlers/webauthn_test.go | 20 ++-- internal/middlewares/authelia_context.go | 2 +- internal/middlewares/authelia_context_test.go | 2 +- internal/mocks/storage.go | 73 +++++++------- internal/oidc/amr.go | 16 +-- internal/oidc/amr_test.go | 20 ++-- internal/oidc/const.go | 6 +- internal/regulation/const.go | 4 +- internal/server/handlers.go | 10 +- internal/server/template.go | 8 +- internal/session/provider_test.go | 32 +++--- internal/session/types.go | 4 +- internal/session/user_session.go | 10 +- internal/storage/const.go | 2 +- internal/storage/errors.go | 4 +- internal/storage/provider.go | 12 +-- internal/storage/sql_provider.go | 98 +++++++++---------- .../storage/sql_provider_backend_postgres.go | 16 +-- internal/storage/sql_provider_encryption.go | 34 +++---- internal/storage/sql_provider_queries.go | 22 ++--- internal/storage/types.go | 2 +- web/src/App.tsx | 6 +- web/src/constants/Routes.ts | 4 +- web/src/services/Api.ts | 8 +- web/src/services/RegisterDevice.ts | 6 +- web/src/services/Webauthn.ts | 22 ++--- ...isterWebauthn.tsx => RegisterWebAuthn.tsx} | 4 +- web/src/views/LoginPortal/LoginPortal.tsx | 4 +- .../SecondFactor/SecondFactorForm.tsx | 12 +-- 46 files changed, 395 insertions(+), 396 deletions(-) rename web/src/views/DeviceRegistration/{RegisterWebauthn.tsx => RegisterWebAuthn.tsx} (98%) diff --git a/api/openapi.yml b/api/openapi.yml index 6bc5cfb79..1daa5f197 100644 --- a/api/openapi.yml +++ b/api/openapi.yml @@ -29,9 +29,9 @@ tags: - name: User Information description: User configuration endpoints {{- end }} - {{- if (or .TOTP .Webauthn .Duo) }} + {{- if (or .TOTP .WebAuthn .Duo) }} - name: Second Factor - description: TOTP, Webauthn and Duo endpoints + description: TOTP, WebAuthn and Duo endpoints externalDocs: url: https://www.authelia.com/configuration/second-factor/introduction/ {{- end }} @@ -721,13 +721,13 @@ paths: security: - authelia_auth: [] {{- end }} - {{- if .Webauthn }} + {{- if .WebAuthn }} /api/secondfactor/webauthn/assertion: get: tags: - Second Factor - summary: Second Factor Authentication - Webauthn (Request) - description: This endpoint starts the second factor authentication process with the FIDO2 Webauthn credential. + summary: Second Factor Authentication - WebAuthn (Request) + description: This endpoint starts the second factor authentication process with the FIDO2 WebAuthn credential. responses: "200": description: Successful Operation @@ -742,8 +742,8 @@ paths: post: tags: - Second Factor - summary: Second Factor Authentication - Webauthn - description: This endpoint completes the second factor authentication process with the FIDO2 Webauthn credential. + summary: Second Factor Authentication - WebAuthn + description: This endpoint completes the second factor authentication process with the FIDO2 WebAuthn credential. requestBody: required: true content: @@ -765,9 +765,9 @@ paths: post: tags: - Second Factor - summary: Identity Verification Webauthn Credential Creation + summary: Identity Verification WebAuthn Credential Creation description: > - This endpoint performs identity verification to begin the FIDO2 Webauthn credential attestation process + This endpoint performs identity verification to begin the FIDO2 WebAuthn credential attestation process (registration). The session generated from this endpoint must be utilised for the subsequent steps in the @@ -785,9 +785,9 @@ paths: post: tags: - Second Factor - summary: Identity Verification FIDO2 Webauthn Credential Validation + summary: Identity Verification FIDO2 WebAuthn Credential Validation description: > - This endpoint performs identity and token verification, upon success generates a FIDO2 Webauthn device + This endpoint performs identity and token verification, upon success generates a FIDO2 WebAuthn device attestation challenge (registration). The session cookie generated from the `/api/secondfactor/webauthn/identity/start` endpoint must be utilised @@ -811,8 +811,8 @@ paths: post: tags: - Second Factor - summary: Webauthn Credential Attestation - description: This endpoint performs Webauthn credential attestation (registration). + summary: WebAuthn Credential Attestation + description: This endpoint performs WebAuthn credential attestation (registration). requestBody: required: true content: @@ -1878,7 +1878,7 @@ components: type: string example: 'otpauth://totp/{{ .Domain | default "example.com" }}:john?algorithm=SHA1&digits=6&issuer=auth.{{ .Domain | default "example.com" }}&period=30&secret=5ZH7Y5CTFWOXN7EOLGBMMXADRNQFHVUDZSYKCN5HMFAIRSLAWY3Q' {{- end }} - {{- if .Webauthn }} + {{- if .WebAuthn }} webauthn.PublicKeyCredential: type: object properties: diff --git a/config.template.yml b/config.template.yml index 077237358..3bc54dbc5 100644 --- a/config.template.yml +++ b/config.template.yml @@ -214,13 +214,13 @@ totp: ## ## Parameters used for WebAuthn. webauthn: - ## Disable Webauthn. + ## Disable WebAuthn. disable: false - ## Adjust the interaction timeout for Webauthn dialogues. + ## Adjust the interaction timeout for WebAuthn dialogues. timeout: 60s - ## The display name the browser should show the user for when using Webauthn to login/register. + ## The display name the browser should show the user for when using WebAuthn to login/register. display_name: Authelia ## Conveyance preference controls if we collect the attestation statement including the AAGUID from the device. @@ -1167,7 +1167,7 @@ regulation: ## ## Notification Provider ## -## Notifications are sent to users when they require a password reset, a Webauthn registration or a TOTP registration. +## Notifications are sent to users when they require a password reset, a WebAuthn registration or a TOTP registration. ## The available providers are: filesystem, smtp. You must use only one of these providers. notifier: ## You can disable the notifier startup check by setting this to true. diff --git a/internal/commands/storage_run.go b/internal/commands/storage_run.go index 615e11686..3aef003ee 100644 --- a/internal/commands/storage_run.go +++ b/internal/commands/storage_run.go @@ -451,7 +451,7 @@ func (ctx *CmdCtx) StorageUserWebAuthnExportRunE(cmd *cobra.Command, args []stri } for page := 0; true; page++ { - if devices, err = ctx.providers.StorageProvider.LoadWebauthnDevices(ctx, limit, page); err != nil { + if devices, err = ctx.providers.StorageProvider.LoadWebAuthnDevices(ctx, limit, page); err != nil { return err } @@ -522,7 +522,7 @@ func (ctx *CmdCtx) StorageUserWebAuthnImportRunE(cmd *cobra.Command, args []stri } for _, device := range export.WebAuthnDevices { - if err = ctx.providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil { + if err = ctx.providers.StorageProvider.SaveWebAuthnDevice(ctx, device); err != nil { return err } } @@ -550,10 +550,10 @@ func (ctx *CmdCtx) StorageUserWebAuthnListRunE(cmd *cobra.Command, args []string user := args[0] - devices, err = ctx.providers.StorageProvider.LoadWebauthnDevicesByUsername(ctx, user) + devices, err = ctx.providers.StorageProvider.LoadWebAuthnDevicesByUsername(ctx, user) switch { - case len(devices) == 0 || (err != nil && errors.Is(err, storage.ErrNoWebauthnDevice)): + case len(devices) == 0 || (err != nil && errors.Is(err, storage.ErrNoWebAuthnDevice)): return fmt.Errorf("user '%s' has no webauthn devices", user) case err != nil: return fmt.Errorf("can't list devices for user '%s': %w", user, err) @@ -586,7 +586,7 @@ func (ctx *CmdCtx) StorageUserWebAuthnListAllRunE(_ *cobra.Command, _ []string) output := strings.Builder{} for page := 0; true; page++ { - if devices, err = ctx.providers.StorageProvider.LoadWebauthnDevices(ctx, limit, page); err != nil { + if devices, err = ctx.providers.StorageProvider.LoadWebAuthnDevices(ctx, limit, page); err != nil { return fmt.Errorf("failed to list devices: %w", err) } @@ -629,13 +629,13 @@ func (ctx *CmdCtx) StorageUserWebAuthnDeleteRunE(cmd *cobra.Command, args []stri } if byKID { - if err = ctx.providers.StorageProvider.DeleteWebauthnDevice(ctx, kid); err != nil { + if err = ctx.providers.StorageProvider.DeleteWebAuthnDevice(ctx, kid); err != nil { return fmt.Errorf("failed to delete webauthn device with kid '%s': %w", kid, err) } fmt.Printf("Successfully deleted WebAuthn device with key id '%s'\n", kid) } else { - err = ctx.providers.StorageProvider.DeleteWebauthnDeviceByUsername(ctx, user, description) + err = ctx.providers.StorageProvider.DeleteWebAuthnDeviceByUsername(ctx, user, description) if all { if err != nil { diff --git a/internal/configuration/config.template.yml b/internal/configuration/config.template.yml index 077237358..3bc54dbc5 100644 --- a/internal/configuration/config.template.yml +++ b/internal/configuration/config.template.yml @@ -214,13 +214,13 @@ totp: ## ## Parameters used for WebAuthn. webauthn: - ## Disable Webauthn. + ## Disable WebAuthn. disable: false - ## Adjust the interaction timeout for Webauthn dialogues. + ## Adjust the interaction timeout for WebAuthn dialogues. timeout: 60s - ## The display name the browser should show the user for when using Webauthn to login/register. + ## The display name the browser should show the user for when using WebAuthn to login/register. display_name: Authelia ## Conveyance preference controls if we collect the attestation statement including the AAGUID from the device. @@ -1167,7 +1167,7 @@ regulation: ## ## Notification Provider ## -## Notifications are sent to users when they require a password reset, a Webauthn registration or a TOTP registration. +## Notifications are sent to users when they require a password reset, a WebAuthn registration or a TOTP registration. ## The available providers are: filesystem, smtp. You must use only one of these providers. notifier: ## You can disable the notifier startup check by setting this to true. diff --git a/internal/configuration/schema/configuration.go b/internal/configuration/schema/configuration.go index 33e799427..74f3e4faf 100644 --- a/internal/configuration/schema/configuration.go +++ b/internal/configuration/schema/configuration.go @@ -21,7 +21,7 @@ type Configuration struct { Notifier NotifierConfiguration `koanf:"notifier"` Server ServerConfiguration `koanf:"server"` Telemetry TelemetryConfig `koanf:"telemetry"` - Webauthn WebauthnConfiguration `koanf:"webauthn"` + WebAuthn WebAuthnConfiguration `koanf:"webauthn"` PasswordPolicy PasswordPolicyConfiguration `koanf:"password_policy"` PrivacyPolicy PrivacyPolicy `koanf:"privacy_policy"` } diff --git a/internal/configuration/schema/webauthn.go b/internal/configuration/schema/webauthn.go index 6a6104486..a544225c5 100644 --- a/internal/configuration/schema/webauthn.go +++ b/internal/configuration/schema/webauthn.go @@ -6,8 +6,8 @@ import ( "github.com/go-webauthn/webauthn/protocol" ) -// WebauthnConfiguration represents the webauthn config. -type WebauthnConfiguration struct { +// WebAuthnConfiguration represents the webauthn config. +type WebAuthnConfiguration struct { Disable bool `koanf:"disable"` DisplayName string `koanf:"display_name"` @@ -17,8 +17,8 @@ type WebauthnConfiguration struct { Timeout time.Duration `koanf:"timeout"` } -// DefaultWebauthnConfiguration describes the default values for the WebauthnConfiguration. -var DefaultWebauthnConfiguration = WebauthnConfiguration{ +// DefaultWebAuthnConfiguration describes the default values for the WebAuthnConfiguration. +var DefaultWebAuthnConfiguration = WebAuthnConfiguration{ DisplayName: "Authelia", Timeout: time.Second * 60, diff --git a/internal/configuration/validator/configuration.go b/internal/configuration/validator/configuration.go index 874e0809b..df3d5e328 100644 --- a/internal/configuration/validator/configuration.go +++ b/internal/configuration/validator/configuration.go @@ -43,7 +43,7 @@ func ValidateConfiguration(config *schema.Configuration, validator *schema.Struc ValidateTOTP(config, validator) - ValidateWebauthn(config, validator) + ValidateWebAuthn(config, validator) ValidateAuthenticationBackend(&config.AuthenticationBackend, validator) @@ -89,7 +89,7 @@ func validateDefault2FAMethod(config *schema.Configuration, validator *schema.St enabledMethods = append(enabledMethods, "totp") } - if !config.Webauthn.Disable { + if !config.WebAuthn.Disable { enabledMethods = append(enabledMethods, "webauthn") } diff --git a/internal/configuration/validator/configuration_test.go b/internal/configuration/validator/configuration_test.go index 7fee1355e..f40aaea1c 100644 --- a/internal/configuration/validator/configuration_test.go +++ b/internal/configuration/validator/configuration_test.go @@ -188,7 +188,7 @@ func TestValidateDefault2FAMethod(t *testing.T) { }, }, { - desc: "ShouldAllowConfiguredMethodWebauthn", + desc: "ShouldAllowConfiguredMethodWebAuthn", have: &schema.Configuration{ Default2FAMethod: "webauthn", DuoAPI: schema.DuoAPIConfiguration{ @@ -225,7 +225,7 @@ func TestValidateDefault2FAMethod(t *testing.T) { }, }, { - desc: "ShouldNotAllowDisabledMethodWebauthn", + desc: "ShouldNotAllowDisabledMethodWebAuthn", have: &schema.Configuration{ Default2FAMethod: "webauthn", DuoAPI: schema.DuoAPIConfiguration{ @@ -233,7 +233,7 @@ func TestValidateDefault2FAMethod(t *testing.T) { IntegrationKey: "another key", Hostname: "none", }, - Webauthn: schema.WebauthnConfiguration{Disable: true}, + WebAuthn: schema.WebAuthnConfiguration{Disable: true}, }, expectedErrs: []string{ "option 'default_2fa_method' must be one of the enabled options 'totp' or 'mobile_push' but it's configured as 'webauthn'", diff --git a/internal/configuration/validator/const.go b/internal/configuration/validator/const.go index 5f697f7e8..3fbaa8ded 100644 --- a/internal/configuration/validator/const.go +++ b/internal/configuration/validator/const.go @@ -197,10 +197,10 @@ const ( "configured to an unsafe value, it should be above 8 but it's configured to %d" ) -// Webauthn Error constants. +// WebAuthn Error constants. const ( - errFmtWebauthnConveyancePreference = "webauthn: option 'attestation_conveyance_preference' must be one of %s but it's configured as '%s'" - errFmtWebauthnUserVerification = "webauthn: option 'user_verification' must be one of %s but it's configured as '%s'" + errFmtWebAuthnConveyancePreference = "webauthn: option 'attestation_conveyance_preference' must be one of %s but it's configured as '%s'" + errFmtWebAuthnUserVerification = "webauthn: option 'user_verification' must be one of %s but it's configured as '%s'" ) // Access Control error constants. @@ -378,8 +378,8 @@ var ( validThemeNames = []string{"light", "dark", "grey", auto} validSessionSameSiteValues = []string{"none", "lax", "strict"} validLogLevels = []string{"trace", "debug", "info", "warn", "error"} - validWebauthnConveyancePreferences = []string{string(protocol.PreferNoAttestation), string(protocol.PreferIndirectAttestation), string(protocol.PreferDirectAttestation)} - validWebauthnUserVerificationRequirement = []string{string(protocol.VerificationDiscouraged), string(protocol.VerificationPreferred), string(protocol.VerificationRequired)} + validWebAuthnConveyancePreferences = []string{string(protocol.PreferNoAttestation), string(protocol.PreferIndirectAttestation), string(protocol.PreferDirectAttestation)} + validWebAuthnUserVerificationRequirement = []string{string(protocol.VerificationDiscouraged), string(protocol.VerificationPreferred), string(protocol.VerificationRequired)} validRFC7231HTTPMethodVerbs = []string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "TRACE", "CONNECT", "OPTIONS"} validRFC4918HTTPMethodVerbs = []string{"COPY", "LOCK", "MKCOL", "MOVE", "PROPFIND", "PROPPATCH", "UNLOCK"} ) diff --git a/internal/configuration/validator/webauthn.go b/internal/configuration/validator/webauthn.go index 406ccc7e6..9a482e22c 100644 --- a/internal/configuration/validator/webauthn.go +++ b/internal/configuration/validator/webauthn.go @@ -7,27 +7,27 @@ import ( "github.com/authelia/authelia/v4/internal/utils" ) -// ValidateWebauthn validates and update Webauthn configuration. -func ValidateWebauthn(config *schema.Configuration, validator *schema.StructValidator) { - if config.Webauthn.DisplayName == "" { - config.Webauthn.DisplayName = schema.DefaultWebauthnConfiguration.DisplayName +// ValidateWebAuthn validates and update WebAuthn configuration. +func ValidateWebAuthn(config *schema.Configuration, validator *schema.StructValidator) { + if config.WebAuthn.DisplayName == "" { + config.WebAuthn.DisplayName = schema.DefaultWebAuthnConfiguration.DisplayName } - if config.Webauthn.Timeout <= 0 { - config.Webauthn.Timeout = schema.DefaultWebauthnConfiguration.Timeout + if config.WebAuthn.Timeout <= 0 { + config.WebAuthn.Timeout = schema.DefaultWebAuthnConfiguration.Timeout } switch { - case config.Webauthn.ConveyancePreference == "": - config.Webauthn.ConveyancePreference = schema.DefaultWebauthnConfiguration.ConveyancePreference - case !utils.IsStringInSlice(string(config.Webauthn.ConveyancePreference), validWebauthnConveyancePreferences): - validator.Push(fmt.Errorf(errFmtWebauthnConveyancePreference, strJoinOr(validWebauthnConveyancePreferences), config.Webauthn.ConveyancePreference)) + case config.WebAuthn.ConveyancePreference == "": + config.WebAuthn.ConveyancePreference = schema.DefaultWebAuthnConfiguration.ConveyancePreference + case !utils.IsStringInSlice(string(config.WebAuthn.ConveyancePreference), validWebAuthnConveyancePreferences): + validator.Push(fmt.Errorf(errFmtWebAuthnConveyancePreference, strJoinOr(validWebAuthnConveyancePreferences), config.WebAuthn.ConveyancePreference)) } switch { - case config.Webauthn.UserVerification == "": - config.Webauthn.UserVerification = schema.DefaultWebauthnConfiguration.UserVerification - case !utils.IsStringInSlice(string(config.Webauthn.UserVerification), validWebauthnUserVerificationRequirement): - validator.Push(fmt.Errorf(errFmtWebauthnUserVerification, strJoinOr(validWebauthnConveyancePreferences), config.Webauthn.UserVerification)) + case config.WebAuthn.UserVerification == "": + config.WebAuthn.UserVerification = schema.DefaultWebAuthnConfiguration.UserVerification + case !utils.IsStringInSlice(string(config.WebAuthn.UserVerification), validWebAuthnUserVerificationRequirement): + validator.Push(fmt.Errorf(errFmtWebAuthnUserVerification, strJoinOr(validWebAuthnConveyancePreferences), config.WebAuthn.UserVerification)) } } diff --git a/internal/configuration/validator/webauthn_test.go b/internal/configuration/validator/webauthn_test.go index 9aaaa0aac..ea93f0382 100644 --- a/internal/configuration/validator/webauthn_test.go +++ b/internal/configuration/validator/webauthn_test.go @@ -11,39 +11,39 @@ import ( "github.com/authelia/authelia/v4/internal/configuration/schema" ) -func TestWebauthnShouldSetDefaultValues(t *testing.T) { +func TestWebAuthnShouldSetDefaultValues(t *testing.T) { validator := schema.NewStructValidator() config := &schema.Configuration{ - Webauthn: schema.WebauthnConfiguration{}, + WebAuthn: schema.WebAuthnConfiguration{}, } - ValidateWebauthn(config, validator) + ValidateWebAuthn(config, validator) require.Len(t, validator.Errors(), 0) - assert.Equal(t, schema.DefaultWebauthnConfiguration.DisplayName, config.Webauthn.DisplayName) - assert.Equal(t, schema.DefaultWebauthnConfiguration.Timeout, config.Webauthn.Timeout) - assert.Equal(t, schema.DefaultWebauthnConfiguration.ConveyancePreference, config.Webauthn.ConveyancePreference) - assert.Equal(t, schema.DefaultWebauthnConfiguration.UserVerification, config.Webauthn.UserVerification) + assert.Equal(t, schema.DefaultWebAuthnConfiguration.DisplayName, config.WebAuthn.DisplayName) + assert.Equal(t, schema.DefaultWebAuthnConfiguration.Timeout, config.WebAuthn.Timeout) + assert.Equal(t, schema.DefaultWebAuthnConfiguration.ConveyancePreference, config.WebAuthn.ConveyancePreference) + assert.Equal(t, schema.DefaultWebAuthnConfiguration.UserVerification, config.WebAuthn.UserVerification) } -func TestWebauthnShouldSetDefaultTimeoutWhenNegative(t *testing.T) { +func TestWebAuthnShouldSetDefaultTimeoutWhenNegative(t *testing.T) { validator := schema.NewStructValidator() config := &schema.Configuration{ - Webauthn: schema.WebauthnConfiguration{ + WebAuthn: schema.WebAuthnConfiguration{ Timeout: -1, }, } - ValidateWebauthn(config, validator) + ValidateWebAuthn(config, validator) require.Len(t, validator.Errors(), 0) - assert.Equal(t, schema.DefaultWebauthnConfiguration.Timeout, config.Webauthn.Timeout) + assert.Equal(t, schema.DefaultWebAuthnConfiguration.Timeout, config.WebAuthn.Timeout) } -func TestWebauthnShouldNotSetDefaultValuesWhenConfigured(t *testing.T) { +func TestWebAuthnShouldNotSetDefaultValuesWhenConfigured(t *testing.T) { validator := schema.NewStructValidator() config := &schema.Configuration{ - Webauthn: schema.WebauthnConfiguration{ + WebAuthn: schema.WebAuthnConfiguration{ DisplayName: "Test", Timeout: time.Second * 50, ConveyancePreference: protocol.PreferNoAttestation, @@ -51,37 +51,37 @@ func TestWebauthnShouldNotSetDefaultValuesWhenConfigured(t *testing.T) { }, } - ValidateWebauthn(config, validator) + ValidateWebAuthn(config, validator) require.Len(t, validator.Errors(), 0) - assert.Equal(t, "Test", config.Webauthn.DisplayName) - assert.Equal(t, time.Second*50, config.Webauthn.Timeout) - assert.Equal(t, protocol.PreferNoAttestation, config.Webauthn.ConveyancePreference) - assert.Equal(t, protocol.VerificationDiscouraged, config.Webauthn.UserVerification) + assert.Equal(t, "Test", config.WebAuthn.DisplayName) + assert.Equal(t, time.Second*50, config.WebAuthn.Timeout) + assert.Equal(t, protocol.PreferNoAttestation, config.WebAuthn.ConveyancePreference) + assert.Equal(t, protocol.VerificationDiscouraged, config.WebAuthn.UserVerification) - config.Webauthn.ConveyancePreference = protocol.PreferIndirectAttestation - config.Webauthn.UserVerification = protocol.VerificationPreferred + config.WebAuthn.ConveyancePreference = protocol.PreferIndirectAttestation + config.WebAuthn.UserVerification = protocol.VerificationPreferred - ValidateWebauthn(config, validator) + ValidateWebAuthn(config, validator) require.Len(t, validator.Errors(), 0) - assert.Equal(t, protocol.PreferIndirectAttestation, config.Webauthn.ConveyancePreference) - assert.Equal(t, protocol.VerificationPreferred, config.Webauthn.UserVerification) + assert.Equal(t, protocol.PreferIndirectAttestation, config.WebAuthn.ConveyancePreference) + assert.Equal(t, protocol.VerificationPreferred, config.WebAuthn.UserVerification) - config.Webauthn.ConveyancePreference = protocol.PreferDirectAttestation - config.Webauthn.UserVerification = protocol.VerificationRequired + config.WebAuthn.ConveyancePreference = protocol.PreferDirectAttestation + config.WebAuthn.UserVerification = protocol.VerificationRequired - ValidateWebauthn(config, validator) + ValidateWebAuthn(config, validator) require.Len(t, validator.Errors(), 0) - assert.Equal(t, protocol.PreferDirectAttestation, config.Webauthn.ConveyancePreference) - assert.Equal(t, protocol.VerificationRequired, config.Webauthn.UserVerification) + assert.Equal(t, protocol.PreferDirectAttestation, config.WebAuthn.ConveyancePreference) + assert.Equal(t, protocol.VerificationRequired, config.WebAuthn.UserVerification) } -func TestWebauthnShouldRaiseErrorsOnInvalidOptions(t *testing.T) { +func TestWebAuthnShouldRaiseErrorsOnInvalidOptions(t *testing.T) { validator := schema.NewStructValidator() config := &schema.Configuration{ - Webauthn: schema.WebauthnConfiguration{ + WebAuthn: schema.WebAuthnConfiguration{ DisplayName: "Test", Timeout: time.Second * 50, ConveyancePreference: "no", @@ -89,7 +89,7 @@ func TestWebauthnShouldRaiseErrorsOnInvalidOptions(t *testing.T) { }, } - ValidateWebauthn(config, validator) + ValidateWebAuthn(config, validator) require.Len(t, validator.Errors(), 2) diff --git a/internal/handlers/const.go b/internal/handlers/const.go index 953b0f748..6560cbc93 100644 --- a/internal/handlers/const.go +++ b/internal/handlers/const.go @@ -8,8 +8,8 @@ const ( // ActionTOTPRegistration is the string representation of the action for which the token has been produced. ActionTOTPRegistration = "RegisterTOTPDevice" - // ActionWebauthnRegistration is the string representation of the action for which the token has been produced. - ActionWebauthnRegistration = "RegisterWebauthnDevice" + // ActionWebAuthnRegistration is the string representation of the action for which the token has been produced. + ActionWebAuthnRegistration = "RegisterWebAuthnDevice" // ActionResetPassword is the string representation of the action for which the token has been produced. ActionResetPassword = "ResetPassword" diff --git a/internal/handlers/handler_configuration_test.go b/internal/handlers/handler_configuration_test.go index 2812479d8..29913445c 100644 --- a/internal/handlers/handler_configuration_test.go +++ b/internal/handlers/handler_configuration_test.go @@ -36,7 +36,7 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldHaveAllConfiguredMethods TOTP: schema.TOTPConfiguration{ Disable: false, }, - Webauthn: schema.WebauthnConfiguration{ + WebAuthn: schema.WebAuthnConfiguration{ Disable: false, }, AccessControl: schema.AccessControlConfiguration{ @@ -66,7 +66,7 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldRemoveTOTPFromAvailableM TOTP: schema.TOTPConfiguration{ Disable: true, }, - Webauthn: schema.WebauthnConfiguration{ + WebAuthn: schema.WebAuthnConfiguration{ Disable: false, }, AccessControl: schema.AccessControlConfiguration{ @@ -88,7 +88,7 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldRemoveTOTPFromAvailableM }) } -func (s *SecondFactorAvailableMethodsFixture) TestShouldRemoveWebauthnFromAvailableMethodsWhenDisabled() { +func (s *SecondFactorAvailableMethodsFixture) TestShouldRemoveWebAuthnFromAvailableMethodsWhenDisabled() { s.mock.Ctx.Configuration = schema.Configuration{ DuoAPI: schema.DuoAPIConfiguration{ Disable: false, @@ -96,7 +96,7 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldRemoveWebauthnFromAvaila TOTP: schema.TOTPConfiguration{ Disable: false, }, - Webauthn: schema.WebauthnConfiguration{ + WebAuthn: schema.WebAuthnConfiguration{ Disable: true, }, AccessControl: schema.AccessControlConfiguration{ @@ -126,7 +126,7 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldRemoveDuoFromAvailableMe TOTP: schema.TOTPConfiguration{ Disable: false, }, - Webauthn: schema.WebauthnConfiguration{ + WebAuthn: schema.WebAuthnConfiguration{ Disable: false, }, AccessControl: schema.AccessControlConfiguration{ @@ -156,7 +156,7 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldRemoveAllMethodsWhenNoTw TOTP: schema.TOTPConfiguration{ Disable: false, }, - Webauthn: schema.WebauthnConfiguration{ + WebAuthn: schema.WebAuthnConfiguration{ Disable: false, }, AccessControl: schema.AccessControlConfiguration{ @@ -186,7 +186,7 @@ func (s *SecondFactorAvailableMethodsFixture) TestShouldRemoveAllMethodsWhenAllD TOTP: schema.TOTPConfiguration{ Disable: true, }, - Webauthn: schema.WebauthnConfiguration{ + WebAuthn: schema.WebAuthnConfiguration{ Disable: true, }, AccessControl: schema.AccessControlConfiguration{ diff --git a/internal/handlers/handler_register_webauthn.go b/internal/handlers/handler_register_webauthn.go index 754041874..40f16cf0f 100644 --- a/internal/handlers/handler_register_webauthn.go +++ b/internal/handlers/handler_register_webauthn.go @@ -18,19 +18,19 @@ var WebauthnIdentityStart = middlewares.IdentityVerificationStart(middlewares.Id MailTitle: "Register your key", MailButtonContent: "Register", TargetEndpoint: "/webauthn/register", - ActionClaim: ActionWebauthnRegistration, + ActionClaim: ActionWebAuthnRegistration, IdentityRetrieverFunc: identityRetrieverFromSession, }, nil) // WebauthnIdentityFinish the handler for finishing the identity validation. var WebauthnIdentityFinish = middlewares.IdentityVerificationFinish( middlewares.IdentityVerificationFinishArgs{ - ActionClaim: ActionWebauthnRegistration, + ActionClaim: ActionWebAuthnRegistration, IsTokenUserValidFunc: isTokenUserValidFor2FARegistration, - }, SecondFactorWebauthnAttestationGET) + }, SecondFactorWebAuthnAttestationGET) -// SecondFactorWebauthnAttestationGET returns the attestation challenge from the server. -func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) { +// SecondFactorWebAuthnAttestationGET returns the attestation challenge from the server. +func SecondFactorWebAuthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) { var ( w *webauthn.WebAuthn user *model.WebAuthnUser @@ -39,15 +39,15 @@ func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) ) if userSession, err = ctx.GetSession(); err != nil { - ctx.Logger.WithError(err).Errorf("Error occurred retrieving session for %s attestation challenge", regulation.AuthTypeWebauthn) + ctx.Logger.WithError(err).Errorf("Error occurred retrieving session for %s attestation challenge", regulation.AuthTypeWebAuthn) respondUnauthorized(ctx, messageUnableToRegisterSecurityKey) return } - if w, err = newWebauthn(ctx); err != nil { - ctx.Logger.Errorf("Unable to create %s attestation challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + if w, err = newWebAuthn(ctx); err != nil { + ctx.Logger.Errorf("Unable to create %s attestation challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageUnableToRegisterSecurityKey) @@ -55,7 +55,7 @@ func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) } if user, err = getWebAuthnUser(ctx, userSession); err != nil { - ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -64,8 +64,8 @@ func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) var credentialCreation *protocol.CredentialCreation - if credentialCreation, userSession.Webauthn, err = w.BeginRegistration(user); err != nil { - ctx.Logger.Errorf("Unable to create %s attestation challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + if credentialCreation, userSession.WebAuthn, err = w.BeginRegistration(user); err != nil { + ctx.Logger.Errorf("Unable to create %s attestation challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageUnableToRegisterSecurityKey) @@ -73,7 +73,7 @@ func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) } if err = ctx.SaveSession(userSession); err != nil { - ctx.Logger.Errorf(logFmtErrSessionSave, "attestation challenge", regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf(logFmtErrSessionSave, "attestation challenge", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageUnableToRegisterSecurityKey) @@ -81,7 +81,7 @@ func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) } if err = ctx.SetJSONBody(credentialCreation); err != nil { - ctx.Logger.Errorf(logFmtErrWriteResponseBody, regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf(logFmtErrWriteResponseBody, regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageUnableToRegisterSecurityKey) @@ -89,8 +89,8 @@ func SecondFactorWebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) } } -// WebauthnAttestationPOST processes the attestation challenge response from the client. -func WebauthnAttestationPOST(ctx *middlewares.AutheliaCtx) { +// WebAuthnAttestationPOST processes the attestation challenge response from the client. +func WebAuthnAttestationPOST(ctx *middlewares.AutheliaCtx) { var ( err error w *webauthn.WebAuthn @@ -103,23 +103,23 @@ func WebauthnAttestationPOST(ctx *middlewares.AutheliaCtx) { ) if userSession, err = ctx.GetSession(); err != nil { - ctx.Logger.WithError(err).Errorf("Error occurred retrieving session for %s attestation response", regulation.AuthTypeWebauthn) + ctx.Logger.WithError(err).Errorf("Error occurred retrieving session for %s attestation response", regulation.AuthTypeWebAuthn) respondUnauthorized(ctx, messageUnableToRegisterSecurityKey) return } - if userSession.Webauthn == nil { - ctx.Logger.Errorf("Webauthn session data is not present in order to handle attestation for user '%s'. This could indicate a user trying to POST to the wrong endpoint, or the session data is not present for the browser they used.", userSession.Username) + if userSession.WebAuthn == nil { + ctx.Logger.Errorf("WebAuthn session data is not present in order to handle attestation for user '%s'. This could indicate a user trying to POST to the wrong endpoint, or the session data is not present for the browser they used.", userSession.Username) respondUnauthorized(ctx, messageMFAValidationFailed) return } - if w, err = newWebauthn(ctx); err != nil { - ctx.Logger.Errorf("Unable to configure %s during assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + if w, err = newWebAuthn(ctx); err != nil { + ctx.Logger.Errorf("Unable to configure %s during assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageUnableToRegisterSecurityKey) @@ -127,7 +127,7 @@ func WebauthnAttestationPOST(ctx *middlewares.AutheliaCtx) { } if attestationResponse, err = protocol.ParseCredentialCreationResponseBody(bytes.NewReader(ctx.PostBody())); err != nil { - ctx.Logger.Errorf("Unable to parse %s assertionfor user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf("Unable to parse %s assertionfor user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -135,15 +135,15 @@ func WebauthnAttestationPOST(ctx *middlewares.AutheliaCtx) { } if user, err = getWebAuthnUser(ctx, userSession); err != nil { - ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) return } - if credential, err = w.CreateCredential(user, *userSession.Webauthn, attestationResponse); err != nil { - ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + if credential, err = w.CreateCredential(user, *userSession.WebAuthn, attestationResponse); err != nil { + ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -152,21 +152,21 @@ func WebauthnAttestationPOST(ctx *middlewares.AutheliaCtx) { device := model.NewWebAuthnDeviceFromCredential(w.Config.RPID, userSession.Username, "Primary", credential) - if err = ctx.Providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil { - ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + if err = ctx.Providers.StorageProvider.SaveWebAuthnDevice(ctx, device); err != nil { + ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) return } - userSession.Webauthn = nil + userSession.WebAuthn = nil if err = ctx.SaveSession(userSession); err != nil { - ctx.Logger.Errorf(logFmtErrSessionSave, "removal of the attestation challenge", regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf(logFmtErrSessionSave, "removal of the attestation challenge", regulation.AuthTypeWebAuthn, userSession.Username, err) } ctx.ReplyOK() ctx.SetStatusCode(fasthttp.StatusCreated) - ctxLogEvent(ctx, userSession.Username, "Second Factor Method Added", map[string]any{"Action": "Second Factor Method Added", "Category": "Webauthn Credential", "Device Name": "Primary"}) + ctxLogEvent(ctx, userSession.Username, "Second Factor Method Added", map[string]any{"Action": "Second Factor Method Added", "Category": "WebAuthn Credential", "Device Name": "Primary"}) } diff --git a/internal/handlers/handler_sign_webauthn.go b/internal/handlers/handler_sign_webauthn.go index cdd633a5b..6bb7e6f32 100644 --- a/internal/handlers/handler_sign_webauthn.go +++ b/internal/handlers/handler_sign_webauthn.go @@ -12,8 +12,8 @@ import ( "github.com/authelia/authelia/v4/internal/session" ) -// WebauthnAssertionGET handler starts the assertion ceremony. -func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) { +// WebAuthnAssertionGET handler starts the assertion ceremony. +func WebAuthnAssertionGET(ctx *middlewares.AutheliaCtx) { var ( w *webauthn.WebAuthn user *model.WebAuthnUser @@ -29,8 +29,8 @@ func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) { return } - if w, err = newWebauthn(ctx); err != nil { - ctx.Logger.Errorf("Unable to configure %s during assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + if w, err = newWebAuthn(ctx); err != nil { + ctx.Logger.Errorf("Unable to configure %s during assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -38,7 +38,7 @@ func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) { } if user, err = getWebAuthnUser(ctx, userSession); err != nil { - ctx.Logger.Errorf("Unable to create %s assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf("Unable to create %s assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -61,8 +61,8 @@ func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) { var assertion *protocol.CredentialAssertion - if assertion, userSession.Webauthn, err = w.BeginLogin(user, opts...); err != nil { - ctx.Logger.Errorf("Unable to create %s assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + if assertion, userSession.WebAuthn, err = w.BeginLogin(user, opts...); err != nil { + ctx.Logger.Errorf("Unable to create %s assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -70,7 +70,7 @@ func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) { } if err = ctx.SaveSession(userSession); err != nil { - ctx.Logger.Errorf(logFmtErrSessionSave, "assertion challenge", regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf(logFmtErrSessionSave, "assertion challenge", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -78,7 +78,7 @@ func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) { } if err = ctx.SetJSONBody(assertion); err != nil { - ctx.Logger.Errorf(logFmtErrWriteResponseBody, regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf(logFmtErrWriteResponseBody, regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -86,21 +86,21 @@ func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) { } } -// WebauthnAssertionPOST handler completes the assertion ceremony after verifying the challenge. +// WebAuthnAssertionPOST handler completes the assertion ceremony after verifying the challenge. // //nolint:gocyclo -func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) { +func WebAuthnAssertionPOST(ctx *middlewares.AutheliaCtx) { var ( userSession session.UserSession err error w *webauthn.WebAuthn - bodyJSON bodySignWebauthnRequest + bodyJSON bodySignWebAuthnRequest ) if err = ctx.ParseBody(&bodyJSON); err != nil { - ctx.Logger.Errorf(logFmtErrParseRequestBody, regulation.AuthTypeWebauthn, err) + ctx.Logger.Errorf(logFmtErrParseRequestBody, regulation.AuthTypeWebAuthn, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -115,16 +115,16 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) { return } - if userSession.Webauthn == nil { - ctx.Logger.Errorf("Webauthn session data is not present in order to handle assertion for user '%s'. This could indicate a user trying to POST to the wrong endpoint, or the session data is not present for the browser they used.", userSession.Username) + if userSession.WebAuthn == nil { + ctx.Logger.Errorf("WebAuthn session data is not present in order to handle assertion for user '%s'. This could indicate a user trying to POST to the wrong endpoint, or the session data is not present for the browser they used.", userSession.Username) respondUnauthorized(ctx, messageMFAValidationFailed) return } - if w, err = newWebauthn(ctx); err != nil { - ctx.Logger.Errorf("Unable to configure %s during assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + if w, err = newWebAuthn(ctx); err != nil { + ctx.Logger.Errorf("Unable to configure %s during assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -138,7 +138,7 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) { ) if assertionResponse, err = protocol.ParseCredentialRequestResponseBody(bytes.NewReader(ctx.PostBody())); err != nil { - ctx.Logger.Errorf("Unable to parse %s assertionfor user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf("Unable to parse %s assertionfor user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -146,15 +146,15 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) { } if user, err = getWebAuthnUser(ctx, userSession); err != nil { - ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf("Unable to load %s devices for assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) return } - if credential, err = w.ValidateLogin(user, *userSession.Webauthn, assertionResponse); err != nil { - _ = markAuthenticationAttempt(ctx, false, nil, userSession.Username, regulation.AuthTypeWebauthn, err) + if credential, err = w.ValidateLogin(user, *userSession.WebAuthn, assertionResponse); err != nil { + _ = markAuthenticationAttempt(ctx, false, nil, userSession.Username, regulation.AuthTypeWebAuthn, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -169,8 +169,8 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) { found = true - if err = ctx.Providers.StorageProvider.UpdateWebauthnDeviceSignIn(ctx, device.ID, device.RPID, device.LastUsedAt, device.SignCount, device.CloneWarning); err != nil { - ctx.Logger.Errorf("Unable to save %s device signin count for assertion challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) + if err = ctx.Providers.StorageProvider.UpdateWebAuthnDeviceSignIn(ctx, device.ID, device.RPID, device.LastUsedAt, device.SignCount, device.CloneWarning); err != nil { + ctx.Logger.Errorf("Unable to save %s device signin count for assertion challenge for user '%s': %+v", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -182,7 +182,7 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) { } if !found { - ctx.Logger.Errorf("Unable to save %s device signin count for assertion challenge for user '%s' device '%x' count '%d': unable to find device", regulation.AuthTypeWebauthn, userSession.Username, credential.ID, credential.Authenticator.SignCount) + ctx.Logger.Errorf("Unable to save %s device signin count for assertion challenge for user '%s' device '%x' count '%d': unable to find device", regulation.AuthTypeWebAuthn, userSession.Username, credential.ID, credential.Authenticator.SignCount) respondUnauthorized(ctx, messageMFAValidationFailed) @@ -190,25 +190,25 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) { } if err = ctx.RegenerateSession(); err != nil { - ctx.Logger.Errorf(logFmtErrSessionRegenerate, regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf(logFmtErrSessionRegenerate, regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) return } - if err = markAuthenticationAttempt(ctx, true, nil, userSession.Username, regulation.AuthTypeWebauthn, nil); err != nil { + if err = markAuthenticationAttempt(ctx, true, nil, userSession.Username, regulation.AuthTypeWebAuthn, nil); err != nil { respondUnauthorized(ctx, messageMFAValidationFailed) return } - userSession.SetTwoFactorWebauthn(ctx.Clock.Now(), + userSession.SetTwoFactorWebAuthn(ctx.Clock.Now(), assertionResponse.Response.AuthenticatorData.Flags.UserPresent(), assertionResponse.Response.AuthenticatorData.Flags.UserVerified()) if err = ctx.SaveSession(userSession); err != nil { - ctx.Logger.Errorf(logFmtErrSessionSave, "removal of the assertion challenge and authentication time", regulation.AuthTypeWebauthn, userSession.Username, err) + ctx.Logger.Errorf(logFmtErrSessionSave, "removal of the assertion challenge and authentication time", regulation.AuthTypeWebAuthn, userSession.Username, err) respondUnauthorized(ctx, messageMFAValidationFailed) diff --git a/internal/handlers/types.go b/internal/handlers/types.go index b69fbce95..986735499 100644 --- a/internal/handlers/types.go +++ b/internal/handlers/types.go @@ -30,8 +30,8 @@ type bodySignTOTPRequest struct { WorkflowID string `json:"workflowID"` } -// bodySignWebauthnRequest is the model of the request body of WebAuthn 2FA authentication endpoint. -type bodySignWebauthnRequest struct { +// bodySignWebAuthnRequest is the model of the request body of WebAuthn 2FA authentication endpoint. +type bodySignWebAuthnRequest struct { TargetURL string `json:"targetURL"` Workflow string `json:"workflow"` WorkflowID string `json:"workflowID"` diff --git a/internal/handlers/webauthn.go b/internal/handlers/webauthn.go index 8899fed79..94e3c7b86 100644 --- a/internal/handlers/webauthn.go +++ b/internal/handlers/webauthn.go @@ -22,14 +22,14 @@ func getWebAuthnUser(ctx *middlewares.AutheliaCtx, userSession session.UserSessi user.DisplayName = user.Username } - if user.Devices, err = ctx.Providers.StorageProvider.LoadWebauthnDevicesByUsername(ctx, userSession.Username); err != nil { + if user.Devices, err = ctx.Providers.StorageProvider.LoadWebAuthnDevicesByUsername(ctx, userSession.Username); err != nil { return nil, err } return user, nil } -func newWebauthn(ctx *middlewares.AutheliaCtx) (w *webauthn.WebAuthn, err error) { +func newWebAuthn(ctx *middlewares.AutheliaCtx) (w *webauthn.WebAuthn, err error) { var ( u *url.URL ) @@ -42,22 +42,22 @@ func newWebauthn(ctx *middlewares.AutheliaCtx) (w *webauthn.WebAuthn, err error) origin := fmt.Sprintf("%s://%s", u.Scheme, u.Host) config := &webauthn.Config{ - RPDisplayName: ctx.Configuration.Webauthn.DisplayName, + RPDisplayName: ctx.Configuration.WebAuthn.DisplayName, RPID: rpID, RPOrigin: origin, RPIcon: "", - AttestationPreference: ctx.Configuration.Webauthn.ConveyancePreference, + AttestationPreference: ctx.Configuration.WebAuthn.ConveyancePreference, AuthenticatorSelection: protocol.AuthenticatorSelection{ AuthenticatorAttachment: protocol.CrossPlatform, - UserVerification: ctx.Configuration.Webauthn.UserVerification, + UserVerification: ctx.Configuration.WebAuthn.UserVerification, RequireResidentKey: protocol.ResidentKeyNotRequired(), }, - Timeout: int(ctx.Configuration.Webauthn.Timeout.Milliseconds()), + Timeout: int(ctx.Configuration.WebAuthn.Timeout.Milliseconds()), } - ctx.Logger.Tracef("Creating new Webauthn RP instance with ID %s and Origins %s", config.RPID, config.RPOrigin) + ctx.Logger.Tracef("Creating new WebAuthn RP instance with ID %s and Origins %s", config.RPID, config.RPOrigin) return webauthn.New(config) } diff --git a/internal/handlers/webauthn_test.go b/internal/handlers/webauthn_test.go index cba439188..434ed496b 100644 --- a/internal/handlers/webauthn_test.go +++ b/internal/handlers/webauthn_test.go @@ -13,7 +13,7 @@ import ( "github.com/authelia/authelia/v4/internal/session" ) -func TestWebauthnGetUser(t *testing.T) { +func TestWebAuthnGetUser(t *testing.T) { ctx := mocks.NewMockAutheliaCtx(t) userSession := session.UserSession{ @@ -21,7 +21,7 @@ func TestWebauthnGetUser(t *testing.T) { DisplayName: "John Smith", } - ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return([]model.WebAuthnDevice{ + ctx.StorageMock.EXPECT().LoadWebAuthnDevicesByUsername(ctx.Ctx, "john").Return([]model.WebAuthnDevice{ { ID: 1, RPID: "https://example.com", @@ -99,14 +99,14 @@ func TestWebauthnGetUser(t *testing.T) { assert.Equal(t, protocol.AuthenticatorTransport("nfc"), descriptors[1].Transport[1]) } -func TestWebauthnGetUserWithoutDisplayName(t *testing.T) { +func TestWebAuthnGetUserWithoutDisplayName(t *testing.T) { ctx := mocks.NewMockAutheliaCtx(t) userSession := session.UserSession{ Username: "john", } - ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return([]model.WebAuthnDevice{ + ctx.StorageMock.EXPECT().LoadWebAuthnDevicesByUsername(ctx.Ctx, "john").Return([]model.WebAuthnDevice{ { ID: 1, RPID: "https://example.com", @@ -129,14 +129,14 @@ func TestWebauthnGetUserWithoutDisplayName(t *testing.T) { assert.Equal(t, "john", user.DisplayName) } -func TestWebauthnGetUserWithErr(t *testing.T) { +func TestWebAuthnGetUserWithErr(t *testing.T) { ctx := mocks.NewMockAutheliaCtx(t) userSession := session.UserSession{ Username: "john", } - ctx.StorageMock.EXPECT().LoadWebauthnDevicesByUsername(ctx.Ctx, "john").Return(nil, errors.New("not found")) + ctx.StorageMock.EXPECT().LoadWebAuthnDevicesByUsername(ctx.Ctx, "john").Return(nil, errors.New("not found")) user, err := getWebAuthnUser(ctx.Ctx, userSession) @@ -144,24 +144,24 @@ func TestWebauthnGetUserWithErr(t *testing.T) { assert.Nil(t, user) } -func TestWebauthnNewWebauthnShouldReturnErrWhenHeadersNotAvailable(t *testing.T) { +func TestWebAuthnNewWebAuthnShouldReturnErrWhenHeadersNotAvailable(t *testing.T) { ctx := mocks.NewMockAutheliaCtx(t) ctx.Ctx.Request.Header.Del("X-Forwarded-Host") - w, err := newWebauthn(ctx.Ctx) + w, err := newWebAuthn(ctx.Ctx) assert.Nil(t, w) assert.EqualError(t, err, "missing required X-Forwarded-Host header") } -func TestWebauthnNewWebauthnShouldReturnErrWhenWebauthnNotConfigured(t *testing.T) { +func TestWebAuthnNewWebAuthnShouldReturnErrWhenWebAuthnNotConfigured(t *testing.T) { ctx := mocks.NewMockAutheliaCtx(t) ctx.Ctx.Request.Header.Set("X-Forwarded-Host", "example.com") ctx.Ctx.Request.Header.Set("X-Forwarded-URI", "/") ctx.Ctx.Request.Header.Set("X-Forwarded-Proto", "https") - w, err := newWebauthn(ctx.Ctx) + w, err := newWebAuthn(ctx.Ctx) assert.Nil(t, w) assert.EqualError(t, err, "Configuration error: Missing RPDisplayName") diff --git a/internal/middlewares/authelia_context.go b/internal/middlewares/authelia_context.go index 4c6367d6b..e81d7b3b6 100644 --- a/internal/middlewares/authelia_context.go +++ b/internal/middlewares/authelia_context.go @@ -49,7 +49,7 @@ func (ctx *AutheliaCtx) AvailableSecondFactorMethods() (methods []string) { methods = append(methods, model.SecondFactorMethodTOTP) } - if !ctx.Configuration.Webauthn.Disable { + if !ctx.Configuration.WebAuthn.Disable { methods = append(methods, model.SecondFactorMethodWebAuthn) } diff --git a/internal/middlewares/authelia_context_test.go b/internal/middlewares/authelia_context_test.go index f53627abd..448113191 100644 --- a/internal/middlewares/authelia_context_test.go +++ b/internal/middlewares/authelia_context_test.go @@ -245,7 +245,7 @@ func TestShouldReturnCorrectSecondFactorMethods(t *testing.T) { assert.Equal(t, []string{model.SecondFactorMethodWebAuthn, model.SecondFactorMethodDuo}, mock.Ctx.AvailableSecondFactorMethods()) - mock.Ctx.Configuration.Webauthn.Disable = true + mock.Ctx.Configuration.WebAuthn.Disable = true assert.Equal(t, []string{model.SecondFactorMethodDuo}, mock.Ctx.AvailableSecondFactorMethods()) diff --git a/internal/mocks/storage.go b/internal/mocks/storage.go index 01a771fc8..c038ae7b7 100644 --- a/internal/mocks/storage.go +++ b/internal/mocks/storage.go @@ -39,7 +39,6 @@ func (m *MockStorage) EXPECT() *MockStorageMockRecorder { return m.recorder } - // AppendAuthenticationLog mocks base method. func (m *MockStorage) AppendAuthenticationLog(arg0 context.Context, arg1 model.AuthenticationAttempt) error { m.ctrl.T.Helper() @@ -167,32 +166,32 @@ func (mr *MockStorageMockRecorder) DeleteTOTPConfiguration(arg0, arg1 interface{ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTOTPConfiguration", reflect.TypeOf((*MockStorage)(nil).DeleteTOTPConfiguration), arg0, arg1) } -// DeleteWebauthnDevice mocks base method. -func (m *MockStorage) DeleteWebauthnDevice(arg0 context.Context, arg1 string) error { +// DeleteWebAuthnDevice mocks base method. +func (m *MockStorage) DeleteWebAuthnDevice(arg0 context.Context, arg1 string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteWebauthnDevice", arg0, arg1) + ret := m.ctrl.Call(m, "DeleteWebAuthnDevice", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } -// DeleteWebauthnDevice indicates an expected call of DeleteWebauthnDevice. -func (mr *MockStorageMockRecorder) DeleteWebauthnDevice(arg0, arg1 interface{}) *gomock.Call { +// DeleteWebAuthnDevice indicates an expected call of DeleteWebAuthnDevice. +func (mr *MockStorageMockRecorder) DeleteWebAuthnDevice(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteWebauthnDevice", reflect.TypeOf((*MockStorage)(nil).DeleteWebauthnDevice), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteWebAuthnDevice", reflect.TypeOf((*MockStorage)(nil).DeleteWebAuthnDevice), arg0, arg1) } -// DeleteWebauthnDeviceByUsername mocks base method. -func (m *MockStorage) DeleteWebauthnDeviceByUsername(arg0 context.Context, arg1, arg2 string) error { +// DeleteWebAuthnDeviceByUsername mocks base method. +func (m *MockStorage) DeleteWebAuthnDeviceByUsername(arg0 context.Context, arg1, arg2 string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteWebauthnDeviceByUsername", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "DeleteWebAuthnDeviceByUsername", arg0, arg1, arg2) ret0, _ := ret[0].(error) return ret0 } -// DeleteWebauthnDeviceByUsername indicates an expected call of DeleteWebauthnDeviceByUsername. -func (mr *MockStorageMockRecorder) DeleteWebauthnDeviceByUsername(arg0, arg1, arg2 interface{}) *gomock.Call { +// DeleteWebAuthnDeviceByUsername indicates an expected call of DeleteWebAuthnDeviceByUsername. +func (mr *MockStorageMockRecorder) DeleteWebAuthnDeviceByUsername(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteWebauthnDeviceByUsername", reflect.TypeOf((*MockStorage)(nil).DeleteWebauthnDeviceByUsername), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteWebAuthnDeviceByUsername", reflect.TypeOf((*MockStorage)(nil).DeleteWebAuthnDeviceByUsername), arg0, arg1, arg2) } // FindIdentityVerification mocks base method. @@ -420,34 +419,34 @@ func (mr *MockStorageMockRecorder) LoadUserOpaqueIdentifiers(arg0 interface{}) * return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadUserOpaqueIdentifiers", reflect.TypeOf((*MockStorage)(nil).LoadUserOpaqueIdentifiers), arg0) } -// LoadWebauthnDevices mocks base method. -func (m *MockStorage) LoadWebauthnDevices(arg0 context.Context, arg1, arg2 int) ([]model.WebAuthnDevice, error) { +// LoadWebAuthnDevices mocks base method. +func (m *MockStorage) LoadWebAuthnDevices(arg0 context.Context, arg1, arg2 int) ([]model.WebAuthnDevice, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadWebauthnDevices", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "LoadWebAuthnDevices", arg0, arg1, arg2) ret0, _ := ret[0].([]model.WebAuthnDevice) ret1, _ := ret[1].(error) return ret0, ret1 } -// LoadWebauthnDevices indicates an expected call of LoadWebauthnDevices. -func (mr *MockStorageMockRecorder) LoadWebauthnDevices(arg0, arg1, arg2 interface{}) *gomock.Call { +// LoadWebAuthnDevices indicates an expected call of LoadWebAuthnDevices. +func (mr *MockStorageMockRecorder) LoadWebAuthnDevices(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadWebauthnDevices", reflect.TypeOf((*MockStorage)(nil).LoadWebauthnDevices), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadWebAuthnDevices", reflect.TypeOf((*MockStorage)(nil).LoadWebAuthnDevices), arg0, arg1, arg2) } -// LoadWebauthnDevicesByUsername mocks base method. -func (m *MockStorage) LoadWebauthnDevicesByUsername(arg0 context.Context, arg1 string) ([]model.WebAuthnDevice, error) { +// LoadWebAuthnDevicesByUsername mocks base method. +func (m *MockStorage) LoadWebAuthnDevicesByUsername(arg0 context.Context, arg1 string) ([]model.WebAuthnDevice, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadWebauthnDevicesByUsername", arg0, arg1) + ret := m.ctrl.Call(m, "LoadWebAuthnDevicesByUsername", arg0, arg1) ret0, _ := ret[0].([]model.WebAuthnDevice) ret1, _ := ret[1].(error) return ret0, ret1 } -// LoadWebauthnDevicesByUsername indicates an expected call of LoadWebauthnDevicesByUsername. -func (mr *MockStorageMockRecorder) LoadWebauthnDevicesByUsername(arg0, arg1 interface{}) *gomock.Call { +// LoadWebAuthnDevicesByUsername indicates an expected call of LoadWebAuthnDevicesByUsername. +func (mr *MockStorageMockRecorder) LoadWebAuthnDevicesByUsername(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadWebauthnDevicesByUsername", reflect.TypeOf((*MockStorage)(nil).LoadWebauthnDevicesByUsername), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadWebAuthnDevicesByUsername", reflect.TypeOf((*MockStorage)(nil).LoadWebAuthnDevicesByUsername), arg0, arg1) } // RevokeOAuth2PARContext mocks base method. @@ -689,18 +688,18 @@ func (mr *MockStorageMockRecorder) SaveUserOpaqueIdentifier(arg0, arg1 interface return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveUserOpaqueIdentifier", reflect.TypeOf((*MockStorage)(nil).SaveUserOpaqueIdentifier), arg0, arg1) } -// SaveWebauthnDevice mocks base method. -func (m *MockStorage) SaveWebauthnDevice(arg0 context.Context, arg1 model.WebAuthnDevice) error { +// SaveWebAuthnDevice mocks base method. +func (m *MockStorage) SaveWebAuthnDevice(arg0 context.Context, arg1 model.WebAuthnDevice) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SaveWebauthnDevice", arg0, arg1) + ret := m.ctrl.Call(m, "SaveWebAuthnDevice", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } -// SaveWebauthnDevice indicates an expected call of SaveWebauthnDevice. -func (mr *MockStorageMockRecorder) SaveWebauthnDevice(arg0, arg1 interface{}) *gomock.Call { +// SaveWebAuthnDevice indicates an expected call of SaveWebAuthnDevice. +func (mr *MockStorageMockRecorder) SaveWebAuthnDevice(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveWebauthnDevice", reflect.TypeOf((*MockStorage)(nil).SaveWebauthnDevice), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveWebAuthnDevice", reflect.TypeOf((*MockStorage)(nil).SaveWebAuthnDevice), arg0, arg1) } // SchemaEncryptionChangeKey mocks base method. @@ -864,16 +863,16 @@ func (mr *MockStorageMockRecorder) UpdateTOTPConfigurationSignIn(arg0, arg1, arg return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTOTPConfigurationSignIn", reflect.TypeOf((*MockStorage)(nil).UpdateTOTPConfigurationSignIn), arg0, arg1, arg2) } -// UpdateWebauthnDeviceSignIn mocks base method. -func (m *MockStorage) UpdateWebauthnDeviceSignIn(arg0 context.Context, arg1 int, arg2 string, arg3 sql.NullTime, arg4 uint32, arg5 bool) error { +// UpdateWebAuthnDeviceSignIn mocks base method. +func (m *MockStorage) UpdateWebAuthnDeviceSignIn(arg0 context.Context, arg1 int, arg2 string, arg3 sql.NullTime, arg4 uint32, arg5 bool) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateWebauthnDeviceSignIn", arg0, arg1, arg2, arg3, arg4, arg5) + ret := m.ctrl.Call(m, "UpdateWebAuthnDeviceSignIn", arg0, arg1, arg2, arg3, arg4, arg5) ret0, _ := ret[0].(error) return ret0 } -// UpdateWebauthnDeviceSignIn indicates an expected call of UpdateWebauthnDeviceSignIn. -func (mr *MockStorageMockRecorder) UpdateWebauthnDeviceSignIn(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call { +// UpdateWebAuthnDeviceSignIn indicates an expected call of UpdateWebAuthnDeviceSignIn. +func (mr *MockStorageMockRecorder) UpdateWebAuthnDeviceSignIn(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateWebauthnDeviceSignIn", reflect.TypeOf((*MockStorage)(nil).UpdateWebauthnDeviceSignIn), arg0, arg1, arg2, arg3, arg4, arg5) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateWebAuthnDeviceSignIn", reflect.TypeOf((*MockStorage)(nil).UpdateWebAuthnDeviceSignIn), arg0, arg1, arg2, arg3, arg4, arg5) } diff --git a/internal/oidc/amr.go b/internal/oidc/amr.go index 4d1338886..cd2d8d6b0 100644 --- a/internal/oidc/amr.go +++ b/internal/oidc/amr.go @@ -5,9 +5,9 @@ type AuthenticationMethodsReferences struct { UsernameAndPassword bool TOTP bool Duo bool - Webauthn bool - WebauthnUserPresence bool - WebauthnUserVerified bool + WebAuthn bool + WebAuthnUserPresence bool + WebAuthnUserVerified bool } // FactorKnowledge returns true if a "something you know" factor of authentication was used. @@ -17,7 +17,7 @@ func (r AuthenticationMethodsReferences) FactorKnowledge() bool { // FactorPossession returns true if a "something you have" factor of authentication was used. func (r AuthenticationMethodsReferences) FactorPossession() bool { - return r.TOTP || r.Webauthn || r.Duo + return r.TOTP || r.WebAuthn || r.Duo } // MultiFactorAuthentication returns true if multiple factors were used. @@ -27,7 +27,7 @@ func (r AuthenticationMethodsReferences) MultiFactorAuthentication() bool { // ChannelBrowser returns true if a browser was used to authenticate. func (r AuthenticationMethodsReferences) ChannelBrowser() bool { - return r.UsernameAndPassword || r.TOTP || r.Webauthn + return r.UsernameAndPassword || r.TOTP || r.WebAuthn } // ChannelService returns true if a non-browser service was used to authenticate. @@ -57,15 +57,15 @@ func (r AuthenticationMethodsReferences) MarshalRFC8176() []string { amr = append(amr, AMRShortMessageService) } - if r.Webauthn { + if r.WebAuthn { amr = append(amr, AMRHardwareSecuredKey) } - if r.WebauthnUserPresence { + if r.WebAuthnUserPresence { amr = append(amr, AMRUserPresence) } - if r.WebauthnUserVerified { + if r.WebAuthnUserVerified { amr = append(amr, AMRPersonalIdentificationNumber) } diff --git a/internal/oidc/amr_test.go b/internal/oidc/amr_test.go index c71ca6a26..d1f382242 100644 --- a/internal/oidc/amr_test.go +++ b/internal/oidc/amr_test.go @@ -49,9 +49,9 @@ func TestAuthenticationMethodsReferences(t *testing.T) { }, }, { - desc: "Webauthn", + desc: "WebAuthn", - is: AuthenticationMethodsReferences{Webauthn: true}, + is: AuthenticationMethodsReferences{WebAuthn: true}, want: testAMRWant{ FactorKnowledge: false, FactorPossession: true, @@ -63,9 +63,9 @@ func TestAuthenticationMethodsReferences(t *testing.T) { }, }, { - desc: "Webauthn User Presence", + desc: "WebAuthn User Presence", - is: AuthenticationMethodsReferences{WebauthnUserPresence: true}, + is: AuthenticationMethodsReferences{WebAuthnUserPresence: true}, want: testAMRWant{ FactorKnowledge: false, FactorPossession: false, @@ -77,9 +77,9 @@ func TestAuthenticationMethodsReferences(t *testing.T) { }, }, { - desc: "Webauthn User Verified", + desc: "WebAuthn User Verified", - is: AuthenticationMethodsReferences{WebauthnUserVerified: true}, + is: AuthenticationMethodsReferences{WebAuthnUserVerified: true}, want: testAMRWant{ FactorKnowledge: false, FactorPossession: false, @@ -91,9 +91,9 @@ func TestAuthenticationMethodsReferences(t *testing.T) { }, }, { - desc: "Webauthn with User Presence and Verified", + desc: "WebAuthn with User Presence and Verified", - is: AuthenticationMethodsReferences{Webauthn: true, WebauthnUserVerified: true, WebauthnUserPresence: true}, + is: AuthenticationMethodsReferences{WebAuthn: true, WebAuthnUserVerified: true, WebAuthnUserPresence: true}, want: testAMRWant{ FactorKnowledge: false, FactorPossession: true, @@ -119,9 +119,9 @@ func TestAuthenticationMethodsReferences(t *testing.T) { }, }, { - desc: "Duo Webauthn TOTP", + desc: "Duo WebAuthn TOTP", - is: AuthenticationMethodsReferences{Duo: true, Webauthn: true, TOTP: true}, + is: AuthenticationMethodsReferences{Duo: true, WebAuthn: true, TOTP: true}, want: testAMRWant{ FactorKnowledge: false, FactorPossession: true, diff --git a/internal/oidc/const.go b/internal/oidc/const.go index 01670e317..3680923c3 100644 --- a/internal/oidc/const.go +++ b/internal/oidc/const.go @@ -195,7 +195,7 @@ const ( // a user presence test. Evidence that the end user is present and interacting with the device. This is sometimes // also referred to as "test of user presence" as per W3C.WD-webauthn-20170216. // - // Authelia utilizes this when a user has used Webauthn to authenticate and the user presence flag was set. + // Authelia utilizes this when a user has used WebAuthn to authenticate and the user presence flag was set. // Factor: Meta, Channel: Meta. // // RFC8176: https://datatracker.ietf.org/doc/html/rfc8176 @@ -208,7 +208,7 @@ const ( // containing only numbers) that a user enters to unlock a key on the device. This mechanism should have a way to // deter an attacker from obtaining the PIN by trying repeated guesses. // - // Authelia utilizes this when a user has used Webauthn to authenticate and the user verified flag was set. + // Authelia utilizes this when a user has used WebAuthn to authenticate and the user verified flag was set. // Factor: Meta, Channel: Meta. // // RFC8176: https://datatracker.ietf.org/doc/html/rfc8176 @@ -244,7 +244,7 @@ const ( // AMRHardwareSecuredKey is an RFC8176 Authentication Method Reference Value that // represents authentication via a proof-of-Possession (PoP) of a hardware-secured key. // - // Authelia utilizes this when a user has used Webauthn to authenticate. Factor: Have, Channel: Browser. + // Authelia utilizes this when a user has used WebAuthn to authenticate. Factor: Have, Channel: Browser. // // RFC8176: https://datatracker.ietf.org/doc/html/rfc8176 AMRHardwareSecuredKey = "hwk" diff --git a/internal/regulation/const.go b/internal/regulation/const.go index 91d93d809..bc0676371 100644 --- a/internal/regulation/const.go +++ b/internal/regulation/const.go @@ -12,8 +12,8 @@ const ( // AuthTypeTOTP is the string representing an auth log for second-factor authentication via TOTP. AuthTypeTOTP = "TOTP" - // AuthTypeWebauthn is the string representing an auth log for second-factor authentication via FIDO2/CTAP2/WebAuthn. - AuthTypeWebauthn = "Webauthn" + // AuthTypeWebAuthn is the string representing an auth log for second-factor authentication via FIDO2/CTAP2/WebAuthn. + AuthTypeWebAuthn = "WebAuthn" // AuthTypeDuo is the string representing an auth log for second-factor authentication via DUO. AuthTypeDuo = "Duo" diff --git a/internal/server/handlers.go b/internal/server/handlers.go index f2ddbea66..402761edc 100644 --- a/internal/server/handlers.go +++ b/internal/server/handlers.go @@ -255,14 +255,14 @@ func handleRouter(config *schema.Configuration, providers middlewares.Providers) r.POST("/api/secondfactor/totp", middleware1FA(handlers.TimeBasedOneTimePasswordPOST)) } - if !config.Webauthn.Disable { - // Webauthn Endpoints. + if !config.WebAuthn.Disable { + // WebAuthn Endpoints. r.POST("/api/secondfactor/webauthn/identity/start", middleware1FA(handlers.WebauthnIdentityStart)) r.POST("/api/secondfactor/webauthn/identity/finish", middleware1FA(handlers.WebauthnIdentityFinish)) - r.POST("/api/secondfactor/webauthn/attestation", middleware1FA(handlers.WebauthnAttestationPOST)) + r.POST("/api/secondfactor/webauthn/attestation", middleware1FA(handlers.WebAuthnAttestationPOST)) - r.GET("/api/secondfactor/webauthn/assertion", middleware1FA(handlers.WebauthnAssertionGET)) - r.POST("/api/secondfactor/webauthn/assertion", middleware1FA(handlers.WebauthnAssertionPOST)) + r.GET("/api/secondfactor/webauthn/assertion", middleware1FA(handlers.WebAuthnAssertionGET)) + r.POST("/api/secondfactor/webauthn/assertion", middleware1FA(handlers.WebAuthnAssertionPOST)) } // Configure DUO api endpoint only if configuration exists. diff --git a/internal/server/template.go b/internal/server/template.go index 57a120c01..91fcd2a80 100644 --- a/internal/server/template.go +++ b/internal/server/template.go @@ -272,7 +272,7 @@ func NewTemplatedFileOptions(config *schema.Configuration) (opts *TemplatedFileO Theme: config.Theme, EndpointsPasswordReset: !(config.AuthenticationBackend.PasswordReset.Disable || config.AuthenticationBackend.PasswordReset.CustomURL.String() != ""), - EndpointsWebauthn: !config.Webauthn.Disable, + EndpointsWebAuthn: !config.WebAuthn.Disable, EndpointsTOTP: !config.TOTP.Disable, EndpointsDuo: !config.DuoAPI.Disable, EndpointsOpenIDConnect: !(config.IdentityProviders.OIDC == nil), @@ -304,7 +304,7 @@ type TemplatedFileOptions struct { Theme string EndpointsPasswordReset bool - EndpointsWebauthn bool + EndpointsWebAuthn bool EndpointsTOTP bool EndpointsDuo bool EndpointsOpenIDConnect bool @@ -362,7 +362,7 @@ func (options *TemplatedFileOptions) OpenAPIData(base, baseURL, domain, nonce st Session: options.Session, PasswordReset: options.EndpointsPasswordReset, - Webauthn: options.EndpointsWebauthn, + WebAuthn: options.EndpointsWebAuthn, TOTP: options.EndpointsTOTP, Duo: options.EndpointsDuo, OpenIDConnect: options.EndpointsOpenIDConnect, @@ -395,7 +395,7 @@ type TemplatedFileOpenAPIData struct { CSPNonce string Session string PasswordReset bool - Webauthn bool + WebAuthn bool TOTP bool Duo bool OpenIDConnect bool diff --git a/internal/session/provider_test.go b/internal/session/provider_test.go index 4073ad546..c6c09cf7d 100644 --- a/internal/session/provider_test.go +++ b/internal/session/provider_test.go @@ -179,7 +179,7 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { AuthenticationMethodRefs: oidc.AuthenticationMethodsReferences{UsernameAndPassword: true}, }, session) - session.SetTwoFactorWebauthn(timeTwoFactor, false, false) + session.SetTwoFactorWebAuthn(timeTwoFactor, false, false) err = provider.SaveSession(ctx, session) assert.NoError(t, err) @@ -187,7 +187,7 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { session, err = provider.GetSession(ctx) assert.NoError(t, err) - assert.Equal(t, oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, Webauthn: true}, session.AuthenticationMethodRefs) + assert.Equal(t, oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, WebAuthn: true}, session.AuthenticationMethodRefs) assert.True(t, session.AuthenticationMethodRefs.MultiFactorAuthentication()) authAt, err = session.AuthenticatedTime(authorization.OneFactor) @@ -202,7 +202,7 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { assert.EqualError(t, err, "invalid authorization level") assert.Equal(t, timeZeroFactor, authAt) - session.SetTwoFactorWebauthn(timeTwoFactor, false, false) + session.SetTwoFactorWebAuthn(timeTwoFactor, false, false) err = provider.SaveSession(ctx, session) assert.NoError(t, err) @@ -211,10 +211,10 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { assert.NoError(t, err) assert.Equal(t, - oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, Webauthn: true}, + oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, WebAuthn: true}, session.AuthenticationMethodRefs) - session.SetTwoFactorWebauthn(timeTwoFactor, false, false) + session.SetTwoFactorWebAuthn(timeTwoFactor, false, false) err = provider.SaveSession(ctx, session) assert.NoError(t, err) @@ -223,10 +223,10 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { assert.NoError(t, err) assert.Equal(t, - oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, Webauthn: true}, + oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, WebAuthn: true}, session.AuthenticationMethodRefs) - session.SetTwoFactorWebauthn(timeTwoFactor, true, false) + session.SetTwoFactorWebAuthn(timeTwoFactor, true, false) err = provider.SaveSession(ctx, session) assert.NoError(t, err) @@ -235,10 +235,10 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { assert.NoError(t, err) assert.Equal(t, - oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, Webauthn: true, WebauthnUserPresence: true}, + oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, WebAuthn: true, WebAuthnUserPresence: true}, session.AuthenticationMethodRefs) - session.SetTwoFactorWebauthn(timeTwoFactor, true, false) + session.SetTwoFactorWebAuthn(timeTwoFactor, true, false) err = provider.SaveSession(ctx, session) assert.NoError(t, err) @@ -247,10 +247,10 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { assert.NoError(t, err) assert.Equal(t, - oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, Webauthn: true, WebauthnUserPresence: true}, + oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, WebAuthn: true, WebAuthnUserPresence: true}, session.AuthenticationMethodRefs) - session.SetTwoFactorWebauthn(timeTwoFactor, false, true) + session.SetTwoFactorWebAuthn(timeTwoFactor, false, true) err = provider.SaveSession(ctx, session) assert.NoError(t, err) @@ -259,10 +259,10 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { assert.NoError(t, err) assert.Equal(t, - oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, Webauthn: true, WebauthnUserVerified: true}, + oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, WebAuthn: true, WebAuthnUserVerified: true}, session.AuthenticationMethodRefs) - session.SetTwoFactorWebauthn(timeTwoFactor, false, true) + session.SetTwoFactorWebAuthn(timeTwoFactor, false, true) err = provider.SaveSession(ctx, session) assert.NoError(t, err) @@ -271,7 +271,7 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { assert.NoError(t, err) assert.Equal(t, - oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, Webauthn: true, WebauthnUserVerified: true}, + oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, WebAuthn: true, WebAuthnUserVerified: true}, session.AuthenticationMethodRefs) session.SetTwoFactorTOTP(timeTwoFactor) @@ -283,7 +283,7 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { assert.NoError(t, err) assert.Equal(t, - oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, TOTP: true, Webauthn: true, WebauthnUserVerified: true}, + oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, TOTP: true, WebAuthn: true, WebAuthnUserVerified: true}, session.AuthenticationMethodRefs) session.SetTwoFactorTOTP(timeTwoFactor) @@ -295,7 +295,7 @@ func TestShouldSetSessionAuthenticationLevelsAMR(t *testing.T) { assert.NoError(t, err) assert.Equal(t, - oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, TOTP: true, Webauthn: true, WebauthnUserVerified: true}, + oidc.AuthenticationMethodsReferences{UsernameAndPassword: true, TOTP: true, WebAuthn: true, WebAuthnUserVerified: true}, session.AuthenticationMethodRefs) } diff --git a/internal/session/types.go b/internal/session/types.go index 9fc7bd5b4..1a41cb2bd 100644 --- a/internal/session/types.go +++ b/internal/session/types.go @@ -35,8 +35,8 @@ type UserSession struct { AuthenticationMethodRefs oidc.AuthenticationMethodsReferences - // Webauthn holds the session registration data for this session. - Webauthn *webauthn.SessionData + // WebAuthn holds the session registration data for this session. + WebAuthn *webauthn.SessionData // This boolean is set to true after identity verification and checked // while doing the query actually updating the password. diff --git a/internal/session/user_session.go b/internal/session/user_session.go index 88511eb5d..6a2fa3c22 100644 --- a/internal/session/user_session.go +++ b/internal/session/user_session.go @@ -56,13 +56,13 @@ func (s *UserSession) SetTwoFactorDuo(now time.Time) { s.AuthenticationMethodRefs.Duo = true } -// SetTwoFactorWebauthn sets the relevant Webauthn AMR's and sets the factor to 2FA. -func (s *UserSession) SetTwoFactorWebauthn(now time.Time, userPresence, userVerified bool) { +// SetTwoFactorWebAuthn sets the relevant WebAuthn AMR's and sets the factor to 2FA. +func (s *UserSession) SetTwoFactorWebAuthn(now time.Time, userPresence, userVerified bool) { s.setTwoFactor(now) - s.AuthenticationMethodRefs.Webauthn = true - s.AuthenticationMethodRefs.WebauthnUserPresence, s.AuthenticationMethodRefs.WebauthnUserVerified = userPresence, userVerified + s.AuthenticationMethodRefs.WebAuthn = true + s.AuthenticationMethodRefs.WebAuthnUserPresence, s.AuthenticationMethodRefs.WebAuthnUserVerified = userPresence, userVerified - s.Webauthn = nil + s.WebAuthn = nil } // AuthenticatedTime returns the unix timestamp this session authenticated successfully at the given level. diff --git a/internal/storage/const.go b/internal/storage/const.go index a5e4bf8ae..286d39620 100644 --- a/internal/storage/const.go +++ b/internal/storage/const.go @@ -11,7 +11,7 @@ const ( tableTOTPConfigurations = "totp_configurations" tableUserOpaqueIdentifier = "user_opaque_identifier" tableUserPreferences = "user_preferences" - tableWebauthnDevices = "webauthn_devices" + tableWebAuthnDevices = "webauthn_devices" tableOAuth2BlacklistedJTI = "oauth2_blacklisted_jti" tableOAuth2ConsentSession = "oauth2_consent_session" diff --git a/internal/storage/errors.go b/internal/storage/errors.go index f3098f643..412a4b5ac 100644 --- a/internal/storage/errors.go +++ b/internal/storage/errors.go @@ -11,8 +11,8 @@ var ( // ErrNoTOTPConfiguration error thrown when no TOTP configuration has been found in DB. ErrNoTOTPConfiguration = errors.New("no TOTP configuration for user") - // ErrNoWebauthnDevice error thrown when no Webauthn device handle has been found in DB. - ErrNoWebauthnDevice = errors.New("no Webauthn device found") + // ErrNoWebAuthnDevice error thrown when no WebAuthn device handle has been found in DB. + ErrNoWebAuthnDevice = errors.New("no WebAuthn device found") // ErrNoDuoDevice error thrown when no Duo device and method has been found in DB. ErrNoDuoDevice = errors.New("no Duo device and method saved") diff --git a/internal/storage/provider.go b/internal/storage/provider.go index 68e939a04..651cdadfa 100644 --- a/internal/storage/provider.go +++ b/internal/storage/provider.go @@ -38,12 +38,12 @@ type Provider interface { LoadTOTPConfiguration(ctx context.Context, username string) (config *model.TOTPConfiguration, err error) LoadTOTPConfigurations(ctx context.Context, limit, page int) (configs []model.TOTPConfiguration, err error) - SaveWebauthnDevice(ctx context.Context, device model.WebAuthnDevice) (err error) - UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt sql.NullTime, signCount uint32, cloneWarning bool) (err error) - DeleteWebauthnDevice(ctx context.Context, kid string) (err error) - DeleteWebauthnDeviceByUsername(ctx context.Context, username, description string) (err error) - LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebAuthnDevice, err error) - LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebAuthnDevice, err error) + SaveWebAuthnDevice(ctx context.Context, device model.WebAuthnDevice) (err error) + UpdateWebAuthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt sql.NullTime, signCount uint32, cloneWarning bool) (err error) + DeleteWebAuthnDevice(ctx context.Context, kid string) (err error) + DeleteWebAuthnDeviceByUsername(ctx context.Context, username, description string) (err error) + LoadWebAuthnDevices(ctx context.Context, limit, page int) (devices []model.WebAuthnDevice, err error) + LoadWebAuthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebAuthnDevice, err error) SavePreferredDuoDevice(ctx context.Context, device model.DuoDevice) (err error) DeletePreferredDuoDevice(ctx context.Context, username string) (err error) diff --git a/internal/storage/sql_provider.go b/internal/storage/sql_provider.go index 7467114a8..0c4d6376e 100644 --- a/internal/storage/sql_provider.go +++ b/internal/storage/sql_provider.go @@ -46,16 +46,16 @@ func NewSQLProvider(config *schema.Configuration, name, driverName, dataSourceNa sqlUpdateTOTPConfigRecordSignIn: fmt.Sprintf(queryFmtUpdateTOTPConfigRecordSignIn, tableTOTPConfigurations), sqlUpdateTOTPConfigRecordSignInByUsername: fmt.Sprintf(queryFmtUpdateTOTPConfigRecordSignInByUsername, tableTOTPConfigurations), - sqlUpsertWebauthnDevice: fmt.Sprintf(queryFmtUpsertWebauthnDevice, tableWebauthnDevices), - sqlSelectWebauthnDevices: fmt.Sprintf(queryFmtSelectWebauthnDevices, tableWebauthnDevices), - sqlSelectWebauthnDevicesByUsername: fmt.Sprintf(queryFmtSelectWebauthnDevicesByUsername, tableWebauthnDevices), + sqlUpsertWebAuthnDevice: fmt.Sprintf(queryFmtUpsertWebAuthnDevice, tableWebAuthnDevices), + sqlSelectWebAuthnDevices: fmt.Sprintf(queryFmtSelectWebAuthnDevices, tableWebAuthnDevices), + sqlSelectWebAuthnDevicesByUsername: fmt.Sprintf(queryFmtSelectWebAuthnDevicesByUsername, tableWebAuthnDevices), - sqlUpdateWebauthnDeviceRecordSignIn: fmt.Sprintf(queryFmtUpdateWebauthnDeviceRecordSignIn, tableWebauthnDevices), - sqlUpdateWebauthnDeviceRecordSignInByUsername: fmt.Sprintf(queryFmtUpdateWebauthnDeviceRecordSignInByUsername, tableWebauthnDevices), + sqlUpdateWebAuthnDeviceRecordSignIn: fmt.Sprintf(queryFmtUpdateWebAuthnDeviceRecordSignIn, tableWebAuthnDevices), + sqlUpdateWebAuthnDeviceRecordSignInByUsername: fmt.Sprintf(queryFmtUpdateWebAuthnDeviceRecordSignInByUsername, tableWebAuthnDevices), - sqlDeleteWebauthnDevice: fmt.Sprintf(queryFmtDeleteWebauthnDevice, tableWebauthnDevices), - sqlDeleteWebauthnDeviceByUsername: fmt.Sprintf(queryFmtDeleteWebauthnDeviceByUsername, tableWebauthnDevices), - sqlDeleteWebauthnDeviceByUsernameAndDescription: fmt.Sprintf(queryFmtDeleteWebauthnDeviceByUsernameAndDescription, tableWebauthnDevices), + sqlDeleteWebAuthnDevice: fmt.Sprintf(queryFmtDeleteWebAuthnDevice, tableWebAuthnDevices), + sqlDeleteWebAuthnDeviceByUsername: fmt.Sprintf(queryFmtDeleteWebAuthnDeviceByUsername, tableWebAuthnDevices), + sqlDeleteWebAuthnDeviceByUsernameAndDescription: fmt.Sprintf(queryFmtDeleteWebAuthnDeviceByUsernameAndDescription, tableWebAuthnDevices), sqlUpsertDuoDevice: fmt.Sprintf(queryFmtUpsertDuoDevice, tableDuoDevices), sqlDeleteDuoDevice: fmt.Sprintf(queryFmtDeleteDuoDevice, tableDuoDevices), @@ -63,7 +63,7 @@ func NewSQLProvider(config *schema.Configuration, name, driverName, dataSourceNa sqlUpsertPreferred2FAMethod: fmt.Sprintf(queryFmtUpsertPreferred2FAMethod, tableUserPreferences), sqlSelectPreferred2FAMethod: fmt.Sprintf(queryFmtSelectPreferred2FAMethod, tableUserPreferences), - sqlSelectUserInfo: fmt.Sprintf(queryFmtSelectUserInfo, tableTOTPConfigurations, tableWebauthnDevices, tableDuoDevices, tableUserPreferences), + sqlSelectUserInfo: fmt.Sprintf(queryFmtSelectUserInfo, tableTOTPConfigurations, tableWebAuthnDevices, tableDuoDevices, tableUserPreferences), sqlInsertUserOpaqueIdentifier: fmt.Sprintf(queryFmtInsertUserOpaqueIdentifier, tableUserOpaqueIdentifier), sqlSelectUserOpaqueIdentifier: fmt.Sprintf(queryFmtSelectUserOpaqueIdentifier, tableUserOpaqueIdentifier), @@ -165,16 +165,16 @@ type SQLProvider struct { sqlUpdateTOTPConfigRecordSignInByUsername string // Table: webauthn_devices. - sqlUpsertWebauthnDevice string - sqlSelectWebauthnDevices string - sqlSelectWebauthnDevicesByUsername string + sqlUpsertWebAuthnDevice string + sqlSelectWebAuthnDevices string + sqlSelectWebAuthnDevicesByUsername string - sqlUpdateWebauthnDeviceRecordSignIn string - sqlUpdateWebauthnDeviceRecordSignInByUsername string + sqlUpdateWebAuthnDeviceRecordSignIn string + sqlUpdateWebAuthnDeviceRecordSignInByUsername string - sqlDeleteWebauthnDevice string - sqlDeleteWebauthnDeviceByUsername string - sqlDeleteWebauthnDeviceByUsernameAndDescription string + sqlDeleteWebAuthnDevice string + sqlDeleteWebAuthnDeviceByUsername string + sqlDeleteWebAuthnDeviceByUsernameAndDescription string // Table: duo_devices. sqlUpsertDuoDevice string @@ -823,7 +823,7 @@ func (p *SQLProvider) SaveTOTPConfiguration(ctx context.Context, config model.TO return nil } -// UpdateTOTPConfigurationSignIn updates a registered Webauthn devices sign in information. +// UpdateTOTPConfigurationSignIn updates a registered WebAuthn devices sign in information. func (p *SQLProvider) UpdateTOTPConfigurationSignIn(ctx context.Context, id int, lastUsedAt sql.NullTime) (err error) { if _, err = p.db.ExecContext(ctx, p.sqlUpdateTOTPConfigRecordSignIn, lastUsedAt, id); err != nil { return fmt.Errorf("error updating TOTP configuration id %d: %w", id, err) @@ -881,95 +881,95 @@ func (p *SQLProvider) LoadTOTPConfigurations(ctx context.Context, limit, page in return configs, nil } -// SaveWebauthnDevice saves a registered Webauthn device. -func (p *SQLProvider) SaveWebauthnDevice(ctx context.Context, device model.WebAuthnDevice) (err error) { +// SaveWebAuthnDevice saves a registered WebAuthn device. +func (p *SQLProvider) SaveWebAuthnDevice(ctx context.Context, device model.WebAuthnDevice) (err error) { if device.PublicKey, err = p.encrypt(device.PublicKey); err != nil { - return fmt.Errorf("error encrypting Webauthn device public key for user '%s' kid '%x': %w", device.Username, device.KID, err) + return fmt.Errorf("error encrypting WebAuthn device public key for user '%s' kid '%x': %w", device.Username, device.KID, err) } - if _, err = p.db.ExecContext(ctx, p.sqlUpsertWebauthnDevice, + if _, err = p.db.ExecContext(ctx, p.sqlUpsertWebAuthnDevice, device.CreatedAt, device.LastUsedAt, device.RPID, device.Username, device.Description, device.KID, device.PublicKey, device.AttestationType, device.Transport, device.AAGUID, device.SignCount, device.CloneWarning, ); err != nil { - return fmt.Errorf("error upserting Webauthn device for user '%s' kid '%x': %w", device.Username, device.KID, err) + return fmt.Errorf("error upserting WebAuthn device for user '%s' kid '%x': %w", device.Username, device.KID, err) } return nil } -// UpdateWebauthnDeviceSignIn updates a registered Webauthn devices sign in information. -func (p *SQLProvider) UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt sql.NullTime, signCount uint32, cloneWarning bool) (err error) { - if _, err = p.db.ExecContext(ctx, p.sqlUpdateWebauthnDeviceRecordSignIn, rpid, lastUsedAt, signCount, cloneWarning, id); err != nil { - return fmt.Errorf("error updating Webauthn signin metadata for id '%x': %w", id, err) +// UpdateWebAuthnDeviceSignIn updates a registered WebAuthn devices sign in information. +func (p *SQLProvider) UpdateWebAuthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt sql.NullTime, signCount uint32, cloneWarning bool) (err error) { + if _, err = p.db.ExecContext(ctx, p.sqlUpdateWebAuthnDeviceRecordSignIn, rpid, lastUsedAt, signCount, cloneWarning, id); err != nil { + return fmt.Errorf("error updating WebAuthn signin metadata for id '%x': %w", id, err) } return nil } -// DeleteWebauthnDevice deletes a registered Webauthn device. -func (p *SQLProvider) DeleteWebauthnDevice(ctx context.Context, kid string) (err error) { - if _, err = p.db.ExecContext(ctx, p.sqlDeleteWebauthnDevice, kid); err != nil { - return fmt.Errorf("error deleting webauthn device with kid '%s': %w", kid, err) +// DeleteWebAuthnDevice deletes a registered WebAuthn device. +func (p *SQLProvider) DeleteWebAuthnDevice(ctx context.Context, kid string) (err error) { + if _, err = p.db.ExecContext(ctx, p.sqlDeleteWebAuthnDevice, kid); err != nil { + return fmt.Errorf("error deleting WebAuthn device with kid '%s': %w", kid, err) } return nil } -// DeleteWebauthnDeviceByUsername deletes registered Webauthn devices by username or username and description. -func (p *SQLProvider) DeleteWebauthnDeviceByUsername(ctx context.Context, username, description string) (err error) { +// DeleteWebAuthnDeviceByUsername deletes registered WebAuthn devices by username or username and description. +func (p *SQLProvider) DeleteWebAuthnDeviceByUsername(ctx context.Context, username, description string) (err error) { if len(username) == 0 { - return fmt.Errorf("error deleting webauthn device with username '%s' and description '%s': username must not be empty", username, description) + return fmt.Errorf("error deleting WebAuthn device with username '%s' and description '%s': username must not be empty", username, description) } if len(description) == 0 { - if _, err = p.db.ExecContext(ctx, p.sqlDeleteWebauthnDeviceByUsername, username); err != nil { - return fmt.Errorf("error deleting webauthn devices for username '%s': %w", username, err) + if _, err = p.db.ExecContext(ctx, p.sqlDeleteWebAuthnDeviceByUsername, username); err != nil { + return fmt.Errorf("error deleting WebAuthn devices for username '%s': %w", username, err) } } else { - if _, err = p.db.ExecContext(ctx, p.sqlDeleteWebauthnDeviceByUsernameAndDescription, username, description); err != nil { - return fmt.Errorf("error deleting webauthn device with username '%s' and description '%s': %w", username, description, err) + if _, err = p.db.ExecContext(ctx, p.sqlDeleteWebAuthnDeviceByUsernameAndDescription, username, description); err != nil { + return fmt.Errorf("error deleting WebAuthn device with username '%s' and description '%s': %w", username, description, err) } } return nil } -// LoadWebauthnDevices loads Webauthn device registrations. -func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebAuthnDevice, err error) { +// LoadWebAuthnDevices loads WebAuthn device registrations. +func (p *SQLProvider) LoadWebAuthnDevices(ctx context.Context, limit, page int) (devices []model.WebAuthnDevice, err error) { devices = make([]model.WebAuthnDevice, 0, limit) - if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebauthnDevices, limit, limit*page); err != nil { + if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebAuthnDevices, limit, limit*page); err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, nil } - return nil, fmt.Errorf("error selecting Webauthn devices: %w", err) + return nil, fmt.Errorf("error selecting WebAuthn devices: %w", err) } for i, device := range devices { if devices[i].PublicKey, err = p.decrypt(device.PublicKey); err != nil { - return nil, fmt.Errorf("error decrypting Webauthn public key for user '%s': %w", device.Username, err) + return nil, fmt.Errorf("error decrypting WebAuthn public key for user '%s': %w", device.Username, err) } } return devices, nil } -// LoadWebauthnDevicesByUsername loads all webauthn devices registration for a given username. -func (p *SQLProvider) LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebAuthnDevice, err error) { - if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebauthnDevicesByUsername, username); err != nil { +// LoadWebAuthnDevicesByUsername loads all WebAuthn devices registration for a given username. +func (p *SQLProvider) LoadWebAuthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebAuthnDevice, err error) { + if err = p.db.SelectContext(ctx, &devices, p.sqlSelectWebAuthnDevicesByUsername, username); err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, ErrNoWebauthnDevice + return nil, ErrNoWebAuthnDevice } - return nil, fmt.Errorf("error selecting Webauthn devices for user '%s': %w", username, err) + return nil, fmt.Errorf("error selecting WebAuthn devices for user '%s': %w", username, err) } for i, device := range devices { if devices[i].PublicKey, err = p.decrypt(device.PublicKey); err != nil { - return nil, fmt.Errorf("error decrypting Webauthn public key for user '%s': %w", username, err) + return nil, fmt.Errorf("error decrypting WebAuthn public key for user '%s': %w", username, err) } } diff --git a/internal/storage/sql_provider_backend_postgres.go b/internal/storage/sql_provider_backend_postgres.go index bc6387a38..252ec3e0e 100644 --- a/internal/storage/sql_provider_backend_postgres.go +++ b/internal/storage/sql_provider_backend_postgres.go @@ -31,7 +31,7 @@ func NewPostgreSQLProvider(config *schema.Configuration, caCertPool *x509.CertPo // Specific alterations to this provider. // PostgreSQL doesn't have a UPSERT statement but has an ON CONFLICT operation instead. - provider.sqlUpsertWebauthnDevice = fmt.Sprintf(queryFmtUpsertWebauthnDevicePostgreSQL, tableWebauthnDevices) + provider.sqlUpsertWebAuthnDevice = fmt.Sprintf(queryFmtUpsertWebAuthnDevicePostgreSQL, tableWebAuthnDevices) provider.sqlUpsertDuoDevice = fmt.Sprintf(queryFmtUpsertDuoDevicePostgreSQL, tableDuoDevices) provider.sqlUpsertTOTPConfig = fmt.Sprintf(queryFmtUpsertTOTPConfigurationPostgreSQL, tableTOTPConfigurations) provider.sqlUpsertPreferred2FAMethod = fmt.Sprintf(queryFmtUpsertPreferred2FAMethodPostgreSQL, tableUserPreferences) @@ -59,13 +59,13 @@ func NewPostgreSQLProvider(config *schema.Configuration, caCertPool *x509.CertPo provider.sqlDeleteTOTPConfig = provider.db.Rebind(provider.sqlDeleteTOTPConfig) provider.sqlSelectTOTPConfigs = provider.db.Rebind(provider.sqlSelectTOTPConfigs) - provider.sqlSelectWebauthnDevices = provider.db.Rebind(provider.sqlSelectWebauthnDevices) - provider.sqlSelectWebauthnDevicesByUsername = provider.db.Rebind(provider.sqlSelectWebauthnDevicesByUsername) - provider.sqlUpdateWebauthnDeviceRecordSignIn = provider.db.Rebind(provider.sqlUpdateWebauthnDeviceRecordSignIn) - provider.sqlUpdateWebauthnDeviceRecordSignInByUsername = provider.db.Rebind(provider.sqlUpdateWebauthnDeviceRecordSignInByUsername) - provider.sqlDeleteWebauthnDevice = provider.db.Rebind(provider.sqlDeleteWebauthnDevice) - provider.sqlDeleteWebauthnDeviceByUsername = provider.db.Rebind(provider.sqlDeleteWebauthnDeviceByUsername) - provider.sqlDeleteWebauthnDeviceByUsernameAndDescription = provider.db.Rebind(provider.sqlDeleteWebauthnDeviceByUsernameAndDescription) + provider.sqlSelectWebAuthnDevices = provider.db.Rebind(provider.sqlSelectWebAuthnDevices) + provider.sqlSelectWebAuthnDevicesByUsername = provider.db.Rebind(provider.sqlSelectWebAuthnDevicesByUsername) + provider.sqlUpdateWebAuthnDeviceRecordSignIn = provider.db.Rebind(provider.sqlUpdateWebAuthnDeviceRecordSignIn) + provider.sqlUpdateWebAuthnDeviceRecordSignInByUsername = provider.db.Rebind(provider.sqlUpdateWebAuthnDeviceRecordSignInByUsername) + provider.sqlDeleteWebAuthnDevice = provider.db.Rebind(provider.sqlDeleteWebAuthnDevice) + provider.sqlDeleteWebAuthnDeviceByUsername = provider.db.Rebind(provider.sqlDeleteWebAuthnDeviceByUsername) + provider.sqlDeleteWebAuthnDeviceByUsernameAndDescription = provider.db.Rebind(provider.sqlDeleteWebAuthnDeviceByUsernameAndDescription) provider.sqlSelectDuoDevice = provider.db.Rebind(provider.sqlSelectDuoDevice) provider.sqlDeleteDuoDevice = provider.db.Rebind(provider.sqlDeleteDuoDevice) diff --git a/internal/storage/sql_provider_encryption.go b/internal/storage/sql_provider_encryption.go index 29d334510..858ad6efa 100644 --- a/internal/storage/sql_provider_encryption.go +++ b/internal/storage/sql_provider_encryption.go @@ -34,7 +34,7 @@ func (p *SQLProvider) SchemaEncryptionChangeKey(ctx context.Context, key string) encChangeFuncs := []EncryptionChangeKeyFunc{ schemaEncryptionChangeKeyTOTP, - schemaEncryptionChangeKeyWebauthn, + schemaEncryptionChangeKeyWebAuthn, } for i := 0; true; i++ { @@ -90,7 +90,7 @@ func (p *SQLProvider) SchemaEncryptionCheckKey(ctx context.Context, verbose bool if verbose { encCheckFuncs := []EncryptionCheckKeyFunc{ schemaEncryptionCheckKeyTOTP, - schemaEncryptionCheckKeyWebauthn, + schemaEncryptionCheckKeyWebAuthn, } for i := 0; true; i++ { @@ -153,10 +153,10 @@ func schemaEncryptionChangeKeyTOTP(ctx context.Context, provider *SQLProvider, t return nil } -func schemaEncryptionChangeKeyWebauthn(ctx context.Context, provider *SQLProvider, tx *sqlx.Tx, key [32]byte) (err error) { +func schemaEncryptionChangeKeyWebAuthn(ctx context.Context, provider *SQLProvider, tx *sqlx.Tx, key [32]byte) (err error) { var count int - if err = tx.GetContext(ctx, &count, fmt.Sprintf(queryFmtSelectRowCount, tableWebauthnDevices)); err != nil { + if err = tx.GetContext(ctx, &count, fmt.Sprintf(queryFmtSelectRowCount, tableWebAuthnDevices)); err != nil { return err } @@ -164,29 +164,29 @@ func schemaEncryptionChangeKeyWebauthn(ctx context.Context, provider *SQLProvide return nil } - devices := make([]encWebauthnDevice, 0, count) + devices := make([]encWebAuthnDevice, 0, count) - if err = tx.SelectContext(ctx, &devices, fmt.Sprintf(queryFmtSelectWebauthnDevicesEncryptedData, tableWebauthnDevices)); err != nil { + if err = tx.SelectContext(ctx, &devices, fmt.Sprintf(queryFmtSelectWebAuthnDevicesEncryptedData, tableWebAuthnDevices)); err != nil { if errors.Is(err, sql.ErrNoRows) { return nil } - return fmt.Errorf("error selecting Webauthn devices: %w", err) + return fmt.Errorf("error selecting WebAuthn devices: %w", err) } - query := provider.db.Rebind(fmt.Sprintf(queryFmtUpdateWebauthnDevicePublicKey, tableWebauthnDevices)) + query := provider.db.Rebind(fmt.Sprintf(queryFmtUpdateWebAuthnDevicePublicKey, tableWebAuthnDevices)) for _, d := range devices { if d.PublicKey, err = provider.decrypt(d.PublicKey); err != nil { - return fmt.Errorf("error decrypting Webauthn device public key with id '%d': %w", d.ID, err) + return fmt.Errorf("error decrypting WebAuthn device public key with id '%d': %w", d.ID, err) } if d.PublicKey, err = utils.Encrypt(d.PublicKey, &key); err != nil { - return fmt.Errorf("error encrypting Webauthn device public key with id '%d': %w", d.ID, err) + return fmt.Errorf("error encrypting WebAuthn device public key with id '%d': %w", d.ID, err) } if _, err = tx.ExecContext(ctx, query, d.PublicKey, d.ID); err != nil { - return fmt.Errorf("error updating Webauthn device public key with id '%d': %w", d.ID, err) + return fmt.Errorf("error updating WebAuthn device public key with id '%d': %w", d.ID, err) } } @@ -262,17 +262,17 @@ func schemaEncryptionCheckKeyTOTP(ctx context.Context, provider *SQLProvider) (t return tableTOTPConfigurations, result } -func schemaEncryptionCheckKeyWebauthn(ctx context.Context, provider *SQLProvider) (table string, result EncryptionValidationTableResult) { +func schemaEncryptionCheckKeyWebAuthn(ctx context.Context, provider *SQLProvider) (table string, result EncryptionValidationTableResult) { var ( rows *sqlx.Rows err error ) - if rows, err = provider.db.QueryxContext(ctx, fmt.Sprintf(queryFmtSelectWebauthnDevicesEncryptedData, tableWebauthnDevices)); err != nil { - return tableWebauthnDevices, EncryptionValidationTableResult{Error: fmt.Errorf("error selecting Webauthn devices: %w", err)} + if rows, err = provider.db.QueryxContext(ctx, fmt.Sprintf(queryFmtSelectWebAuthnDevicesEncryptedData, tableWebAuthnDevices)); err != nil { + return tableWebAuthnDevices, EncryptionValidationTableResult{Error: fmt.Errorf("error selecting WebAuthn devices: %w", err)} } - var device encWebauthnDevice + var device encWebAuthnDevice for rows.Next() { result.Total++ @@ -280,7 +280,7 @@ func schemaEncryptionCheckKeyWebauthn(ctx context.Context, provider *SQLProvider if err = rows.StructScan(&device); err != nil { _ = rows.Close() - return tableWebauthnDevices, EncryptionValidationTableResult{Error: fmt.Errorf("error scanning Webauthn device to struct: %w", err)} + return tableWebAuthnDevices, EncryptionValidationTableResult{Error: fmt.Errorf("error scanning WebAuthn device to struct: %w", err)} } if _, err = provider.decrypt(device.PublicKey); err != nil { @@ -290,7 +290,7 @@ func schemaEncryptionCheckKeyWebauthn(ctx context.Context, provider *SQLProvider _ = rows.Close() - return tableWebauthnDevices, result + return tableWebAuthnDevices, result } func schemaEncryptionCheckKeyOpenIDConnect(typeOAuth2Session OAuth2SessionType) EncryptionCheckKeyFunc { diff --git a/internal/storage/sql_provider_queries.go b/internal/storage/sql_provider_queries.go index 5f1aa3cec..b089e23ce 100644 --- a/internal/storage/sql_provider_queries.go +++ b/internal/storage/sql_provider_queries.go @@ -119,59 +119,59 @@ const ( ) const ( - queryFmtSelectWebauthnDevices = ` + queryFmtSelectWebAuthnDevices = ` SELECT id, created_at, last_used_at, rpid, username, description, kid, public_key, attestation_type, transport, aaguid, sign_count, clone_warning FROM %s LIMIT ? OFFSET ?;` - queryFmtSelectWebauthnDevicesEncryptedData = ` + queryFmtSelectWebAuthnDevicesEncryptedData = ` SELECT id, public_key FROM %s;` - queryFmtSelectWebauthnDevicesByUsername = ` + queryFmtSelectWebAuthnDevicesByUsername = ` SELECT id, created_at, last_used_at, rpid, username, description, kid, public_key, attestation_type, transport, aaguid, sign_count, clone_warning FROM %s WHERE username = ?;` - queryFmtUpdateWebauthnDevicePublicKey = ` + queryFmtUpdateWebAuthnDevicePublicKey = ` UPDATE %s SET public_key = ? WHERE id = ?;` - queryFmtUpdateWebauthnDeviceRecordSignIn = ` + queryFmtUpdateWebAuthnDeviceRecordSignIn = ` UPDATE %s SET rpid = ?, last_used_at = ?, sign_count = ?, clone_warning = CASE clone_warning WHEN TRUE THEN TRUE ELSE ? END WHERE id = ?;` - queryFmtUpdateWebauthnDeviceRecordSignInByUsername = ` + queryFmtUpdateWebAuthnDeviceRecordSignInByUsername = ` UPDATE %s SET rpid = ?, last_used_at = ?, sign_count = ?, clone_warning = CASE clone_warning WHEN TRUE THEN TRUE ELSE ? END WHERE username = ? AND kid = ?;` - queryFmtUpsertWebauthnDevice = ` + queryFmtUpsertWebAuthnDevice = ` REPLACE INTO %s (created_at, last_used_at, rpid, username, description, kid, public_key, attestation_type, transport, aaguid, sign_count, clone_warning) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);` - queryFmtUpsertWebauthnDevicePostgreSQL = ` + queryFmtUpsertWebAuthnDevicePostgreSQL = ` INSERT INTO %s (created_at, last_used_at, rpid, username, description, kid, public_key, attestation_type, transport, aaguid, sign_count, clone_warning) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) ON CONFLICT (username, description) DO UPDATE SET created_at = $1, last_used_at = $2, rpid = $3, kid = $6, public_key = $7, attestation_type = $8, transport = $9, aaguid = $10, sign_count = $11, clone_warning = $12;` - queryFmtDeleteWebauthnDevice = ` + queryFmtDeleteWebAuthnDevice = ` DELETE FROM %s WHERE kid = ?;` - queryFmtDeleteWebauthnDeviceByUsername = ` + queryFmtDeleteWebAuthnDeviceByUsername = ` DELETE FROM %s WHERE username = ?;` - queryFmtDeleteWebauthnDeviceByUsernameAndDescription = ` + queryFmtDeleteWebAuthnDeviceByUsernameAndDescription = ` DELETE FROM %s WHERE username = ? AND description = ?;` ) diff --git a/internal/storage/types.go b/internal/storage/types.go index 327f52c4d..7537c7695 100644 --- a/internal/storage/types.go +++ b/internal/storage/types.go @@ -32,7 +32,7 @@ type encOAuth2Session struct { Session []byte `db:"session_data"` } -type encWebauthnDevice struct { +type encWebAuthnDevice struct { ID int `db:"id"` PublicKey []byte `db:"public_key"` } diff --git a/web/src/App.tsx b/web/src/App.tsx index 77ea8aff7..ab8be3fa1 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -12,7 +12,7 @@ import { IndexRoute, LogoutRoute, RegisterOneTimePasswordRoute, - RegisterWebauthnRoute, + RegisterWebAuthnRoute, ResetPasswordStep1Route, ResetPasswordStep2Route, } from "@constants/Routes"; @@ -28,7 +28,7 @@ import { getTheme, } from "@utils/Configuration"; import RegisterOneTimePassword from "@views/DeviceRegistration/RegisterOneTimePassword"; -import RegisterWebauthn from "@views/DeviceRegistration/RegisterWebauthn"; +import RegisterWebAuthn from "@views/DeviceRegistration/RegisterWebAuthn"; import BaseLoadingPage from "@views/LoadingPage/BaseLoadingPage"; import ConsentView from "@views/LoginPortal/ConsentView/ConsentView"; import LoginPortal from "@views/LoginPortal/LoginPortal"; @@ -89,7 +89,7 @@ const App: React.FC = (props: Props) => { } /> } /> - } /> + } /> } /> } /> } /> diff --git a/web/src/constants/Routes.ts b/web/src/constants/Routes.ts index 55c7f576f..25d47d342 100644 --- a/web/src/constants/Routes.ts +++ b/web/src/constants/Routes.ts @@ -3,12 +3,12 @@ export const AuthenticatedRoute: string = "/authenticated"; export const ConsentRoute: string = "/consent"; export const SecondFactorRoute: string = "/2fa/"; -export const SecondFactorWebauthnSubRoute: string = "webauthn"; +export const SecondFactorWebAuthnSubRoute: string = "webauthn"; export const SecondFactorTOTPSubRoute: string = "one-time-password"; export const SecondFactorPushSubRoute: string = "push-notification"; export const ResetPasswordStep1Route: string = "/reset-password/step1"; export const ResetPasswordStep2Route: string = "/reset-password/step2"; -export const RegisterWebauthnRoute: string = "/webauthn/register"; +export const RegisterWebAuthnRoute: string = "/webauthn/register"; export const RegisterOneTimePasswordRoute: string = "/one-time-password/register"; export const LogoutRoute: string = "/logout"; diff --git a/web/src/services/Api.ts b/web/src/services/Api.ts index 03bb4e1ce..0e301d628 100644 --- a/web/src/services/Api.ts +++ b/web/src/services/Api.ts @@ -11,11 +11,11 @@ export const FirstFactorPath = basePath + "/api/firstfactor"; export const InitiateTOTPRegistrationPath = basePath + "/api/secondfactor/totp/identity/start"; export const CompleteTOTPRegistrationPath = basePath + "/api/secondfactor/totp/identity/finish"; -export const WebauthnIdentityStartPath = basePath + "/api/secondfactor/webauthn/identity/start"; -export const WebauthnIdentityFinishPath = basePath + "/api/secondfactor/webauthn/identity/finish"; -export const WebauthnAttestationPath = basePath + "/api/secondfactor/webauthn/attestation"; +export const WebAuthnIdentityStartPath = basePath + "/api/secondfactor/webauthn/identity/start"; +export const WebAuthnIdentityFinishPath = basePath + "/api/secondfactor/webauthn/identity/finish"; +export const WebAuthnAttestationPath = basePath + "/api/secondfactor/webauthn/attestation"; -export const WebauthnAssertionPath = basePath + "/api/secondfactor/webauthn/assertion"; +export const WebAuthnAssertionPath = basePath + "/api/secondfactor/webauthn/assertion"; export const InitiateDuoDeviceSelectionPath = basePath + "/api/secondfactor/duo_devices"; export const CompleteDuoDeviceSelectionPath = basePath + "/api/secondfactor/duo_device"; diff --git a/web/src/services/RegisterDevice.ts b/web/src/services/RegisterDevice.ts index 431b336af..3dc0eb42c 100644 --- a/web/src/services/RegisterDevice.ts +++ b/web/src/services/RegisterDevice.ts @@ -1,4 +1,4 @@ -import { CompleteTOTPRegistrationPath, InitiateTOTPRegistrationPath, WebauthnIdentityStartPath } from "@services/Api"; +import { CompleteTOTPRegistrationPath, InitiateTOTPRegistrationPath, WebAuthnIdentityStartPath } from "@services/Api"; import { Post, PostWithOptionalResponse } from "@services/Client"; export async function initiateTOTPRegistrationProcess() { @@ -14,6 +14,6 @@ export async function completeTOTPRegistrationProcess(processToken: string) { return Post(CompleteTOTPRegistrationPath, { token: processToken }); } -export async function initiateWebauthnRegistrationProcess() { - return PostWithOptionalResponse(WebauthnIdentityStartPath); +export async function initiateWebAuthnRegistrationProcess() { + return PostWithOptionalResponse(WebAuthnIdentityStartPath); } diff --git a/web/src/services/Webauthn.ts b/web/src/services/Webauthn.ts index 7dc2de6ce..ecd2dbfe8 100644 --- a/web/src/services/Webauthn.ts +++ b/web/src/services/Webauthn.ts @@ -20,14 +20,14 @@ import { import { OptionalDataServiceResponse, ServiceResponse, - WebauthnAssertionPath, - WebauthnAttestationPath, - WebauthnIdentityFinishPath, + WebAuthnAssertionPath, + WebAuthnAttestationPath, + WebAuthnIdentityFinishPath, } from "@services/Api"; import { SignInResponse } from "@services/SignIn"; import { getBase64WebEncodingFromBytes, getBytesFromBase64 } from "@utils/Base64"; -export function isWebauthnSecure(): boolean { +export function isWebAuthnSecure(): boolean { if (window.isSecureContext) { return true; } @@ -35,12 +35,12 @@ export function isWebauthnSecure(): boolean { return window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1"; } -export function isWebauthnSupported(): boolean { +export function isWebAuthnSupported(): boolean { return window?.PublicKeyCredential !== undefined && typeof window.PublicKeyCredential === "function"; } -export async function isWebauthnPlatformAuthenticatorAvailable(): Promise { - if (!isWebauthnSupported()) { +export async function isWebAuthnPlatformAuthenticatorAvailable(): Promise { + if (!isWebAuthnSupported()) { return false; } @@ -215,7 +215,7 @@ function getAssertionResultFromDOMException( async function getAttestationCreationOptions(token: string): Promise { let response: AxiosResponse>; - response = await axios.post>(WebauthnIdentityFinishPath, { + response = await axios.post>(WebAuthnIdentityFinishPath, { token: token, }); @@ -234,7 +234,7 @@ async function getAttestationCreationOptions(token: string): Promise { let response: AxiosResponse>; - response = await axios.get>(WebauthnAssertionPath); + response = await axios.get>(WebAuthnAssertionPath); if (response.data.status !== "OK" || response.data.data == null) { return { @@ -317,7 +317,7 @@ async function postAttestationPublicKeyCredentialResult( ): Promise>> { const credentialJSON = encodeAttestationPublicKeyCredential(credential); - return axios.post>(WebauthnAttestationPath, credentialJSON); + return axios.post>(WebAuthnAttestationPath, credentialJSON); } export async function postAssertionPublicKeyCredentialResult( @@ -328,7 +328,7 @@ export async function postAssertionPublicKeyCredentialResult( ): Promise>> { const credentialJSON = encodeAssertionPublicKeyCredential(credential, targetURL, workflow, workflowID); - return axios.post>(WebauthnAssertionPath, credentialJSON); + return axios.post>(WebAuthnAssertionPath, credentialJSON); } export async function performAttestationCeremony(token: string): Promise { diff --git a/web/src/views/DeviceRegistration/RegisterWebauthn.tsx b/web/src/views/DeviceRegistration/RegisterWebAuthn.tsx similarity index 98% rename from web/src/views/DeviceRegistration/RegisterWebauthn.tsx rename to web/src/views/DeviceRegistration/RegisterWebAuthn.tsx index 055479047..33a93ef6a 100644 --- a/web/src/views/DeviceRegistration/RegisterWebauthn.tsx +++ b/web/src/views/DeviceRegistration/RegisterWebAuthn.tsx @@ -13,7 +13,7 @@ import { AttestationResult } from "@models/Webauthn"; import { FirstFactorPath } from "@services/Api"; import { performAttestationCeremony } from "@services/Webauthn"; -const RegisterWebauthn = function () { +const RegisterWebAuthn = function () { const styles = useStyles(); const navigate = useNavigate(); const { createErrorNotification } = useNotifications(); @@ -99,7 +99,7 @@ const RegisterWebauthn = function () { ); }; -export default RegisterWebauthn; +export default RegisterWebAuthn; const useStyles = makeStyles((theme: Theme) => ({ icon: { diff --git a/web/src/views/LoginPortal/LoginPortal.tsx b/web/src/views/LoginPortal/LoginPortal.tsx index c31d0f7c9..9a3b9accc 100644 --- a/web/src/views/LoginPortal/LoginPortal.tsx +++ b/web/src/views/LoginPortal/LoginPortal.tsx @@ -8,7 +8,7 @@ import { SecondFactorPushSubRoute, SecondFactorRoute, SecondFactorTOTPSubRoute, - SecondFactorWebauthnSubRoute, + SecondFactorWebAuthnSubRoute, } from "@constants/Routes"; import { RedirectionURL } from "@constants/SearchParams"; import { useConfiguration } from "@hooks/Configuration"; @@ -144,7 +144,7 @@ const LoginPortal = function (props: Props) { redirect(AuthenticatedRoute, false); } else { if (userInfo.method === SecondFactorMethod.Webauthn) { - redirect(`${SecondFactorRoute}${SecondFactorWebauthnSubRoute}`); + redirect(`${SecondFactorRoute}${SecondFactorWebAuthnSubRoute}`); } else if (userInfo.method === SecondFactorMethod.MobilePush) { redirect(`${SecondFactorRoute}${SecondFactorPushSubRoute}`); } else { diff --git a/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx b/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx index dde55deac..e86b1afd0 100644 --- a/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx +++ b/web/src/views/LoginPortal/SecondFactor/SecondFactorForm.tsx @@ -8,7 +8,7 @@ import { Route, Routes, useNavigate } from "react-router-dom"; import { SecondFactorPushSubRoute, SecondFactorTOTPSubRoute, - SecondFactorWebauthnSubRoute, + SecondFactorWebAuthnSubRoute, LogoutRoute as SignOutRoute, } from "@constants/Routes"; import { useNotifications } from "@hooks/NotificationsContext"; @@ -16,10 +16,10 @@ import LoginLayout from "@layouts/LoginLayout"; import { Configuration } from "@models/Configuration"; import { SecondFactorMethod } from "@models/Methods"; import { UserInfo } from "@models/UserInfo"; -import { initiateTOTPRegistrationProcess, initiateWebauthnRegistrationProcess } from "@services/RegisterDevice"; +import { initiateTOTPRegistrationProcess, initiateWebAuthnRegistrationProcess } from "@services/RegisterDevice"; import { AuthenticationLevel } from "@services/State"; import { setPreferred2FAMethod } from "@services/UserInfo"; -import { isWebauthnSupported } from "@services/Webauthn"; +import { isWebAuthnSupported } from "@services/Webauthn"; import MethodSelectionDialog from "@views/LoginPortal/SecondFactor/MethodSelectionDialog"; import OneTimePasswordMethod from "@views/LoginPortal/SecondFactor/OneTimePasswordMethod"; import PushNotificationMethod from "@views/LoginPortal/SecondFactor/PushNotificationMethod"; @@ -45,7 +45,7 @@ const SecondFactorForm = function (props: Props) { const { t: translate } = useTranslation(); useEffect(() => { - setWebauthnSupported(isWebauthnSupported()); + setWebauthnSupported(isWebAuthnSupported()); }, [setWebauthnSupported]); const initiateRegistration = (initiateRegistrationFunc: () => Promise) => { @@ -124,14 +124,14 @@ const SecondFactorForm = function (props: Props) { } /> createErrorNotification(err.message)} onSignInSuccess={props.onAuthenticationSuccess} />