Basic Login flow use session
Why?
When we build one website, the most basic part is login. But some programmer don't clear about it, includes me. Because of that, i think i need write down some notes for future project. So let's start!
Why i choose cookies generate by server (with flag httpOnly)?
I choose cookies generated with enable option httpOnly, because of cookies with send one by one request/response between client and server, so at client side we don't need store in localStorage or sessionStorage. It's convenient, we don't need check or insert to header with content like
Authorization: 'Bearer sercet-token'Basic setup
Client
For passing cookies on each request, client need set withCredentials: true on each request, read more
Server
server.use(
session({
name: config.COOKIE_NAME,
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 365 * 10,
httpOnly: true,
secure: config.IS_PROD, // only https
sameSite: 'lax', // csrf
},
saveUninitialized: false,
secret: config.COOKIE_SECURE,
resave: false,
}),
);Middleware verify on server side
On server side, we write a middleware to check each time client request come.
export const isSignedIn = ({ req, res, next }) => {
if (!req.session?.token) {
res.status(401).send({ message: 'You are not signed in' });
return;
}
// verify token
const { token } = req.session;
const isValid = verify(token, 'secret key');
if (!isValid) {
res.status(401).send({ message: 'Invalid token, please sign in again' });
return;
}
// if pass all use case, we next to middlware or route
return next();
};Verifing at client side
Because of cookie is httpOnly: true, javascript client can't read it. but we can use other way.
Write route /me on server
When client's request come, is must throught middlware isSignedIn, if success, return user information, but not, response a error message with status code 401
Write a custom hook
We can use a custom hook useAuth (or HOC) to check for private pages
export const useAuth = () => {
const [user, setUser] = useState();
useEffect(async () => {
try {
const res = await axios.get('/me');
setUser(res.data);
} catch(e) {
if (e.response?.status === 401) {
alert(e.response.data.message || 'You are not sign in');
history.push('/login');
}
}
}, []);
return user;
}Conclustion
With this way, we have simple and secure auth way. But when we restart server, all session we destroy and users will re-signin
Comments