koque
koque

Reputation: 2256

Why is jsonwebtoken declaring my token invalid?

On the client, I have the following function that calls the server api to register a user. The user token is returned and put in localstorage.

  public register = (user) => {
    this.httpClient.post<User>(this.url, user).pipe(
      tap(userData => {
        console.log('userData register.userData', userData)
        localStorage.setItem('userToken', JSON.stringify(userData.token));
        // this.router.navigate(['/home']);
      })
    ).subscribe(),
    catchError(error => {
      console.log('error', error)
      this.store.dispatch(messageActions.SetError({error}))
      throw error;
    })
  }

A copy of the token is seen here:

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NTRkNzc4MzFkMGUxN2ZiZTI1MDMyM2EiLCJpYXQiOjE2OTk1NzU3ODQsImV4cCI6MTY5OTU3NzU4NH0.3HsdFjARnAjWn35_VlXsJQ6oFbfL_3OLHTPsroIOayU"

An interceptor appends the token to the header for every request to the server as shown here:

intercept(request: HttpRequest<unknown>, next: HttpHandler): 
Observable<HttpEvent<unknown>> {
   const token = localStorage.getItem('userToken');
   console.log('token', token)

   if(token) {
    // const authReq = req.clone({setHeaders:{token:token}});

    const authReq = request.clone({setHeaders:{"Authorization":"Bearer " + token}});

    console.log('authReq', authReq)
    return next.handle(authReq)
}

    return next.handle(request);
  }
}

These are the stripped-down codes on the server side that pertains to creating the token:

exports.register = async (req, res) => {
    try {
        let userData = {};
        userData.token = generateAccessToken(newUser._id);
        userData.cart = cart;

       console.log("userData", userData);

        return res.status(201).json(userData)

    } catch (error) {
        console.log(error);
        res.status(500).send('Problem signing up user!')
        // throw error;

    }
};


function generateAccessToken(userId) {
    return jwt.sign({ userId }, process.env.JWT_SECRET, { expiresIn: '1800s' });
}

function authenticateToken(req, res) {
    const authHeader = req.headers.authorization
    console.log('authHeader', authHeader)
    const token = authHeader && authHeader.split(' ')[1]
    console.log('token', token)

    try {
        if (token == null) return res.status(500).send('Problem authenticating user token.')

         const {
            userId
        } = jwt.verify(token, process.env.JWT_SECRET)

        return userId;
    
   } catch(err) {
       console.log(err);
        res.status(500).send('Problem authenticating user token.')
    }
}

This is a copy of the token transmitted from transmitted from the interceptor to the server. (The 'Bearer ' is stripped off, of course.

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NTRkNzc4MzFkMGUxN2ZiZTI1MDMyM2EiLCJpYXQiOjE2OTk1NzU3ODQsImV4cCI6MTY5OTU3NzU4NH0.3HsdFjARnAjWn35_VlXsJQ6oFbfL_3OLHTPsroIOayU"

The authenticateToken function errors out when jwt.verify is called with the message: Invalid token.

Upvotes: 0

Views: 47

Answers (1)

Phil
Phil

Reputation: 164952

localStorage.setItem('userToken', JSON.stringify(userData.token));

You're using JSON.stringify() to store the token but aren't using JSON.parse() when retrieving it.

It will have embedded " characters wrapping the actual token.

const token = "my-jwt-token";

console.log("compare");
console.log({ Authorization: `Bearer ${token}` });
console.log({ Authorization: `Bearer ${JSON.stringify(token)}` });

Considering the token is just a string, I wouldn't bother with JSON.stringify()

localStorage.setItem('userToken', userData.token);

Upvotes: 1

Related Questions