JWT not decoding "JWT malformed" - Node Angular

32,320

Glad you got it figured out! The problem, for posterity, was the following: A JWT consists of three components, a header, the payload, and the signature (a good, thorough explanation can be found in this toptal post), so when you were splitting the JWT into components with var token = req.headers.authorization.split('.'), the value you were assigning to token referred to the payload only, rather than the full JWT.

Because the jwt-simple decode method expects the full token and you were only giving it the payload to assess, your code was triggering the 'jwt malformed' error. In your case, since you preceded the token with Bearer in your Authorization header, you could grab the full token with var token = req.headers.authorization.split(' ') instead.

Share:
32,320
Les Paul
Author by

Les Paul

Updated on July 23, 2022

Comments

  • Les Paul
    Les Paul almost 2 years

    Upon logging in I send a JSON web token to the client-side. I have a custom authInterceptor which sends the JSON web token back to the server side.

    When I log in, everything works. Go to different sub-pages, works great. This is because I have a function which either checks for Passport authentication or token authentication, and upon logging in the Passport authentication works.

    When I close the browser and return to the site, the JWT cannot decode. The JWT can decode when it is placed just under the encoding function. I have tried both the jwt-simple node module and the jsonwebtoken node modules, and I come back with the same error.

    This is my custom function which checks for a valid token:

    function checkAuthentication(req, res, next){
      if (!req.headers.authorization) {
         return res.status(401).send({ message: 'Please make sure your request has an Authorization header' });
      }
      console.log("Here");
      var token = req.headers.authorization.split('.')[1];
      console.log(token);
      console.log(config.secret);
      var payload = null;
      try {
        console.log("And here....");
        payload = jwt.decode(token, config.secret);
        console.log(payload);
      }
      catch (err) {
        console.log(err);
        return false;
      }
    
      if (payload.exp <= moment().unix()) {
        return false;
      }
      req.user = payload.sub;
      return true;
    }
    

    jwt-simple uses jwt.encode() and jwt.decode, and jsonwebtoken uses jwt.sign() and jwt.verify(). This is what I get in my console:

    Here
    eyJzdWIiOiI1NmEyZDk3MWQwZDg2OThhMTYwYTBkM2QiLCJleHAiOjE0NTYxOTEyNzQsImlhdCI6MTQ1NTMyNzI3NH0
    VerySecretPhrase
    And here....
    { [JsonWebTokenError: jwt malformed] name: 'JsonWebTokenError', message: 'jwt malformed' } 
    

    This is the authInterceptor on the client-side. I collect the token and set it in the request header:

    app.factory('httpInterceptor', function($q, $store, $window) {
    return {
        request: function (config){
            config.headers = config.headers || {};
            if($store.get('token')){
                var token = config.headers.Authorization = 'Bearer ' + $store.get('token');
            }
            return config;
        },
        responseError: function(response){
            if(response.status === 401 || response.status === 403) {
                $window.location.href = "http://localhost:3000/login";
            }
            return $q.reject(response);
        }
    };
    });