Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store jwt in cookie and pass it to authentication function when redirecting a page?

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?

like image 911
Annie Avatar asked Jun 10 '19 10:06

Annie


People also ask

Can we store JWT token in cookie?

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.

How do I store JWT Inside an httpOnly cookie?

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.

How do I store JWT in cookie react?

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.

Should I send JWT as cookie?

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.


1 Answers

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.

like image 176
shaochuancs Avatar answered Sep 20 '22 07:09

shaochuancs