Home > Software design >  JWT token not set in the response header
JWT token not set in the response header

Time:08-01

I have the following function, which authenticates a user by creating a response header:

function authenticateUser(res, id) {
    const payload = {
        id
    }
    const token = jwt.sign(payload, config.JWT_KEY, {
        expiresIn: '24h'
    })
    res.set('authorization', token)
    res.redirect('/user/profile')
    res.end()
}

However, when I redirect to the /user/profile, it outputs undefined for the authorization header:

controller.checkAuthorizaion = (req, res, next) => {
    const token = getJWTToken(req)
    console.log(token);
    if(!token) 
        Router.redirect(res, '/', 401)
    else {
        jwt.verify(token, config.JWT_KEY, (err, data) => {
            if(err)
                Router.redirect(res, '/', 401)
            else  {
                res.userId = data.id
                next()
            }
        })
    }
}

Why is it not working? How do I send my jwt token back to the client? I thought that jwt.sign() sends it automatically.

CodePudding user response:

If you use jsonwebtoken then you need to call it as async function or provide a callback:

async function authenticateUser(res, id) {
    const payload = {
        id
    }
    const token = await jwt.sign(payload, config.JWT_KEY, {
        expiresIn: '24h'
    })
    res.set('authorization', token)
    res.redirect('/user/profile')
    res.end()
}

getJWTToken(req) also should be called as async one:

controller.checkAuthorizaion = async (req, res, next) => {
    const token = await getJWTToken(req)
    console.log(token);

And, of course, inside the getJWTToken: you should call jwt.verify as an async function as well.

CodePudding user response:

  1. Authorization is a request header. It should not be used in responses and I think that most browsers ignore this header in the response.

  2. You are sending a redirect response to the browser. The browser reads that response and sends a new request to the /user/profile endpoint. The Authorization header is not added automatically by the browser to your requests.

If you send the original request as an AJAX call, then you would have to make sure that the client you're using (e.g. axios) reads the Authorization header from the response before sending another request to the endpoint that you redirect to. I haven't checked that, but I'm pretty sure that JS clients like axios ignore the Authorization header in responses and won't automatically copy it to another request.

Apart from that, @Anatoly has some valid points about calling async functions, so have a look at that as well.

How do I send my jwt token back to the client? I thought that jwt.sign() sends it automatically.

Normally, you send the token in the body of the response and let your client read the body and store the token somewhere - in memory, local storage, etc. Another solution would be to store the token in a cookie, but that will only work if you already own the backend that you're calling with the token. (If you do own the backend, then in fact there is no point in using access tokens. You could just use plain-old HTTP sessions.)

  • Related