refactor: reduce complexity

feat-otp-verification
James Elliott 2023-02-01 22:10:38 +11:00
parent 3af20a7daf
commit d7be1c1359
No known key found for this signature in database
GPG Key ID: 0F1C4A096E857E49
8 changed files with 40 additions and 152 deletions

View File

@ -15,28 +15,6 @@ import (
"github.com/authelia/authelia/v4/internal/storage" "github.com/authelia/authelia/v4/internal/storage"
) )
// WebauthnIdentityStart the handler for initiating the identity validation.
var WebauthnIdentityStart = middlewares.IdentityVerificationStart(
middlewares.IdentityVerificationStartArgs{
MailTitle: "Register your key",
MailButtonContent: "Register",
TargetEndpoint: "/webauthn/register",
ActionClaim: ActionWebauthnRegistration,
IdentityRetrieverFunc: identityRetrieverFromSession,
}, nil)
// WebauthnIdentityFinish the handler for finishing the identity validation.
var WebauthnIdentityFinish = middlewares.IdentityVerificationFinish(
middlewares.IdentityVerificationFinishArgs{
ActionClaim: ActionWebauthnRegistration,
IsTokenUserValidFunc: isTokenUserValidFor2FARegistration,
}, WebauthnAttestationGET)
// WebauthnAttestationGET returns the attestation challenge from the server.
func WebauthnAttestationGET(ctx *middlewares.AutheliaCtx, _ string) {
WebauthnRegistrationGET(ctx)
}
// WebauthnRegistrationGET returns the attestation challenge from the server. // WebauthnRegistrationGET returns the attestation challenge from the server.
func WebauthnRegistrationGET(ctx *middlewares.AutheliaCtx) { func WebauthnRegistrationGET(ctx *middlewares.AutheliaCtx) {
var ( var (
@ -113,7 +91,7 @@ func WebauthnRegistrationPOST(ctx *middlewares.AutheliaCtx) {
) )
if userSession, err = ctx.GetSession(); err != nil { 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 registration response", regulation.AuthTypeWebauthn)
respondUnauthorized(ctx, messageUnableToRegisterSecurityKey) respondUnauthorized(ctx, messageUnableToRegisterSecurityKey)
@ -121,7 +99,7 @@ func WebauthnRegistrationPOST(ctx *middlewares.AutheliaCtx) {
} }
if userSession.Webauthn == nil { 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) ctx.Logger.Errorf("Webauthn session data is not present in order to handle %s registration 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.", regulation.AuthTypeWebauthn, userSession.Username)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -129,7 +107,7 @@ func WebauthnRegistrationPOST(ctx *middlewares.AutheliaCtx) {
} }
if w, err = newWebauthn(ctx); err != nil { 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) ctx.Logger.Errorf("Unable to configure %s during registration for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageUnableToRegisterSecurityKey) respondUnauthorized(ctx, messageUnableToRegisterSecurityKey)
@ -137,7 +115,7 @@ func WebauthnRegistrationPOST(ctx *middlewares.AutheliaCtx) {
} }
if err = json.Unmarshal(ctx.PostBody(), &bodyJSON); err != nil { if err = json.Unmarshal(ctx.PostBody(), &bodyJSON); err != nil {
ctx.Logger.Errorf("Unable to parse %s assertion request data for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) ctx.Logger.Errorf("Unable to parse %s registration request POST data for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -145,7 +123,7 @@ func WebauthnRegistrationPOST(ctx *middlewares.AutheliaCtx) {
} }
if response, err = protocol.ParseCredentialCreationResponseBody(bytes.NewReader(bodyJSON.Response)); err != nil { if response, err = protocol.ParseCredentialCreationResponseBody(bytes.NewReader(bodyJSON.Response)); err != nil {
ctx.Logger.Errorf("Unable to parse %s assertion for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err) ctx.Logger.Errorf("Unable to parse %s registration for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -155,7 +133,7 @@ func WebauthnRegistrationPOST(ctx *middlewares.AutheliaCtx) {
ctx.Logger.WithField("att_format", response.Response.AttestationObject.Format).Debug("Response Data") ctx.Logger.WithField("att_format", response.Response.AttestationObject.Format).Debug("Response Data")
if user, err = getWebAuthnUser(ctx, userSession); err != nil { 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 user details for registration for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -163,7 +141,7 @@ func WebauthnRegistrationPOST(ctx *middlewares.AutheliaCtx) {
} }
if credential, err = w.CreateCredential(user, *userSession.Webauthn, response); err != nil { if credential, err = w.CreateCredential(user, *userSession.Webauthn, response); 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 create %s credential for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -196,7 +174,7 @@ func WebauthnRegistrationPOST(ctx *middlewares.AutheliaCtx) {
device := model.NewWebauthnDeviceFromCredential(w.Config.RPID, userSession.Username, bodyJSON.Description, credential) device := model.NewWebauthnDeviceFromCredential(w.Config.RPID, userSession.Username, bodyJSON.Description, credential)
if err = ctx.Providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil { 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) ctx.Logger.Errorf("Unable to save %s device registration for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageUnableToRegisterSecurityKey) respondUnauthorized(ctx, messageUnableToRegisterSecurityKey)
@ -205,7 +183,7 @@ func WebauthnRegistrationPOST(ctx *middlewares.AutheliaCtx) {
userSession.Webauthn = nil userSession.Webauthn = nil
if err = ctx.SaveSession(userSession); err != 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 registration challenge", regulation.AuthTypeWebauthn, userSession.Username, err)
} }
ctx.ReplyOK() ctx.ReplyOK()

View File

@ -30,7 +30,7 @@ func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) {
} }
if w, err = newWebauthn(ctx); err != nil { 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) ctx.Logger.Errorf("Unable to configure %s during authentication challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -38,7 +38,7 @@ func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) {
} }
if user, err = getWebAuthnUser(ctx, userSession); err != nil { 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 load %s user details during authentication challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -62,7 +62,7 @@ func WebauthnAssertionGET(ctx *middlewares.AutheliaCtx) {
var assertion *protocol.CredentialAssertion var assertion *protocol.CredentialAssertion
if assertion, userSession.Webauthn, err = w.BeginLogin(user, opts...); err != nil { 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) ctx.Logger.Errorf("Unable to create %s authentication challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -116,7 +116,7 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) {
} }
if userSession.Webauthn == nil { 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) ctx.Logger.Errorf("Webauthn session data is not present in order to handle authentication challenge 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) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -124,7 +124,7 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) {
} }
if w, err = newWebauthn(ctx); err != nil { 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) ctx.Logger.Errorf("Unable to configure %s during authentication challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -138,7 +138,7 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) {
) )
if assertionResponse, err = protocol.ParseCredentialRequestResponseBody(bytes.NewReader(bodyJSON.Response)); err != nil { if assertionResponse, err = protocol.ParseCredentialRequestResponseBody(bytes.NewReader(bodyJSON.Response)); 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 authentication challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -146,7 +146,7 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) {
} }
if user, err = getWebAuthnUser(ctx, userSession); err != nil { 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 credentials for authentication challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -170,7 +170,7 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) {
found = true found = true
if err = ctx.Providers.StorageProvider.UpdateWebauthnDeviceSignIn(ctx, device.ID, device.RPID, device.LastUsedAt, device.SignCount, device.CloneWarning); err != nil { 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) ctx.Logger.Errorf("Unable to save %s device signin count for authentication challenge for user '%s': %+v", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -182,7 +182,7 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) {
} }
if !found { 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 authentication challenge for user '%s' device '%x' count '%d': unable to find device", regulation.AuthTypeWebauthn, userSession.Username, credential.ID, credential.Authenticator.SignCount)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)
@ -208,7 +208,7 @@ func WebauthnAssertionPOST(ctx *middlewares.AutheliaCtx) {
assertionResponse.Response.AuthenticatorData.Flags.UserVerified()) assertionResponse.Response.AuthenticatorData.Flags.UserVerified())
if err = ctx.SaveSession(userSession); err != nil { 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 authentiation challenge and authentication time", regulation.AuthTypeWebauthn, userSession.Username, err)
respondUnauthorized(ctx, messageMFAValidationFailed) respondUnauthorized(ctx, messageMFAValidationFailed)

View File

@ -235,22 +235,15 @@ func handleRouter(config schema.Configuration, providers middlewares.Providers)
} }
if !config.Webauthn.Disable { if !config.Webauthn.Disable {
// Webauthn Endpoints. r.GET("/api/secondfactor/webauthn", middleware1FA(handlers.WebauthnAssertionGET))
r.POST("/api/secondfactor/webauthn/identity/start", middleware1FA(handlers.WebauthnIdentityStart)) r.POST("/api/secondfactor/webauthn", middleware1FA(handlers.WebauthnAssertionPOST))
r.POST("/api/secondfactor/webauthn/identity/finish", middleware1FA(handlers.WebauthnIdentityFinish))
r.GET("/api/secondfactor/register/webauthn", middleware1FA(handlers.WebauthnRegistrationGET))
r.POST("/api/secondfactor/register/webauthn", middleware1FA(handlers.WebauthnRegistrationPOST))
r.POST("/api/secondfactor/webauthn/attestation", middleware1FA(handlers.WebauthnRegistrationPOST))
r.GET("/api/secondfactor/webauthn/assertion", middleware1FA(handlers.WebauthnAssertionGET))
r.POST("/api/secondfactor/webauthn/assertion", middleware1FA(handlers.WebauthnAssertionPOST))
// Management of the webauthn devices. // Management of the webauthn devices.
r.GET("/api/secondfactor/webauthn/devices", middleware1FA(handlers.WebauthnDevicesGET)) r.GET("/api/secondfactor/webauthn/credentials", middleware1FA(handlers.WebauthnDevicesGET))
r.PUT("/api/secondfactor/webauthn/device/{deviceID}", middleware2FA(handlers.WebauthnDevicePUT)) r.GET("/api/secondfactor/webauthn/credential/register", middleware1FA(handlers.WebauthnRegistrationGET))
r.DELETE("/api/secondfactor/webauthn/device/{deviceID}", middleware2FA(handlers.WebauthnDeviceDELETE)) r.POST("/api/secondfactor/webauthn/credential/register", middleware1FA(handlers.WebauthnRegistrationPOST))
r.PUT("/api/secondfactor/webauthn/credential/{deviceID}", middleware2FA(handlers.WebauthnDevicePUT))
r.DELETE("/api/secondfactor/webauthn/credential/{deviceID}", middleware2FA(handlers.WebauthnDeviceDELETE))
} }
// Configure DUO api endpoint only if configuration exists. // Configure DUO api endpoint only if configuration exists.

View File

@ -28,8 +28,8 @@
"@mui/icons-material": "5.11.0", "@mui/icons-material": "5.11.0",
"@mui/material": "5.11.6", "@mui/material": "5.11.6",
"@mui/styles": "5.11.2", "@mui/styles": "5.11.2",
"@simplewebauthn/browser": "^7.0.1", "@simplewebauthn/browser": "7.0.1",
"@simplewebauthn/typescript-types": "^7.0.0", "@simplewebauthn/typescript-types": "7.0.0",
"axios": "1.2.6", "axios": "1.2.6",
"broadcast-channel": "4.20.2", "broadcast-channel": "4.20.2",
"classnames": "2.3.2", "classnames": "2.3.2",

View File

@ -14,8 +14,8 @@ specifiers:
'@mui/icons-material': 5.11.0 '@mui/icons-material': 5.11.0
'@mui/material': 5.11.6 '@mui/material': 5.11.6
'@mui/styles': 5.11.2 '@mui/styles': 5.11.2
'@simplewebauthn/browser': ^7.0.1 '@simplewebauthn/browser': 7.0.1
'@simplewebauthn/typescript-types': ^7.0.0 '@simplewebauthn/typescript-types': 7.0.0
'@testing-library/jest-dom': 5.16.5 '@testing-library/jest-dom': 5.16.5
'@testing-library/react': 13.4.0 '@testing-library/react': 13.4.0
'@types/jest': 29.4.0 '@types/jest': 29.4.0
@ -504,7 +504,6 @@ packages:
/@babel/parser/7.20.7: /@babel/parser/7.20.7:
resolution: {integrity: sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==} resolution: {integrity: sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
hasBin: true
dependencies: dependencies:
'@babel/types': 7.20.7 '@babel/types': 7.20.7
dev: true dev: true
@ -2021,7 +2020,6 @@ packages:
/@cnakazawa/watch/1.0.4: /@cnakazawa/watch/1.0.4:
resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==} resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==}
engines: {node: '>=0.1.95'} engines: {node: '>=0.1.95'}
hasBin: true
dependencies: dependencies:
exec-sh: 0.3.6 exec-sh: 0.3.6
minimist: 1.2.6 minimist: 1.2.6
@ -2030,7 +2028,6 @@ packages:
/@commitlint/cli/17.4.2: /@commitlint/cli/17.4.2:
resolution: {integrity: sha512-0rPGJ2O1owhpxMIXL9YJ2CgPkdrFLKZElIZHXDN8L8+qWK1DGH7Q7IelBT1pchXTYTuDlqkOTdh//aTvT3bSUA==} resolution: {integrity: sha512-0rPGJ2O1owhpxMIXL9YJ2CgPkdrFLKZElIZHXDN8L8+qWK1DGH7Q7IelBT1pchXTYTuDlqkOTdh//aTvT3bSUA==}
engines: {node: '>=v14'} engines: {node: '>=v14'}
hasBin: true
dependencies: dependencies:
'@commitlint/format': 17.4.0 '@commitlint/format': 17.4.0
'@commitlint/lint': 17.4.2 '@commitlint/lint': 17.4.2
@ -4042,7 +4039,6 @@ packages:
/JSONStream/1.3.5: /JSONStream/1.3.5:
resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
hasBin: true
dependencies: dependencies:
jsonparse: 1.3.1 jsonparse: 1.3.1
through: 2.3.8 through: 2.3.8
@ -4080,13 +4076,11 @@ packages:
/acorn/7.4.1: /acorn/7.4.1:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true
dev: true dev: true
/acorn/8.8.0: /acorn/8.8.0:
resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==} resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true
dev: true dev: true
/agent-base/6.0.2: /agent-base/6.0.2:
@ -4290,7 +4284,6 @@ packages:
/atob/2.1.2: /atob/2.1.2:
resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==}
engines: {node: '>= 4.5.0'} engines: {node: '>= 4.5.0'}
hasBin: true
dev: true dev: true
/available-typed-arrays/1.0.5: /available-typed-arrays/1.0.5:
@ -4620,7 +4613,6 @@ packages:
/browserslist/4.21.4: /browserslist/4.21.4:
resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies: dependencies:
caniuse-lite: 1.0.30001425 caniuse-lite: 1.0.30001425
electron-to-chromium: 1.4.284 electron-to-chromium: 1.4.284
@ -4852,7 +4844,6 @@ packages:
/conventional-commits-parser/3.2.4: /conventional-commits-parser/3.2.4:
resolution: {integrity: sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==} resolution: {integrity: sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==}
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true
dependencies: dependencies:
JSONStream: 1.3.5 JSONStream: 1.3.5
is-text-path: 1.0.1 is-text-path: 1.0.1
@ -5303,7 +5294,6 @@ packages:
/esbuild/0.16.17: /esbuild/0.16.17:
resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==} resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==}
engines: {node: '>=12'} engines: {node: '>=12'}
hasBin: true
requiresBuild: true requiresBuild: true
optionalDependencies: optionalDependencies:
'@esbuild/android-arm': 0.16.17 '@esbuild/android-arm': 0.16.17
@ -5333,7 +5323,6 @@ packages:
/esbuild/0.17.5: /esbuild/0.17.5:
resolution: {integrity: sha512-Bu6WLCc9NMsNoMJUjGl3yBzTjVLXdysMltxQWiLAypP+/vQrf+3L1Xe8fCXzxaECus2cEJ9M7pk4yKatEwQMqQ==} resolution: {integrity: sha512-Bu6WLCc9NMsNoMJUjGl3yBzTjVLXdysMltxQWiLAypP+/vQrf+3L1Xe8fCXzxaECus2cEJ9M7pk4yKatEwQMqQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
hasBin: true
requiresBuild: true requiresBuild: true
optionalDependencies: optionalDependencies:
'@esbuild/android-arm': 0.17.5 '@esbuild/android-arm': 0.17.5
@ -5381,7 +5370,6 @@ packages:
/escodegen/2.0.0: /escodegen/2.0.0:
resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==}
engines: {node: '>=6.0'} engines: {node: '>=6.0'}
hasBin: true
dependencies: dependencies:
esprima: 4.0.1 esprima: 4.0.1
estraverse: 5.3.0 estraverse: 5.3.0
@ -5393,7 +5381,6 @@ packages:
/eslint-config-prettier/8.6.0_eslint@8.33.0: /eslint-config-prettier/8.6.0_eslint@8.33.0:
resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==} resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==}
hasBin: true
peerDependencies: peerDependencies:
eslint: '>=7.0.0' eslint: '>=7.0.0'
dependencies: dependencies:
@ -5699,7 +5686,6 @@ packages:
/eslint/8.33.0: /eslint/8.33.0:
resolution: {integrity: sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==} resolution: {integrity: sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
dependencies: dependencies:
'@eslint/eslintrc': 1.4.1 '@eslint/eslintrc': 1.4.1
'@humanwhocodes/config-array': 0.11.8 '@humanwhocodes/config-array': 0.11.8
@ -5756,7 +5742,6 @@ packages:
/esprima/4.0.1: /esprima/4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'} engines: {node: '>=4'}
hasBin: true
dev: true dev: true
/esquery/1.4.0: /esquery/1.4.0:
@ -6133,7 +6118,6 @@ packages:
/git-raw-commits/2.0.11: /git-raw-commits/2.0.11:
resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==} resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==}
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true
dependencies: dependencies:
dargs: 7.0.0 dargs: 7.0.0
lodash: 4.17.21 lodash: 4.17.21
@ -6366,7 +6350,6 @@ packages:
/husky/8.0.3: /husky/8.0.3:
resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true
dev: true dev: true
/hyphenate-style-name/1.0.4: /hyphenate-style-name/1.0.4:
@ -6415,7 +6398,6 @@ packages:
/import-local/3.1.0: /import-local/3.1.0:
resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==}
engines: {node: '>=8'} engines: {node: '>=8'}
hasBin: true
dependencies: dependencies:
pkg-dir: 4.2.0 pkg-dir: 4.2.0
resolve-cwd: 3.0.0 resolve-cwd: 3.0.0
@ -6511,7 +6493,6 @@ packages:
/is-ci/2.0.0: /is-ci/2.0.0:
resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==}
hasBin: true
dependencies: dependencies:
ci-info: 2.0.0 ci-info: 2.0.0
dev: true dev: true
@ -6569,7 +6550,6 @@ packages:
/is-docker/2.2.1: /is-docker/2.2.1:
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
hasBin: true
dev: true dev: true
/is-extendable/0.1.1: /is-extendable/0.1.1:
@ -6865,7 +6845,6 @@ packages:
/jest-cli/29.4.1_@types+node@18.11.18: /jest-cli/29.4.1_@types+node@18.11.18:
resolution: {integrity: sha512-jz7GDIhtxQ37M+9dlbv5K+/FVcIo1O/b1sX3cJgzlQUf/3VG25nvuWzlDC4F1FLLzUThJeWLu8I7JF9eWpuURQ==} resolution: {integrity: sha512-jz7GDIhtxQ37M+9dlbv5K+/FVcIo1O/b1sX3cJgzlQUf/3VG25nvuWzlDC4F1FLLzUThJeWLu8I7JF9eWpuURQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
peerDependencies: peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
peerDependenciesMeta: peerDependenciesMeta:
@ -7334,7 +7313,6 @@ packages:
/jest/29.4.1_@types+node@18.11.18: /jest/29.4.1_@types+node@18.11.18:
resolution: {integrity: sha512-cknimw7gAXPDOmj0QqztlxVtBVCw2lYY9CeIE5N6kD+kET1H4H79HSNISJmijb1HF+qk+G+ploJgiDi5k/fRlg==} resolution: {integrity: sha512-cknimw7gAXPDOmj0QqztlxVtBVCw2lYY9CeIE5N6kD+kET1H4H79HSNISJmijb1HF+qk+G+ploJgiDi5k/fRlg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
peerDependencies: peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
peerDependenciesMeta: peerDependenciesMeta:
@ -7360,7 +7338,6 @@ packages:
/js-yaml/3.14.1: /js-yaml/3.14.1:
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
hasBin: true
dependencies: dependencies:
argparse: 1.0.10 argparse: 1.0.10
esprima: 4.0.1 esprima: 4.0.1
@ -7368,7 +7345,6 @@ packages:
/js-yaml/4.1.0: /js-yaml/4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
dependencies: dependencies:
argparse: 2.0.1 argparse: 2.0.1
dev: true dev: true
@ -7417,13 +7393,11 @@ packages:
/jsesc/0.5.0: /jsesc/0.5.0:
resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==}
hasBin: true
dev: true dev: true
/jsesc/2.5.2: /jsesc/2.5.2:
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
engines: {node: '>=4'} engines: {node: '>=4'}
hasBin: true
dev: true dev: true
/json-parse-even-better-errors/2.3.1: /json-parse-even-better-errors/2.3.1:
@ -7443,7 +7417,6 @@ packages:
/json5/1.0.1: /json5/1.0.1:
resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==}
hasBin: true
dependencies: dependencies:
minimist: 1.2.6 minimist: 1.2.6
dev: true dev: true
@ -7451,7 +7424,6 @@ packages:
/json5/2.2.3: /json5/2.2.3:
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
engines: {node: '>=6'} engines: {node: '>=6'}
hasBin: true
dev: true dev: true
/jsonfile/6.1.0: /jsonfile/6.1.0:
@ -7664,7 +7636,6 @@ packages:
/loose-envify/1.4.0: /loose-envify/1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
dependencies: dependencies:
js-tokens: 4.0.0 js-tokens: 4.0.0
@ -7683,7 +7654,6 @@ packages:
/lz-string/1.4.4: /lz-string/1.4.4:
resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==}
hasBin: true
dev: true dev: true
/magic-string/0.27.0: /magic-string/0.27.0:
@ -7848,7 +7818,6 @@ packages:
/nanoid/3.3.4: /nanoid/3.3.4:
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
dev: true dev: true
/nanomatch/1.2.13: /nanomatch/1.2.13:
@ -8247,7 +8216,6 @@ packages:
/prettier/2.8.3: /prettier/2.8.3:
resolution: {integrity: sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==} resolution: {integrity: sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==}
engines: {node: '>=10.13.0'} engines: {node: '>=10.13.0'}
hasBin: true
dev: true dev: true
/pretty-format/27.5.1: /pretty-format/27.5.1:
@ -8560,7 +8528,6 @@ packages:
/regjsparser/0.8.4: /regjsparser/0.8.4:
resolution: {integrity: sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==} resolution: {integrity: sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==}
hasBin: true
dependencies: dependencies:
jsesc: 0.5.0 jsesc: 0.5.0
dev: true dev: true
@ -8614,7 +8581,6 @@ packages:
/resolve-url/0.2.1: /resolve-url/0.2.1:
resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==}
deprecated: https://github.com/lydell/resolve-url#deprecated
dev: true dev: true
/resolve.exports/2.0.0: /resolve.exports/2.0.0:
@ -8624,7 +8590,6 @@ packages:
/resolve/1.22.1: /resolve/1.22.1:
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
hasBin: true
dependencies: dependencies:
is-core-module: 2.11.0 is-core-module: 2.11.0
path-parse: 1.0.7 path-parse: 1.0.7
@ -8632,7 +8597,6 @@ packages:
/resolve/2.0.0-next.4: /resolve/2.0.0-next.4:
resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==} resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==}
hasBin: true
dependencies: dependencies:
is-core-module: 2.11.0 is-core-module: 2.11.0
path-parse: 1.0.7 path-parse: 1.0.7
@ -8651,14 +8615,12 @@ packages:
/rimraf/3.0.2: /rimraf/3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
hasBin: true
dependencies: dependencies:
glob: 7.2.3 glob: 7.2.3
/rollup/2.78.0: /rollup/2.78.0:
resolution: {integrity: sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg==} resolution: {integrity: sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
hasBin: true
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.2
dev: true dev: true
@ -8666,7 +8628,6 @@ packages:
/rollup/3.7.4: /rollup/3.7.4:
resolution: {integrity: sha512-jN9rx3k5pfg9H9al0r0y1EYKSeiRANZRYX32SuNXAnKzh6cVyf4LZVto1KAuDnbHT03E1CpsgqDKaqQ8FZtgxw==} resolution: {integrity: sha512-jN9rx3k5pfg9H9al0r0y1EYKSeiRANZRYX32SuNXAnKzh6cVyf4LZVto1KAuDnbHT03E1CpsgqDKaqQ8FZtgxw==}
engines: {node: '>=14.18.0', npm: '>=8.0.0'} engines: {node: '>=14.18.0', npm: '>=8.0.0'}
hasBin: true
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.2
dev: true dev: true
@ -8710,8 +8671,6 @@ packages:
/sane/4.1.0: /sane/4.1.0:
resolution: {integrity: sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==} resolution: {integrity: sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==}
engines: {node: 6.* || 8.* || >= 10.*} engines: {node: 6.* || 8.* || >= 10.*}
deprecated: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added
hasBin: true
dependencies: dependencies:
'@cnakazawa/watch': 1.0.4 '@cnakazawa/watch': 1.0.4
anymatch: 2.0.0 anymatch: 2.0.0
@ -8740,23 +8699,19 @@ packages:
/semver/5.7.1: /semver/5.7.1:
resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
hasBin: true
dev: true dev: true
/semver/6.3.0: /semver/6.3.0:
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
hasBin: true
dev: true dev: true
/semver/7.0.0: /semver/7.0.0:
resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==} resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==}
hasBin: true
dev: true dev: true
/semver/7.3.8: /semver/7.3.8:
resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==}
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true
dependencies: dependencies:
lru-cache: 6.0.0 lru-cache: 6.0.0
dev: true dev: true
@ -8865,7 +8820,6 @@ packages:
/source-map-resolve/0.5.3: /source-map-resolve/0.5.3:
resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==}
deprecated: See https://github.com/lydell/source-map-resolve#deprecated
dependencies: dependencies:
atob: 2.1.2 atob: 2.1.2
decode-uri-component: 0.2.2 decode-uri-component: 0.2.2
@ -8883,7 +8837,6 @@ packages:
/source-map-url/0.4.1: /source-map-url/0.4.1:
resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==}
deprecated: See https://github.com/lydell/source-map-url#deprecated
dev: true dev: true
/source-map/0.5.7: /source-map/0.5.7:
@ -9214,7 +9167,6 @@ packages:
/ts-node/10.9.0_awa2wsr5thmg3i7jqycphctjfq: /ts-node/10.9.0_awa2wsr5thmg3i7jqycphctjfq:
resolution: {integrity: sha512-bunW18GUyaCSYRev4DPf4SQpom3pWH29wKl0sDk5zE7ze19RImEVhCW7K4v3hHKkUyfWotU08ToE2RS+Y49aug==} resolution: {integrity: sha512-bunW18GUyaCSYRev4DPf4SQpom3pWH29wKl0sDk5zE7ze19RImEVhCW7K4v3hHKkUyfWotU08ToE2RS+Y49aug==}
hasBin: true
peerDependencies: peerDependencies:
'@swc/core': '>=1.2.50' '@swc/core': '>=1.2.50'
'@swc/wasm': '>=1.2.50' '@swc/wasm': '>=1.2.50'
@ -9246,7 +9198,6 @@ packages:
/tsconfck/2.0.1_typescript@4.9.4: /tsconfck/2.0.1_typescript@4.9.4:
resolution: {integrity: sha512-/ipap2eecmVBmBlsQLBRbUmUNFwNJV/z2E+X0FPtHNjPwroMZQ7m39RMaCywlCulBheYXgMdUlWDd9rzxwMA0Q==} resolution: {integrity: sha512-/ipap2eecmVBmBlsQLBRbUmUNFwNJV/z2E+X0FPtHNjPwroMZQ7m39RMaCywlCulBheYXgMdUlWDd9rzxwMA0Q==}
engines: {node: ^14.13.1 || ^16 || >=18, pnpm: ^7.0.1} engines: {node: ^14.13.1 || ^16 || >=18, pnpm: ^7.0.1}
hasBin: true
peerDependencies: peerDependencies:
typescript: ^4.3.5 typescript: ^4.3.5
peerDependenciesMeta: peerDependenciesMeta:
@ -9341,7 +9292,6 @@ packages:
/typescript/4.9.4: /typescript/4.9.4:
resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==} resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==}
engines: {node: '>=4.2.0'} engines: {node: '>=4.2.0'}
hasBin: true
dev: true dev: true
/unbox-primitive/1.0.2: /unbox-primitive/1.0.2:
@ -9410,7 +9360,6 @@ packages:
/update-browserslist-db/1.0.10_browserslist@4.21.4: /update-browserslist-db/1.0.10_browserslist@4.21.4:
resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==}
hasBin: true
peerDependencies: peerDependencies:
browserslist: '>= 4.21.0' browserslist: '>= 4.21.0'
dependencies: dependencies:
@ -9427,7 +9376,6 @@ packages:
/urix/0.1.0: /urix/0.1.0:
resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==}
deprecated: Please see https://github.com/lydell/urix#deprecated
dev: true dev: true
/use/3.1.1: /use/3.1.1:
@ -9513,7 +9461,6 @@ packages:
/vite/4.0.4_@types+node@18.11.18: /vite/4.0.4_@types+node@18.11.18:
resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==} resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
peerDependencies: peerDependencies:
'@types/node': '>= 14' '@types/node': '>= 14'
less: '*' less: '*'
@ -9551,7 +9498,6 @@ packages:
/w3c-hr-time/1.0.2: /w3c-hr-time/1.0.2:
resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
deprecated: Use your platform's native performance.now() and performance.timeOrigin.
dependencies: dependencies:
browser-process-hrtime: 1.0.0 browser-process-hrtime: 1.0.0
dev: true dev: true
@ -9638,7 +9584,6 @@ packages:
/which/1.3.1: /which/1.3.1:
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
hasBin: true
dependencies: dependencies:
isexe: 2.0.0 isexe: 2.0.0
dev: true dev: true
@ -9646,7 +9591,6 @@ packages:
/which/2.0.2: /which/2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
hasBin: true
dependencies: dependencies:
isexe: 2.0.0 isexe: 2.0.0
dev: true dev: true

