diff --git a/backend/src/db/migrations/20240609133400_private-key-handoff.ts b/backend/src/db/migrations/20240609133400_private-key-handoff.ts new file mode 100644 index 000000000..9741c6029 --- /dev/null +++ b/backend/src/db/migrations/20240609133400_private-key-handoff.ts @@ -0,0 +1,61 @@ +import { Knex } from "knex"; + +import { TableName } from "../schemas"; + +export async function up(knex: Knex): Promise { + const doesPasswordFieldExist = await knex.schema.hasColumn(TableName.UserEncryptionKey, "hashedPassword"); + const doesPrivateKeyFieldExist = await knex.schema.hasColumn( + TableName.UserEncryptionKey, + "serverEncryptedPrivateKey" + ); + const doesPrivateKeyIVFieldExist = await knex.schema.hasColumn( + TableName.UserEncryptionKey, + "serverEncryptedPrivateKeyIV" + ); + const doesPrivateKeyTagFieldExist = await knex.schema.hasColumn( + TableName.UserEncryptionKey, + "serverEncryptedPrivateKeyTag" + ); + const doesPrivateKeyEncodingFieldExist = await knex.schema.hasColumn( + TableName.UserEncryptionKey, + "serverEncryptedPrivateKeyEncoding" + ); + if (await knex.schema.hasTable(TableName.UserEncryptionKey)) { + await knex.schema.alterTable(TableName.UserEncryptionKey, (t) => { + if (!doesPasswordFieldExist) t.string("hashedPassword"); + if (!doesPrivateKeyFieldExist) t.text("serverEncryptedPrivateKey"); + if (!doesPrivateKeyIVFieldExist) t.text("serverEncryptedPrivateKeyIV"); + if (!doesPrivateKeyTagFieldExist) t.text("serverEncryptedPrivateKeyTag"); + if (!doesPrivateKeyEncodingFieldExist) t.text("serverEncryptedPrivateKeyEncoding"); + }); + } +} + +export async function down(knex: Knex): Promise { + const doesPasswordFieldExist = await knex.schema.hasColumn(TableName.UserEncryptionKey, "hashedPassword"); + const doesPrivateKeyFieldExist = await knex.schema.hasColumn( + TableName.UserEncryptionKey, + "serverEncryptedPrivateKey" + ); + const doesPrivateKeyIVFieldExist = await knex.schema.hasColumn( + TableName.UserEncryptionKey, + "serverEncryptedPrivateKeyIV" + ); + const doesPrivateKeyTagFieldExist = await knex.schema.hasColumn( + TableName.UserEncryptionKey, + "serverEncryptedPrivateKeyTag" + ); + const doesPrivateKeyEncodingFieldExist = await knex.schema.hasColumn( + TableName.UserEncryptionKey, + "serverEncryptedPrivateKeyEncoding" + ); + if (await knex.schema.hasTable(TableName.UserEncryptionKey)) { + await knex.schema.alterTable(TableName.UserEncryptionKey, (t) => { + if (doesPasswordFieldExist) t.dropColumn("hashedPassword"); + if (doesPrivateKeyFieldExist) t.dropColumn("serverEncryptedPrivateKey"); + if (doesPrivateKeyIVFieldExist) t.dropColumn("serverEncryptedPrivateKeyIV"); + if (doesPrivateKeyTagFieldExist) t.dropColumn("serverEncryptedPrivateKeyTag"); + if (doesPrivateKeyEncodingFieldExist) t.dropColumn("serverEncryptedPrivateKeyEncoding"); + }); + } +} diff --git a/backend/src/db/schemas/user-encryption-keys.ts b/backend/src/db/schemas/user-encryption-keys.ts index 693b73b4c..fd9d21a9d 100644 --- a/backend/src/db/schemas/user-encryption-keys.ts +++ b/backend/src/db/schemas/user-encryption-keys.ts @@ -21,7 +21,12 @@ export const UserEncryptionKeysSchema = z.object({ tag: z.string(), salt: z.string(), verifier: z.string(), - userId: z.string().uuid() + userId: z.string().uuid(), + hashedPassword: z.string().nullable().optional(), + serverEncryptedPrivateKey: z.string().nullable().optional(), + serverEncryptedPrivateKeyIV: z.string().nullable().optional(), + serverEncryptedPrivateKeyTag: z.string().nullable().optional(), + serverEncryptedPrivateKeyEncoding: z.string().nullable().optional() }); export type TUserEncryptionKeys = z.infer; diff --git a/backend/src/ee/services/ldap-config/ldap-config-service.ts b/backend/src/ee/services/ldap-config/ldap-config-service.ts index dd49bd0ae..8027f5907 100644 --- a/backend/src/ee/services/ldap-config/ldap-config-service.ts +++ b/backend/src/ee/services/ldap-config/ldap-config-service.ts @@ -73,7 +73,13 @@ type TLdapConfigServiceFactoryDep = { >; userDAL: Pick< TUserDALFactory, - "create" | "findOne" | "transaction" | "updateById" | "findUserEncKeyByUserIdsBatch" | "find" + | "create" + | "findOne" + | "transaction" + | "updateById" + | "findUserEncKeyByUserIdsBatch" + | "find" + | "findUserEncKeyByUserId" >; userAliasDAL: Pick; permissionService: Pick; @@ -592,12 +598,14 @@ export const ldapConfigServiceFactory = ({ }); const isUserCompleted = Boolean(user.isAccepted); + const userEnc = await userDAL.findUserEncKeyByUserId(user.id); const providerAuthToken = jwt.sign( { authTokenType: AuthTokenType.PROVIDER_TOKEN, userId: user.id, username: user.username, + hasExchangedPrivateKey: Boolean(userEnc?.serverEncryptedPrivateKey), ...(user.email && { email: user.email, isEmailVerified: user.isEmailVerified }), firstName, lastName, diff --git a/backend/src/ee/services/saml-config/saml-config-service.ts b/backend/src/ee/services/saml-config/saml-config-service.ts index 5d7b7ec3b..3cc51e1c2 100644 --- a/backend/src/ee/services/saml-config/saml-config-service.ts +++ b/backend/src/ee/services/saml-config/saml-config-service.ts @@ -41,7 +41,10 @@ import { TCreateSamlCfgDTO, TGetSamlCfgDTO, TSamlLoginDTO, TUpdateSamlCfgDTO } f type TSamlConfigServiceFactoryDep = { samlConfigDAL: Pick; - userDAL: Pick; + userDAL: Pick< + TUserDALFactory, + "create" | "findOne" | "transaction" | "updateById" | "findById" | "findUserEncKeyByUserId" + >; userAliasDAL: Pick; orgDAL: Pick< TOrgDALFactory, @@ -452,6 +455,7 @@ export const samlConfigServiceFactory = ({ await licenseService.updateSubscriptionOrgMemberCount(organization.id); const isUserCompleted = Boolean(user.isAccepted); + const userEnc = await userDAL.findUserEncKeyByUserId(user.id); const providerAuthToken = jwt.sign( { authTokenType: AuthTokenType.PROVIDER_TOKEN, @@ -464,6 +468,7 @@ export const samlConfigServiceFactory = ({ organizationId: organization.id, organizationSlug: organization.slug, authMethod: authProvider, + hasExchangedPrivateKey: Boolean(userEnc?.serverEncryptedPrivateKey), authType: UserAliasType.SAML, isUserCompleted, ...(relayState diff --git a/backend/src/lib/config/env.ts b/backend/src/lib/config/env.ts index 80a2111fc..f4da71293 100644 --- a/backend/src/lib/config/env.ts +++ b/backend/src/lib/config/env.ts @@ -29,7 +29,7 @@ const envSchema = z DB_USER: zpStr(z.string().describe("Postgres database username").optional()), DB_PASSWORD: zpStr(z.string().describe("Postgres database password").optional()), DB_NAME: zpStr(z.string().describe("Postgres database name").optional()), - + BCRYPT_SALT_ROUND: z.number().default(12), NODE_ENV: z.enum(["development", "test", "production"]).default("production"), SALT_ROUNDS: z.coerce.number().default(10), INITIAL_ORGANIZATION_NAME: zpStr(z.string().optional()), diff --git a/backend/src/lib/crypto/srp.ts b/backend/src/lib/crypto/srp.ts index bc29cdb3f..8d7ea656a 100644 --- a/backend/src/lib/crypto/srp.ts +++ b/backend/src/lib/crypto/srp.ts @@ -6,7 +6,7 @@ import tweetnacl from "tweetnacl-util"; import { TUserEncryptionKeys } from "@app/db/schemas"; -import { decryptSymmetric, encryptAsymmetric, encryptSymmetric } from "./encryption"; +import { decryptSymmetric128BitHexKeyUTF8, encryptAsymmetric, encryptSymmetric } from "./encryption"; export const generateSrpServerKey = async (salt: string, verifier: string) => { // eslint-disable-next-line new-cap @@ -97,7 +97,13 @@ export const generateUserSrpKeys = async (email: string, password: string) => { }; }; -export const getUserPrivateKey = async (password: string, user: TUserEncryptionKeys) => { +export const getUserPrivateKey = async ( + password: string, + user: Pick< + TUserEncryptionKeys, + "protectedKeyTag" | "protectedKey" | "protectedKeyIV" | "encryptedPrivateKey" | "iv" | "salt" | "tag" + > +) => { const derivedKey = await argon2.hash(password, { salt: Buffer.from(user.salt), memoryCost: 65536, @@ -108,17 +114,18 @@ export const getUserPrivateKey = async (password: string, user: TUserEncryptionK raw: true }); if (!derivedKey) throw new Error("Failed to derive key from password"); - const key = decryptSymmetric({ - ciphertext: user.protectedKey!, - iv: user.protectedKeyIV!, - tag: user.protectedKeyTag!, - key: derivedKey.toString("base64") + const key = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: user.protectedKey as string, + iv: user.protectedKeyIV as string, + tag: user.protectedKeyTag as string, + key: derivedKey }); - const privateKey = decryptSymmetric({ + + const privateKey = decryptSymmetric128BitHexKeyUTF8({ ciphertext: user.encryptedPrivateKey, iv: user.iv, tag: user.tag, - key + key: Buffer.from(key, "hex") }); return privateKey; }; diff --git a/backend/src/server/routes/v1/admin-router.ts b/backend/src/server/routes/v1/admin-router.ts index 572409d9b..97c3449d9 100644 --- a/backend/src/server/routes/v1/admin-router.ts +++ b/backend/src/server/routes/v1/admin-router.ts @@ -79,6 +79,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => { schema: { body: z.object({ email: z.string().email().trim(), + password: z.string().trim(), firstName: z.string().trim(), lastName: z.string().trim().optional(), protectedKey: z.string().trim(), diff --git a/backend/src/server/routes/v1/password-router.ts b/backend/src/server/routes/v1/password-router.ts index a8ef3fb77..c94e5d4cb 100644 --- a/backend/src/server/routes/v1/password-router.ts +++ b/backend/src/server/routes/v1/password-router.ts @@ -51,7 +51,8 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => { encryptedPrivateKeyIV: z.string().trim(), encryptedPrivateKeyTag: z.string().trim(), salt: z.string().trim(), - verifier: z.string().trim() + verifier: z.string().trim(), + password: z.string().trim() }), response: { 200: z.object({ diff --git a/backend/src/server/routes/v1/sso-router.ts b/backend/src/server/routes/v1/sso-router.ts index 60bbec7db..3d8d02e6f 100644 --- a/backend/src/server/routes/v1/sso-router.ts +++ b/backend/src/server/routes/v1/sso-router.ts @@ -259,4 +259,50 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => { ); } }); + + server.route({ + url: "/token-exchange", + method: "POST", + schema: { + body: z.object({ + providerAuthToken: z.string(), + email: z.string() + }) + }, + handler: async (req, res) => { + const userAgent = req.headers["user-agent"]; + if (!userAgent) throw new Error("user agent header is required"); + + const data = await server.services.login.oauth2TokenExchange({ + email: req.body.email, + ip: req.realIp, + userAgent, + providerAuthToken: req.body.providerAuthToken + }); + + if (data.isMfaEnabled) { + return { mfaEnabled: true, token: data.token } as const; // for discriminated union + } + + void res.setCookie("jid", data.token.refresh, { + httpOnly: true, + path: "/", + sameSite: "strict", + secure: appCfg.HTTPS_ENABLED + }); + + return { + mfaEnabled: false, + encryptionVersion: data.user.encryptionVersion, + token: data.token.access, + publicKey: data.user.publicKey, + encryptedPrivateKey: data.user.encryptedPrivateKey, + iv: data.user.iv, + tag: data.user.tag, + protectedKey: data.user.protectedKey || null, + protectedKeyIV: data.user.protectedKeyIV || null, + protectedKeyTag: data.user.protectedKeyTag || null + } as const; + } + }); }; diff --git a/backend/src/server/routes/v1/user-router.ts b/backend/src/server/routes/v1/user-router.ts index 3d9f531b9..b9269d66e 100644 --- a/backend/src/server/routes/v1/user-router.ts +++ b/backend/src/server/routes/v1/user-router.ts @@ -19,7 +19,23 @@ export const registerUserRouter = async (server: FastifyZodProvider) => { schema: { response: { 200: z.object({ - user: UsersSchema.merge(UserEncryptionKeysSchema.omit({ verifier: true })) + user: UsersSchema.merge( + UserEncryptionKeysSchema.pick({ + clientPublicKey: true, + serverPrivateKey: true, + encryptionVersion: true, + protectedKey: true, + protectedKeyIV: true, + protectedKeyTag: true, + publicKey: true, + encryptedPrivateKey: true, + iv: true, + tag: true, + salt: true, + verifier: true, + userId: true + }) + ) }) } }, @@ -30,6 +46,26 @@ export const registerUserRouter = async (server: FastifyZodProvider) => { } }); + server.route({ + method: "GET", + url: "/private-key", + config: { + rateLimit: readLimit + }, + schema: { + response: { + 200: z.object({ + privateKey: z.string() + }) + } + }, + onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }), + handler: async (req) => { + const privateKey = await server.services.user.getUserPrivateKey(req.permission.id); + return { privateKey }; + } + }); + server.route({ method: "GET", url: "/:userId/unlock", diff --git a/backend/src/server/routes/v2/user-router.ts b/backend/src/server/routes/v2/user-router.ts index 1f15008c7..21dd32021 100644 --- a/backend/src/server/routes/v2/user-router.ts +++ b/backend/src/server/routes/v2/user-router.ts @@ -255,7 +255,23 @@ export const registerUserRouter = async (server: FastifyZodProvider) => { description: "Retrieve the current user on the request", response: { 200: z.object({ - user: UsersSchema.merge(UserEncryptionKeysSchema.omit({ verifier: true })) + user: UsersSchema.merge( + UserEncryptionKeysSchema.pick({ + clientPublicKey: true, + serverPrivateKey: true, + encryptionVersion: true, + protectedKey: true, + protectedKeyIV: true, + protectedKeyTag: true, + publicKey: true, + encryptedPrivateKey: true, + iv: true, + tag: true, + salt: true, + verifier: true, + userId: true + }) + ) }) } }, diff --git a/backend/src/server/routes/v3/login-router.ts b/backend/src/server/routes/v3/login-router.ts index 4c7df5612..61a0c74e5 100644 --- a/backend/src/server/routes/v3/login-router.ts +++ b/backend/src/server/routes/v3/login-router.ts @@ -81,7 +81,8 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => { email: z.string().trim(), providerAuthToken: z.string().trim().optional(), clientProof: z.string().trim(), - captchaToken: z.string().trim().optional() + captchaToken: z.string().trim().optional(), + password: z.string().optional() }), response: { 200: z.discriminatedUnion("mfaEnabled", [ @@ -112,7 +113,8 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => { ip: req.realIp, userAgent, providerAuthToken: req.body.providerAuthToken, - clientProof: req.body.clientProof + clientProof: req.body.clientProof, + password: req.body.password }); if (data.isMfaEnabled) { diff --git a/backend/src/server/routes/v3/signup-router.ts b/backend/src/server/routes/v3/signup-router.ts index ac43df36d..59131464a 100644 --- a/backend/src/server/routes/v3/signup-router.ts +++ b/backend/src/server/routes/v3/signup-router.ts @@ -102,7 +102,8 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => { verifier: z.string().trim(), organizationName: z.string().trim().min(1), providerAuthToken: z.string().trim().optional().nullish(), - attributionSource: z.string().trim().optional() + attributionSource: z.string().trim().optional(), + password: z.string() }), response: { 200: z.object({ @@ -167,6 +168,7 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => { schema: { body: z.object({ email: z.string().email().trim(), + password: z.string(), firstName: z.string().trim(), lastName: z.string().trim().optional(), protectedKey: z.string().trim(), diff --git a/backend/src/services/auth/auth-fns.ts b/backend/src/services/auth/auth-fns.ts index ecbf73a48..e8574a8b9 100644 --- a/backend/src/services/auth/auth-fns.ts +++ b/backend/src/services/auth/auth-fns.ts @@ -15,10 +15,10 @@ export const validateProviderAuthToken = (providerToken: string, username?: stri if (decodedToken.username !== username) throw new Error("Invalid auth credentials"); if (decodedToken.organizationId) { - return { orgId: decodedToken.organizationId, authMethod: decodedToken.authMethod }; + return { orgId: decodedToken.organizationId, authMethod: decodedToken.authMethod, userName: decodedToken.username }; } - return { authMethod: decodedToken.authMethod, orgId: null }; + return { authMethod: decodedToken.authMethod, orgId: null, userName: decodedToken.username }; }; export const validateSignUpAuthorization = (token: string, userId: string, validate = true) => { diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts index a136508e7..29a2a176f 100644 --- a/backend/src/services/auth/auth-login-service.ts +++ b/backend/src/services/auth/auth-login-service.ts @@ -1,3 +1,4 @@ +import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import { TUsers, UserDeviceSchema } from "@app/db/schemas"; @@ -5,6 +6,8 @@ import { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns"; import { getConfig } from "@app/lib/config/env"; import { request } from "@app/lib/config/request"; import { generateSrpServerKey, srpCheckClientProof } from "@app/lib/crypto"; +import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption"; +import { getUserPrivateKey } from "@app/lib/crypto/srp"; import { BadRequestError, DatabaseError, UnauthorizedError } from "@app/lib/errors"; import { getServerCfg } from "@app/services/super-admin/super-admin-service"; @@ -19,6 +22,7 @@ import { TLoginClientProofDTO, TLoginGenServerPublicKeyDTO, TOauthLoginDTO, + TOauthTokenExchangeDTO, TVerifyMfaTokenDTO } from "./auth-login-type"; import { AuthMethod, AuthModeJwtTokenPayload, AuthModeMfaJwtTokenPayload, AuthTokenType } from "./auth-type"; @@ -101,7 +105,7 @@ export const authLoginServiceFactory = ({ user: TUsers; ip: string; userAgent: string; - organizationId: string | undefined; + organizationId?: string; authMethod: AuthMethod; }) => { const cfg = getConfig(); @@ -178,7 +182,8 @@ export const authLoginServiceFactory = ({ ip, userAgent, providerAuthToken, - captchaToken + captchaToken, + password }: TLoginClientProofDTO) => { const appCfg = getConfig(); @@ -248,14 +253,29 @@ export const authLoginServiceFactory = ({ throw new Error("Failed to authenticate. Try again?"); } - await userDAL.updateUserEncryptionByUserId(userEnc.userId, { - serverPrivateKey: null, - clientPublicKey: null - }); - await userDAL.updateById(userEnc.userId, { consecutiveFailedPasswordAttempts: 0 }); + // from password decrypt the private key + if (password) { + const privateKey = await getUserPrivateKey(password, userEnc); + const hashedPassword = await bcrypt.hash(password, cfg.BCRYPT_SALT_ROUND); + const { iv, tag, ciphertext, encoding } = infisicalSymmetricEncypt(privateKey); + await userDAL.updateUserEncryptionByUserId(userEnc.userId, { + serverPrivateKey: null, + clientPublicKey: null, + hashedPassword, + serverEncryptedPrivateKey: ciphertext, + serverEncryptedPrivateKeyIV: iv, + serverEncryptedPrivateKeyTag: tag, + serverEncryptedPrivateKeyEncoding: encoding + }); + } else { + await userDAL.updateUserEncryptionByUserId(userEnc.userId, { + serverPrivateKey: null, + clientPublicKey: null + }); + } // send multi factor auth token if they it enabled if (userEnc.isMfaEnabled && userEnc.email) { @@ -499,8 +519,14 @@ export const authLoginServiceFactory = ({ authMethods: [authMethod], isGhost: false }); + } else { + const isLinkingRequired = !user?.authMethods?.includes(authMethod); + if (isLinkingRequired) { + user = await userDAL.updateById(user.id, { authMethods: [...(user.authMethods || []), authMethod] }); + } } - const isLinkingRequired = !user?.authMethods?.includes(authMethod); + + const userEnc = await userDAL.findUserEncKeyByUserId(user.id); const isUserCompleted = user.isAccepted; const providerAuthToken = jwt.sign( { @@ -511,9 +537,9 @@ export const authLoginServiceFactory = ({ isEmailVerified: user.isEmailVerified, firstName: user.firstName, lastName: user.lastName, + hasExchangedPrivateKey: Boolean(userEnc?.serverEncryptedPrivateKey), authMethod, isUserCompleted, - isLinkingRequired, ...(callbackPort ? { callbackPort @@ -525,10 +551,71 @@ export const authLoginServiceFactory = ({ expiresIn: appCfg.JWT_PROVIDER_AUTH_LIFETIME } ); - return { isUserCompleted, providerAuthToken }; }; + /** + * Handles OAuth2 token exchange for user login with private key handoff. + * + * The process involves exchanging a provider's authorization token for an Infisical access token. + * The provider token is returned to the client, who then sends it back to obtain the Infisical access token. + * + * This approach is used instead of directly sending the access token for the following reasons: + * 1. To facilitate easier logic changes from SRP OAuth to simple OAuth. + * 2. To avoid attaching the access token to the URL, which could be logged. The provider token has a very short lifespan, reducing security risks. + */ + const oauth2TokenExchange = async ({ userAgent, ip, providerAuthToken, email }: TOauthTokenExchangeDTO) => { + const decodedProviderToken = validateProviderAuthToken(providerAuthToken, email); + + const appCfg = getConfig(); + const { authMethod, userName } = decodedProviderToken; + if (!userName) throw new BadRequestError({ message: "Missing user name" }); + const organizationId = + (isAuthMethodSaml(authMethod) || authMethod === AuthMethod.LDAP) && decodedProviderToken.orgId + ? decodedProviderToken.orgId + : undefined; + + const userEnc = await userDAL.findUserEncKeyByUsername({ + username: email + }); + if (!userEnc) throw new BadRequestError({ message: "Invalid token" }); + if (!userEnc.serverEncryptedPrivateKey) + throw new BadRequestError({ message: "Key handoff incomplete. Please try logging in again." }); + // send multi factor auth token if they it enabled + if (userEnc.isMfaEnabled && userEnc.email) { + enforceUserLockStatus(Boolean(userEnc.isLocked), userEnc.temporaryLockDateEnd); + + const mfaToken = jwt.sign( + { + authMethod, + authTokenType: AuthTokenType.MFA_TOKEN, + userId: userEnc.userId + }, + appCfg.AUTH_SECRET, + { + expiresIn: appCfg.JWT_MFA_LIFETIME + } + ); + + await sendUserMfaCode({ + userId: userEnc.userId, + email: userEnc.email + }); + + return { isMfaEnabled: true, token: mfaToken } as const; + } + + const token = await generateUserTokens({ + user: { ...userEnc, id: userEnc.userId }, + ip, + userAgent, + authMethod, + organizationId + }); + + return { token, isMfaEnabled: false, user: userEnc } as const; + }; + /* * logout user by incrementing the version by 1 meaning any old session will become invalid * as there number is behind @@ -542,6 +629,7 @@ export const authLoginServiceFactory = ({ loginExchangeClientProof, logout, oauth2Login, + oauth2TokenExchange, resendMfaToken, verifyMfaToken, selectOrganization, diff --git a/backend/src/services/auth/auth-login-type.ts b/backend/src/services/auth/auth-login-type.ts index 4f73ec996..db57d730e 100644 --- a/backend/src/services/auth/auth-login-type.ts +++ b/backend/src/services/auth/auth-login-type.ts @@ -13,6 +13,7 @@ export type TLoginClientProofDTO = { ip: string; userAgent: string; captchaToken?: string; + password?: string; }; export type TVerifyMfaTokenDTO = { @@ -31,3 +32,10 @@ export type TOauthLoginDTO = { authMethod: AuthMethod; callbackPort?: string; }; + +export type TOauthTokenExchangeDTO = { + providerAuthToken: string; + ip: string; + userAgent: string; + email: string; +}; diff --git a/backend/src/services/auth/auth-password-service.ts b/backend/src/services/auth/auth-password-service.ts index a400c297b..0e6558966 100644 --- a/backend/src/services/auth/auth-password-service.ts +++ b/backend/src/services/auth/auth-password-service.ts @@ -1,3 +1,4 @@ +import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import { SecretEncryptionAlgo, SecretKeyEncoding } from "@app/db/schemas"; @@ -57,7 +58,8 @@ export const authPaswordServiceFactory = ({ encryptedPrivateKeyTag, salt, verifier, - tokenVersionId + tokenVersionId, + password }: TChangePasswordDTO) => { const userEnc = await userDAL.findUserEncKeyByUserId(userId); if (!userEnc) throw new Error("Failed to find user"); @@ -76,6 +78,8 @@ export const authPaswordServiceFactory = ({ ); if (!isValidClientProof) throw new Error("Failed to authenticate. Try again?"); + const appCfg = getConfig(); + const hashedPassword = await bcrypt.hash(password, appCfg.BCRYPT_SALT_ROUND); await userDAL.updateUserEncryptionByUserId(userId, { encryptionVersion: 2, protectedKey, @@ -87,7 +91,8 @@ export const authPaswordServiceFactory = ({ salt, verifier, serverPrivateKey: null, - clientPublicKey: null + clientPublicKey: null, + hashedPassword }); if (tokenVersionId) { diff --git a/backend/src/services/auth/auth-password-type.ts b/backend/src/services/auth/auth-password-type.ts index cf2aac08d..a52374506 100644 --- a/backend/src/services/auth/auth-password-type.ts +++ b/backend/src/services/auth/auth-password-type.ts @@ -10,6 +10,7 @@ export type TChangePasswordDTO = { salt: string; verifier: string; tokenVersionId?: string; + password: string; }; export type TResetPasswordViaBackupKeyDTO = { diff --git a/backend/src/services/auth/auth-signup-service.ts b/backend/src/services/auth/auth-signup-service.ts index 528cb44fa..8cf2c9d34 100644 --- a/backend/src/services/auth/auth-signup-service.ts +++ b/backend/src/services/auth/auth-signup-service.ts @@ -1,3 +1,4 @@ +import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import { OrgMembershipStatus, TableName } from "@app/db/schemas"; @@ -6,6 +7,8 @@ import { TUserGroupMembershipDALFactory } from "@app/ee/services/group/user-grou import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns"; import { getConfig } from "@app/lib/config/env"; +import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption"; +import { getUserPrivateKey } from "@app/lib/crypto/srp"; import { BadRequestError } from "@app/lib/errors"; import { isDisposableEmail } from "@app/lib/validator"; import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal"; @@ -119,6 +122,7 @@ export const authSignupServiceFactory = ({ const completeEmailAccountSignup = async ({ email, + password, firstName, lastName, providerAuthToken, @@ -137,6 +141,7 @@ export const authSignupServiceFactory = ({ userAgent, authorization }: TCompleteAccountSignupDTO) => { + const appCfg = getConfig(); const user = await userDAL.findOne({ username: email }); if (!user || (user && user.isAccepted)) { throw new Error("Failed to complete account for complete user"); @@ -152,6 +157,17 @@ export const authSignupServiceFactory = ({ validateSignUpAuthorization(authorization, user.id); } + const hashedPassword = await bcrypt.hash(password, appCfg.BCRYPT_SALT_ROUND); + const privateKey = await getUserPrivateKey(password, { + salt, + protectedKey, + protectedKeyIV, + protectedKeyTag, + encryptedPrivateKey, + iv: encryptedPrivateKeyIV, + tag: encryptedPrivateKeyTag + }); + const { tag, encoding, ciphertext, iv } = infisicalSymmetricEncypt(privateKey); const updateduser = await authDAL.transaction(async (tx) => { const us = await userDAL.updateById(user.id, { firstName, lastName, isAccepted: true }, tx); if (!us) throw new Error("User not found"); @@ -166,7 +182,12 @@ export const authSignupServiceFactory = ({ protectedKeyTag, encryptedPrivateKey, iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag + tag: encryptedPrivateKeyTag, + hashedPassword, + serverEncryptedPrivateKeyEncoding: encoding, + serverEncryptedPrivateKeyTag: tag, + serverEncryptedPrivateKeyIV: iv, + serverEncryptedPrivateKey: ciphertext }, tx ); @@ -227,7 +248,6 @@ export const authSignupServiceFactory = ({ userId: updateduser.info.id }); if (!tokenSession) throw new Error("Failed to create token"); - const appCfg = getConfig(); const accessToken = jwt.sign( { @@ -265,6 +285,7 @@ export const authSignupServiceFactory = ({ ip, salt, email, + password, verifier, firstName, publicKey, @@ -295,6 +316,18 @@ export const authSignupServiceFactory = ({ name: "complete account invite" }); + const appCfg = getConfig(); + const hashedPassword = await bcrypt.hash(password, appCfg.BCRYPT_SALT_ROUND); + const privateKey = await getUserPrivateKey(password, { + salt, + protectedKey, + protectedKeyIV, + protectedKeyTag, + encryptedPrivateKey, + iv: encryptedPrivateKeyIV, + tag: encryptedPrivateKeyTag + }); + const { tag, encoding, ciphertext, iv } = infisicalSymmetricEncypt(privateKey); const updateduser = await authDAL.transaction(async (tx) => { const us = await userDAL.updateById(user.id, { firstName, lastName, isAccepted: true }, tx); if (!us) throw new Error("User not found"); @@ -310,7 +343,12 @@ export const authSignupServiceFactory = ({ protectedKeyTag, encryptedPrivateKey, iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag + tag: encryptedPrivateKeyTag, + hashedPassword, + serverEncryptedPrivateKeyEncoding: encoding, + serverEncryptedPrivateKeyTag: tag, + serverEncryptedPrivateKeyIV: iv, + serverEncryptedPrivateKey: ciphertext }, tx ); @@ -343,7 +381,6 @@ export const authSignupServiceFactory = ({ userId: updateduser.info.id }); if (!tokenSession) throw new Error("Failed to create token"); - const appCfg = getConfig(); const accessToken = jwt.sign( { diff --git a/backend/src/services/auth/auth-signup-type.ts b/backend/src/services/auth/auth-signup-type.ts index a37a1cd96..9cd70f8c7 100644 --- a/backend/src/services/auth/auth-signup-type.ts +++ b/backend/src/services/auth/auth-signup-type.ts @@ -1,5 +1,6 @@ export type TCompleteAccountSignupDTO = { email: string; + password: string; firstName: string; lastName?: string; protectedKey: string; @@ -21,6 +22,7 @@ export type TCompleteAccountSignupDTO = { export type TCompleteAccountInviteDTO = { email: string; + password: string; firstName: string; lastName?: string; protectedKey: string; diff --git a/backend/src/services/super-admin/super-admin-service.ts b/backend/src/services/super-admin/super-admin-service.ts index bec8f3f37..f1d931b20 100644 --- a/backend/src/services/super-admin/super-admin-service.ts +++ b/backend/src/services/super-admin/super-admin-service.ts @@ -1,6 +1,10 @@ +import bcrypt from "bcrypt"; + import { TSuperAdmin, TSuperAdminUpdate } from "@app/db/schemas"; import { TKeyStoreFactory } from "@app/keystore/keystore"; import { getConfig } from "@app/lib/config/env"; +import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption"; +import { getUserPrivateKey } from "@app/lib/crypto/srp"; import { BadRequestError } from "@app/lib/errors"; import { TAuthLoginFactory } from "../auth/auth-login-service"; @@ -77,6 +81,7 @@ export const superAdminServiceFactory = ({ firstName, salt, email, + password, verifier, publicKey, protectedKey, @@ -92,6 +97,17 @@ export const superAdminServiceFactory = ({ const existingUser = await userDAL.findOne({ email }); if (existingUser) throw new BadRequestError({ name: "Admin sign up", message: "User already exist" }); + const privateKey = await getUserPrivateKey(password, { + salt, + protectedKey, + protectedKeyIV, + protectedKeyTag, + encryptedPrivateKey, + iv: encryptedPrivateKeyIV, + tag: encryptedPrivateKeyTag + }); + const hashedPassword = await bcrypt.hash(password, appCfg.BCRYPT_SALT_ROUND); + const { iv, tag, ciphertext, encoding } = infisicalSymmetricEncypt(privateKey); const userInfo = await userDAL.transaction(async (tx) => { const newUser = await userDAL.create( { @@ -119,7 +135,12 @@ export const superAdminServiceFactory = ({ iv: encryptedPrivateKeyIV, tag: encryptedPrivateKeyTag, verifier, - userId: newUser.id + userId: newUser.id, + hashedPassword, + serverEncryptedPrivateKey: ciphertext, + serverEncryptedPrivateKeyIV: iv, + serverEncryptedPrivateKeyTag: tag, + serverEncryptedPrivateKeyEncoding: encoding }, tx ); diff --git a/backend/src/services/super-admin/super-admin-types.ts b/backend/src/services/super-admin/super-admin-types.ts index e586946f2..e444c8843 100644 --- a/backend/src/services/super-admin/super-admin-types.ts +++ b/backend/src/services/super-admin/super-admin-types.ts @@ -1,5 +1,6 @@ export type TAdminSignUpDTO = { email: string; + password: string; publicKey: string; salt: string; lastName?: string; diff --git a/backend/src/services/user/user-service.ts b/backend/src/services/user/user-service.ts index 693078fbd..4ee8bdc1f 100644 --- a/backend/src/services/user/user-service.ts +++ b/backend/src/services/user/user-service.ts @@ -1,3 +1,5 @@ +import { SecretKeyEncoding } from "@app/db/schemas"; +import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption"; import { BadRequestError } from "@app/lib/errors"; import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service"; import { TokenType } from "@app/services/auth-token/auth-token-types"; @@ -230,6 +232,21 @@ export const userServiceFactory = ({ ); }; + const getUserPrivateKey = async (userId: string) => { + const user = await userDAL.findUserEncKeyByUserId(userId); + if (!user?.serverEncryptedPrivateKey || !user.serverEncryptedPrivateKeyIV || !user.serverEncryptedPrivateKeyTag) { + throw new BadRequestError({ message: "Private key not found. Please login again" }); + } + const privateKey = infisicalSymmetricDecrypt({ + ciphertext: user.serverEncryptedPrivateKey, + tag: user.serverEncryptedPrivateKeyTag, + iv: user.serverEncryptedPrivateKeyIV, + keyEncoding: user.serverEncryptedPrivateKeyEncoding as SecretKeyEncoding + }); + + return privateKey; + }; + return { sendEmailVerificationCode, verifyEmailVerificationCode, @@ -240,6 +257,7 @@ export const userServiceFactory = ({ getMe, createUserAction, getUserAction, - unlockUser + unlockUser, + getUserPrivateKey }; }; diff --git a/cli/packages/api/model.go b/cli/packages/api/model.go index 56b9807f7..0fffe0520 100644 --- a/cli/packages/api/model.go +++ b/cli/packages/api/model.go @@ -233,6 +233,7 @@ type GetLoginOneV2Response struct { type GetLoginTwoV2Request struct { Email string `json:"email"` ClientProof string `json:"clientProof"` + Password string `json:"password"` } type GetLoginTwoV2Response struct { diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go index 61e24b12f..a81a903a8 100644 --- a/cli/packages/cmd/login.go +++ b/cli/packages/cmd/login.go @@ -539,6 +539,7 @@ func getFreshUserCredentials(email string, password string) (*api.GetLoginOneV2R loginTwoResponseResult, err := api.CallLogin2V2(httpClient, api.GetLoginTwoV2Request{ Email: email, ClientProof: hex.EncodeToString(srpM1), + Password: password, }) if err != nil { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 489df0ea1..b79dd8815 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -4,6 +4,7 @@ "requires": true, "packages": { "": { + "name": "frontend", "dependencies": { "@casl/ability": "^6.5.0", "@casl/react": "^3.1.0", @@ -2109,9 +2110,9 @@ } }, "node_modules/@babel/register": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", - "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", + "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", "dev": true, "dependencies": { "clone-deep": "^4.0.1", @@ -6199,15 +6200,15 @@ } }, "node_modules/@storybook/builder-manager": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.6.8.tgz", - "integrity": "sha512-4CZo1RHPlDJA7G+lJoVdi+/3/L1ERxVxtvwuGgk8CxVDt6vFNpoc7fEGryNv3GRzKN1/luNYNU1MTnCUSn0B2g==", + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.6.19.tgz", + "integrity": "sha512-Dt5OLh97xeWh4h2mk9uG0SbCxBKHPhIiHLHAKEIDzIZBdwUhuyncVNDPHW2NlXM+S7U0/iKs2tw05waqh2lHvg==", "dev": true, "dependencies": { "@fal-works/esbuild-plugin-global-externals": "^2.1.2", - "@storybook/core-common": "7.6.8", - "@storybook/manager": "7.6.8", - "@storybook/node-logger": "7.6.8", + "@storybook/core-common": "7.6.19", + "@storybook/manager": "7.6.19", + "@storybook/node-logger": "7.6.19", "@types/ejs": "^3.1.1", "@types/find-cache-dir": "^3.2.1", "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", @@ -6226,6 +6227,111 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/builder-manager/node_modules/@storybook/channels": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.19.tgz", + "integrity": "sha512-2JGh+i95GwjtjqWqhtEh15jM5ifwbRGmXeFqkY7dpdHH50EEWafYHr2mg3opK3heVDwg0rJ/VBptkmshloXuvA==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "7.6.19", + "@storybook/core-events": "7.6.19", + "@storybook/global": "^5.0.0", + "qs": "^6.10.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@storybook/client-logger": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.19.tgz", + "integrity": "sha512-oGzOxbmLmciSIfd5gsxDzPmX8DttWhoYdPKxjMuCuWLTO2TWpkCWp1FTUMWO72mm/6V/FswT/aqpJJBBvdZ3RQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@storybook/core-common": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.6.19.tgz", + "integrity": "sha512-njwpGzFJrfbJr/AFxGP8KMrfPfxN85KOfSlxYnQwRm5Z0H1D/lT33LhEBf5m37gaGawHeG7KryxO6RvaioMt2Q==", + "dev": true, + "dependencies": { + "@storybook/core-events": "7.6.19", + "@storybook/node-logger": "7.6.19", + "@storybook/types": "7.6.19", + "@types/find-cache-dir": "^3.2.1", + "@types/node": "^18.0.0", + "@types/node-fetch": "^2.6.4", + "@types/pretty-hrtime": "^1.0.0", + "chalk": "^4.1.0", + "esbuild": "^0.18.0", + "esbuild-register": "^3.5.0", + "file-system-cache": "2.3.0", + "find-cache-dir": "^3.0.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "glob": "^10.0.0", + "handlebars": "^4.7.7", + "lazy-universal-dotenv": "^4.0.0", + "node-fetch": "^2.0.0", + "picomatch": "^2.3.0", + "pkg-dir": "^5.0.0", + "pretty-hrtime": "^1.0.3", + "resolve-from": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@storybook/core-events": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.19.tgz", + "integrity": "sha512-K/W6Uvum0ocZSgjbi8hiotpe+wDEHDZlvN+KlPqdh9ae9xDK8aBNBq9IelCoqM+uKO1Zj+dDfSQds7CD781DJg==", + "dev": true, + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@storybook/node-logger": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.19.tgz", + "integrity": "sha512-2g29QC44Zl1jKY37DmQ0/dO7+VSKnGgPI/x0mwVwQffypSapxH3rwLLT5Q5XLHeFyD+fhRu5w9Cj4vTGynJgpA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/builder-manager/node_modules/@storybook/types": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.19.tgz", + "integrity": "sha512-DeGYrRPRMGTVfT7o2rEZtRzyLT2yKTI2exgpnxbwPWEFAduZCSfzBrcBXZ/nb5B0pjA9tUNWls1YzGkJGlkhpg==", + "dev": true, + "dependencies": { + "@storybook/channels": "7.6.19", + "@types/babel__core": "^7.0.0", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/builder-webpack5": { "version": "7.6.8", "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-7.6.8.tgz", @@ -6332,23 +6438,23 @@ } }, "node_modules/@storybook/cli": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.6.8.tgz", - "integrity": "sha512-Is8nkgsbIOu+Jk9Z7x5sgMPgGs9RTVDum3cz9eA4UspPiIBJsf7nGHAWOtc+mCIm6Z3eeNbT1YMOWxz9EuqboA==", + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.6.19.tgz", + "integrity": "sha512-7OVy7nPgkLfgivv6/dmvoyU6pKl9EzWFk+g9izyQHiM/jS8jOiEyn6akG8Ebj6k5pWslo5lgiXUSW+cEEZUnqQ==", "dev": true, "dependencies": { "@babel/core": "^7.23.2", "@babel/preset-env": "^7.23.2", "@babel/types": "^7.23.0", "@ndelangen/get-tarball": "^3.0.7", - "@storybook/codemod": "7.6.8", - "@storybook/core-common": "7.6.8", - "@storybook/core-events": "7.6.8", - "@storybook/core-server": "7.6.8", - "@storybook/csf-tools": "7.6.8", - "@storybook/node-logger": "7.6.8", - "@storybook/telemetry": "7.6.8", - "@storybook/types": "7.6.8", + "@storybook/codemod": "7.6.19", + "@storybook/core-common": "7.6.19", + "@storybook/core-events": "7.6.19", + "@storybook/core-server": "7.6.19", + "@storybook/csf-tools": "7.6.19", + "@storybook/node-logger": "7.6.19", + "@storybook/telemetry": "7.6.19", + "@storybook/types": "7.6.19", "@types/semver": "^7.3.4", "@yarnpkg/fslib": "2.10.3", "@yarnpkg/libzip": "2.3.0", @@ -6373,7 +6479,6 @@ "puppeteer-core": "^2.1.1", "read-pkg-up": "^7.0.1", "semver": "^7.3.7", - "simple-update-notifier": "^2.0.0", "strip-json-comments": "^3.0.1", "tempy": "^1.0.1", "ts-dedent": "^2.0.0", @@ -6388,6 +6493,132 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/cli/node_modules/@storybook/channels": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.19.tgz", + "integrity": "sha512-2JGh+i95GwjtjqWqhtEh15jM5ifwbRGmXeFqkY7dpdHH50EEWafYHr2mg3opK3heVDwg0rJ/VBptkmshloXuvA==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "7.6.19", + "@storybook/core-events": "7.6.19", + "@storybook/global": "^5.0.0", + "qs": "^6.10.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/cli/node_modules/@storybook/client-logger": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.19.tgz", + "integrity": "sha512-oGzOxbmLmciSIfd5gsxDzPmX8DttWhoYdPKxjMuCuWLTO2TWpkCWp1FTUMWO72mm/6V/FswT/aqpJJBBvdZ3RQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/cli/node_modules/@storybook/core-common": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.6.19.tgz", + "integrity": "sha512-njwpGzFJrfbJr/AFxGP8KMrfPfxN85KOfSlxYnQwRm5Z0H1D/lT33LhEBf5m37gaGawHeG7KryxO6RvaioMt2Q==", + "dev": true, + "dependencies": { + "@storybook/core-events": "7.6.19", + "@storybook/node-logger": "7.6.19", + "@storybook/types": "7.6.19", + "@types/find-cache-dir": "^3.2.1", + "@types/node": "^18.0.0", + "@types/node-fetch": "^2.6.4", + "@types/pretty-hrtime": "^1.0.0", + "chalk": "^4.1.0", + "esbuild": "^0.18.0", + "esbuild-register": "^3.5.0", + "file-system-cache": "2.3.0", + "find-cache-dir": "^3.0.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "glob": "^10.0.0", + "handlebars": "^4.7.7", + "lazy-universal-dotenv": "^4.0.0", + "node-fetch": "^2.0.0", + "picomatch": "^2.3.0", + "pkg-dir": "^5.0.0", + "pretty-hrtime": "^1.0.3", + "resolve-from": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/cli/node_modules/@storybook/core-events": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.19.tgz", + "integrity": "sha512-K/W6Uvum0ocZSgjbi8hiotpe+wDEHDZlvN+KlPqdh9ae9xDK8aBNBq9IelCoqM+uKO1Zj+dDfSQds7CD781DJg==", + "dev": true, + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/cli/node_modules/@storybook/csf-tools": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.6.19.tgz", + "integrity": "sha512-8Vzia3cHhDdGHuS3XKXJReCRxmfRq3vmTm/Te9yKZnPSAsC58CCKcMh8FNEFJ44vxYF9itKTkRutjGs+DprKLQ==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/types": "7.6.19", + "fs-extra": "^11.1.0", + "recast": "^0.23.1", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/cli/node_modules/@storybook/node-logger": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.19.tgz", + "integrity": "sha512-2g29QC44Zl1jKY37DmQ0/dO7+VSKnGgPI/x0mwVwQffypSapxH3rwLLT5Q5XLHeFyD+fhRu5w9Cj4vTGynJgpA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/cli/node_modules/@storybook/types": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.19.tgz", + "integrity": "sha512-DeGYrRPRMGTVfT7o2rEZtRzyLT2yKTI2exgpnxbwPWEFAduZCSfzBrcBXZ/nb5B0pjA9tUNWls1YzGkJGlkhpg==", + "dev": true, + "dependencies": { + "@storybook/channels": "7.6.19", + "@types/babel__core": "^7.0.0", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/cli/node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -6432,26 +6663,11 @@ "node": ">=10.17.0" } }, - "node_modules/@storybook/cli/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@storybook/cli/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -6459,12 +6675,6 @@ "node": ">=10" } }, - "node_modules/@storybook/cli/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@storybook/client-api": { "version": "7.6.8", "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.6.8.tgz", @@ -6493,18 +6703,18 @@ } }, "node_modules/@storybook/codemod": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.6.8.tgz", - "integrity": "sha512-3Gk+ZsD35DUgqbbRNdX547kzZK/ajIbgwynmR0FuPhZhhZuYI4+2eMNzdmI/Oe9Nov4R16senQuAZjw/Dc5LrA==", + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.6.19.tgz", + "integrity": "sha512-bmHE0iEEgWZ65dXCmasd+GreChjPiWkXu2FEa0cJmNz/PqY12GsXGls4ke1TkNTj4gdSZnbtJxbclPZZnib2tQ==", "dev": true, "dependencies": { "@babel/core": "^7.23.2", "@babel/preset-env": "^7.23.2", "@babel/types": "^7.23.0", "@storybook/csf": "^0.1.2", - "@storybook/csf-tools": "7.6.8", - "@storybook/node-logger": "7.6.8", - "@storybook/types": "7.6.8", + "@storybook/csf-tools": "7.6.19", + "@storybook/node-logger": "7.6.19", + "@storybook/types": "7.6.19", "@types/cross-spawn": "^6.0.2", "cross-spawn": "^7.0.3", "globby": "^11.0.2", @@ -6518,6 +6728,97 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/codemod/node_modules/@storybook/channels": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.19.tgz", + "integrity": "sha512-2JGh+i95GwjtjqWqhtEh15jM5ifwbRGmXeFqkY7dpdHH50EEWafYHr2mg3opK3heVDwg0rJ/VBptkmshloXuvA==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "7.6.19", + "@storybook/core-events": "7.6.19", + "@storybook/global": "^5.0.0", + "qs": "^6.10.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/@storybook/client-logger": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.19.tgz", + "integrity": "sha512-oGzOxbmLmciSIfd5gsxDzPmX8DttWhoYdPKxjMuCuWLTO2TWpkCWp1FTUMWO72mm/6V/FswT/aqpJJBBvdZ3RQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/@storybook/core-events": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.19.tgz", + "integrity": "sha512-K/W6Uvum0ocZSgjbi8hiotpe+wDEHDZlvN+KlPqdh9ae9xDK8aBNBq9IelCoqM+uKO1Zj+dDfSQds7CD781DJg==", + "dev": true, + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/@storybook/csf-tools": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.6.19.tgz", + "integrity": "sha512-8Vzia3cHhDdGHuS3XKXJReCRxmfRq3vmTm/Te9yKZnPSAsC58CCKcMh8FNEFJ44vxYF9itKTkRutjGs+DprKLQ==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/types": "7.6.19", + "fs-extra": "^11.1.0", + "recast": "^0.23.1", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/@storybook/node-logger": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.19.tgz", + "integrity": "sha512-2g29QC44Zl1jKY37DmQ0/dO7+VSKnGgPI/x0mwVwQffypSapxH3rwLLT5Q5XLHeFyD+fhRu5w9Cj4vTGynJgpA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/@storybook/types": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.19.tgz", + "integrity": "sha512-DeGYrRPRMGTVfT7o2rEZtRzyLT2yKTI2exgpnxbwPWEFAduZCSfzBrcBXZ/nb5B0pjA9tUNWls1YzGkJGlkhpg==", + "dev": true, + "dependencies": { + "@storybook/channels": "7.6.19", + "@types/babel__core": "^7.0.0", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/components": { "version": "7.6.8", "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.6.8.tgz", @@ -6762,26 +7063,26 @@ } }, "node_modules/@storybook/core-server": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.6.8.tgz", - "integrity": "sha512-/csAFNuAhF11f6D9neYNavmKPFK/ZxTskaktc4iDwBRgBM95kZ6DBFjg9ErRi5Q8Z/i92wk6qORkq4bkN/lI9w==", + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.6.19.tgz", + "integrity": "sha512-7mKL73Wv5R2bEl0kJ6QJ9bOu5YY53Idu24QgvTnUdNsQazp2yUONBNwHIrNDnNEXm8SfCi4Mc9o0mmNRMIoiRA==", "dev": true, "dependencies": { "@aw-web-design/x-default-browser": "1.4.126", "@discoveryjs/json-ext": "^0.5.3", - "@storybook/builder-manager": "7.6.8", - "@storybook/channels": "7.6.8", - "@storybook/core-common": "7.6.8", - "@storybook/core-events": "7.6.8", + "@storybook/builder-manager": "7.6.19", + "@storybook/channels": "7.6.19", + "@storybook/core-common": "7.6.19", + "@storybook/core-events": "7.6.19", "@storybook/csf": "^0.1.2", - "@storybook/csf-tools": "7.6.8", + "@storybook/csf-tools": "7.6.19", "@storybook/docs-mdx": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/manager": "7.6.8", - "@storybook/node-logger": "7.6.8", - "@storybook/preview-api": "7.6.8", - "@storybook/telemetry": "7.6.8", - "@storybook/types": "7.6.8", + "@storybook/manager": "7.6.19", + "@storybook/node-logger": "7.6.19", + "@storybook/preview-api": "7.6.19", + "@storybook/telemetry": "7.6.19", + "@storybook/types": "7.6.19", "@types/detect-port": "^1.3.0", "@types/node": "^18.0.0", "@types/pretty-hrtime": "^1.0.0", @@ -6794,7 +7095,7 @@ "express": "^4.17.3", "fs-extra": "^11.1.0", "globby": "^11.0.2", - "ip": "^2.0.0", + "ip": "^2.0.1", "lodash": "^4.17.21", "open": "^8.4.0", "pretty-hrtime": "^1.0.3", @@ -6814,26 +7115,163 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/core-server/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@storybook/core-server/node_modules/@storybook/channels": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.19.tgz", + "integrity": "sha512-2JGh+i95GwjtjqWqhtEh15jM5ifwbRGmXeFqkY7dpdHH50EEWafYHr2mg3opK3heVDwg0rJ/VBptkmshloXuvA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "@storybook/client-logger": "7.6.19", + "@storybook/core-events": "7.6.19", + "@storybook/global": "^5.0.0", + "qs": "^6.10.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" }, - "engines": { - "node": ">=10" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@storybook/client-logger": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.19.tgz", + "integrity": "sha512-oGzOxbmLmciSIfd5gsxDzPmX8DttWhoYdPKxjMuCuWLTO2TWpkCWp1FTUMWO72mm/6V/FswT/aqpJJBBvdZ3RQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@storybook/core-common": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.6.19.tgz", + "integrity": "sha512-njwpGzFJrfbJr/AFxGP8KMrfPfxN85KOfSlxYnQwRm5Z0H1D/lT33LhEBf5m37gaGawHeG7KryxO6RvaioMt2Q==", + "dev": true, + "dependencies": { + "@storybook/core-events": "7.6.19", + "@storybook/node-logger": "7.6.19", + "@storybook/types": "7.6.19", + "@types/find-cache-dir": "^3.2.1", + "@types/node": "^18.0.0", + "@types/node-fetch": "^2.6.4", + "@types/pretty-hrtime": "^1.0.0", + "chalk": "^4.1.0", + "esbuild": "^0.18.0", + "esbuild-register": "^3.5.0", + "file-system-cache": "2.3.0", + "find-cache-dir": "^3.0.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "glob": "^10.0.0", + "handlebars": "^4.7.7", + "lazy-universal-dotenv": "^4.0.0", + "node-fetch": "^2.0.0", + "picomatch": "^2.3.0", + "pkg-dir": "^5.0.0", + "pretty-hrtime": "^1.0.3", + "resolve-from": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@storybook/core-events": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.19.tgz", + "integrity": "sha512-K/W6Uvum0ocZSgjbi8hiotpe+wDEHDZlvN+KlPqdh9ae9xDK8aBNBq9IelCoqM+uKO1Zj+dDfSQds7CD781DJg==", + "dev": true, + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@storybook/csf-tools": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.6.19.tgz", + "integrity": "sha512-8Vzia3cHhDdGHuS3XKXJReCRxmfRq3vmTm/Te9yKZnPSAsC58CCKcMh8FNEFJ44vxYF9itKTkRutjGs+DprKLQ==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/types": "7.6.19", + "fs-extra": "^11.1.0", + "recast": "^0.23.1", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@storybook/node-logger": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.19.tgz", + "integrity": "sha512-2g29QC44Zl1jKY37DmQ0/dO7+VSKnGgPI/x0mwVwQffypSapxH3rwLLT5Q5XLHeFyD+fhRu5w9Cj4vTGynJgpA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@storybook/preview-api": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.19.tgz", + "integrity": "sha512-04hdMSQucroJT4dBjQzRd7ZwH2hij8yx2nm5qd4HYGkd1ORkvlH6GOLph4XewNJl5Um3xfzFQzBhvkqvG0WaCQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "7.6.19", + "@storybook/client-logger": "7.6.19", + "@storybook/core-events": "7.6.19", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/types": "7.6.19", + "@types/qs": "^6.9.5", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server/node_modules/@storybook/types": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.19.tgz", + "integrity": "sha512-DeGYrRPRMGTVfT7o2rEZtRzyLT2yKTI2exgpnxbwPWEFAduZCSfzBrcBXZ/nb5B0pjA9tUNWls1YzGkJGlkhpg==", + "dev": true, + "dependencies": { + "@storybook/channels": "7.6.19", + "@types/babel__core": "^7.0.0", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, "node_modules/@storybook/core-server/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -6841,12 +7279,6 @@ "node": ">=10" } }, - "node_modules/@storybook/core-server/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@storybook/core-webpack": { "version": "7.6.8", "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-7.6.8.tgz", @@ -6940,9 +7372,9 @@ "dev": true }, "node_modules/@storybook/manager": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.6.8.tgz", - "integrity": "sha512-INoXXoHXyw9PPMJAOAhwf9u2GNDDNdv1JAI1fhrbCAECzDabHT9lRVUo6v8I5XMc+YdMHLM1Vz38DbB+w18hFw==", + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.6.19.tgz", + "integrity": "sha512-fZWQcf59x4P0iiBhrL74PZrqKJAPuk9sWjP8BIkGbf8wTZtUunbY5Sv4225fOL4NLJbuX9/RYLUPoxQ3nucGHA==", "dev": true, "funding": { "type": "opencollective", @@ -7378,14 +7810,14 @@ } }, "node_modules/@storybook/telemetry": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.6.8.tgz", - "integrity": "sha512-hHUS3fyHjKR3ZdbG+/OVI+pwXXKOmS8L8GMuWKlpUovvCYBLm0/Q0MUQ9XaLuByOCzvAurqB3Owp3ZV7GiY30Q==", + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.6.19.tgz", + "integrity": "sha512-rA5xum4I36M57iiD3uzmW0MOdpl0vEpHWBSAa5hK0a0ALPeY9TgAsQlI/0dSyNYJ/K7aczEEN6d4qm1NC4u10A==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.8", - "@storybook/core-common": "7.6.8", - "@storybook/csf-tools": "7.6.8", + "@storybook/client-logger": "7.6.19", + "@storybook/core-common": "7.6.19", + "@storybook/csf-tools": "7.6.19", "chalk": "^4.1.0", "detect-package-manager": "^2.0.1", "fetch-retry": "^5.0.2", @@ -7397,6 +7829,132 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/telemetry/node_modules/@storybook/channels": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.19.tgz", + "integrity": "sha512-2JGh+i95GwjtjqWqhtEh15jM5ifwbRGmXeFqkY7dpdHH50EEWafYHr2mg3opK3heVDwg0rJ/VBptkmshloXuvA==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "7.6.19", + "@storybook/core-events": "7.6.19", + "@storybook/global": "^5.0.0", + "qs": "^6.10.0", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/telemetry/node_modules/@storybook/client-logger": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.19.tgz", + "integrity": "sha512-oGzOxbmLmciSIfd5gsxDzPmX8DttWhoYdPKxjMuCuWLTO2TWpkCWp1FTUMWO72mm/6V/FswT/aqpJJBBvdZ3RQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/telemetry/node_modules/@storybook/core-common": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.6.19.tgz", + "integrity": "sha512-njwpGzFJrfbJr/AFxGP8KMrfPfxN85KOfSlxYnQwRm5Z0H1D/lT33LhEBf5m37gaGawHeG7KryxO6RvaioMt2Q==", + "dev": true, + "dependencies": { + "@storybook/core-events": "7.6.19", + "@storybook/node-logger": "7.6.19", + "@storybook/types": "7.6.19", + "@types/find-cache-dir": "^3.2.1", + "@types/node": "^18.0.0", + "@types/node-fetch": "^2.6.4", + "@types/pretty-hrtime": "^1.0.0", + "chalk": "^4.1.0", + "esbuild": "^0.18.0", + "esbuild-register": "^3.5.0", + "file-system-cache": "2.3.0", + "find-cache-dir": "^3.0.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "glob": "^10.0.0", + "handlebars": "^4.7.7", + "lazy-universal-dotenv": "^4.0.0", + "node-fetch": "^2.0.0", + "picomatch": "^2.3.0", + "pkg-dir": "^5.0.0", + "pretty-hrtime": "^1.0.3", + "resolve-from": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/telemetry/node_modules/@storybook/core-events": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.19.tgz", + "integrity": "sha512-K/W6Uvum0ocZSgjbi8hiotpe+wDEHDZlvN+KlPqdh9ae9xDK8aBNBq9IelCoqM+uKO1Zj+dDfSQds7CD781DJg==", + "dev": true, + "dependencies": { + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/telemetry/node_modules/@storybook/csf-tools": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.6.19.tgz", + "integrity": "sha512-8Vzia3cHhDdGHuS3XKXJReCRxmfRq3vmTm/Te9yKZnPSAsC58CCKcMh8FNEFJ44vxYF9itKTkRutjGs+DprKLQ==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/types": "7.6.19", + "fs-extra": "^11.1.0", + "recast": "^0.23.1", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/telemetry/node_modules/@storybook/node-logger": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.19.tgz", + "integrity": "sha512-2g29QC44Zl1jKY37DmQ0/dO7+VSKnGgPI/x0mwVwQffypSapxH3rwLLT5Q5XLHeFyD+fhRu5w9Cj4vTGynJgpA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/telemetry/node_modules/@storybook/types": { + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.19.tgz", + "integrity": "sha512-DeGYrRPRMGTVfT7o2rEZtRzyLT2yKTI2exgpnxbwPWEFAduZCSfzBrcBXZ/nb5B0pjA9tUNWls1YzGkJGlkhpg==", + "dev": true, + "dependencies": { + "@storybook/channels": "7.6.19", + "@types/babel__core": "^7.0.0", + "@types/express": "^4.7.0", + "file-system-cache": "2.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "node_modules/@storybook/testing-library": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/@storybook/testing-library/-/testing-library-0.2.2.tgz", @@ -7897,9 +8455,9 @@ "dev": true }, "node_modules/@types/emscripten": { - "version": "1.39.10", - "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.10.tgz", - "integrity": "sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw==", + "version": "1.39.13", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.13.tgz", + "integrity": "sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw==", "dev": true }, "node_modules/@types/escodegen": { @@ -10066,12 +10624,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -10531,9 +11089,9 @@ } }, "node_modules/citty": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.5.tgz", - "integrity": "sha512-AS7n5NSc0OQVMV9v6wt3ByujNIrne0/cTjiC2MYqhvao57VNfiuVksTSr2p17nVOhEr2KtqiAkGwHcgMC/qUuQ==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", "dev": true, "dependencies": { "consola": "^3.2.3" @@ -11862,9 +12420,9 @@ } }, "node_modules/detect-port": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", - "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", "dev": true, "dependencies": { "address": "^1.0.1", @@ -11873,6 +12431,9 @@ "bin": { "detect": "bin/detect-port.js", "detect-port": "bin/detect-port.js" + }, + "engines": { + "node": ">= 4.0.0" } }, "node_modules/detective": { @@ -12306,9 +12867,9 @@ } }, "node_modules/envinfo": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", - "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", "dev": true, "bin": { "envinfo": "dist/cli.js" @@ -13652,9 +14213,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -13828,9 +14389,9 @@ "dev": true }, "node_modules/flow-parser": { - "version": "0.226.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.226.0.tgz", - "integrity": "sha512-YlH+Y/P/5s0S7Vg14RwXlJMF/JsGfkG7gcKB/zljyoqaPNX9YVsGzx+g6MLTbhZaWbPhs4347aTpmSb9GgiPtw==", + "version": "0.237.2", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.237.2.tgz", + "integrity": "sha512-mvI/kdfr3l1waaPbThPA8dJa77nHXrfZIun+SWvFwSwDjmeByU7mGJGRmv1+7guU6ccyLV8e1lqZA1lD4iMGnQ==", "dev": true, "engines": { "node": ">=0.4.0" @@ -14287,18 +14848,18 @@ } }, "node_modules/giget": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.1.tgz", - "integrity": "sha512-4VG22mopWtIeHwogGSy1FViXVo0YT+m6BrqZfz0JJFwbSsePsCdOzdLIIli5BtMp7Xe8f/o2OmBpQX2NBOC24g==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", + "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", "dev": true, "dependencies": { - "citty": "^0.1.5", + "citty": "^0.1.6", "consola": "^3.2.3", - "defu": "^6.1.3", - "node-fetch-native": "^1.6.1", - "nypm": "^0.3.3", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.3", + "nypm": "^0.3.8", "ohash": "^1.1.3", - "pathe": "^1.1.1", + "pathe": "^1.1.2", "tar": "^6.2.0" }, "bin": { @@ -15856,9 +16417,9 @@ } }, "node_modules/jake": { - "version": "10.8.7", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", - "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz", + "integrity": "sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==", "dev": true, "dependencies": { "async": "^3.2.3", @@ -16024,9 +16585,9 @@ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" }, "node_modules/jscodeshift": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.1.tgz", - "integrity": "sha512-hIJfxUy8Rt4HkJn/zZPU9ChKfKZM1342waJ1QC2e2YsPcWhM+3BJ4dcfQCzArTrk1jJeNLB341H+qOcEHRxJZg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", + "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", "dev": true, "dependencies": { "@babel/core": "^7.23.0", @@ -17897,9 +18458,9 @@ } }, "node_modules/node-fetch-native": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.1.tgz", - "integrity": "sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw==", + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", + "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", "dev": true }, "node_modules/node-int64": { @@ -18061,15 +18622,16 @@ } }, "node_modules/nypm": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.4.tgz", - "integrity": "sha512-1JLkp/zHBrkS3pZ692IqOaIKSYHmQXgqfELk6YTOfVBnwealAmPA1q2kKK7PHJAHSMBozerThEFZXP3G6o7Ukg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.8.tgz", + "integrity": "sha512-IGWlC6So2xv6V4cIDmoV0SwwWx7zLG086gyqkyumteH2fIgCAM4nDVFB2iDRszDvmdSVW9xb1N+2KjQ6C7d4og==", "dev": true, "dependencies": { - "citty": "^0.1.5", + "citty": "^0.1.6", + "consola": "^3.2.3", "execa": "^8.0.1", - "pathe": "^1.1.1", - "ufo": "^1.3.2" + "pathe": "^1.1.2", + "ufo": "^1.4.0" }, "bin": { "nypm": "dist/cli.mjs" @@ -18147,9 +18709,9 @@ } }, "node_modules/nypm/node_modules/npm-run-path": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", - "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { "path-key": "^4.0.0" @@ -19643,6 +20205,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -19693,6 +20256,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { "glob": "^7.1.3" @@ -21653,51 +22217,6 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-update-notifier/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-update-notifier/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -21788,9 +22307,9 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -21804,9 +22323,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", - "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", + "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", "dev": true }, "node_modules/split-on-first": { @@ -21902,12 +22421,12 @@ "dev": true }, "node_modules/storybook": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.6.8.tgz", - "integrity": "sha512-ugRtDSs2eTgHMOZ3wKXbUEbPnlJ2XImPbnvxNssK14py2mHKwPnhSqLNrjlQMkmkO13GdjalLDyj4lZtoYdo0Q==", + "version": "7.6.19", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.6.19.tgz", + "integrity": "sha512-xWD1C4vD/4KMffCrBBrUpsLUO/9uNpm8BVW8+Vcb30gkQDfficZ0oziWkmLexpT53VSioa24iazGXMwBqllYjQ==", "dev": true, "dependencies": { - "@storybook/cli": "7.6.8" + "@storybook/cli": "7.6.19" }, "bin": { "sb": "index.js", @@ -21997,9 +22516,9 @@ } }, "node_modules/stream-shift": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.2.tgz", - "integrity": "sha512-rV4Bovi9xx0BFzOb/X0B2GqoIjvqPCttZdu0Wgtx2Dxkj7ETyWl9gmqJ4EutWRLvtZWm8dxE+InQZX1IryZn/w==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", "dev": true }, "node_modules/streamx": { @@ -22548,6 +23067,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -22568,6 +23088,7 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { "glob": "^7.1.3" @@ -23161,9 +23682,9 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, "node_modules/ufo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", - "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", "dev": true }, "node_modules/uglify-js": { @@ -24141,9 +24662,9 @@ } }, "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", "dev": true, "engines": { "node": ">=10.0.0" diff --git a/frontend/src/components/signup/UserInfoStep.tsx b/frontend/src/components/signup/UserInfoStep.tsx index c98998e35..705b490bb 100644 --- a/frontend/src/components/signup/UserInfoStep.tsx +++ b/frontend/src/components/signup/UserInfoStep.tsx @@ -161,6 +161,7 @@ export default function UserInfoStep({ const response = await completeAccountSignup({ email, + password, firstName: name.split(" ")[0], lastName: name.split(" ").slice(1).join(" "), protectedKey, diff --git a/frontend/src/components/utilities/attemptChangePassword.ts b/frontend/src/components/utilities/attemptChangePassword.ts index 5a810334b..45281f2f2 100644 --- a/frontend/src/components/utilities/attemptChangePassword.ts +++ b/frontend/src/components/utilities/attemptChangePassword.ts @@ -72,6 +72,7 @@ const attemptChangePassword = ({ email, currentPassword, newPassword }: Params): }); await changePassword({ + password: newPassword, clientProof, protectedKey, protectedKeyIV, diff --git a/frontend/src/components/utilities/attemptCliLogin.ts b/frontend/src/components/utilities/attemptCliLogin.ts index 8f7c4bb9f..6eba08d61 100644 --- a/frontend/src/components/utilities/attemptCliLogin.ts +++ b/frontend/src/components/utilities/attemptCliLogin.ts @@ -71,6 +71,7 @@ const attemptLogin = async ({ tag } = await login2({ email, + password, clientProof, providerAuthToken, captchaToken diff --git a/frontend/src/components/utilities/attemptLogin.ts b/frontend/src/components/utilities/attemptLogin.ts index b909b1ba7..120ae62ec 100644 --- a/frontend/src/components/utilities/attemptLogin.ts +++ b/frontend/src/components/utilities/attemptLogin.ts @@ -62,6 +62,7 @@ const attemptLogin = async ({ } = await login2({ captchaToken, email, + password, clientProof, providerAuthToken }); diff --git a/frontend/src/hooks/api/admin/types.ts b/frontend/src/hooks/api/admin/types.ts index 6a42e6ed0..8d5f59ede 100644 --- a/frontend/src/hooks/api/admin/types.ts +++ b/frontend/src/hooks/api/admin/types.ts @@ -10,6 +10,7 @@ export type TServerConfig = { export type TCreateAdminUserDTO = { email: string; + password: string; firstName: string; lastName?: string; protectedKey: string; diff --git a/frontend/src/hooks/api/auth/index.tsx b/frontend/src/hooks/api/auth/index.tsx index 505f7b05f..66688cbdc 100644 --- a/frontend/src/hooks/api/auth/index.tsx +++ b/frontend/src/hooks/api/auth/index.tsx @@ -1,5 +1,6 @@ export { useGetAuthToken, + useOauthTokenExchange, useResetPassword, useSelectOrganization, useSendMfaToken, @@ -7,4 +8,5 @@ export { useSendVerificationEmail, useVerifyMfaToken, useVerifyPasswordResetCode, - useVerifySignupEmailVerificationCode} from "./queries"; + useVerifySignupEmailVerificationCode +} from "./queries"; diff --git a/frontend/src/hooks/api/auth/queries.tsx b/frontend/src/hooks/api/auth/queries.tsx index cba815fae..fcec4f2ef 100644 --- a/frontend/src/hooks/api/auth/queries.tsx +++ b/frontend/src/hooks/api/auth/queries.tsx @@ -23,6 +23,7 @@ import { SendMfaTokenDTO, SRP1DTO, SRPR1Res, + TOauthTokenExchangeDTO, VerifyMfaTokenDTO, VerifyMfaTokenRes, VerifySignupInviteDTO @@ -92,6 +93,7 @@ export const useLogin2 = () => { mutationFn: async (details: { email: string; clientProof: string; + password: string; providerAuthToken?: string; }) => { return login2(details); @@ -99,6 +101,20 @@ export const useLogin2 = () => { }); }; +export const oauthTokenExchange = async (details: TOauthTokenExchangeDTO) => { + const { data } = await apiRequest.post("/api/v1/sso/token-exchange", details); + return data; +}; + +export const useOauthTokenExchange = () => { + // note: use after srp1 + return useMutation({ + mutationFn: async (details: TOauthTokenExchangeDTO) => { + return oauthTokenExchange(details); + } + }); +}; + export const srp1 = async (details: SRP1DTO) => { const { data } = await apiRequest.post("/api/v1/password/srp1", details); return data; diff --git a/frontend/src/hooks/api/auth/types.ts b/frontend/src/hooks/api/auth/types.ts index ce1b18bc8..1b4dff1f0 100644 --- a/frontend/src/hooks/api/auth/types.ts +++ b/frontend/src/hooks/api/auth/types.ts @@ -23,6 +23,11 @@ export type VerifyMfaTokenRes = { tag: string; }; +export type TOauthTokenExchangeDTO = { + providerAuthToken: string; + email: string; +}; + export type Login1DTO = { email: string; clientPublicKey: string; @@ -34,6 +39,7 @@ export type Login2DTO = { email: string; clientProof: string; providerAuthToken?: string; + password: string; }; export type Login1Res = { @@ -86,6 +92,7 @@ export type CompleteAccountDTO = { encryptedPrivateKeyTag: string; salt: string; verifier: string; + password: string; }; export type CompleteAccountSignupDTO = CompleteAccountDTO & { @@ -101,6 +108,7 @@ export type VerifySignupInviteDTO = { }; export type ChangePasswordDTO = { + password: string; clientProof: string; protectedKey: string; protectedKeyIV: string; diff --git a/frontend/src/hooks/api/users/queries.tsx b/frontend/src/hooks/api/users/queries.tsx index a443c6750..fa0b932ea 100644 --- a/frontend/src/hooks/api/users/queries.tsx +++ b/frontend/src/hooks/api/users/queries.tsx @@ -20,6 +20,7 @@ import { export const userKeys = { getUser: ["user"] as const, + getPrivateKey: ["user"] as const, userAction: ["user-action"] as const, getOrgUsers: (orgId: string) => [{ orgId }, "user"], myIp: ["ip"] as const, @@ -351,3 +352,11 @@ export const useGetMyOrganizationProjects = (orgId: string) => { enabled: true }); }; + +export const fetchMyPrivateKey = async () => { + const { + data: { privateKey } + } = await apiRequest.get<{ privateKey: string }>("/api/v1/user/private-key"); + + return privateKey; +}; diff --git a/frontend/src/pages/signupinvite.tsx b/frontend/src/pages/signupinvite.tsx index a0c2f2430..725dc6113 100644 --- a/frontend/src/pages/signupinvite.tsx +++ b/frontend/src/pages/signupinvite.tsx @@ -149,6 +149,7 @@ export default function SignupInvite() { const { token: jwtToken } = await completeAccountSignupInvite({ email, + password, firstName, lastName, protectedKey, diff --git a/frontend/src/views/Login/components/MFAStep/MFAStep.tsx b/frontend/src/views/Login/components/MFAStep/MFAStep.tsx index b23af1cef..5e613008d 100644 --- a/frontend/src/views/Login/components/MFAStep/MFAStep.tsx +++ b/frontend/src/views/Login/components/MFAStep/MFAStep.tsx @@ -9,13 +9,12 @@ import Error from "@app/components/basic/Error"; import { createNotification } from "@app/components/notifications"; import attemptCliLoginMfa from "@app/components/utilities/attemptCliLoginMfa"; import attemptLoginMfa from "@app/components/utilities/attemptLoginMfa"; +import SecurityClient from "@app/components/utilities/SecurityClient"; import { Button } from "@app/components/v2"; -import { useUpdateUserAuthMethods } from "@app/hooks/api"; import { useSendMfaToken } from "@app/hooks/api/auth"; -import { useSelectOrganization } from "@app/hooks/api/auth/queries"; +import { useSelectOrganization, verifyMfaToken } from "@app/hooks/api/auth/queries"; import { fetchOrganizations } from "@app/hooks/api/organization/queries"; -import { fetchUserDetails } from "@app/hooks/api/users/queries"; -import { AuthMethod } from "@app/hooks/api/users/types"; +import { fetchMyPrivateKey } from "@app/hooks/api/users/queries"; import { navigateUserToOrg, navigateUserToSelectOrg } from "../../Login.utils"; @@ -56,15 +55,59 @@ export const MFAStep = ({ email, password, providerAuthToken }: Props) => { const { t } = useTranslation(); const sendMfaToken = useSendMfaToken(); - const { mutateAsync: updateUserAuthMethodsMutateAsync } = useUpdateUserAuthMethods(); const { mutateAsync: selectOrganization } = useSelectOrganization(); + // They don't have password + const handleLoginMfaOauth = async (callbackPort: string, organizationId?: string) => { + setIsLoading(true); + const { token } = await verifyMfaToken({ + email, + mfaCode + }); + // + // unset temporary (MFA) JWT token and set JWT token + SecurityClient.setMfaToken(""); + SecurityClient.setToken(token); + SecurityClient.setProviderAuthToken(""); + const privateKey = await fetchMyPrivateKey(); + localStorage.setItem("PRIVATE_KEY", privateKey); + + // case: organization ID is present from the provider auth token -- select the org and use the new jwt token in the CLI, then navigate to the org + if (organizationId) { + const { token: newJwtToken } = await selectOrganization({ organizationId }); + if (callbackPort) { + const cliUrl = `http://127.0.0.1:${callbackPort}/`; + const instance = axios.create(); + await instance.post(cliUrl, { + email, + privateKey, + JTWToken: newJwtToken + }); + } + await navigateUserToOrg(router, organizationId); + } + // case: no organization ID is present -- navigate to the select org page IF the user has any orgs + // if the user has no orgs, navigate to the create org page + else { + const userOrgs = await fetchOrganizations(); + + // case: user has orgs, so we navigate the user to select an org + if (userOrgs.length > 0) { + navigateUserToSelectOrg(router, callbackPort); + } + // case: no orgs found, so we navigate the user to create an org + // cli login will fail in this case + else { + await navigateUserToOrg(router); + } + } + }; + const handleLoginMfa = async () => { try { - let isLinkingRequired: undefined | boolean; let callbackPort: undefined | string; - let authMethod: undefined | AuthMethod; let organizationId: undefined | string; + let hasExchangedPrivateKey: undefined | boolean; const queryParams = new URLSearchParams(window.location.search); @@ -73,10 +116,9 @@ export const MFAStep = ({ email, password, providerAuthToken }: Props) => { if (providerAuthToken) { const decodedToken = jwt_decode(providerAuthToken) as any; - isLinkingRequired = decodedToken.isLinkingRequired; callbackPort = decodedToken.callbackPort; - authMethod = decodedToken.authMethod; organizationId = decodedToken?.organizationId; + hasExchangedPrivateKey = decodedToken?.hasExchangedPrivateKey; } if (mfaCode.length !== 6) { @@ -87,6 +129,11 @@ export const MFAStep = ({ email, password, providerAuthToken }: Props) => { return; } + if (hasExchangedPrivateKey) { + await handleLoginMfaOauth(callbackPort as string, organizationId); + return; + } + setIsLoading(true); if (callbackPort) { // attemptCliLogin @@ -145,14 +192,6 @@ export const MFAStep = ({ email, password, providerAuthToken }: Props) => { type: "success" }); - if (isLinkingRequired && authMethod) { - const user = await fetchUserDetails(); - const newAuthMethods = [...user.authMethods, authMethod]; - await updateUserAuthMethodsMutateAsync({ - authMethods: newAuthMethods - }); - } - if (organizationId) { await navigateUserToOrg(router, organizationId); } else { diff --git a/frontend/src/views/Login/components/PasswordStep/PasswordStep.tsx b/frontend/src/views/Login/components/PasswordStep/PasswordStep.tsx index 2ba90528f..06438a2f8 100644 --- a/frontend/src/views/Login/components/PasswordStep/PasswordStep.tsx +++ b/frontend/src/views/Login/components/PasswordStep/PasswordStep.tsx @@ -1,4 +1,4 @@ -import { useRef, useState } from "react"; +import { useEffect, useRef,useState } from "react"; import { useTranslation } from "react-i18next"; import Link from "next/link"; import { useRouter } from "next/router"; @@ -10,11 +10,11 @@ import { createNotification } from "@app/components/notifications"; import attemptCliLogin from "@app/components/utilities/attemptCliLogin"; import attemptLogin from "@app/components/utilities/attemptLogin"; import { CAPTCHA_SITE_KEY } from "@app/components/utilities/config"; -import { Button, Input } from "@app/components/v2"; -import { useUpdateUserAuthMethods } from "@app/hooks/api"; -import { useSelectOrganization } from "@app/hooks/api/auth/queries"; +import SecurityClient from "@app/components/utilities/SecurityClient"; +import { Button, Input, Spinner } from "@app/components/v2"; +import { useOauthTokenExchange, useSelectOrganization } from "@app/hooks/api"; import { fetchOrganizations } from "@app/hooks/api/organization/queries"; -import { fetchUserDetails } from "@app/hooks/api/users/queries"; +import { fetchMyPrivateKey } from "@app/hooks/api/users/queries"; import { navigateUserToOrg, navigateUserToSelectOrg } from "../../Login.utils"; @@ -36,12 +36,94 @@ export const PasswordStep = ({ const [isLoading, setIsLoading] = useState(false); const { t } = useTranslation(); const router = useRouter(); - const { mutateAsync } = useUpdateUserAuthMethods(); const { mutateAsync: selectOrganization } = useSelectOrganization(); + const { mutateAsync: oauthTokenExchange } = useOauthTokenExchange(); - const { callbackPort, isLinkingRequired, authMethod, organizationId } = jwt_decode( - providerAuthToken - ) as any; + const { callbackPort, organizationId, hasExchangedPrivateKey } = + jwt_decode(providerAuthToken) as any; + + const handleExchange = async () => { + try { + setIsLoading(true); + const oauthLogin = await oauthTokenExchange({ + email, + providerAuthToken + }); + + // attemptCliLogin + if (oauthLogin.mfaEnabled) { + SecurityClient.setMfaToken(oauthLogin.token); + // case: login requires MFA step + setStep(2); + setIsLoading(false); + return; + } + const cliUrl = `http://127.0.0.1:${callbackPort}/`; + + // case: MFA is not enabled + + // unset provider auth token in case it was used + SecurityClient.setProviderAuthToken(""); + // set JWT token + SecurityClient.setToken(oauthLogin.token); + + const privateKey = await fetchMyPrivateKey(); + localStorage.setItem("PRIVATE_KEY", privateKey); + + // case: organization ID is present from the provider auth token -- select the org and use the new jwt token in the CLI, then navigate to the org + if (organizationId) { + const { token: newJwtToken } = await selectOrganization({ organizationId }); + if (callbackPort) { + console.log("organization id was present. new JWT token to be used in CLI:", newJwtToken); + const instance = axios.create(); + await instance.post(cliUrl, { + privateKey, + email, + JTWToken: newJwtToken + }); + } + + await navigateUserToOrg(router, organizationId); + } + // case: no organization ID is present -- navigate to the select org page IF the user has any orgs + // if the user has no orgs, navigate to the create org page + else { + const userOrgs = await fetchOrganizations(); + + // case: user has orgs, so we navigate the user to select an org + if (userOrgs.length > 0) { + navigateUserToSelectOrg(router, callbackPort); + } + // case: no orgs found, so we navigate the user to create an org + else { + await navigateUserToOrg(router); + } + } + } catch (err: any) { + setIsLoading(false); + console.error(err); + + if (err.response.data.error === "User Locked") { + createNotification({ + title: err.response.data.error, + text: err.response.data.message, + type: "error" + }); + return; + } + + createNotification({ + text: "Login unsuccessful. Double-check your master password and try again.", + type: "error" + }); + } + }; + + useEffect(() => { + if (hasExchangedPrivateKey) { + handleExchange(); + } + }, []); const [captchaToken, setCaptchaToken] = useState(""); const [shouldShowCaptcha, setShouldShowCaptcha] = useState(false); @@ -128,14 +210,6 @@ export const PasswordStep = ({ type: "success" }); - if (isLinkingRequired) { - const user = await fetchUserDetails(); - const newAuthMethods = [...user.authMethods, authMethod]; - await mutateAsync({ - authMethods: newAuthMethods - }); - } - // case: organization ID is present from the provider auth token -- navigate directly to the org if (organizationId) { await navigateUserToOrg(router, organizationId); @@ -183,20 +257,21 @@ export const PasswordStep = ({ setCaptchaToken(""); }; + if (hasExchangedPrivateKey) { + return ( +
+ +

Loading, please wait

+
+ ); + } + return (

- {isLinkingRequired ? "Link your account" : "What's your Infisical password?"} + What's your Infisical password?

- {isLinkingRequired && ( -
- - An existing account without this SSO authentication method enabled was found under the - same email. Login with your password to link the account. - -
- )}
diff --git a/frontend/src/views/Signup/components/UserInfoSSOStep/UserInfoSSOStep.tsx b/frontend/src/views/Signup/components/UserInfoSSOStep/UserInfoSSOStep.tsx index 69168e0af..c65317662 100644 --- a/frontend/src/views/Signup/components/UserInfoSSOStep/UserInfoSSOStep.tsx +++ b/frontend/src/views/Signup/components/UserInfoSSOStep/UserInfoSSOStep.tsx @@ -2,14 +2,10 @@ import crypto from "crypto"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { faInfoCircle, faXmark } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import jsrp from "jsrp"; import nacl from "tweetnacl"; import { encodeBase64 } from "tweetnacl-util"; -import InputField from "@app/components/basic/InputField"; -import checkPassword from "@app/components/utilities/checks/password/checkPassword"; import Aes256Gcm from "@app/components/utilities/cryptography/aes-256-gcm"; import { deriveArgonKey } from "@app/components/utilities/cryptography/crypto"; import { saveTokenToLocalStorage } from "@app/components/utilities/saveTokenToLocalStorage"; @@ -32,17 +28,6 @@ type Props = { providerAuthToken?: string; }; -type Errors = { - tooShort?: string; - tooLong?: string; - noLetterChar?: string; - noNumOrSpecialChar?: string; - repeatedChar?: string; - escapeChar?: string; - lowEntropy?: string; - breached?: string; -}; - /** * This is the step of the sign up flow where people provife their name/surname and password * @param {object} obj @@ -69,12 +54,13 @@ export const UserInfoSSOStep = ({ const [organizationName, setOrganizationName] = useState(""); const [organizationNameError, setOrganizationNameError] = useState(false); const [attributionSource, setAttributionSource] = useState(""); - const [errors, setErrors] = useState({}); const [isLoading, setIsLoading] = useState(false); const { t } = useTranslation(); const { mutateAsync: selectOrganization } = useSelectOrganization(); useEffect(() => { + const randomPassword = crypto.randomBytes(32).toString("hex"); + setPassword(randomPassword); if (providerOrganizationName !== undefined) { setOrganizationName(providerOrganizationName); } @@ -98,11 +84,6 @@ export const UserInfoSSOStep = ({ setOrganizationNameError(false); } - errorCheck = await checkPassword({ - password, - setErrors - }); - if (!errorCheck) { // Generate a random pair of a public and a private key const pair = nacl.box.keyPair(); @@ -158,6 +139,7 @@ export const UserInfoSSOStep = ({ const response = await completeAccountSignup({ email: username, + password, firstName: name.split(" ")[0], lastName: name.split(" ").slice(1).join(" "), protectedKey, @@ -214,6 +196,12 @@ export const UserInfoSSOStep = ({ } }; + useEffect(() => { + if (password && providerOrganizationName) { + signupErrorCheck(); + } + }, [providerOrganizationName, password]); + return (

@@ -272,53 +260,6 @@ export const UserInfoSSOStep = ({ />

)} -
- { - setPassword(pass); - await checkPassword({ - password: pass, - setErrors - }); - }} - type="password" - value={password} - isRequired - error={Object.keys(errors).length > 0} - autoComplete="new-password" - id="new-password" - /> -
- - Infisical Password is used as part of the encryption mechanism so that even the - authentication provider is not able to access your secrets. -
- {Object.keys(errors).length > 0 && ( -
-
- {t("section.password.validate-base")} -
- {Object.keys(errors).map((key) => { - if (errors[key as keyof Errors]) { - return ( -
-
- -
-

{errors[key as keyof Errors]}

-
- ); - } - - return null; - })} -
- )} -