What steps should I take to create code that can generate a JWT token for user authentication and authorization?

I'm struggling to get this working. I have a dilemma with two files: permissionCtrl.js and tokenCtrl.js. My tech stack includes nJWT, Node.js/Express.js, Sequelize & Postgres.

The permission file contains a function called hasPermission that is linked to the token file. This function is supposed to verify the token generated in the token file and return either a successful result callback or a 403 response with messages provided below. If successful, it will allow the user access to a secure route based on their role and access level. Please note that the tokenCtrl.hasPermission.js is imported into this file.

hasPermission.js

exports.hasPermission = (req, res, permission, success) => {
  const token = req.get('Authorization');
  const hasPermission = tokenCtrl.hasPermission(token, permission); //throws an error here
  console.log('permission', permission);
  if (hasPermission) {
    return success();
  } else {
    res.status(403);
    return res.json({
      error: {
        status: 403,
        message: 'Unauthorized',
      },
    });
  }
};

tokenCtrl.js

const nJwt = require('njwt');
const secureRandom = require('secure-random');
const signingKey = secureRandom(512, {type: 'Buffer'}); // Generates a highly random byte array of 256 bytes
const base64SigningKey = signingKey.toString('base64');

const claims = {
  iss: "mysite.com",  
  sub: "users/user1234",    
  scope: "user, admins"
};

module.exports = {

  getToken: (claims, signingKey) => {
    const jwt = nJwt.create(claims, signingKey, 'HS512');
    console.log(jwt);
    const token = jwt.compact();
     console.log("Token :" + token);
    return (token);
},

    validateToken: (token, signingKey) => {
      nJwt.verify(token, signingKey, 'HS512', function(err, verifiedJwt){
        if(err){
          console.log(err); 
        }else{
          console.log(verifiedJwt);
        }
        return (verifiedJwt);
      });
  },

  token_post: (req, res) => {
  res.send(this.validateToken(req.header.Authorization, signingKey));
},

getSecret: () => {
  const secret = require('../config/secret.json').secret;
  console.log('secret', secret);
  return secret;
},

hasPermission: (token, resource) => {
  const result = this.validateToken(token, signingKey); 
  console.log(result);
  if (result.name === 'JsonWebTokenError') {
    return false;
  } else if (result.permissions) {
    let permissionSet = new Set(result.permissions);
    console.log('permissions in token', JSON.stringify(permissionSet));
    return permissionSet.has(resource);
  } else {
    return false;
  }
}

}

ERRORS

  1. Error occurs at this line: 'this.validateToken not a function' as indicated in the code comment.

  2. Error occurs at this line: 'tokenCtrl.hasPermission not a function' as shown in the code comment.

IMPORTANT: The getSecret function in the tokenCtrl file is utilized by other files.

Answer №1

Your code is encountering issues with how this behaves in arrow functions. Previously, functions would create a new empty this in their inner scope; however, in arrow functions, this is bound to the enclosing scope. Since you are declaring the function inside the exports object, you might expect this to bind to the enclosing object, but it does not.

A solution would be to declare your functions first and then add them to your exports afterwards. This way, you can avoid using this and simply call your validateToken function.

const validateToken = (token, signingKey) => {
      nJwt.verify(token, signingKey, 'HS512', function(err, verifiedJwt){
        if(err){
          console.log(err); // Token has expired, has been tampered with, etc
        }else{
          console.log(verifiedJwt); // Will contain the header and body
        }
        return (verifiedJwt);
      });
  };

const hasPermission = (token, resource) => {
  const result = validateToken(token, signingKey); //this.validateToken not a function error here
  console.log(result);
  if (result.name === 'JsonWebTokenError') {
    return false;
  } else if (result.permissions) {
    let permissionSet = new Set(result.permissions);
    console.log('permissions in token', JSON.stringify(permissionSet));
    return permissionSet.has(resource);
  } else {
    return false;
  }
};

