I have a node.js express backend built with Postman and tested with Jest. I wrote a front end with hbs and the next step is to stitch them. However I still keep getting "please authenticate" error message that's from my auth function, which I guess is because I'm not successfully passing my jwt token.
So on login page (users/login) I want to login with email and password then I want to redirect to me page(users/me) where I can perform other stuff that belongs to this user.
Front-end login page code:
<section class="login-bg">
<div class="login-form">
<p>Welcome to Task Manager, please log in!</p>
<form class="input-group" action="/users/login" method="POST">
<label>Email:</label>
<input type="email" name="email" placeholder="type your email" value="{{user.email}}" required >
<label>Password:</label>
<input type="password" name="password" placeholder="type your password" value="{{user.password}}" required>
<button class="button" type="submit">Log In</button>
</form>
</div>
</section>
Back-end
in middleware/auth.js
const jwt = require('jsonwebtoken')
const User = require('../models/user')
const auth = async (req, res, next) => {
try {
const token = req.header('Authorization').replace('Bearer ', '')
const decoded = jwt.verify(token, process.env.JWT_SECRET)
const user = await User.findOne({_id: decoded._id, 'tokens.token': token})
if (!user) {
throw new Error()
}
req.token = token
req.user = user
next()
} catch (error) {
res.status(401).send({error: 'Please authenticate.'})
}
}
module.exports = auth
in src/routers/users.js
router.post('/login', async (req, res) => {
try {
const user = await User.findByCredentials(req.body.email, req.body.password)
const token = await user.generateAuthToken()
res.cookie('jwt',token, { httpOnly: true, secure: true, maxAge: 3600000 })
res.redirect('/users/me')
} catch (error) {
res.status(400).send()
}
})
However, when I do console.log(document.cookie) in users/me it says undefined.
Then I have the cookie-parser installed and import to app.js, and try to write this part in src/routers/users.js:
router.get('/me', auth, async (req, res) => {
console.log('Cookies: ', req.cookies)
try {
res.render('me', {name: user.name})
} catch (error) {
res.status(500).send()
}
})
but this console doesn't print anything, probably cos I am getting error from auth.
I also have a a js file attached to me page but I have no clue if I could write this way, probably wrong:
const userToken = document.cookie.jwt.token
fetch('/users/me', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + userToken
}
})
.then(res => res.json())
.then(data => { console.log(data) })
.catch(err => { console.log(err) })
then in the Network / Headers, I have
Request URL:
http://localhost:3000/users/login
Request Method:
POST
Status Code:
302 Found
Remote Address:
Referrer Policy:
no-referrer-when-downgrade
Response Headers
Connection:
keep-alive
Content-Length:
62
Content-Type:
text/html; charset=utf-8
Date:
Fri, 07 Jun 2019 18:41:47 GMT
Location:
/users/me
Set-Cookie:
jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1Y2Y2NjNlMTQwMTQyYjE0MzhmZTJjNDMiLCJpYXQiOjE1NTk5MzI5MDd9.T_P8O-j98cs9gtahTzspJjx1qNMSe3M5OAySyeH25fs; Max-Age=3600; Path=/; Expires=Fri, 07 Jun 2019 19:41:47 GMT; HttpOnly; Secure
Vary:
Accept
X-Powered-By:
Express
There is no request cookies, only response cookies. I am not sure what those means...@_@
I want to pass the jwt to successfully login and render the me page properly, how could I do that?
To keep them secure, you should always store JWTs inside an httpOnly cookie. This is a special kind of cookie that's only sent in HTTP requests to the server. It's never accessible (both for reading or writing) from JavaScript running in the browser.
HTTP Only JWT Cookie: In a SPA(Single Page Application) Authentication JWT token either can be stored in browser 'LocalStorage' or in 'Cookie'. Storing JWT token inside of the cookie then the cookie should be HTTP Only. The HTTP-Only cookie nature is that it will be only accessible by the server application.
JWT in CookieA cookie can be set from the server-side and also in client-side, First we can see how to set and get the JWT from the cookie in the React and using the browser console. The cookie is set to the current domain by default and expiry date is set to 1st Jan 2021.
Cookies have a size limit of 4KB. Therefore, if you're using a big JWT Token, storing in the cookie is not an option. There are scenarios where you can't share cookies with your API server or the API requires you to put the access token in the Authorization header.
Your jwt token cookie does not work because it declares flag secure: true
in the following code:
res.cookie('jwt',token, { httpOnly: true, secure: true, maxAge: 3600000 })
which lead to Secure
flag in HTTP response, indicating this cookie is only available under HTTPS environment:
Set-Cookie:
jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1Y2Y2NjNlMTQwMTQyYjE0MzhmZTJjNDMiLCJpYXQiOjE1NTk5MzI5MDd9.T_P8O-j98cs9gtahTzspJjx1qNMSe3M5OAySyeH25fs;
Max-Age=3600; Path=/;
Expires=Fri, 07 Jun 2019 19:41:47 GMT; HttpOnly; Secure
As your request URL is using HTTP (http://localhost:3000/users/login
), the cookie would be ignored by browser.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With