feat: srp handover for admin and minor bug fix in mfa

This commit is contained in:
=
2024-06-12 19:25:06 +05:30
parent f3ea7b3dfd
commit 736f067178
7 changed files with 73 additions and 50 deletions
@@ -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(),
+11 -10
View File
@@ -570,20 +570,21 @@ export const authLoginServiceFactory = ({
? decodedProviderToken.orgId
: undefined;
const user = await userDAL.findUserEncKeyByUsername({
const userEnc = await userDAL.findUserEncKeyByUsername({
username: email
});
if (!user) throw new BadRequestError({ message: "Invalid token" });
if (!user.serverEncryptedPrivateKey) throw new BadRequestError({ message: "Private key handoff needs to be done" });
if (!userEnc) throw new BadRequestError({ message: "Invalid token" });
if (!userEnc.serverEncryptedPrivateKey)
throw new BadRequestError({ message: "Private key handoff needs to be done" });
// send multi factor auth token if they it enabled
if (user.isMfaEnabled && user.email) {
enforceUserLockStatus(Boolean(user.isLocked), user.temporaryLockDateEnd);
if (userEnc.isMfaEnabled && userEnc.email) {
enforceUserLockStatus(Boolean(userEnc.isLocked), userEnc.temporaryLockDateEnd);
const mfaToken = jwt.sign(
{
authMethod,
authTokenType: AuthTokenType.MFA_TOKEN,
userId: user.userId
userId: userEnc.userId
},
appCfg.AUTH_SECRET,
{
@@ -592,22 +593,22 @@ export const authLoginServiceFactory = ({
);
await sendUserMfaCode({
userId: user.id,
email: user.email
userId: userEnc.userId,
email: userEnc.email
});
return { isMfaEnabled: true, token: mfaToken } as const;
}
const token = await generateUserTokens({
user: { ...user, id: user.userId },
user: { ...userEnc, id: userEnc.userId },
ip,
userAgent,
authMethod,
organizationId
});
return { token, isMfaEnabled: false, user } as const;
return { token, isMfaEnabled: false, user: userEnc } as const;
};
/*
@@ -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,
password: hashedPassword,
serverEncryptedPrivateKey: ciphertext,
serverEncryptedPrivateKeyIV: iv,
serverEncryptedPrivateKeyTag: tag,
serverEncryptedPrivateKeyEncoding: encoding
},
tx
);
@@ -1,5 +1,6 @@
export type TAdminSignUpDTO = {
email: string;
password: string;
publicKey: string;
salt: string;
lastName?: string;
+1
View File
@@ -10,6 +10,7 @@ export type TServerConfig = {
export type TCreateAdminUserDTO = {
email: string;
password: string;
firstName: string;
lastName?: string;
protectedKey: string;
@@ -60,8 +60,6 @@ export const MFAStep = ({ email, password, providerAuthToken }: Props) => {
// They don't have password
const handleLoginMfaOauth = async (callbackPort: string, organizationId?: string) => {
setIsLoading(true);
if (callbackPort) {
// attemptCliLogin
const { token } = await verifyMfaToken({
email,
mfaCode
@@ -103,7 +101,6 @@ export const MFAStep = ({ email, password, providerAuthToken }: Props) => {
await navigateUserToOrg(router);
}
}
}
};
const handleLoginMfa = async () => {
@@ -73,6 +73,7 @@ export const SignUpPage = () => {
const { privateKey, ...userPass } = await generateUserPassKey(email, password);
const res = await createAdminUser({
email,
password,
firstName,
lastName,
...userPass