module.exports = {
  vaildiateToken,
  hasPermission
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

a function that is not returning a boolean value, but rather returning

There seems to be a simple thing I'm missing here, but for the life of me, I can't figure out why the function below is returning undefined. var isOrphanEan = function isOrphanEan (ean) { Products.findOne({ 'ean': ean }, func ...

React components need to refresh after fetching data from an API

I am currently working on a React application using TypeScript and integrating JSONPlaceholder for simulating API calls. I have successfully set up everything I need, but I am encountering an issue with re-rendering components that display response data fr ...

can you explain which documents outline the parameters that are passed into the express app.METHOD callback function?

As a beginner in javascript and nodejs, I often struggle with understanding callback functions. One thing that particularly confuses me is determining what arguments are passed into a callback function. Let's consider the following example: app.get( ...

Is it possible to continuously divide or multiply numbers by 2 without encountering any rounding errors when working with floating point numbers?

binary can only represent those numbers as a finite fraction where the denominator is a power of 2 Are calculations done in binary/floating point format still accurate, even after multiple additions or multiplications by 2 without any rounding errors? co ...

What is the best way to switch between light and dark themes with the ability to locally store the current theme?

Being new to the realm of react, I have been delving into the implementation of new features using Material-UI. One particular feature I am working on involves toggling between light and dark themes, with the current theme being stored locally within the b ...

Vue.js is like the modern version of jquery-cron

Is there a similar tool to jquery-cron with an easy-to-use text/select interface that anyone knows of? I've come across vue-cron and point-vue-cron, but they seem too complicated for my needs. ...

Tips for automatically filling in fields when a button is clicked in a React application

I'm attempting to pre-fill the form fields that are duplicated with data from already filled fields. When I click the "Add Fields" button, new fields are replicated, but I want them to be pre-populated with data from existing fields. How can I access ...

What are some effective methods for concealing API request payloads in a web browser?

Struggling to hide the request payload when using Express with React on the front end? Check out the image below for reference: https://i.stack.imgur.com/ZT7T7.png Here's a snippet of backend code for you to review: router.post('/fit_spend ...

How can I retrieve the width of a responsive React element during its initial rendering phase?

In my React project, there is a component called ResultList which is used to display products in a gallery format. The challenge I'm facing is determining the appropriate number of products to show per row based on the available width for the ResultL ...

Develop a Modal Form using Bootstrap (HTML)

I followed a tutorial on creating a modal form with Bootstrap, you can find it here: http://www.youtube.com/watch?v=HCEbp07hfLw I replicated the steps shown in the video, but when I try to open the page in my browser, nothing appears. I have added the Bo ...

Is there a way to make my code on Google Sheets work across multiple tabs?

My Google Sheets code successfully pulls information from the main tab into my CRM Software every time someone fills out a form online. However, I'm struggling to get the script to run for multiple tabs on the same spreadsheet. I've tried a few s ...

Use JQuery's $ajax to exclusively retrieve items that have a date prior to the current date

In my jQuery code, I have a function called fetchResults that makes an AJAX request to '/Search/GetResults' and returns the JSON-formatted data. This endpoint does not require any specific criteria to be passed. The returned data looks like this ...

What is the best way to enable a DOM element's height to be resized?

I have a widget displayed in the corner of my browser that I would like to make resizable by dragging the header upwards to increase its height. The widget's position remains fixed with its bottom, left, and right properties unchanged, but I need the ...

Mapping an array using getServerSideProps in NextJS - the ultimate guide!

I'm facing an issue while trying to utilize data fetched from the Twitch API in order to generate a list of streamers. However, when attempting to map the props obtained from getServerSideProps, I end up with a blank page. Interestingly, upon using co ...

What is the best way to locate a member using a particular nickname?

Is there a way to search for a user by their unique nickname within a particular server? ...

What steps do I need to take in order to transform this code into a MUI component complete with

Having some trouble converting my hero banner code to MUI in a React project. The styling is not coming out correctly. Here is the HTML code: <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120 ...

Encountering a problem while trying to execute npm run serve on a newly created Vue-CLI project

Struggling to execute npm run serve on a fresh vue Project made with the Vue CLI. I initiated the project using vue create app, navigated to the project directory cd app, and ran npm run serve, a routine I have followed in previous projects. However, start ...

Overabundance of Recursive Calls in Node.js Project Dependencies

After a tiring day at work, I noticed an alert for Windows SkyDrive showing that files couldn't be uploaded due to the path being too long. The lengthy directory structure made me chuckle at the technological limitation. However, it got me thinking: ...

Error received on Node.js controller when calling Jquery getJSON from Ajax form

I have a Node.js / Sails.js application with a client-side form that submits to a Controller using jQuery ajax: $(function () { $("form").submit(function (e) { e.preventDefault(); var form = $(this); $.ajax({ url: ...

Optimal approach for organizing code in Sails.js (Node.js) applications

In my application, I have different parts such as Public API, Admin API, Admin Console (GUI), Private API, and Auth API (oauth2, local, socials). Although these components are distinct from each other, they share the same models. Some routes will experienc ...