mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-11 05:28:51 +00:00
Removed all references to commonPasswords & the data file. This api route can be deprecated in favor of the client-side secure call to the haveIBeenPwnd password API. Further the datafile contains no passwords that meet the minimum password criteria.
This commit is contained in:
@@ -1,32 +1,20 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import fs from "fs";
|
|
||||||
import path from "path";
|
|
||||||
import jwt from "jsonwebtoken";
|
import jwt from "jsonwebtoken";
|
||||||
import * as bigintConversion from "bigint-conversion";
|
import * as bigintConversion from "bigint-conversion";
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const jsrp = require("jsrp");
|
const jsrp = require("jsrp");
|
||||||
import {
|
import { LoginSRPDetail, TokenVersion, User } from "../../models";
|
||||||
LoginSRPDetail,
|
|
||||||
TokenVersion,
|
|
||||||
User,
|
|
||||||
} from "../../models";
|
|
||||||
import { clearTokens, createToken, issueAuthTokens } from "../../helpers/auth";
|
import { clearTokens, createToken, issueAuthTokens } from "../../helpers/auth";
|
||||||
import { checkUserDevice } from "../../helpers/user";
|
import { checkUserDevice } from "../../helpers/user";
|
||||||
import {
|
import { ACTION_LOGIN, ACTION_LOGOUT } from "../../variables";
|
||||||
ACTION_LOGIN,
|
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
||||||
ACTION_LOGOUT,
|
|
||||||
} from "../../variables";
|
|
||||||
import {
|
|
||||||
BadRequestError,
|
|
||||||
UnauthorizedRequestError,
|
|
||||||
} from "../../utils/errors";
|
|
||||||
import { EELogService } from "../../ee/services";
|
import { EELogService } from "../../ee/services";
|
||||||
import { getUserAgentType } from "../../utils/posthog";
|
import { getUserAgentType } from "../../utils/posthog";
|
||||||
import {
|
import {
|
||||||
getHttpsEnabled,
|
getHttpsEnabled,
|
||||||
getJwtAuthLifetime,
|
getJwtAuthLifetime,
|
||||||
getJwtAuthSecret,
|
getJwtAuthSecret,
|
||||||
getJwtRefreshSecret,
|
getJwtRefreshSecret
|
||||||
} from "../../config";
|
} from "../../config";
|
||||||
import { ActorType } from "../../ee/models";
|
import { ActorType } from "../../ee/models";
|
||||||
|
|
||||||
@@ -44,13 +32,10 @@ declare module "jsonwebtoken" {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const login1 = async (req: Request, res: Response) => {
|
export const login1 = async (req: Request, res: Response) => {
|
||||||
const {
|
const { email, clientPublicKey }: { email: string; clientPublicKey: string } = req.body;
|
||||||
email,
|
|
||||||
clientPublicKey,
|
|
||||||
}: { email: string; clientPublicKey: string } = req.body;
|
|
||||||
|
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
email,
|
email
|
||||||
}).select("+salt +verifier");
|
}).select("+salt +verifier");
|
||||||
|
|
||||||
if (!user) throw new Error("Failed to find user");
|
if (!user) throw new Error("Failed to find user");
|
||||||
@@ -59,21 +44,25 @@ export const login1 = async (req: Request, res: Response) => {
|
|||||||
server.init(
|
server.init(
|
||||||
{
|
{
|
||||||
salt: user.salt,
|
salt: user.salt,
|
||||||
verifier: user.verifier,
|
verifier: user.verifier
|
||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
// generate server-side public key
|
// generate server-side public key
|
||||||
const serverPublicKey = server.getPublicKey();
|
const serverPublicKey = server.getPublicKey();
|
||||||
|
|
||||||
await LoginSRPDetail.findOneAndReplace({ email: email }, {
|
await LoginSRPDetail.findOneAndReplace(
|
||||||
|
{ email: email },
|
||||||
|
{
|
||||||
email: email,
|
email: email,
|
||||||
clientPublicKey: clientPublicKey,
|
clientPublicKey: clientPublicKey,
|
||||||
serverBInt: bigintConversion.bigintToBuf(server.bInt),
|
serverBInt: bigintConversion.bigintToBuf(server.bInt)
|
||||||
}, { upsert: true, returnNewDocument: false })
|
},
|
||||||
|
{ upsert: true, returnNewDocument: false }
|
||||||
|
);
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
serverPublicKey,
|
serverPublicKey,
|
||||||
salt: user.salt,
|
salt: user.salt
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -89,15 +78,19 @@ export const login1 = async (req: Request, res: Response) => {
|
|||||||
export const login2 = async (req: Request, res: Response) => {
|
export const login2 = async (req: Request, res: Response) => {
|
||||||
const { email, clientProof } = req.body;
|
const { email, clientProof } = req.body;
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
email,
|
email
|
||||||
}).select("+salt +verifier +publicKey +encryptedPrivateKey +iv +tag");
|
}).select("+salt +verifier +publicKey +encryptedPrivateKey +iv +tag");
|
||||||
|
|
||||||
if (!user) throw new Error("Failed to find user");
|
if (!user) throw new Error("Failed to find user");
|
||||||
|
|
||||||
const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: email })
|
const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: email });
|
||||||
|
|
||||||
if (!loginSRPDetailFromDB) {
|
if (!loginSRPDetailFromDB) {
|
||||||
return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again"))
|
return BadRequestError(
|
||||||
|
Error(
|
||||||
|
"It looks like some details from the first login are not found. Please try login one again"
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const server = new jsrp.server();
|
const server = new jsrp.server();
|
||||||
@@ -105,7 +98,7 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
{
|
{
|
||||||
salt: user.salt,
|
salt: user.salt,
|
||||||
verifier: user.verifier,
|
verifier: user.verifier,
|
||||||
b: loginSRPDetailFromDB.serverBInt,
|
b: loginSRPDetailFromDB.serverBInt
|
||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey);
|
server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey);
|
||||||
@@ -117,13 +110,13 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
await checkUserDevice({
|
await checkUserDevice({
|
||||||
user,
|
user,
|
||||||
ip: req.realIP,
|
ip: req.realIP,
|
||||||
userAgent: req.headers["user-agent"] ?? "",
|
userAgent: req.headers["user-agent"] ?? ""
|
||||||
});
|
});
|
||||||
|
|
||||||
const tokens = await issueAuthTokens({
|
const tokens = await issueAuthTokens({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
ip: req.realIP,
|
ip: req.realIP,
|
||||||
userAgent: req.headers["user-agent"] ?? "",
|
userAgent: req.headers["user-agent"] ?? ""
|
||||||
});
|
});
|
||||||
|
|
||||||
// store (refresh) token in httpOnly cookie
|
// store (refresh) token in httpOnly cookie
|
||||||
@@ -131,20 +124,21 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
path: "/",
|
path: "/",
|
||||||
sameSite: "strict",
|
sameSite: "strict",
|
||||||
secure: await getHttpsEnabled(),
|
secure: await getHttpsEnabled()
|
||||||
});
|
});
|
||||||
|
|
||||||
const loginAction = await EELogService.createAction({
|
const loginAction = await EELogService.createAction({
|
||||||
name: ACTION_LOGIN,
|
name: ACTION_LOGIN,
|
||||||
userId: user._id,
|
userId: user._id
|
||||||
});
|
});
|
||||||
|
|
||||||
loginAction && await EELogService.createLog({
|
loginAction &&
|
||||||
|
(await EELogService.createLog({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
actions: [loginAction],
|
actions: [loginAction],
|
||||||
channel: getUserAgentType(req.headers["user-agent"]),
|
channel: getUserAgentType(req.headers["user-agent"]),
|
||||||
ipAddress: req.realIP,
|
ipAddress: req.realIP
|
||||||
});
|
}));
|
||||||
|
|
||||||
// return (access) token in response
|
// return (access) token in response
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
@@ -152,12 +146,12 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
publicKey: user.publicKey,
|
publicKey: user.publicKey,
|
||||||
encryptedPrivateKey: user.encryptedPrivateKey,
|
encryptedPrivateKey: user.encryptedPrivateKey,
|
||||||
iv: user.iv,
|
iv: user.iv,
|
||||||
tag: user.tag,
|
tag: user.tag
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(400).send({
|
return res.status(400).send({
|
||||||
message: "Failed to authenticate. Try again?",
|
message: "Failed to authenticate. Try again?"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -171,7 +165,7 @@ export const login2 = async (req: Request, res: Response) => {
|
|||||||
*/
|
*/
|
||||||
export const logout = async (req: Request, res: Response) => {
|
export const logout = async (req: Request, res: Response) => {
|
||||||
if (req.authData.actor.type === ActorType.USER && req.authData.tokenVersionId) {
|
if (req.authData.actor.type === ActorType.USER && req.authData.tokenVersionId) {
|
||||||
await clearTokens(req.authData.tokenVersionId)
|
await clearTokens(req.authData.tokenVersionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear httpOnly cookie
|
// clear httpOnly cookie
|
||||||
@@ -179,49 +173,44 @@ export const logout = async (req: Request, res: Response) => {
|
|||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
path: "/",
|
path: "/",
|
||||||
sameSite: "strict",
|
sameSite: "strict",
|
||||||
secure: (await getHttpsEnabled()) as boolean,
|
secure: (await getHttpsEnabled()) as boolean
|
||||||
});
|
});
|
||||||
|
|
||||||
const logoutAction = await EELogService.createAction({
|
const logoutAction = await EELogService.createAction({
|
||||||
name: ACTION_LOGOUT,
|
name: ACTION_LOGOUT,
|
||||||
userId: req.user._id,
|
userId: req.user._id
|
||||||
});
|
});
|
||||||
|
|
||||||
logoutAction && await EELogService.createLog({
|
logoutAction &&
|
||||||
|
(await EELogService.createLog({
|
||||||
userId: req.user._id,
|
userId: req.user._id,
|
||||||
actions: [logoutAction],
|
actions: [logoutAction],
|
||||||
channel: getUserAgentType(req.headers["user-agent"]),
|
channel: getUserAgentType(req.headers["user-agent"]),
|
||||||
ipAddress: req.realIP,
|
ipAddress: req.realIP
|
||||||
});
|
}));
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: "Successfully logged out.",
|
message: "Successfully logged out."
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getCommonPasswords = async (req: Request, res: Response) => {
|
|
||||||
const commonPasswords = fs.readFileSync(
|
|
||||||
path.resolve(__dirname, "../../data/" + "common_passwords.txt"),
|
|
||||||
"utf8"
|
|
||||||
).split("\n");
|
|
||||||
|
|
||||||
return res.status(200).send(commonPasswords);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const revokeAllSessions = async (req: Request, res: Response) => {
|
export const revokeAllSessions = async (req: Request, res: Response) => {
|
||||||
await TokenVersion.updateMany({
|
await TokenVersion.updateMany(
|
||||||
user: req.user._id,
|
{
|
||||||
}, {
|
user: req.user._id
|
||||||
|
},
|
||||||
|
{
|
||||||
$inc: {
|
$inc: {
|
||||||
refreshVersion: 1,
|
refreshVersion: 1,
|
||||||
accessVersion: 1,
|
accessVersion: 1
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: "Successfully revoked all sessions.",
|
message: "Successfully revoked all sessions."
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return user is authenticated
|
* Return user is authenticated
|
||||||
@@ -231,9 +220,9 @@ export const revokeAllSessions = async (req: Request, res: Response) => {
|
|||||||
*/
|
*/
|
||||||
export const checkAuth = async (req: Request, res: Response) => {
|
export const checkAuth = async (req: Request, res: Response) => {
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
message: "Authenticated",
|
message: "Authenticated"
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return new JWT access token by first validating the refresh token
|
* Return new JWT access token by first validating the refresh token
|
||||||
@@ -244,47 +233,47 @@ export const checkAuth = async (req: Request, res: Response) => {
|
|||||||
export const getNewToken = async (req: Request, res: Response) => {
|
export const getNewToken = async (req: Request, res: Response) => {
|
||||||
const refreshToken = req.cookies.jid;
|
const refreshToken = req.cookies.jid;
|
||||||
|
|
||||||
if (!refreshToken) throw BadRequestError({
|
if (!refreshToken)
|
||||||
|
throw BadRequestError({
|
||||||
message: "Failed to find refresh token in request cookies"
|
message: "Failed to find refresh token in request cookies"
|
||||||
});
|
});
|
||||||
|
|
||||||
const decodedToken = <jwt.UserIDJwtPayload>(
|
const decodedToken = <jwt.UserIDJwtPayload>jwt.verify(refreshToken, await getJwtRefreshSecret());
|
||||||
jwt.verify(refreshToken, await getJwtRefreshSecret())
|
|
||||||
);
|
|
||||||
|
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
_id: decodedToken.userId,
|
_id: decodedToken.userId
|
||||||
}).select("+publicKey +refreshVersion +accessVersion");
|
}).select("+publicKey +refreshVersion +accessVersion");
|
||||||
|
|
||||||
if (!user) throw new Error("Failed to authenticate unfound user");
|
if (!user) throw new Error("Failed to authenticate unfound user");
|
||||||
if (!user?.publicKey)
|
if (!user?.publicKey) throw new Error("Failed to authenticate not fully set up account");
|
||||||
throw new Error("Failed to authenticate not fully set up account");
|
|
||||||
|
|
||||||
const tokenVersion = await TokenVersion.findById(decodedToken.tokenVersionId);
|
const tokenVersion = await TokenVersion.findById(decodedToken.tokenVersionId);
|
||||||
|
|
||||||
if (!tokenVersion) throw UnauthorizedRequestError({
|
if (!tokenVersion)
|
||||||
message: "Failed to validate refresh token",
|
throw UnauthorizedRequestError({
|
||||||
|
message: "Failed to validate refresh token"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (decodedToken.refreshVersion !== tokenVersion.refreshVersion) throw BadRequestError({
|
if (decodedToken.refreshVersion !== tokenVersion.refreshVersion)
|
||||||
message: "Failed to validate refresh token",
|
throw BadRequestError({
|
||||||
|
message: "Failed to validate refresh token"
|
||||||
});
|
});
|
||||||
|
|
||||||
const token = createToken({
|
const token = createToken({
|
||||||
payload: {
|
payload: {
|
||||||
userId: decodedToken.userId,
|
userId: decodedToken.userId,
|
||||||
tokenVersionId: tokenVersion._id.toString(),
|
tokenVersionId: tokenVersion._id.toString(),
|
||||||
accessVersion: tokenVersion.refreshVersion,
|
accessVersion: tokenVersion.refreshVersion
|
||||||
},
|
},
|
||||||
expiresIn: await getJwtAuthLifetime(),
|
expiresIn: await getJwtAuthLifetime(),
|
||||||
secret: await getJwtAuthSecret(),
|
secret: await getJwtAuthSecret()
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
token,
|
token
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const handleAuthProviderCallback = (req: Request, res: Response) => {
|
export const handleAuthProviderCallback = (req: Request, res: Response) => {
|
||||||
res.redirect(`/login/provider/success?token=${encodeURIComponent(req.providerAuthToken)}`);
|
res.redirect(`/login/provider/success?token=${encodeURIComponent(req.providerAuthToken)}`);
|
||||||
}
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,8 @@ import { AuthMode } from "../../variables";
|
|||||||
|
|
||||||
router.post("/token", validateRequest, authController.getNewToken);
|
router.post("/token", validateRequest, authController.getNewToken);
|
||||||
|
|
||||||
router.post( // TODO endpoint: deprecate (moved to api/v3/auth/login1)
|
router.post(
|
||||||
|
// TODO endpoint: deprecate (moved to api/v3/auth/login1)
|
||||||
"/login1",
|
"/login1",
|
||||||
authLimiter,
|
authLimiter,
|
||||||
body("email").exists().trim().notEmpty(),
|
body("email").exists().trim().notEmpty(),
|
||||||
@@ -17,7 +18,8 @@ router.post( // TODO endpoint: deprecate (moved to api/v3/auth/login1)
|
|||||||
authController.login1
|
authController.login1
|
||||||
);
|
);
|
||||||
|
|
||||||
router.post( // TODO endpoint: deprecate (moved to api/v3/auth/login2)
|
router.post(
|
||||||
|
// TODO endpoint: deprecate (moved to api/v3/auth/login2)
|
||||||
"/login2",
|
"/login2",
|
||||||
authLimiter,
|
authLimiter,
|
||||||
body("email").exists().trim().notEmpty(),
|
body("email").exists().trim().notEmpty(),
|
||||||
@@ -30,7 +32,7 @@ router.post(
|
|||||||
"/logout",
|
"/logout",
|
||||||
authLimiter,
|
authLimiter,
|
||||||
requireAuth({
|
requireAuth({
|
||||||
acceptedAuthModes: [AuthMode.JWT],
|
acceptedAuthModes: [AuthMode.JWT]
|
||||||
}),
|
}),
|
||||||
authController.logout
|
authController.logout
|
||||||
);
|
);
|
||||||
@@ -38,22 +40,17 @@ router.post(
|
|||||||
router.post(
|
router.post(
|
||||||
"/checkAuth",
|
"/checkAuth",
|
||||||
requireAuth({
|
requireAuth({
|
||||||
acceptedAuthModes: [AuthMode.JWT],
|
acceptedAuthModes: [AuthMode.JWT]
|
||||||
}),
|
}),
|
||||||
authController.checkAuth
|
authController.checkAuth
|
||||||
);
|
);
|
||||||
|
|
||||||
router.get(
|
router.delete(
|
||||||
"/common-passwords",
|
// TODO endpoint: deprecate (moved to DELETE v2/users/me/sessions)
|
||||||
authLimiter,
|
|
||||||
authController.getCommonPasswords
|
|
||||||
);
|
|
||||||
|
|
||||||
router.delete( // TODO endpoint: deprecate (moved to DELETE v2/users/me/sessions)
|
|
||||||
"/sessions",
|
"/sessions",
|
||||||
authLimiter,
|
authLimiter,
|
||||||
requireAuth({
|
requireAuth({
|
||||||
acceptedAuthModes: [AuthMode.JWT],
|
acceptedAuthModes: [AuthMode.JWT]
|
||||||
}),
|
}),
|
||||||
authController.revokeAllSessions
|
authController.revokeAllSessions
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import jsrp from "jsrp";
|
|||||||
import nacl from "tweetnacl";
|
import nacl from "tweetnacl";
|
||||||
import { encodeBase64 } from "tweetnacl-util";
|
import { encodeBase64 } from "tweetnacl-util";
|
||||||
|
|
||||||
import { useGetCommonPasswords } from "@app/hooks/api";
|
|
||||||
import { completeAccountSignup } from "@app/hooks/api/auth/queries";
|
import { completeAccountSignup } from "@app/hooks/api/auth/queries";
|
||||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||||
import ProjectService from "@app/services/ProjectService";
|
import ProjectService from "@app/services/ProjectService";
|
||||||
@@ -47,7 +46,6 @@ type Errors = {
|
|||||||
specialChar?: string;
|
specialChar?: string;
|
||||||
repeatedChar?: string;
|
repeatedChar?: string;
|
||||||
isBeachedPassword?: string;
|
isBeachedPassword?: string;
|
||||||
isCommonPassword?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,7 +74,6 @@ export default function UserInfoStep({
|
|||||||
setAttributionSource,
|
setAttributionSource,
|
||||||
providerAuthToken
|
providerAuthToken
|
||||||
}: UserInfoStepProps): JSX.Element {
|
}: UserInfoStepProps): JSX.Element {
|
||||||
const { data: commonPasswords } = useGetCommonPasswords();
|
|
||||||
const [nameError, setNameError] = useState(false);
|
const [nameError, setNameError] = useState(false);
|
||||||
const [organizationNameError, setOrganizationNameError] = useState(false);
|
const [organizationNameError, setOrganizationNameError] = useState(false);
|
||||||
|
|
||||||
@@ -105,7 +102,6 @@ export default function UserInfoStep({
|
|||||||
|
|
||||||
errorCheck = await checkPassword({
|
errorCheck = await checkPassword({
|
||||||
password,
|
password,
|
||||||
commonPasswords,
|
|
||||||
setErrors
|
setErrors
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -272,11 +268,10 @@ export default function UserInfoStep({
|
|||||||
<div className="mt-2 flex max-h-60 w-1/4 w-full min-w-[20rem] flex-col items-center justify-center rounded-lg py-2 lg:w-1/6">
|
<div className="mt-2 flex max-h-60 w-1/4 w-full min-w-[20rem] flex-col items-center justify-center rounded-lg py-2 lg:w-1/6">
|
||||||
<InputField
|
<InputField
|
||||||
label={t("section.password.password")}
|
label={t("section.password.password")}
|
||||||
onChangeHandler={(pass: string) => {
|
onChangeHandler={async (pass: string) => {
|
||||||
setPassword(pass);
|
setPassword(pass);
|
||||||
checkPassword({
|
await checkPassword({
|
||||||
password: pass,
|
password: pass,
|
||||||
commonPasswords,
|
|
||||||
setErrors
|
setErrors
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -9,12 +9,10 @@ type Errors = {
|
|||||||
specialChar?: string;
|
specialChar?: string;
|
||||||
repeatedChar?: string;
|
repeatedChar?: string;
|
||||||
isBreachedPassword?: string;
|
isBreachedPassword?: string;
|
||||||
isCommonPassword?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface CheckPasswordParams {
|
interface CheckPasswordParams {
|
||||||
password: string;
|
password: string;
|
||||||
commonPasswords: string[];
|
|
||||||
setErrors: (value: Errors) => void;
|
setErrors: (value: Errors) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +26,6 @@ interface CheckPasswordParams {
|
|||||||
* - Contains at least 1 special character
|
* - Contains at least 1 special character
|
||||||
* - Does not contain 3 repeat, consecutive characters
|
* - Does not contain 3 repeat, consecutive characters
|
||||||
* - Is not in a database of breached passwords
|
* - Is not in a database of breached passwords
|
||||||
* - Is not in a list of common passwords
|
|
||||||
*
|
*
|
||||||
* The function returns whether or not the password [password]
|
* The function returns whether or not the password [password]
|
||||||
* passes the minimum requirements above. It sets errors on
|
* passes the minimum requirements above. It sets errors on
|
||||||
@@ -38,11 +35,7 @@ interface CheckPasswordParams {
|
|||||||
* @param {String} obj.password - the password to check
|
* @param {String} obj.password - the password to check
|
||||||
* @param {Function} obj.setErrors - set state function to set error object
|
* @param {Function} obj.setErrors - set state function to set error object
|
||||||
*/
|
*/
|
||||||
const checkPassword = async ({
|
const checkPassword = async ({ password, setErrors }: CheckPasswordParams): Promise<boolean> => {
|
||||||
password,
|
|
||||||
commonPasswords,
|
|
||||||
setErrors
|
|
||||||
}: CheckPasswordParams): Promise<boolean> => {
|
|
||||||
const errors: Errors = {};
|
const errors: Errors = {};
|
||||||
|
|
||||||
// tooShort
|
// tooShort
|
||||||
@@ -86,11 +79,6 @@ const checkPassword = async ({
|
|||||||
"The password you provided is in a list of passwords commonly used on other websites. Please try again with a stronger password.";
|
"The password you provided is in a list of passwords commonly used on other websites. Please try again with a stronger password.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// commonPassword
|
|
||||||
if (commonPasswords.includes(password)) {
|
|
||||||
errors.isCommonPassword = "No common passwords";
|
|
||||||
}
|
|
||||||
|
|
||||||
setErrors(errors);
|
setErrors(errors);
|
||||||
return Object.keys(errors).length > 0;
|
return Object.keys(errors).length > 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
export {
|
export {
|
||||||
useGetAuthToken,
|
useGetAuthToken,
|
||||||
useGetCommonPasswords,
|
|
||||||
useResetPassword,
|
useResetPassword,
|
||||||
useSendMfaToken,
|
useSendMfaToken,
|
||||||
useSendPasswordResetEmail,
|
useSendPasswordResetEmail,
|
||||||
useSendVerificationEmail,
|
useSendVerificationEmail,
|
||||||
useVerifyEmailVerificationCode,
|
useVerifyEmailVerificationCode,
|
||||||
useVerifyMfaToken,
|
useVerifyMfaToken,
|
||||||
useVerifyPasswordResetCode} from "./queries"
|
useVerifyPasswordResetCode
|
||||||
|
} from "./queries";
|
||||||
|
|||||||
@@ -20,22 +20,22 @@ import {
|
|||||||
SRPR1Res,
|
SRPR1Res,
|
||||||
VerifyMfaTokenDTO,
|
VerifyMfaTokenDTO,
|
||||||
VerifyMfaTokenRes,
|
VerifyMfaTokenRes,
|
||||||
VerifySignupInviteDTO} from "./types";
|
VerifySignupInviteDTO
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
const authKeys = {
|
const authKeys = {
|
||||||
getAuthToken: ["token"] as const,
|
getAuthToken: ["token"] as const
|
||||||
commonPasswords: ["common-passwords"] as const
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const login1 = async (loginDetails: Login1DTO) => {
|
export const login1 = async (loginDetails: Login1DTO) => {
|
||||||
const { data } = await apiRequest.post<Login1Res>("/api/v3/auth/login1", loginDetails);
|
const { data } = await apiRequest.post<Login1Res>("/api/v3/auth/login1", loginDetails);
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const login2 = async (loginDetails: Login2DTO) => {
|
export const login2 = async (loginDetails: Login2DTO) => {
|
||||||
const { data } = await apiRequest.post<Login2Res>("/api/v3/auth/login2", loginDetails);
|
const { data } = await apiRequest.post<Login2Res>("/api/v3/auth/login2", loginDetails);
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useLogin1 = () => {
|
export const useLogin1 = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
@@ -47,7 +47,7 @@ export const useLogin1 = () => {
|
|||||||
return login1(details);
|
return login1(details);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useLogin2 = () => {
|
export const useLogin2 = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
@@ -59,22 +59,22 @@ export const useLogin2 = () => {
|
|||||||
return login2(details);
|
return login2(details);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const srp1 = async (details: SRP1DTO) => {
|
export const srp1 = async (details: SRP1DTO) => {
|
||||||
const { data } = await apiRequest.post<SRPR1Res>("/api/v1/password/srp1", details);
|
const { data } = await apiRequest.post<SRPR1Res>("/api/v1/password/srp1", details);
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const completeAccountSignup = async (details: CompleteAccountSignupDTO) => {
|
export const completeAccountSignup = async (details: CompleteAccountSignupDTO) => {
|
||||||
const { data } = await apiRequest.post("/api/v3/signup/complete-account/signup", details);
|
const { data } = await apiRequest.post("/api/v3/signup/complete-account/signup", details);
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const completeAccountSignupInvite = async (details: CompleteAccountDTO) => {
|
export const completeAccountSignupInvite = async (details: CompleteAccountDTO) => {
|
||||||
const { data } = await apiRequest.post("/api/v2/signup/complete-account/invite", details);
|
const { data } = await apiRequest.post("/api/v2/signup/complete-account/invite", details);
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useCompleteAccountSignup = () => {
|
export const useCompleteAccountSignup = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
@@ -82,7 +82,7 @@ export const useCompleteAccountSignup = () => {
|
|||||||
return completeAccountSignup(details);
|
return completeAccountSignup(details);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useSendMfaToken = () => {
|
export const useSendMfaToken = () => {
|
||||||
return useMutation<{}, {}, SendMfaTokenDTO>({
|
return useMutation<{}, {}, SendMfaTokenDTO>({
|
||||||
@@ -91,22 +91,16 @@ export const useSendMfaToken = () => {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const verifyMfaToken = async ({
|
export const verifyMfaToken = async ({ email, mfaCode }: { email: string; mfaCode: string }) => {
|
||||||
email,
|
|
||||||
mfaCode
|
|
||||||
}: {
|
|
||||||
email: string;
|
|
||||||
mfaCode: string;
|
|
||||||
}) => {
|
|
||||||
const { data } = await apiRequest.post("/api/v2/auth/mfa/verify", {
|
const { data } = await apiRequest.post("/api/v2/auth/mfa/verify", {
|
||||||
email,
|
email,
|
||||||
mfaToken: mfaCode
|
mfaToken: mfaCode
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useVerifyMfaToken = () => {
|
export const useVerifyMfaToken = () => {
|
||||||
return useMutation<VerifyMfaTokenRes, {}, VerifyMfaTokenDTO>({
|
return useMutation<VerifyMfaTokenRes, {}, VerifyMfaTokenDTO>({
|
||||||
@@ -117,20 +111,16 @@ export const useVerifyMfaToken = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const verifySignupInvite = async (details: VerifySignupInviteDTO) => {
|
export const verifySignupInvite = async (details: VerifySignupInviteDTO) => {
|
||||||
const { data } = await apiRequest.post("/api/v1/invite-org/verify", details);
|
const { data } = await apiRequest.post("/api/v1/invite-org/verify", details);
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useSendVerificationEmail = () => {
|
export const useSendVerificationEmail = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({
|
mutationFn: async ({ email }: { email: string }) => {
|
||||||
email
|
|
||||||
}: {
|
|
||||||
email: string;
|
|
||||||
}) => {
|
|
||||||
const { data } = await apiRequest.post("/api/v1/signup/email/signup", {
|
const { data } = await apiRequest.post("/api/v1/signup/email/signup", {
|
||||||
email
|
email
|
||||||
});
|
});
|
||||||
@@ -138,17 +128,11 @@ export const useSendVerificationEmail = () => {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useVerifyEmailVerificationCode = () => {
|
export const useVerifyEmailVerificationCode = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({
|
mutationFn: async ({ email, code }: { email: string; code: string }) => {
|
||||||
email,
|
|
||||||
code
|
|
||||||
}: {
|
|
||||||
email: string;
|
|
||||||
code: string;
|
|
||||||
}) => {
|
|
||||||
const { data } = await apiRequest.post("/api/v1/signup/email/verify", {
|
const { data } = await apiRequest.post("/api/v1/signup/email/verify", {
|
||||||
email,
|
email,
|
||||||
code
|
code
|
||||||
@@ -157,15 +141,11 @@ export const useVerifyEmailVerificationCode = () => {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useSendPasswordResetEmail = () => {
|
export const useSendPasswordResetEmail = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({
|
mutationFn: async ({ email }: { email: string }) => {
|
||||||
email
|
|
||||||
}: {
|
|
||||||
email: string;
|
|
||||||
}) => {
|
|
||||||
const { data } = await apiRequest.post("/api/v1/password/email/password-reset", {
|
const { data } = await apiRequest.post("/api/v1/password/email/password-reset", {
|
||||||
email
|
email
|
||||||
});
|
});
|
||||||
@@ -173,17 +153,11 @@ export const useSendPasswordResetEmail = () => {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useVerifyPasswordResetCode = () => {
|
export const useVerifyPasswordResetCode = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({
|
mutationFn: async ({ email, code }: { email: string; code: string }) => {
|
||||||
email,
|
|
||||||
code
|
|
||||||
}: {
|
|
||||||
email: string;
|
|
||||||
code: string;
|
|
||||||
}) => {
|
|
||||||
const { data } = await apiRequest.post("/api/v1/password/email/password-reset-verify", {
|
const { data } = await apiRequest.post("/api/v1/password/email/password-reset-verify", {
|
||||||
email,
|
email,
|
||||||
code
|
code
|
||||||
@@ -192,12 +166,12 @@ export const useVerifyPasswordResetCode = () => {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const issueBackupPrivateKey = async (details: IssueBackupPrivateKeyDTO) => {
|
export const issueBackupPrivateKey = async (details: IssueBackupPrivateKeyDTO) => {
|
||||||
const { data } = await apiRequest.post("/api/v1/password/backup-private-key", details);
|
const { data } = await apiRequest.post("/api/v1/password/backup-private-key", details);
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const getBackupEncryptedPrivateKey = async ({
|
export const getBackupEncryptedPrivateKey = async ({
|
||||||
verificationToken
|
verificationToken
|
||||||
@@ -209,12 +183,14 @@ export const getBackupEncryptedPrivateKey = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return data.backupPrivateKey;
|
return data.backupPrivateKey;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useResetPassword = () => {
|
export const useResetPassword = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async (details: ResetPasswordDTO) => {
|
mutationFn: async (details: ResetPasswordDTO) => {
|
||||||
const { data } = await apiRequest.post("/api/v1/password/password-reset", {
|
const { data } = await apiRequest.post(
|
||||||
|
"/api/v1/password/password-reset",
|
||||||
|
{
|
||||||
protectedKey: details.protectedKey,
|
protectedKey: details.protectedKey,
|
||||||
protectedKeyIV: details.protectedKeyIV,
|
protectedKeyIV: details.protectedKeyIV,
|
||||||
protectedKeyTag: details.protectedKeyTag,
|
protectedKeyTag: details.protectedKeyTag,
|
||||||
@@ -223,21 +199,23 @@ export const useResetPassword = () => {
|
|||||||
encryptedPrivateKeyTag: details.encryptedPrivateKeyTag,
|
encryptedPrivateKeyTag: details.encryptedPrivateKeyTag,
|
||||||
salt: details.salt,
|
salt: details.salt,
|
||||||
verifier: details.verifier
|
verifier: details.verifier
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${details.verificationToken}`
|
Authorization: `Bearer ${details.verificationToken}`
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const changePassword = async (details: ChangePasswordDTO) => {
|
export const changePassword = async (details: ChangePasswordDTO) => {
|
||||||
const { data } = await apiRequest.post("/api/v1/password/change-password", details);
|
const { data } = await apiRequest.post("/api/v1/password/change-password", details);
|
||||||
return data;
|
return data;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const useChangePassword = () => {
|
export const useChangePassword = () => {
|
||||||
// note: use after srp1
|
// note: use after srp1
|
||||||
@@ -246,7 +224,7 @@ export const useChangePassword = () => {
|
|||||||
return changePassword(details);
|
return changePassword(details);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Refresh token is set as cookie when logged in
|
// Refresh token is set as cookie when logged in
|
||||||
// Using that we fetch the auth bearer token needed for auth calls
|
// Using that we fetch the auth bearer token needed for auth calls
|
||||||
@@ -263,11 +241,3 @@ export const useGetAuthToken = () =>
|
|||||||
onSuccess: (data) => setAuthToken(data.token),
|
onSuccess: (data) => setAuthToken(data.token),
|
||||||
retry: 0
|
retry: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
const fetchCommonPasswords = async () => {
|
|
||||||
const { data } = await apiRequest.get("/api/v1/auth/common-passwords");
|
|
||||||
return data || [];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useGetCommonPasswords = () =>
|
|
||||||
useQuery({ queryKey: authKeys.commonPasswords, queryFn: fetchCommonPasswords });
|
|
||||||
@@ -22,31 +22,23 @@ import { deriveArgonKey } from "@app/components/utilities/cryptography/crypto";
|
|||||||
import issueBackupKey from "@app/components/utilities/cryptography/issueBackupKey";
|
import issueBackupKey from "@app/components/utilities/cryptography/issueBackupKey";
|
||||||
import { saveTokenToLocalStorage } from "@app/components/utilities/saveTokenToLocalStorage";
|
import { saveTokenToLocalStorage } from "@app/components/utilities/saveTokenToLocalStorage";
|
||||||
import SecurityClient from "@app/components/utilities/SecurityClient";
|
import SecurityClient from "@app/components/utilities/SecurityClient";
|
||||||
import {
|
import { completeAccountSignupInvite, verifySignupInvite } from "@app/hooks/api/auth/queries";
|
||||||
useGetCommonPasswords
|
|
||||||
} from "@app/hooks/api";
|
|
||||||
import {
|
|
||||||
completeAccountSignupInvite,
|
|
||||||
verifySignupInvite
|
|
||||||
} from "@app/hooks/api/auth/queries";
|
|
||||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||||
|
|
||||||
// eslint-disable-next-line new-cap
|
// eslint-disable-next-line new-cap
|
||||||
const client = new jsrp.client();
|
const client = new jsrp.client();
|
||||||
|
|
||||||
type Errors = {
|
type Errors = {
|
||||||
length?: string,
|
length?: string;
|
||||||
upperCase?: string,
|
upperCase?: string;
|
||||||
lowerCase?: string,
|
lowerCase?: string;
|
||||||
number?: string,
|
number?: string;
|
||||||
specialChar?: string,
|
specialChar?: string;
|
||||||
repeatedChar?: string,
|
repeatedChar?: string;
|
||||||
breachedPassword?: string
|
breachedPassword?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SignupInvite() {
|
export default function SignupInvite() {
|
||||||
const { data: commonPasswords } = useGetCommonPasswords();
|
|
||||||
|
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [firstName, setFirstName] = useState("");
|
const [firstName, setFirstName] = useState("");
|
||||||
const [lastName, setLastName] = useState("");
|
const [lastName, setLastName] = useState("");
|
||||||
@@ -83,7 +75,6 @@ export default function SignupInvite() {
|
|||||||
|
|
||||||
errorCheck = await checkPassword({
|
errorCheck = await checkPassword({
|
||||||
password,
|
password,
|
||||||
commonPasswords,
|
|
||||||
setErrors
|
setErrors
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -140,9 +131,7 @@ export default function SignupInvite() {
|
|||||||
secret: Buffer.from(derivedKey.hash)
|
secret: Buffer.from(derivedKey.hash)
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const { token: jwtToken } = await completeAccountSignupInvite({
|
||||||
token: jwtToken
|
|
||||||
} = await completeAccountSignupInvite({
|
|
||||||
email,
|
email,
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
@@ -189,12 +178,12 @@ export default function SignupInvite() {
|
|||||||
|
|
||||||
// Step 4 of the sign up process (download the emergency kit pdf)
|
// Step 4 of the sign up process (download the emergency kit pdf)
|
||||||
const stepConfirmEmail = (
|
const stepConfirmEmail = (
|
||||||
<div className="border border-mineshaft-600 bg-mineshaft-800 flex flex-col items-center w-full max-w-xs md:max-w-lg h-7/12 py-8 px-4 md:px-6 mx-1 mb-36 md:mb-16 rounded-xl drop-shadow-xl">
|
<div className="h-7/12 mx-1 mb-36 flex w-full max-w-xs flex-col items-center rounded-xl border border-mineshaft-600 bg-mineshaft-800 py-8 px-4 drop-shadow-xl md:mb-16 md:max-w-lg md:px-6">
|
||||||
<p className="text-4xl text-center font-semibold mb-6 flex justify-center text-primary-100">
|
<p className="mb-6 flex justify-center text-center text-4xl font-semibold text-primary-100">
|
||||||
Confirm your email
|
Confirm your email
|
||||||
</p>
|
</p>
|
||||||
<Image src="/images/dragon-signupinvite.svg" height={262} width={410} alt="verify email" />
|
<Image src="/images/dragon-signupinvite.svg" height={262} width={410} alt="verify email" />
|
||||||
<div className="flex flex-col items-center justify-center md:p-2 max-h-24 max-w-md mx-auto text-lg px-4 mt-10 mb-2">
|
<div className="mx-auto mt-10 mb-2 flex max-h-24 max-w-md flex-col items-center justify-center px-4 text-lg md:p-2">
|
||||||
<Button
|
<Button
|
||||||
text="Confirm Email"
|
text="Confirm Email"
|
||||||
onButtonPressed={async () => {
|
onButtonPressed={async () => {
|
||||||
@@ -230,11 +219,11 @@ export default function SignupInvite() {
|
|||||||
|
|
||||||
// Because this is the invite signup - we directly go to the last step of signup (email is already verified)
|
// Because this is the invite signup - we directly go to the last step of signup (email is already verified)
|
||||||
const main = (
|
const main = (
|
||||||
<div className="border border-mineshaft-600 bg-mineshaft-800 w-max mx-auto h-7/12 py-10 px-8 rounded-xl drop-shadow-xl mb-32 md:mb-16">
|
<div className="h-7/12 mx-auto mb-32 w-max rounded-xl border border-mineshaft-600 bg-mineshaft-800 py-10 px-8 drop-shadow-xl md:mb-16">
|
||||||
<p className="text-4xl font-bold flex justify-center mb-6 mx-8 md:mx-16 text-transparent bg-clip-text bg-gradient-to-tr from-mineshaft-300 to-white">
|
<p className="mx-8 mb-6 flex justify-center bg-gradient-to-tr from-mineshaft-300 to-white bg-clip-text text-4xl font-bold text-transparent md:mx-16">
|
||||||
Almost there!
|
Almost there!
|
||||||
</p>
|
</p>
|
||||||
<div className="relative z-0 flex items-center justify-end w-full md:p-2 rounded-lg max-h-24">
|
<div className="relative z-0 flex max-h-24 w-full items-center justify-end rounded-lg md:p-2">
|
||||||
<InputField
|
<InputField
|
||||||
label="First Name"
|
label="First Name"
|
||||||
onChangeHandler={setFirstName}
|
onChangeHandler={setFirstName}
|
||||||
@@ -246,7 +235,7 @@ export default function SignupInvite() {
|
|||||||
autoComplete="given-name"
|
autoComplete="given-name"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-center w-full md:p-2 rounded-lg max-h-24">
|
<div className="flex max-h-24 w-full items-center justify-center rounded-lg md:p-2">
|
||||||
<InputField
|
<InputField
|
||||||
label="Last Name"
|
label="Last Name"
|
||||||
onChangeHandler={setLastName}
|
onChangeHandler={setLastName}
|
||||||
@@ -258,14 +247,13 @@ export default function SignupInvite() {
|
|||||||
autoComplete="family-name"
|
autoComplete="family-name"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 flex flex-col items-center justify-center w-full md:p-2 rounded-lg max-h-60">
|
<div className="mt-2 flex max-h-60 w-full flex-col items-center justify-center rounded-lg md:p-2">
|
||||||
<InputField
|
<InputField
|
||||||
label="Password"
|
label="Password"
|
||||||
onChangeHandler={(pass) => {
|
onChangeHandler={(pass) => {
|
||||||
setPassword(pass);
|
setPassword(pass);
|
||||||
checkPassword({
|
checkPassword({
|
||||||
password: pass,
|
password: pass,
|
||||||
commonPasswords,
|
|
||||||
setErrors
|
setErrors
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -282,16 +270,11 @@ export default function SignupInvite() {
|
|||||||
{Object.keys(errors).map((key) => {
|
{Object.keys(errors).map((key) => {
|
||||||
if (errors[key as keyof Errors]) {
|
if (errors[key as keyof Errors]) {
|
||||||
return (
|
return (
|
||||||
<div className="ml-1 flex flex-row items-top justify-start" key={key}>
|
<div className="items-top ml-1 flex flex-row justify-start" key={key}>
|
||||||
<div>
|
<div>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon icon={faXmark} className="text-md ml-0.5 mr-2.5 text-red" />
|
||||||
icon={faXmark}
|
|
||||||
className="text-md text-red ml-0.5 mr-2.5"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-gray-400 text-sm">
|
<p className="text-sm text-gray-400">{errors[key as keyof Errors]}</p>
|
||||||
{errors[key as keyof Errors]}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -301,7 +284,7 @@ export default function SignupInvite() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-center justify-center md:px-4 md:py-5 mt-2 px-2 py-3 max-h-24 max-w-max mx-auto text-lg">
|
<div className="mx-auto mt-2 flex max-h-24 max-w-max flex-col items-center justify-center px-2 py-3 text-lg md:px-4 md:py-5">
|
||||||
<Button
|
<Button
|
||||||
text="Sign Up"
|
text="Sign Up"
|
||||||
onButtonPressed={() => {
|
onButtonPressed={() => {
|
||||||
@@ -316,21 +299,21 @@ export default function SignupInvite() {
|
|||||||
|
|
||||||
// Step 4 of the sign up process (download the emergency kit pdf)
|
// Step 4 of the sign up process (download the emergency kit pdf)
|
||||||
const step4 = (
|
const step4 = (
|
||||||
<div className="border border-mineshaft-600 bg-mineshaft-800 flex flex-col items-center w-full max-w-xs md:max-w-lg h-7/12 pt-8 pb-6 px-4 md:px-6 mx-1 mb-36 md:mb-16 rounded-xl drop-shadow-xl">
|
<div className="h-7/12 mx-1 mb-36 flex w-full max-w-xs flex-col items-center rounded-xl border border-mineshaft-600 bg-mineshaft-800 px-4 pt-8 pb-6 drop-shadow-xl md:mb-16 md:max-w-lg md:px-6">
|
||||||
<p className="text-4xl text-center font-semibold flex justify-center text-transparent bg-clip-text bg-gradient-to-br from-white to-mineshaft-300">
|
<p className="flex justify-center bg-gradient-to-br from-white to-mineshaft-300 bg-clip-text text-center text-4xl font-semibold text-transparent">
|
||||||
Save your Emergency Kit
|
Save your Emergency Kit
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-col items-center justify-center w-full mt-4 md:mt-8 max-w-md text-gray-400 text-md rounded-md px-2">
|
<div className="text-md mt-4 flex w-full max-w-md flex-col items-center justify-center rounded-md px-2 text-gray-400 md:mt-8">
|
||||||
<div>
|
<div>
|
||||||
If you get locked out of your account, your Emergency Kit is the only way to sign in.
|
If you get locked out of your account, your Emergency Kit is the only way to sign in.
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-3">We recommend you download it and keep it somewhere safe.</div>
|
<div className="mt-3">We recommend you download it and keep it somewhere safe.</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full p-2 flex flex-row items-center bg-white/10 text-gray-400 rounded-md max-w-xs md:max-w-md mx-auto mt-4">
|
<div className="mx-auto mt-4 flex w-full max-w-xs flex-row items-center rounded-md bg-white/10 p-2 text-gray-400 md:max-w-md">
|
||||||
<FontAwesomeIcon icon={faWarning} className="ml-2 mr-4 text-4xl" />
|
<FontAwesomeIcon icon={faWarning} className="ml-2 mr-4 text-4xl" />
|
||||||
It contains your Secret Key which we cannot access or recover for you if you lose it.
|
It contains your Secret Key which we cannot access or recover for you if you lose it.
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-center justify-center md:px-4 md:py-5 mt-4 px-2 py-3 max-h-24 max-w-max mx-auto text-lg">
|
<div className="mx-auto mt-4 flex max-h-24 max-w-max flex-col items-center justify-center px-2 py-3 text-lg md:px-4 md:py-5">
|
||||||
<Button
|
<Button
|
||||||
text="Download PDF"
|
text="Download PDF"
|
||||||
onButtonPressed={async () => {
|
onButtonPressed={async () => {
|
||||||
@@ -350,7 +333,7 @@ export default function SignupInvite() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 h-screen flex flex-col items-center justify-center">
|
<div className="flex h-screen flex-col items-center justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Sign Up</title>
|
<title>Sign Up</title>
|
||||||
<link rel="icon" href="/infisical.ico" />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
|
|||||||
-5
@@ -11,7 +11,6 @@ import attemptChangePassword from "@app/components/utilities/attemptChangePasswo
|
|||||||
import checkPassword from "@app/components/utilities/checks/checkPassword";
|
import checkPassword from "@app/components/utilities/checks/checkPassword";
|
||||||
import { Button, FormControl, Input } from "@app/components/v2";
|
import { Button, FormControl, Input } from "@app/components/v2";
|
||||||
import { useUser } from "@app/context";
|
import { useUser } from "@app/context";
|
||||||
import { useGetCommonPasswords } from "@app/hooks/api";
|
|
||||||
|
|
||||||
type Errors = {
|
type Errors = {
|
||||||
tooShort?: string;
|
tooShort?: string;
|
||||||
@@ -22,7 +21,6 @@ type Errors = {
|
|||||||
specialChar?: string;
|
specialChar?: string;
|
||||||
repeatedChar?: string;
|
repeatedChar?: string;
|
||||||
isBreachedPassword?: string;
|
isBreachedPassword?: string;
|
||||||
isCommonPassword?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const schema = yup
|
const schema = yup
|
||||||
@@ -38,7 +36,6 @@ export const ChangePasswordSection = () => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { createNotification } = useNotificationContext();
|
const { createNotification } = useNotificationContext();
|
||||||
const { user } = useUser();
|
const { user } = useUser();
|
||||||
const { data: commonPasswords } = useGetCommonPasswords();
|
|
||||||
const { reset, control, handleSubmit } = useForm({
|
const { reset, control, handleSubmit } = useForm({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
oldPassword: "",
|
oldPassword: "",
|
||||||
@@ -52,11 +49,9 @@ export const ChangePasswordSection = () => {
|
|||||||
const onFormSubmit = async ({ oldPassword, newPassword }: FormData) => {
|
const onFormSubmit = async ({ oldPassword, newPassword }: FormData) => {
|
||||||
try {
|
try {
|
||||||
if (!user?.email) return;
|
if (!user?.email) return;
|
||||||
if (!commonPasswords) return;
|
|
||||||
|
|
||||||
const errorCheck = await checkPassword({
|
const errorCheck = await checkPassword({
|
||||||
password: newPassword,
|
password: newPassword,
|
||||||
commonPasswords,
|
|
||||||
setErrors
|
setErrors
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import { deriveArgonKey } from "@app/components/utilities/cryptography/crypto";
|
|||||||
import { saveTokenToLocalStorage } from "@app/components/utilities/saveTokenToLocalStorage";
|
import { saveTokenToLocalStorage } from "@app/components/utilities/saveTokenToLocalStorage";
|
||||||
import SecurityClient from "@app/components/utilities/SecurityClient";
|
import SecurityClient from "@app/components/utilities/SecurityClient";
|
||||||
import { Button, Input } from "@app/components/v2";
|
import { Button, Input } from "@app/components/v2";
|
||||||
import { useGetCommonPasswords } from "@app/hooks/api";
|
|
||||||
import { completeAccountSignup } from "@app/hooks/api/auth/queries";
|
import { completeAccountSignup } from "@app/hooks/api/auth/queries";
|
||||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||||
import ProjectService from "@app/services/ProjectService";
|
import ProjectService from "@app/services/ProjectService";
|
||||||
@@ -42,7 +41,6 @@ type Errors = {
|
|||||||
specialChar?: string;
|
specialChar?: string;
|
||||||
repeatedChar?: string;
|
repeatedChar?: string;
|
||||||
isBeachedPassword?: string;
|
isBeachedPassword?: string;
|
||||||
isCommonPassword?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +65,6 @@ export const UserInfoSSOStep = ({
|
|||||||
setStep,
|
setStep,
|
||||||
providerAuthToken
|
providerAuthToken
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { data: commonPasswords } = useGetCommonPasswords();
|
|
||||||
const [nameError, setNameError] = useState(false);
|
const [nameError, setNameError] = useState(false);
|
||||||
const [organizationName, setOrganizationName] = useState("");
|
const [organizationName, setOrganizationName] = useState("");
|
||||||
const [organizationNameError, setOrganizationNameError] = useState(false);
|
const [organizationNameError, setOrganizationNameError] = useState(false);
|
||||||
@@ -102,7 +99,6 @@ export const UserInfoSSOStep = ({
|
|||||||
|
|
||||||
errorCheck = await checkPassword({
|
errorCheck = await checkPassword({
|
||||||
password,
|
password,
|
||||||
commonPasswords,
|
|
||||||
setErrors
|
setErrors
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -277,7 +273,6 @@ export const UserInfoSSOStep = ({
|
|||||||
setPassword(pass);
|
setPassword(pass);
|
||||||
await checkPassword({
|
await checkPassword({
|
||||||
password: pass,
|
password: pass,
|
||||||
commonPasswords,
|
|
||||||
setErrors
|
setErrors
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user