View File

@ -11,13 +11,12 @@ export const FirstFactorPath = basePath + "/api/firstfactor";
export const InitiateTOTPRegistrationPath = basePath + "/api/secondfactor/totp/identity/start"; export const InitiateTOTPRegistrationPath = basePath + "/api/secondfactor/totp/identity/start";
export const CompleteTOTPRegistrationPath = basePath + "/api/secondfactor/totp/identity/finish"; export const CompleteTOTPRegistrationPath = basePath + "/api/secondfactor/totp/identity/finish";
export const WebauthnIdentityStartPath = basePath + "/api/secondfactor/webauthn/identity/start"; export const WebauthnRegistrationPath = basePath + "/api/secondfactor/webauthn/credential/register";
export const WebauthnRegistrationPath = basePath + "/api/secondfactor/register/webauthn";
export const WebauthnAssertionPath = basePath + "/api/secondfactor/webauthn/assertion"; export const WebauthnAssertionPath = basePath + "/api/secondfactor/webauthn";
export const WebauthnDevicesPath = basePath + "/api/secondfactor/webauthn/devices"; export const WebauthnDevicesPath = basePath + "/api/secondfactor/webauthn/credentials";
export const WebauthnDevicePath = basePath + "/api/secondfactor/webauthn/device"; export const WebauthnDevicePath = basePath + "/api/secondfactor/webauthn/credential";
export const InitiateDuoDeviceSelectionPath = basePath + "/api/secondfactor/duo_devices"; export const InitiateDuoDeviceSelectionPath = basePath + "/api/secondfactor/duo_devices";
export const CompleteDuoDeviceSelectionPath = basePath + "/api/secondfactor/duo_device"; export const CompleteDuoDeviceSelectionPath = basePath + "/api/secondfactor/duo_device";

