Skip to content

Commit ecf7b20

Browse files
perf: improve auth security
1 parent 1e2f883 commit ecf7b20

19 files changed

Lines changed: 234 additions & 64 deletions

File tree

frontend/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"react-dom": "^17.0.1",
1616
"react-router-dom": "^5.2.0",
1717
"react-scripts": "^4.0.3",
18+
"react-swipeable-views": "^0.13.9",
1819
"swr": "^0.5.6",
1920
"web-vitals": "^0.2.4",
2021
"yup": "^0.32.9",
@@ -52,6 +53,7 @@
5253
"@types/react": "^17.0.5",
5354
"@types/react-dom": "^17.0.3",
5455
"@types/react-router-dom": "^5.1.7",
56+
"@types/react-swipeable-views": "^0.13.0",
5557
"@typescript-eslint/eslint-plugin": "^4.23.0",
5658
"@typescript-eslint/parser": "^4.23.0",
5759
"eslint": "^7.26.0",

frontend/src/App.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { updateAccessToken } from "./utils/updateAccessToken";
44
import Backdrop from "@material-ui/core/Backdrop";
55
import CircularProgress from "@material-ui/core/CircularProgress";
66
import { makeStyles, createStyles, Theme } from "@material-ui/core/styles";
7-
import { getToken } from "./store/tokenStore";
7+
import useTokenStore from "./store/tokenStore";
88

