Crazy Horse
asked on
jwt auth implimentation not redirecting with altered cookie/incorrect token value
I have a node.js API and a next.js frontend application. The login is working for the most part. But if I open google dev tools and I change the value of the token cookie and try to access the secret page again, it still lets me. Shouldn't it kick me out because the token is no longer the same?
Here is the backend where I check login credentials and then create the token.
Here is the backend where I check login credentials and then create the token.
exports.login = async (req, res, next) => {
// check if email exists
const user = await User.findOne({ email: req.body.email });
if (!user)
return res.status(400).send({ errors: ["Invalid login credentials"] });
//email exists, check password
const validPass = await bcrypt.compare(req.body.password, user.password);
if (!validPass)
return res.status(400).send({ errors: ["Invalid login credentials"] });
// create jwt token
const token = jwt.sign(
{ email: user.email, _id: user._id },
process.env.TOKEN_SECRET,
{ expiresIn: "1h" }
);
// add token to header
res.header("auth-token", token).send(token);
};
Then here is the frontend code for the login where I set the cookie with the token value from the server: handleSubmit = async event => {
const { email, password } = this.state;
event.preventDefault();
const user = {
email,
password
};
// client side validation
const errors = this.validate(user);
this.setState({ errors: errors || {} });
if (errors) return;
try {
const response = await login(user);
const token = response.data;
cookies.set("token", token);
} catch (ex) {
if (ex.response) {
const errors = ex.response.data.errors;
this.setState({ errors });
}
}
};
Then I created a route which you can only access if logged in:Secret.getInitialProps = async ctx => {
await handleAuthSSR(ctx);
const response = await axios.get("http://localhost:8000/api/user");
return {
users: response.data
};
};
Here is the auth function (I am using next-cookies)import nextCookie from "next-cookies";
export const handleAuthSSR = ctx => {
const { token } = nextCookie(ctx);
if (ctx.req && !token) {
ctx.res.writeHead(302, { Location: "/login" });
ctx.res.end();
return;
}
if (!token) {
console.log("no token found");
Router.push("/");
}
return token;
};
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I have tried this now. It works but not sure if it's correct.
Secret.getInitialProps = async ctx => {
const { token } = nextCookie(ctx);
try {
const response = await axios.get("http://localhost:8000/api/user", {
headers: { Authorization: token }
});
return {
users: response.data
};
} catch (ex) {
ctx.res.writeHead(302, { Location: "/login" });
ctx.res.end();
return;
}
};
The last getInitialProps looks fine. You can only return response.data if calling to server succeeds (with valid token),
ASKER
Open in new window
My try/catch block on the frontend isn't working though:
Open in new window
The error I am getting is that response is not defined. If I drop the try/catch then I get the data back but if I test without sending the token in the header then I get a nasty looking page. For now I just want to console.log the error.