Saving JWT token to local storage - node.js

I want to save a JWT token into local storage in order to authenticate routes. My code is below but when this route is hit the browser just sits on loading and then says this page isnt working. Removing the localStorage.setItem() makes it work. Im wondering why this is happening. Thanks.
} else {
bcrypt.compare(password, user.password).then(Matched => {
if (Matched) {
//Create the payload for JWT to code
const payload = { id: user.id, name: user.name, email: user.email };
jwt.sign(
payload,
keys.JWT_KEY,
{ expiresIn: 3600 },
(err, token) => {
**localStorage.setItem("token", token);
res.redirect("/");**
}
);
} else {

Because localStorage.setItem("token", token) doesn't exist in nodejs, so the app will crash on this line and res.redirect("/"); is never executed, so the response is never sent back and your browser hangs while waiting for the response.
To fix it, send token back to client using res.json({ token: token }); and run localStorage.setItem("token", token); in the browser.

Related

How to get access token in Nodejs using #okta/okta-auth-js signInWithCredentials method

I am new to Okta authentication in nodejs, I've been struggling to get an access token. I am using okta-auth-js's signInWithCredentials.
new OktaAuth({
issuer: OKTA_AUTHORISER_ISSUER_URI,
clientId: OKTA_WEB_APP_CLIENT_ID,
redirectUri: OKTA_REDIRECT_URI,
responseType: "token",
});
await this.authClient.signInWithCredentials({
username: email,
password,
});
But this only gets me a sessionToken. How can I get an access token after this? I think I am missing setting an authState here but I am not sure how to do it.
Thanks
You should use something like that to get back the access token :
await this.authClient.signInWithCredentials({
username: email,
password,
});
this.authClient.isAuthenticated().then(value => {
if (!value) {
console.log('not authenticated');
} else {
authClient.tokenManager.get('accessToken').then(value => {
console.log(value.accessToken);
})
}
})

Destroy JsonWebToken on logout request in Node.js

I want to destroy the JWT whenever user sends the logout request to the app.
First of all, I am not storing JWT in the database so I can not delete that and I am also not using cookies or sessions. Is JWT stored on the client side? If so how can I destroy the JWT and invalidate the user's requests after logging out of the app.
The token middleware:
module.exports = middlewares = {
authenticateToken: async (req, res, next) => {
try {
if (!req.headers["x-access-token"]) {
return res.status(401).json({
error: "Key x-access-token not found",
});
}
if (req.headers["x-access-token"] === "") {
return res.status(401).json({
error: "Token not found",
});
}
const token = req.headers["x-access-token"];
const data = jwt.verify(token, keys.JWToken);
if (!data) return res.status(401).json({ error: "Invalid token" });
req.data = data;
next();
} catch (err) {
return res.status(400).json({ error: err.message });
}
},
};
Here's how I generate token on the registration and login requests:
const payload = { id: new_user._id };
const JWToken = jwt.sign(payload, keys.JWToken, { expiresIn: 31556926 });
The code provided is from the server, hence I don't know how its being saved on the client side, usually it is done using localhost, cookie or session. But you have mentioned that you are not using cookie or session, hence there is a chance that you are using local storage to store the jwt token. You can check your local storage on chrome by going to developer options -> Application -> Local Storage. You may find your token by how you named it, you can access it and delete by localStorage.removeItem("name of your token");

Get User Display Name from Firebase VerifyToken (part2)

I have the same situation as the other post with the same title. I have a custom backend (node+express) and I am able to update the displayName on the front end. However, when looking at the DecodedIdToken on the backend, there's no "name" when registering the user. I need the display name of the user so it can be synced with other clients on the backend.
If I sign out the newly registered user and log back in, the DecodedIdToken now shows the "name" on the backend.
Client side code:
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then(dataBeforeEmail => {
firebase.auth().onAuthStateChanged(function(user) {
user.sendEmailVerification();
user.updateProfile({displayName: displayName})
});
})
.then(dataAfterEmail => {
firebase.auth().onAuthStateChanged(async function(user) {
if (user) {
// Sign up successful
dispatch({
type: REGISTER_SUCCESS,
payload:user
});
const header = await tokenConfig();
try{
axios
.post('/api/auth/',{}, header)
.then(res=>
dispatch({
type: REGISTER_SUCCESS,
payload: res.data
})
(console.log(res.data))
)
}
catch(err) {
dispatch({
type: REGISTER_FAIL,
payload:
"Something went wrong, we couldn't create your account. Please try again."
});
};
export const tokenConfig = async () => {
const user = firebase.auth().currentUser;
const token = user && (await user.getIdToken());
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
};
return config;
};
Is there a way to have it show without having the user log out and log back in?
This is because of how the client SDK is handling the ID tokens. ID tokens are cached up to an hour. So you have to do one of the following before any changes to the user account are reflected on the ID token:
Wait for the current ID token to expire, and the SDK to automatically fetch a new one.
Sign-out and sign-in, which cycles out the ID token.
Explicitly request an ID token refresh on the client SDK. If you're using the JS SDK this will look something like this:
firebase.auth().currentUser.getIdToken(/* forceRefresh */ true)
For more details:
https://firebase.google.com/docs/auth/admin/verify-id-tokens#retrieve_id_tokens_on_clients
https://firebase.google.com/docs/auth/admin/manage-sessions

How to receive a cookie on reactjs from nodejs

I'm attempting to create a login where login data is sent to the nodejs server and if that login data is correct the server will send a JWT token through "res.cookie", what I would like to know is how will the reactjs client receive this cookie and also clear this cookie.
app.post('/login', (req, res) => {
const userData = {
email: req.body.email,
password: req.body.password
}
if(userData.email === email && userData.password === password){
const payload = { email };
const token = jwt.sign(payload, secret, {
expiresIn: '1h'
});
console.log(token)
res.cookie('token', token, { httpOnly: true })
.sendStatus(200);
}else{
res.send('incorrect params')
}
console.log(userData)
})
Here are the steps that need to happen.
User types their username and password and clicks sign in
Server receives credentials and validates them.
Server then creates a JWT for the users session and the server creates a cookie that contains the value of the jwt
the server simply returns and the cookie will be delivered as long as it is part of the response object.
hit control/command + i and view the cookie in chrome under your applications tab on the dev tools.
Also you probably want to use the nodejs https://www.npmjs.com/package/cookie-parser package to make your life easier.

How to send Bearer token to client and then call token from client

I have done a tutorial trying to get my head around JWT tokens. I seem to have got my head around the token creation as well as using the token to allow or disallow access to a route.
This all works great using postman, but in postman I enter the token under authorization. My question is:
1. how do I send the token to the client so it is saved on that client side.
2. How does the client return the token when they try to access a route?
I need to understand how this happens when NOT using postman. I am sure its pretty simple.
Do I just send
`res.header('Authorization', 'Bearer', + token);`
`res.header('Authorization', 'Bearer' + token);`
But can I send this with other stuff like a message / data etc?
Then when the user tries to access a protected route later, How do I access this header. IOW how is it stored client-side?
This is what I have thus far:
`//login route`
`app.post('/login', async function(req, res, next) {
const { name, password } = req.body;
if (name && password) {
let user = await getUser({ name: name });
if (!user) {
res.status(401).json({ message: 'No such user found' });
}
if (user.password === password) {
// from now on we'll identify the user by the id and the id is the
// only personalized value that goes into our token
let payload = { id: user.id };
let token = jwt.sign(payload, jwtOptions.secretOrKey);
res.json({ msg: 'ok', token: token });
} else {
res.status(401).json({ msg: 'Password is incorrect' });
}
}
});`
`// protected route
app.get('/protected', passport.authenticate('jwt', { session: false }), function(req, res) {
console.log('REQUEST HEADERS ON PROTECTED::',req.headers.authorization)
res.json('Success! You can now see this without a token.');
});`
The console.log under protected route gives me:
"REQUEST HEADERS ON PROTECTED:: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTU2NjI3NTczfQ.gAU2VzpUpXHpcgM6_n8gf7D-xLCS59tK6K2RIlIk-L4" but I gather this is because I used the authorization in postman.
I recently worked with jwt auth using react as my front end and hapi.js as backend. To save the token on the client side, you can use localstorage like this:
You have to save this on the user login component.
localStorage.setItem('token', res.data.token);
And then, to access this token on the protected router, use this :
let token = localStorage.getItem('token');
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
I hope this may help you to solve your problem on the client side.

Resources