Inside our src
folder, we will have an api
folder and inside it we have an auth.js
file, here is where we put our authentication functions.
- Create a function
register
that takesuserInfo
as a parameter and send a post request to the register end-point with theuserInfo
. (This step is already done) - Go to
Register.js
page and importregister
function fromapi/auth.js
. - Use the
useMutation
hook with theregister
function and pass ituserInfo
- Call your mutate function inside the
handleFormSubmit
function! - Now go to
auth.js
in the api folder and add the following code to yourregister
function:
const formData = new FormData();
for (const key in userInfo) formData.append(key, userInfo[key]);
- Then, replace the
userInfo
inside the post request withformData
. - This step will enable you to send files with the request
- Create a function
login
that takesuserInfo
as a parameter and send a post request to the login end-point with theuserInfo
. (This step is already done) - Go to
Login.js
page and import thelogin
function fromapi/auth.js
. - Use the
useMutation
hook with thelogin
function and pass ituserInfo
. - Call your mutate function inside the
handleFormSubmit
function!
- In auth.js create the storeToken function
const storeToken = (token) => {
localStorage.setItem("token", token);
};
- Now go to both
login
andregister
functions and callstoreToken()
after getting the data and pass it your data.token
const login = async (userInfo) => {
try {
const { data } = await instance.post("/auth/login", userInfo);
storeToken(data.token); // <--- This
return data;
} catch (error) {
console.log(error);
}
};
const register = async (userInfo) => {
try {
// This is for seding the request with files
const formData = new FormData();
for (const key in userInfo) formData.append(key, userInfo[key]);
// END
const { data } = await instance.post("/auth/register", formData);
storeToken(data.token); // <--- This
return data;
} catch (error) {
console.log(error);
}
};
npm install jwt-decode
- In
auth.js
, import jwt_decode fromjwt-decode
and create a functioncheckToken
. - Inside it create a variable
token
that retrieves the token from yourlocalStorage
using getItem. - Now check if token is available, create a variable
decode
that decodes the token and create a variablecurrentTime
that gives you the current time.(Hint: use Date.now() ) - Now check if the token is expired (Hint: compare the currentTime with decode.exp), if it is expired, remove the token from
localStorage
using removeItem and return false, Otherwise return true. - Also return false outside the if condition.
const checkToken = () => {
const token = localStorage.getItem("token");
if (token) {
const decode = jwt_decode(token);
const cureentTime = Date.now() / 1000;
if (decode.exp < cureentTime) {
localStorage.removeItem("token");
return false;
}
return true;
}
return false;
};
- In your src folder, create a
context
folder, and inside it add aUserContext
file. - Now import
createContext
and initialize a UserContext. (Export it)
//src/context/UserContext.js
import { createContext } from "react";
const UserContext = createContext();
export default UserContext;
- Now go to
App.js
and importUserContext
. - Create a user state and give it false as an initial value.
- Now wrap the whole app with
<UserContext.Provider>
and pass it a value of [user, setUser]. - Your App should look like this
function App() {
const [user, setUser] = useState(false);
useEffect(() => {
setUser(checkToken());
}, []);
return (
<UserContext.Provider value={[user, setUser]}>
// ....
// ....
</UserContext.Provider>
- Now go to
NavBar.js
inside your components folder, and importuseContext
(from react) andUserContext
that we just created - Use useContext hook for
[user and setUser]
and give it the (UserContext). Hint:
const [user, setUser] = useContext(UserContext);
- Then check if the user is true, show the logout button, if false show the register and login buttons. (hint: search ternary operator).
{
user ? <> /*components*/ </> : <> /*components*/ </>;
}
- Go to
auth.js
in the api folder - Create a function
logout
that removes the token from the localStorage using removeItem.
const logout = () => {
localStorage.removeItem("token");
};
- Now go to
NavBar.js
inside your components folder - create a function
handleLogout
that calls thelogout
function fromapi/auth.js
- use
setUser
from the useContext to set the user tofalse
- Finally, Pass the
handleLogout
function to the onClick method of the logout button.
- In
index.js
inside the api folder, use yourinstance
to create an interceptor using theinterceptors.request.use()
and pass it an anonymous function. - If the token is in the localStorage then config.headers.authorization = token.
- return config.
hint:
instance.interceptors.request.use((config) => {
const token = localStorage.getItem("token");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});