View File

@ -1,4 +1,4 @@
import { CompleteTOTPRegistrationPath, InitiateTOTPRegistrationPath, WebauthnIdentityStartPath } from "@services/Api"; import { CompleteTOTPRegistrationPath, InitiateTOTPRegistrationPath } from "@services/Api";
import { Post, PostWithOptionalResponse } from "@services/Client"; import { Post, PostWithOptionalResponse } from "@services/Client";
export async function initiateTOTPRegistrationProcess() { export async function initiateTOTPRegistrationProcess() {
@ -13,7 +13,3 @@ interface CompleteTOTPRegistrationResponse {
export async function completeTOTPRegistrationProcess(processToken: string) { export async function completeTOTPRegistrationProcess(processToken: string) {
return Post<CompleteTOTPRegistrationResponse>(CompleteTOTPRegistrationPath, { token: processToken }); return Post<CompleteTOTPRegistrationResponse>(CompleteTOTPRegistrationPath, { token: processToken });
} }
export async function initiateWebauthnRegistrationProcess() {
return PostWithOptionalResponse(WebauthnIdentityStartPath);
}

View File

@ -1,13 +1,10 @@
import React, { Fragment, Suspense, useState } from "react"; import React, { Fragment, Suspense } from "react";
import { Box, Button, Paper, Stack, Typography } from "@mui/material"; import { Box, Button, Paper, Stack, Typography } from "@mui/material";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { RegisterWebauthnRoute } from "@constants/Routes"; import { RegisterWebauthnRoute } from "@constants/Routes";
import { useNotifications } from "@hooks/NotificationsContext"; import { AutheliaState } from "@services/State";
import { initiateWebauthnRegistrationProcess } from "@services/RegisterDevice";
import { AutheliaState, AuthenticationLevel } from "@services/State";
import LoadingPage from "@views/LoadingPage/LoadingPage"; import LoadingPage from "@views/LoadingPage/LoadingPage";
import WebauthnDevicesStack from "@views/Settings/TwoFactorAuthentication/WebauthnDevicesStack"; import WebauthnDevicesStack from "@views/Settings/TwoFactorAuthentication/WebauthnDevicesStack";
@ -16,33 +13,14 @@ interface Props {
} }
export default function WebauthnDevices(props: Props) { export default function WebauthnDevices(props: Props) {
const { t: translate } = useTranslation("settings");
const navigate = useNavigate(); const navigate = useNavigate();
const { createInfoNotification, createErrorNotification } = useNotifications(); const initiateRegistration = async (redirectRoute: string) => {
const [registrationInProgress, setRegistrationInProgress] = useState(false);
const initiateRegistration = async (initiateRegistrationFunc: () => Promise<void>, redirectRoute: string) => {
if (props.state.authentication_level >= AuthenticationLevel.TwoFactor) {
navigate(redirectRoute); navigate(redirectRoute);
} else {
if (registrationInProgress) {
return;
}
setRegistrationInProgress(true);
try {
await initiateRegistrationFunc();
createInfoNotification(translate("An email has been sent to your address to complete the process"));
} catch (err) {
console.error(err);
createErrorNotification(translate("There was a problem initiating the registration process"));
}
setRegistrationInProgress(false);
}
}; };
const handleAddKeyButtonClick = () => { const handleAddKeyButtonClick = () => {
initiateRegistration(initiateWebauthnRegistrationProcess, RegisterWebauthnRoute); initiateRegistration(RegisterWebauthnRoute);
}; };
return ( return (