Skip to content

Commit

Permalink
feat: Enable two-factor authentication on login page
Browse files Browse the repository at this point in the history
  • Loading branch information
simlarsen committed Jul 29, 2024
1 parent ee3de66 commit df8d2f2
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 45 deletions.
92 changes: 57 additions & 35 deletions Accounts/src/Pages/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,29 @@ const LoginPage: () => JSX.Element = () => {
src={OneUptimeLogo}
alt="OneUptime"
/>
{!showTwoFactorAuth && <><h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Sign in to your account
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Join thousands of business that use OneUptime to help them stay online
all the time.
</p></>}
{!showTwoFactorAuth && (
<>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Sign in to your account
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Join thousands of business that use OneUptime to help them stay
online all the time.
</p>
</>
)}

{showTwoFactorAuth && <><h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Two Factor Authentication
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Select two factor authentication method. You will be asked to enter a code from the selected method.
</p></>}
{showTwoFactorAuth && (
<>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Two Factor Authentication
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Select two factor authentication method. You will be asked to
enter a code from the selected method.
</p>
</>
)}
</div>

<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
Expand Down Expand Up @@ -143,10 +152,15 @@ const LoginPage: () => JSX.Element = () => {
value: User | JSONObject,
miscData: JSONObject | undefined,
) => {
if ((miscData as JSONObject)["twoFactorAuth"] === true) {
if (
miscData &&
(miscData as JSONObject)["twoFactorAuth"] === true
) {
const twoFactorAuthList: Array<UserTwoFactorAuth> =
UserTwoFactorAuth.fromJSONArray(
(miscData as JSONObject)["twoFactorAuthList"] as JSONArray,
(miscData as JSONObject)[
"twoFactorAuthList"
] as JSONArray,
UserTwoFactorAuth,
);
setTwoFactorAuthList(twoFactorAuthList);
Expand Down Expand Up @@ -196,7 +210,7 @@ const LoginPage: () => JSX.Element = () => {
description: "Enter the code from your authenticator app",
required: true,
dataTestId: "code",
fieldType: FormFieldSchemaType.Text
fieldType: FormFieldSchemaType.Text,
},
]}
submitButtonText={"Login"}
Expand All @@ -208,7 +222,8 @@ const LoginPage: () => JSX.Element = () => {

try {
const code: string = data["code"] as string;
const twoFactorAuthId: string = selectedTwoFactorAuth.id?.toString() as string;
const twoFactorAuthId: string =
selectedTwoFactorAuth.id?.toString() as string;

const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
await API.post(VERIFY_TWO_FACTOR_AUTH_API_URL, {
Expand Down Expand Up @@ -242,24 +257,31 @@ const LoginPage: () => JSX.Element = () => {
)}
</div>
<div className="mt-10 text-center">
{!selectedTwoFactorAuth && <div className="text-muted mb-0 text-gray-500">
Don&apos;t have an account?{" "}
<Link
to={new Route("/accounts/register")}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Register.
</Link>
</div>}
{selectedTwoFactorAuth ? <div className="text-muted mb-0 text-gray-500">
<Link
onClick={() => {
setSelectedTwoFactorAuth(undefined);
}}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Select a different two factor authentication method
</Link></div> : <></>}
{!selectedTwoFactorAuth && (
<div className="text-muted mb-0 text-gray-500">
Don&apos;t have an account?{" "}
<Link
to={new Route("/accounts/register")}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Register.
</Link>
</div>
)}
{selectedTwoFactorAuth ? (
<div className="text-muted mb-0 text-gray-500">
<Link
onClick={() => {
setSelectedTwoFactorAuth(undefined);
}}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Select a different two factor authentication method
</Link>
</div>
) : (
<></>
)}
</div>
</div>
</div>
Expand Down
22 changes: 13 additions & 9 deletions App/FeatureSet/Identity/API/Authentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,9 @@ const login: LoginFunction = async (options: {
return Response.sendErrorResponse(
req,
res,
new BadDataException("Invalid login: Email or password does not match."),
new BadDataException(
"Invalid login: Email or password does not match.",
),
);
}

Expand All @@ -654,14 +656,16 @@ const login: LoginFunction = async (options: {
);
}

return Response.sendEntityResponse(
req, res, user, User, {
miscData: {
twoFactorAuthList: UserTwoFactorAuth.toJSONArray(twoFactorAuthList, UserTwoFactorAuth),
twoFactorAuth: true
},
});
}
return Response.sendEntityResponse(req, res, user, User, {
miscData: {
twoFactorAuthList: UserTwoFactorAuth.toJSONArray(
twoFactorAuthList,
UserTwoFactorAuth,
),
twoFactorAuth: true,
},
});
}

if (verifyTwoFactorAuth) {
// code from req
Expand Down
1 change: 0 additions & 1 deletion CommonServer/Services/UserTwoFactorAuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export class Service extends DatabaseService<Model> {
protected override async onBeforeDelete(
deleteBy: DeleteBy<Model>,
): Promise<OnDelete<Model>> {

const itemsToBeDeleted: Array<Model> = await this.findBy({
query: deleteBy.query,
select: {
Expand Down

0 comments on commit df8d2f2

Please sign in to comment.