Skip to content

Commit 88548af

Browse files
Completed 2FA with email sent code. (#144)
* debug and start of 2fa * Finished 2FA with email sending * feat: improved security of code verification --------- Co-authored-by: Isaac Nguyen <isaachn@uci.edu>
1 parent e35b5dd commit 88548af

File tree

10 files changed

+270
-58
lines changed

10 files changed

+270
-58
lines changed

client/src/App.tsx

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { ViewPage } from "./components/clientPage/ViewPage";
1414
import { LandingPage } from "./components/login/LandingPage";
1515
import { ChooseLogin } from "./components/login/ChooseLogin";
1616
import { ForgotPassword } from "./components/forgotPassword/ForgotPassword";
17-
import { AdminPin } from "./components/authentification/AdminPin";
17+
import { Authentification } from "./components/authentification/authentification";
1818
import { Dashboard } from "./components/dashboard/Dashboard";
1919
import { Donations } from "./components/donations/Donations"
2020
import { ExitSurvey } from "./components/exit_survey/ExitSurvey";
@@ -59,7 +59,7 @@ const App = () => {
5959
currentRoute === 'choose-login' ||
6060
currentRoute === 'signup' ||
6161
currentRoute === 'forgot-password' ||
62-
currentRoute === 'admin-pin'
62+
currentRoute === 'authentification'
6363
);
6464

6565
return (
@@ -91,16 +91,16 @@ const App = () => {
9191
element={<ForgotPassword />}
9292
/>
9393
<Route
94-
path="/admin-pin/:userType?"
95-
element={<AdminPin />}
94+
path="/authentification/:userType?"
95+
element={<Authentification />}
9696
/>
9797
<Route
9898
path="/exit-survey"
99-
element={<ExitSurvey />}
99+
element={<ProtectedRoute element={<ExitSurvey />}/>}
100100
/>
101101
<Route
102102
path="/success-story"
103-
element={<SuccessStory />}
103+
element={<ProtectedRoute element={<SuccessStory />}/>}
104104
/>
105105
<Route
106106
path="/settings"
@@ -112,23 +112,23 @@ const App = () => {
112112
/>
113113
<Route
114114
path="/client-interview-screening"
115-
element={<ClientInterviewScreening />}
115+
element={<ProtectedRoute element={<ClientInterviewScreening />} />}
116116
/>
117117
<Route
118118
path="/monthly-statistics"
119119
element={<ProtectedRoute element={<CaseManagerMonthlyStats />} />}
120120
/>
121121
<Route
122122
path="/forms-hub"
123-
element={<FormsHub />}
123+
element={<ProtectedRoute element={<FormsHub />}/>}
124124
/>
125125
<Route
126126
path="/start-form"
127-
element={<StartForms />}
127+
element={<ProtectedRoute element={<StartForms />} />}
128128
/>
129129
<Route
130130
path="/admin-client-list"
131-
element={<AdminClientList />}
131+
element={<ProtectedRoute element ={<AdminClientList />} />}
132132
/>
133133
<Route
134134
path="/accounts"
@@ -141,17 +141,17 @@ const App = () => {
141141
/>
142142
<Route
143143
path="/clientlist"
144-
element={<ClientList />}
144+
element={<ProtectedRoute element = {<ClientList />} />}
145145
/>
146146

147147
<Route
148148
path="/clientdata"
149-
element={<ClientData />}
149+
element={<ProtectedRoute element={<ClientData />} />}
150150
/>
151151

152152
<Route
153153
path = "/donations"
154-
element = {<Donations />}
154+
element = {<ProtectedRoute element={<Donations />} />}
155155
/>
156156
<Route
157157
path = "/volunteer-tracking"
@@ -163,47 +163,47 @@ const App = () => {
163163
/>
164164
<Route
165165
path="/ViewClient/:id"
166-
element={<ViewPage />}
166+
element={<ProtectedRoute element = {<ViewPage />} />}
167167
/>
168168
<Route
169169
path="/casemanager"
170-
element={<CaseManager />}
170+
element={<ProtectedRoute element={<CaseManager />} />}
171171
/>
172172
<Route
173173
path="/random-client-survey"
174-
element={<RandomClientSurvey />}
174+
element={<ProtectedRoute element={<RandomClientSurvey />} />}
175175
/>
176176
<Route
177-
path ="/frontDesk"
178-
element ={<FrontDeskMonthlyStats/>}
177+
path ="/frontDesk"
178+
element ={<ProtectedRoute element={<FrontDeskMonthlyStats/>}/>}
179179
/>
180180
<Route
181181
path ="/intakeStats"
182-
element ={<IntakeStats/>}
182+
element ={<ProtectedRoute element= {<IntakeStats/>} />}
183183
/>
184184
<Route
185185
path ="/personal"
186-
element ={<PersonalInformation hidden={false}/>}
186+
element ={<ProtectedRoute element={<PersonalInformation hidden={false}/>}/>}
187187
/>
188188
<Route
189189
path ="/financial"
190-
element ={<FinancialInformation hidden={false}/>}
190+
element ={<ProtectedRoute element={<FinancialInformation hidden={false}/>} />}
191191
/>
192192
<Route
193193
path ="/health"
194-
element ={<HealthSocialInformation hidden={false}/>}
194+
element ={<ProtectedRoute element={<HealthSocialInformation hidden={false}/>}/>}
195195
/>
196196
<Route
197197
path ="/additional"
198-
element ={<AdditionalInformation hidden={false}/>}
198+
element ={<ProtectedRoute element={<AdditionalInformation hidden={false}/>}/>}
199199
/>
200200
<Route
201201
path ="/review"
202-
element ={<ReviewInformation/>}
202+
element ={<ProtectedRoute element={<ReviewInformation/>}/>}
203203
/>
204204
<Route
205205
path ="/success"
206-
element ={<Success/>}
206+
element ={<ProtectedRoute element={<Success/>} />}
207207
/>
208208
<Route path="/playground" element={<Playground/>}/>
209209
<Route

client/src/components/authentification/AdminPin.tsx renamed to client/src/components/authentification/authentification.tsx

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useEffect } from "react";
1+
import { useCallback, useEffect, useState } from "react";
22
import {
33
Button,
44
Center,
@@ -35,19 +35,54 @@ const resetPasswordSchema = z.object({
3535

3636
type ResetPasswordFormValues = z.infer<typeof resetPasswordSchema>;
3737

38-
export const AdminPin = () => {
38+
export const Authentification = () => {
3939
const navigate = useNavigate();
4040
const toast = useToast();
4141
const { userType } = useParams<{ userType: string }>();
4242
const userAbbreviation = userType === "Case Manager" ? "CM" : "AD";
4343

44-
const { resetPassword, handleRedirectResult } = useAuthContext();
44+
const { handleRedirectResult, createCode, authenticate } = useAuthContext();
4545
const { backend } = useBackendContext();
46-
// update when 2FA is integrated
47-
const handlePinSubmit = () => {
48-
navigate("/casemanager")
49-
}
46+
const [pin, setPin] = useState("");
5047

48+
const handlePinChange = (value: string) => {
49+
setPin(value);
50+
};
51+
52+
const handlePinSubmit = async (event: React.FormEvent) => {
53+
event.preventDefault();
54+
55+
try {
56+
await authenticate({code: Number(pin)});
57+
if (userType === "Case Manager") {
58+
navigate("/clientlist");
59+
}
60+
else if (userType === "Admin") {
61+
navigate("/admin-client-list");
62+
}
63+
} catch (error) {
64+
toast({
65+
title: "Authentication Failed",
66+
description: "The entered PIN is incorrect. Please try again.",
67+
status: "error",
68+
duration: 5000,
69+
isClosable: true,
70+
});
71+
72+
setPin("");
73+
}
74+
};
75+
76+
useEffect( () => {
77+
const generateCode = async () => {
78+
try {
79+
await createCode();
80+
} catch (err) {
81+
console.error('Error posting code: ', err);
82+
}
83+
};
84+
generateCode();
85+
}, [createCode]);
5186

5287
useEffect(() => {
5388
handleRedirectResult(backend, navigate, toast);
@@ -100,7 +135,7 @@ export const AdminPin = () => {
100135

101136
<FormControl w={"100%"} >
102137
<HStack justify="center" m={3}>
103-
<PinInput size="lg">
138+
<PinInput size="lg" value={pin} onChange={handlePinChange}>
104139
<PinInputField size="lg" />
105140
<PinInputField size="lg" />
106141
<PinInputField size="lg" />
@@ -111,7 +146,7 @@ export const AdminPin = () => {
111146
</HStack>
112147

113148
</FormControl>
114-
<Text fontWeight="light" fontSize="sm" textAlign="center" mb={5}>Admin pins are sent to admins for confirmation. After pin is entered, a request is sent to that admin to verify your account. </Text>
149+
<Text fontWeight="light" fontSize="sm" textAlign="center" mb={5}>An email has been sent with a 2FA code. Please input it here. </Text>
115150

116151
<Button
117152
type="submit"
@@ -122,7 +157,7 @@ export const AdminPin = () => {
122157
mx={"auto"}
123158
mb={4}
124159
>
125-
Send Request
160+
Confirm Code
126161
</Button>
127162
</Stack>
128163
</form>

client/src/components/login/ChooseLogin.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ export const ChooseLogin = () => {
66

77
const handleUserSelection = (userType: string) => {
88
navigate(`/login/${userType}`);
9-
console.log("user type: ", userType);
109
};
1110

1211
return (

client/src/components/login/Login.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,10 @@ export const Login = () => {
7373
email: data.email,
7474
password: data.password,
7575
});
76-
if (userType === "Case Manager") navigate("/clientlist");
77-
else if (userType === "Admin") navigate("/admin-client-list");
76+
77+
78+
if (userType === "Case Manager") navigate("/authentification/Case Manager");
79+
else if (userType === "Admin") navigate("/authentification/Admin");
7880
} catch (err) {
7981
const errorCode = err.code;
8082
const firebaseErrorMsg = err.message;

client/src/components/signup/Signup.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,9 @@ export const Signup = () => {
6868
});
6969

7070
const handleSignup = async (data: SignupFormValues) => {
71-
console.log("submitted");
71+
7272
try {
73-
console.log({
74-
email: data.email,
75-
password: data.password,
76-
firstName: data.firstName,
77-
lastName: data.lastName,
78-
phoneNumber: data.phoneNumber,
79-
role: userType === "Admin" ? "admin" : (userType === "Case Manager" ? "user" : "client"),
80-
});
73+
8174
const user = await signup({
8275
email: data.email,
8376
password: data.password,
@@ -86,9 +79,8 @@ export const Signup = () => {
8679
phoneNumber: data.phoneNumber,
8780
role: userType === "Admin" ? "admin" : (userType === "Case Manager" ? "user" : "client"),
8881
});
89-
console.log(user);
9082
if (user) {
91-
navigate(`/admin-pin/${userType}`);
83+
navigate(`/clientlist`);
9284
}
9385
} catch (err) {
9486
if (err instanceof Error) {

0 commit comments

Comments
 (0)