99
const useStyles = makeStyles((theme: Theme) =>
1010
createStyles({
@@ -18,14 +18,10 @@ const useStyles = makeStyles((theme: Theme) =>
1818
const App: React.FC = () => {
1919
const classes = useStyles();
2020
const [loading, setLoading] = React.useState(true);
21+
const setToken = useTokenStore((state) => state.setToken);
2122
React.useEffect(() => {
22-
const accessToken = getToken();
23-
if (!!accessToken) {
24-
updateAccessToken(setLoading);
25-
} else {
26-
setLoading(false);
27-
}
28-
});
23+
updateAccessToken(setToken, setLoading);
24+
}, []);
2925
return (
3026
<>
3127
<Routes />

frontend/src/Routes.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@ import Registration from "./pages/Registration";
88
import GoogleRedirect from "./pages/GoogleRedirect";
99
import Meeting from "./pages/Meeting";
1010
import { updateAccessToken } from "./utils/updateAccessToken";
11-
import { getToken } from "./store/tokenStore";
11+
import useTokenStore from "./store/tokenStore";
1212

13+
const REFRESH_TIME_MS = 60 * 60 * 1000;
1314
const Routes: React.FC = () => {
14-
const REFRESH_TIME_MS = 60 * 60 * 1000;
15+
const accessToken = useTokenStore((state) => state.token);
16+
const setToken = useTokenStore((state) => state.setToken);
1517
React.useEffect(() => {
1618
const interval = setInterval(() => {
17-
const accessToken = getToken();
1819
if (!!accessToken) {
1920
console.log("Refreshing token...");
20-
updateAccessToken();
21+
updateAccessToken(setToken);
2122
}
2223
}, REFRESH_TIME_MS);
2324

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,93 @@
11
import React from "react";
2-
import { createStyles, makeStyles } from "@material-ui/core/styles";
3-
4-
const useStyles = makeStyles(() =>
5-
createStyles({
6-
root: {
7-
flexGrow: 1,
8-
},
9-
})
10-
);
2+
import SwipeableViews from "react-swipeable-views";
3+
import { makeStyles, Theme, useTheme } from "@material-ui/core/styles";
4+
import AppBar from "@material-ui/core/AppBar";
5+
import Tabs from "@material-ui/core/Tabs";
6+
import Tab from "@material-ui/core/Tab";
7+
import Box from "@material-ui/core/Box";
8+
9+
interface TabPanelProps {
10+
children?: React.ReactNode;
11+
dir?: string;
12+
index: number;
13+
value: number;
14+
}
15+
16+
function TabPanel(props: TabPanelProps) {
17+
const { children, value, index, ...other } = props;
18+
19+
return (
20+
<div
21+
role="tabpanel"
22+
hidden={value !== index}
23+
id={`full-width-tabpanel-${index}`}
24+
aria-labelledby={`full-width-tab-${index}`}
25+
{...other}
26+
>
27+
{value === index && <Box p={2}>{children}</Box>}
28+
</div>
29+
);
30+
}
31+
32+
function a11yProps(index: number) {
33+
return {
34+
id: `full-width-tab-${index}`,
35+
"aria-controls": `full-width-tabpanel-${index}`,
36+
};
37+
}
38+
39+
const useStyles = makeStyles((theme: Theme) => ({
40+
root: {
41+
width: "100vw",
42+
},
43+
tabbar: {
44+
backgroundColor: theme.palette.background.paper,
45+
},
46+
}));
47+
1148
const MeetingTabs: React.FC = () => {
1249
const classes = useStyles();
13-
return <div className={classes.root}>yolo</div>;
14-
};
50+
const theme = useTheme();
51+
const [value, setValue] = React.useState(0);
52+
53+
// eslint-disable-next-line @typescript-eslint/ban-types
54+
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
55+
setValue(newValue);
56+
};
1557

58+
const handleChangeIndex = (index: number) => {
59+
setValue(index);
60+
};
61+
62+
return (
63+
<div className={classes.root}>
64+
<AppBar position="static" color="default">
65+
<Tabs
66+
className={classes.tabbar}
67+
value={value}
68+
onChange={handleChange}
69+
indicatorColor="primary"
70+
textColor="primary"
71+
variant="fullWidth"
72+
aria-label="full width tabs example"
73+
>
74+
<Tab label="Meetings" {...a11yProps(0)} />
75+
<Tab label="Polls" {...a11yProps(1)} />
76+
</Tabs>
77+
</AppBar>
78+
<SwipeableViews
79+
axis={theme.direction === "rtl" ? "x-reverse" : "x"}
80+
index={value}
81+
onChangeIndex={handleChangeIndex}
82+
>
83+
<TabPanel value={value} index={0} dir={theme.direction}>
84+
SecrET meETiNg
85+
</TabPanel>
86+
<TabPanel value={value} index={1} dir={theme.direction}>
87+
Pollllllling
88+
</TabPanel>
89+
</SwipeableViews>
90+
</div>
91+
);
92+
};
1693
export default MeetingTabs;

frontend/src/components/Navs/Navbar/index.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Toolbar from "@material-ui/core/Toolbar";
1313
import { Link, useHistory } from "react-router-dom";
1414
import MenuIcon from "@material-ui/icons/Menu";
1515
import { linklist } from "../linklist";
16-
import { getToken } from "src/store/tokenStore";
16+
import useTokenStore from "../../../store/tokenStore";
1717
import { logout } from "../../../utils/logout";
1818

1919
const useStyles = makeStyles((theme: Theme) =>
@@ -66,6 +66,8 @@ const useStyles = makeStyles((theme: Theme) =>
6666
})
6767
);
6868
const HomePage: React.FC = () => {
69+
const token = useTokenStore((state) => state.token);
70+
const setToken = useTokenStore((state) => state.setToken);
6971
const classes = useStyles();
7072
const [drawerOpen, setdrawerOpen] = React.useState(false);
7173

@@ -76,7 +78,7 @@ const HomePage: React.FC = () => {
7678
const history = useHistory();
7779

7880
const handleLogout = async (url: string) => {
79-
const res = await logout();
81+
const res = await logout(setToken);
8082
if (res) {
8183
history.push(url);
8284
}
@@ -93,7 +95,6 @@ const HomePage: React.FC = () => {
9395
<List>
9496
{linklist.map((e, key) => {
9597
if (e.loginReq) {
96-
const token = getToken();
9798
if (!!token)
9899
return (
99100
<div
@@ -141,7 +142,6 @@ const HomePage: React.FC = () => {
141142
<Container className={classes.flexbox}>
142143
{linklist.map((e, key) => {
143144
if (e.loginReq) {
144-
const token = getToken();
145145
if (!!token) {
146146
return (
147147
<div

frontend/src/components/Navs/navLinks/index.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import styles from "./style.module.css";
33
import { Link, useHistory } from "react-router-dom";
44
import { linklist } from "../linklist";
55
import { logout } from "src/utils/logout";
6-
import { getToken } from "src/store/tokenStore";
6+
import useTokenStore from "src/store/tokenStore";
77

88
const NavLinks: React.FC = () => {
9+
const setToken = useTokenStore((state) => state.setToken);
910
const history = useHistory();
1011
const styling = [
1112
styles.first,
@@ -17,17 +18,17 @@ const NavLinks: React.FC = () => {
1718
];
1819

1920
const handleLogout = async (url: string) => {
20-
const res = await logout();
21+
const res = await logout(setToken);
2122
if (res) {
2223
history.push(url);
2324
}
2425
};
26+
const token = useTokenStore((state) => state.token);
2527

2628
return (
2729
<>
2830
{linklist.map((e, key) => {
2931
if (e.loginReq) {
30-
const token = getToken();
3132
if (!!token) {
3233
return (
3334
<div

frontend/src/components/RegistrationForm/Login.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { fetchLogin } from "src/utils/fetchLogin";
88
import { useHistory } from "react-router";
99
import Snackbar from "@material-ui/core/Snackbar";
1010
import Alert from "@material-ui/lab/Alert";
11+
import useTokenStore from "src/store/tokenStore";
1112

1213
interface LoginProps {
1314
// setLogin: React.Dispatch<React.SetStateAction<boolean>>;
@@ -29,6 +30,7 @@ const validSchema = yup.object({
2930

3031
const Login: React.FC<LoginProps> = ({ setPage }) => {
3132
const history = useHistory();
33+
const setToken = useTokenStore((state) => state.setToken);
3234
const classes = useSignupLoginStyles();
3335
const [openError, setOpenError] = useState(false);
3436
const handleClose = (event?: React.SyntheticEvent, reason?: string) => {
@@ -48,7 +50,7 @@ const Login: React.FC<LoginProps> = ({ setPage }) => {
4850
validationSchema={validSchema}
4951
onSubmit={async (data, { setSubmitting, resetForm }) => {
5052
setSubmitting(true);
51-
const res = await fetchLogin(data);
53+
const res = await fetchLogin(data, setToken);
5254
if (!res.done) {
5355
console.log("ERROR FROM BACKEND");
5456
setOpenError(true);

frontend/src/components/RegistrationForm/Signup.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { fetchRegister } from "src/utils/fetchRegister";
88
import { useHistory } from "react-router";
99
import Snackbar from "@material-ui/core/Snackbar";
1010
import Alert from "@material-ui/lab/Alert";
11+
import useTokenStore from "src/store/tokenStore";
1112

1213
interface SignupProps {
1314
// setLogin: React.Dispatch<React.SetStateAction<boolean>>;
@@ -31,6 +32,7 @@ const validSchema = yup.object({
3132
const Signup: React.FC<SignupProps> = ({ setPage }) => {
3233
const history = useHistory();
3334
const classes = useSignupLoginStyles();
35+
const setToken = useTokenStore((state) => state.setToken);
3436
const [openError, setOpenError] = React.useState(false);
3537
const handleClose = (event?: React.SyntheticEvent, reason?: string) => {
3638
if (reason === "clickaway") {
@@ -50,7 +52,7 @@ const Signup: React.FC<SignupProps> = ({ setPage }) => {
5052
validationSchema={validSchema}
5153
onSubmit={async (data, { setSubmitting, resetForm }) => {
5254
setSubmitting(true);
53-
const res = await fetchRegister(data);
55+
const res = await fetchRegister(data, setToken);
5456
if (!res.done) {
5557
console.log("ERROR FROM BACKEND");
5658
setOpenError(true);

frontend/src/pages/GoogleRedirect/index.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { createStyles, makeStyles } from "@material-ui/core/styles";
33
import { useHistory, useLocation } from "react-router";
44
import queryString from "query-string";
55
import { server } from "src/store/global";
6-
import { setToken } from "src/store/tokenStore";
6+
import useTokenStore from "../../store/tokenStore";
77

88
const useStyles = makeStyles(() =>
99
createStyles({
@@ -22,19 +22,21 @@ const GoogleRedirect: React.FC = () => {
2222
const { search } = useLocation();
2323
const queries = queryString.parse(search);
2424
const id = queries.token;
25+
const setToken = useTokenStore((state) => state.setToken);
2526
React.useEffect(() => {
2627
const googleToken = async () => {
2728
const res = await fetch(server + "/api/user/google-login/" + id);
2829
const payload = await res.json();
2930
if (payload.done) {
3031
setToken(payload.accessToken);
31-
history.push("/events");
32+
history.push("/");
3233
} else {
3334
history.push("/registration");
3435
}
3536
};
37+
console.log("google redirect" + id);
3638
googleToken();
37-
});
39+
}, []);
3840
return <div className={classes.root}>Loading...</div>;
3941
};
4042

frontend/src/pages/Meeting/index.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React from "react";
22
import { createStyles, makeStyles } from "@material-ui/core/styles";
3-
import { getToken } from "src/store/tokenStore";
4-
import { Redirect } from "react-router";
3+
import useTokenStore from "src/store/tokenStore";
54
import Navbar from "../../components/Navs/Navbar";
6-
import MeetingTabs from "src/components/Meeting/MeetingTabs";
5+
import MeetingTabs from "../../components/Meeting/MeetingTabs";
6+
import { useHistory } from "react-router-dom";
77

88
const useStyles = makeStyles(() =>
99
createStyles({
@@ -15,10 +15,16 @@ const useStyles = makeStyles(() =>
1515

1616
const Meeting: React.FC = () => {
1717
const classes = useStyles();
18-
const token = getToken();
19-
if (!!!token) {
20-
return <Redirect to="/registration" />;
21-
}
18+
const history = useHistory();
19+
const token = useTokenStore((state) => state.token);
20+
React.useEffect(() => {
21+
setTimeout(() => {
22+
console.log(token);
23+
if (token && token === "") {
24+
history.push("/registration");
25+
}
26+
}, 2000);
27+
}, [token]);
2228
return (
2329
<div className={classes.root}>
2430
<Navbar />

0 commit comments

Comments
 (0)