Skip to content

Commit d3729dc

Browse files
committed
logout when token is expired
1 parent ef8d08a commit d3729dc

File tree

7 files changed

+119
-3
lines changed

7 files changed

+119
-3
lines changed

README.md

+47-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
## React Hooks: JWT Authentication (without Redux) example
22

33
For more detail, please visit:
4+
> [React Hooks: JWT Authentication & Authorization (without Redux) example](https://bezkoder.com/react-hooks-jwt-auth/)
45
5-
> [React Hooks: JWT Authentication & Authorization example](https://bezkoder.com/react-hooks-jwt-auth/)
6+
> [React Redux Login, Logout, Registration example with Hooks](https://bezkoder.com/react-hooks-redux-login-registration-example/)
7+
8+
> [React (Components) JWT Authentication & Authorization example](https://bezkoder.com/react-jwt-auth/)
9+
10+
Fullstack (JWT Authentication & Authorization example):
11+
> [React + Spring Boot](https://bezkoder.com/spring-boot-react-jwt-auth/)
12+
13+
> [React + Node.js Express](https://bezkoder.com/react-express-authentication-jwt/)
614
715
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
816

@@ -12,7 +20,7 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo
1220
PORT=8081
1321
```
1422

15-
## Note:
23+
### Note:
1624
Open `src/services/auth-header.js` and modify `return` statement for appropriate back-end (found in the tutorial).
1725

1826
```js
@@ -28,7 +36,7 @@ export default function authHeader() {
2836
}
2937
```
3038

31-
## Project setup
39+
### Project setup
3240

3341
In the project directory, you can run:
3442

@@ -51,3 +59,39 @@ yarn start
5159
Open [http://localhost:8081](http://localhost:8081) to view it in the browser.
5260

5361
The page will reload if you make edits.
62+
63+
### Related Posts
64+
> [In-depth Introduction to JWT-JSON Web Token](https://bezkoder.com/jwt-json-web-token/)
65+
66+
> [React CRUD example using Hooks](https://bezkoder.com/react-hooks-crud-axios-api/)
67+
68+
> [React Pagination using Hooks example](https://bezkoder.com/react-pagination-hooks/)
69+
70+
> [React Hooks File Upload example](https://bezkoder.com/react-hooks-file-upload/)
71+
72+
Fullstack with Node.js Express:
73+
> [React.js + Node.js Express + MySQL](https://bezkoder.com/react-node-express-mysql/)
74+
75+
> [React.js + Node.js Express + PostgreSQL](https://bezkoder.com/react-node-express-postgresql/)
76+
77+
> [React.js + Node.js Express + MongoDB](https://bezkoder.com/react-node-express-mongodb-mern-stack/)
78+
79+
Fullstack with Spring Boot:
80+
> [React.js + Spring Boot + MySQL](https://bezkoder.com/react-spring-boot-crud/)
81+
82+
> [React.js + Spring Boot + PostgreSQL](https://bezkoder.com/spring-boot-react-postgresql/)
83+
84+
> [React.js + Spring Boot + MongoDB](https://bezkoder.com/react-spring-boot-mongodb/)
85+
86+
Fullstack with Django:
87+
> [React.js Hooks + Django Rest Framework](https://bezkoder.com/django-react-hooks/)
88+
89+
Serverless:
90+
> [React Hooks Firebase Realtime Database: CRUD App ](https://bezkoder.com/react-firebase-hooks-crud/)
91+
92+
> [React Hooks Firestore example: CRUD App](https://bezkoder.com/react-hooks-firestore/)
93+
94+
Integration (run back-end & front-end on same server/port)
95+
> [Integrate React with Spring Boot](https://bezkoder.com/integrate-reactjs-spring-boot/)
96+
97+
> [Integrate React with Node.js Express](https://bezkoder.com/integrate-react-express-same-server-port/)

src/App.js

+16
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import BoardUser from "./components/BoardUser";
1313
import BoardModerator from "./components/BoardModerator";
1414
import BoardAdmin from "./components/BoardAdmin";
1515

16+
// import AuthVerify from "./common/AuthVerify";
17+
import EventBus from "./common/EventBus";
18+
1619
const App = () => {
1720
const [showModeratorBoard, setShowModeratorBoard] = useState(false);
1821
const [showAdminBoard, setShowAdminBoard] = useState(false);
@@ -26,10 +29,21 @@ const App = () => {
2629
setShowModeratorBoard(user.roles.includes("ROLE_MODERATOR"));
2730
setShowAdminBoard(user.roles.includes("ROLE_ADMIN"));
2831
}
32+
33+
EventBus.on("logout", () => {
34+
logOut();
35+
});
36+
37+
return () => {
38+
EventBus.remove("logout");
39+
};
2940
}, []);
3041

3142
const logOut = () => {
3243
AuthService.logout();
44+
setShowModeratorBoard(false);
45+
setShowAdminBoard(false);
46+
setCurrentUser(undefined);
3347
};
3448

3549
return (
@@ -111,6 +125,8 @@ const App = () => {
111125
<Route path="/admin" component={BoardAdmin} />
112126
</Switch>
113127
</div>
128+
129+
{/* <AuthVerify logOut={logOut}/> */}
114130
</div>
115131
);
116132
};

src/common/AuthVerify.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from "react";
2+
import { withRouter } from "react-router-dom";
3+
4+
const parseJwt = (token) => {
5+
try {
6+
return JSON.parse(atob(token.split(".")[1]));
7+
} catch (e) {
8+
return null;
9+
}
10+
};
11+
12+
const AuthVerify = (props) => {
13+
props.history.listen(() => {
14+
const user = JSON.parse(localStorage.getItem("user"));
15+
16+
if (user) {
17+
const decodedJwt = parseJwt(user.accessToken);
18+
19+
if (decodedJwt.exp * 1000 < Date.now()) {
20+
props.logOut();
21+
}
22+
}
23+
});
24+
25+
return <div></div>;
26+
};
27+
28+
export default withRouter(AuthVerify);

src/common/EventBus.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const eventBus = {
2+
on(event, callback) {
3+
document.addEventListener(event, (e) => callback(e.detail));
4+
},
5+
dispatch(event, data) {
6+
document.dispatchEvent(new CustomEvent(event, { detail: data }));
7+
},
8+
remove(event, callback) {
9+
document.removeEventListener(event, callback);
10+
},
11+
};
12+
13+
export default eventBus;

src/components/BoardAdmin.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useState, useEffect } from "react";
22

33
import UserService from "../services/user.service";
4+
import EventBus from "../common/EventBus";
45

56
const BoardAdmin = () => {
67
const [content, setContent] = useState("");
@@ -19,6 +20,10 @@ const BoardAdmin = () => {
1920
error.toString();
2021

2122
setContent(_content);
23+
24+
if (error.response && error.response.status === 401) {
25+
EventBus.dispatch("logout");
26+
}
2227
}
2328
);
2429
}, []);

src/components/BoardModerator.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useState, useEffect } from "react";
22

33
import UserService from "../services/user.service";
4+
import EventBus from "../common/EventBus";
45

56
const BoardModerator = () => {
67
const [content, setContent] = useState("");
@@ -19,6 +20,10 @@ const BoardModerator = () => {
1920
error.toString();
2021

2122
setContent(_content);
23+
24+
if (error.response && error.response.status === 401) {
25+
EventBus.dispatch("logout");
26+
}
2227
}
2328
);
2429
}, []);

src/components/BoardUser.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useState, useEffect } from "react";
22

33
import UserService from "../services/user.service";
4+
import EventBus from "../common/EventBus";
45

56
const BoardUser = () => {
67
const [content, setContent] = useState("");
@@ -19,6 +20,10 @@ const BoardUser = () => {
1920
error.toString();
2021

2122
setContent(_content);
23+
24+
if (error.response && error.response.status === 401) {
25+
EventBus.dispatch("logout");
26+
}
2227
}
2328
);
2429
}, []);

0 commit comments

Comments
 (0)