问题
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?
回答1:
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.
回答2:
First: you can't view the cookie on client side because you set the following ({ secure:true, httpOnly:true}) -secure means it should only use the cookie over an https network while -httpOnly means the cookie should be read by any client side Javascript..
Second: did you really add the "Authorization" header after generating the jwt or you just put it in a cookie 🤔
If so, then try:
jwt.verify(token, <your secret>).then(user=> console.log(user)).catch(err=>console.log(err.toString());
For those who may run into same problem in the future
回答3:
From express-session docs:
Only set the secure tag if you're in production.
if (app.get('env') === 'production') {
app.set('trust proxy', 1) // trust first proxy
sess.cookie.secure = true // serve secure cookies
}
来源:https://stackoverflow.com/questions/56524264/how-to-store-jwt-in-cookie-and-pass-it-to-authentication-function-when-redirecti