DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Nginx + Node.JS: Perform Identification and Authentication
  • Jakarta Security and REST on Cloud: Part 4 Combining JWT With OAuth2
  • 10 Node.js Security Practices
  • Fixing Common Oracle Database Problems

Trending

  • DZone's Article Submission Guidelines
  • A Complete Guide to Modern AI Developer Tools
  • Vibe Coding With GitHub Copilot: Optimizing API Performance in Fintech Microservices
  • Start Coding With Google Cloud Workstations
  1. DZone
  2. Data Engineering
  3. Databases
  4. Authentication With Node.js, JWTs, and Oracle Database

Authentication With Node.js, JWTs, and Oracle Database

Authentication is your first line of defense against cybercriminals. Read on to learn how to implement it in your web application.

By 
Dan McGhan user avatar
Dan McGhan
·
Nov. 13, 17 · Tutorial
Likes (5)
Comment
Save
Tweet
Share
8.1K Views

Join the DZone community and get the full member experience.

Join For Free

Authentication isn't exactly hard, it's just that there are a lot of moving pieces to consider. Should you provide local authentication or 3rd party authentication via identity providers such as Google and Facebook? Can you reuse an existing credential store like Active Directory? What libraries should you use to help you encrypt passwords and manage logins? Should you use cookie-based authentication with sessions or use the emerging JSON Web Token (JWT) standard instead. Are there libraries for JWTs? Which is the best? Okay fine, authentication is hard. But it's also necessary.

Authentication strategies should be tailored to the application being built. If it's an internal application you'll likely want to reuse an existing credential store. Public facing applications will probably use a combination of local credentials and identity providers. In this post, I'll show you how to create a very basic API that authenticates users via local credentials stored in an Oracle Database table and uses JWTs to identify users after they've been authenticated. Once understood, the concepts used here could be adapted to better fit your specific authentication needs.

What's a JWT (pronounced "jot") you ask? That's a great question, but it's not one I'm going to attempt to answer here in full. Suffice it to say, JWTs are an alternative to cookies that can be used to identify users post authentication. With JWTs, claims (such as one's identity) can be encrypted and signed before being encoded and then transferred to and from the client. This avoids the need to create and lookup sessions making JWTs stateless in nature and easy to scale. Also, because JWTs use HTTP headers rather than cookies, RESTful APIs that use JWTs can be used by mobile apps as well as web applications (or anything else that can make HTTP requests). For more information on JWTs, check out these resources:

  • http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html
  • https://scotch.io/tutorials/the-anatomy-of-a-json-web-token

Prerequisites

To complete this tutorial, you'll need to have an Oracle Database, Node.js, and the Oracle Database Node.js driver (v0.5 or better) ready to go. Check out Up and Running with Node.js and Oracle if you are interested in getting a VM setup with these requirements.

There will not be a front-end application included with this post (though I may release one in a future post), so you'll need to have access to a REST client that allows you to test making requests and examine the responses. If you use the Chrome web browser and prefer a GUI, I recommend either Postman or Advanced REST client, both of which are available for free in the Chrome Web Store. If you prefer command line tools I recommend cURL.

Database Objects

Let's kick things off by creating three tables and some supporting objects in the database. Execute this code in the schema that you'll be connecting to from Node.js using a tool like SQL Developer.

create table jsao_users (
   id number not null,
   email varchar2(100 byte) not null,
   role varchar2(10 byte) not null,
   password varchar2(100 byte) not null,
   constraint jsao_users_pk primary key (id),
   constraint jsao_users_chk1 check (role in ('BASE', 'ADMIN')),
   constraint jsao_users_uk1 unique (email)
);

create sequence jsao_users_seq;

create or replace trigger bir_jsao_users_trg
   before insert on jsao_users
   for each row
begin
   if :new.id is null
   then
      :new.id := jsao_users_seq.nextval;
   end if;
end bir_jsao_users_trg;
/

create table jsao_public_things (
   column1 varchar2(200 byte) not null
);

insert into jsao_public_things (column1) values ('Lorem ipsum dolor sit amet, consectetur adipiscing elit.');
insert into jsao_public_things (column1) values ('Morbi interdum, justo a commodo gravida, magna tortor scelerisque nisl, vitae iaculis odio nisi vel risus.');
insert into jsao_public_things (column1) values ('Fusce ac dui ullamcorper, dignissim purus sit amet, consequat dolor.');
insert into jsao_public_things (column1) values ('Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris porttitor tincidunt magna nec pharetra. ');
insert into jsao_public_things (column1) values ('Vestibulum mi purus, ornare ut sem sed, porttitor fermentum erat.');

create table jsao_protected_things(
   column1 varchar2(200 byte) not null
);

insert into jsao_protected_things (column1) values ('Bacon ipsum dolor amet shank sirloin capicola tenderloin pork chop salami.');
insert into jsao_protected_things (column1) values ('Pancetta frankfurter ham hock t-bone. ');
insert into jsao_protected_things (column1) values ('Boudin drumstick tongue ground round pork jerky prosciutto pork belly brisket meatball ham, doner biltong sausage.');
insert into jsao_protected_things (column1) values ('Beef ribs jerky chicken t-bone, andouille rump spare ribs short loin shankle frankfurter sirloin ham hock ball tip pork loin turducken.');
insert into jsao_protected_things (column1) values ('Porchetta beef brisket, jowl flank leberkas capicola turducken ground round meatloaf hamburger strip steak venison. ');

commit;

The jsao_users table will contain our users and we'll use the email and password fields for authentication (passwords will be stored hashed). The other tables, jsao_protected_things and jsao_public_things, will be used to demonstrate creating API routes that do and do not require authentication, respectively.

Starting the API

Create a new directory named auth-api where you’re running Node.js. This will be the API’s top level directory. Then create the following package.json file within the auth-api directory.

{
  "name": "auth-api",
  "version": "1.0.0",
  "description": "A demonstration of authentication with Node.js, JWTs, and Oracle Database",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "The Oracle Database Advocates Team",
  "license": "ISC",
  "dependencies": {
    "bcrypt": "^0.8.3",
    "body-parser": "^1.12.4",
    "express": "^4.12.4",
    "jsonwebtoken": "^5.0.1",
    "morgan": "^1.5.3"
  }
}

The package.json is used by NPM to keep track of the dependencies in this project, of which we have 5 (excluding oracledb which should be installed globally):

  1. Express is a popular webserver for Node.js.
  2. Morgan is a logger for Express.
  3. Body-parser is an Express module that handles parsing the body portion of incoming HTTP requests.
  4. Bcrypt is a module used for encrypting and decrypting things in Node.js. If you're running Node.js on Windows, you may run into some compilation errors. If this happens, have a look at this Stack Overflow post.
  5. jsonwebtoken is fairly standard module for working with JWTs in Node.js.

Once you've created this file you can open the auth-api directory in a terminal window and run:

npm install

This will instruct NPM to begin installing the dependencies, which it will place in a new directory named node_modules.

Next, we'll create the server.js file in the auth-api directory.

var express = require('express');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var app;
var router;
var port = 3000;

app = express();

app.use(morgan('combined')); //logger
app.use(bodyParser.json());

router = express.Router();

router.get('/public_things', function(req, res) {
   res.json({"message": "Here are the public things..."});
});

app.use('/api', router);

app.listen(port, function() {
    console.log('Web server listening on localhost:' + port);
});

The server.js file can be thought of as our "main" API file. This is the file we'll actually be executing with Node.js. As you can see, it brings in a number of dependencies and then starts a web server that listens for requests on port 3000. A router is created and used to listen to GET requests on /api/public_things. The logic that handles the GET request on that route simply responds with a JSON message. Later, we'll create logic that gets data from Oracle Database. But before we get to that, let's test everything up to this point.

Open the auth-api directory in a terminal window and run:

node server.js

If you see the "Web server listening on localhost:3000" message then your web server should be running. Open your REST client and issue a GET request on http://localhost:3000/api/public_things. Here's an example in Postman:

If you see the JSON response with the message, "Here are the public things..." then everything should be working.

Creating a Public Route

Time to bring in the database! Create the following config.js file in auth-api. Note that this tutorial will not be using a connection pool. If you plan on running a web server in production you should look into using a connection pool. Also, see my earlier post, Making a Wrapper Module for the Node.js Driver for Oracle Database, for ways to make that easier.

module.exports = {
    database: {
        user: 'hr',
        password: 'oracle',
        connectString: 'localhost:1521/orcl'
    }
};

The config.js is used to hold our API's configuration data. You will likely need to update the connection information to work with your database instance.

Create a subdirectory in auth-api name routes, then add the following publicThings.js file.

var oracledb = require('oracledb');
var config = require(__dirname + '../../config.js');

function get(req, res, next) {
    oracledb.getConnection(
        config.database,
        function(err, connection){
            if (err) {
                return next(err);
            }

            connection.execute(
                'select column1 as "column1" ' +
                'from jsao_public_things ',
                {},//no binds
                {
                    outFormat: oracledb.OBJECT
                },
                function(err, results){
                    if (err) {
                        connection.release(function(err) {
                            if (err) {
                                console.error(err.message);
                            }
                        });

                        return next(err);
                    }

                    res.status(200).json(results.rows);

                    connection.release(function(err) {
                        if (err) {
                            console.error(err.message);
                        }
                    });
                });
        }
    );
}

module.exports.get = get;

publicThings.js requires the Oracle Database driver and uses it to execute a query and send the results out through the response. The get function is exported from the module which allows us to use it in server.js.

var express = require('express');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var publicThings = require(__dirname + '/routes/publicThings.js');
var app;
var router;
var port = 3000;

app = express();

app.use(morgan('combined')); //logger
app.use(bodyParser.json());

router = express.Router();

router.get('/public_things', publicThings.get);

app.use('/api', router);

app.listen(port, function() {
    console.log('Web server listening on localhost:' + port);
});

Let's run another test to try out the new logic. Stop your previous Node.js process if it's still running with ctrl + c and then start it back up. Use your REST client to issue the same GET request as before. You should see results like the following:

Now users of our API can access the data from the /api/public_things route, awesome!

Creating a Protected Route

Of course, not all of our data should be accessed so easily! Let's create a /api/protected_things route that requires a valid JWT to return data. We'll start by updating the config.js to include a secret key (shhhh, don't tell anyone!).

module.exports = {
    database: {
        user: 'hr',
        password: 'oracle',
        connectString: 'localhost:1523/orcl'
    },
    jwtSecretKey: "jmvhDdDBMvqb=M@6h&QVA7x"
};

Now we can create our /api/protected_things route logic in a new file named protectedThings.js in the routes directory.

var oracledb = require('oracledb');
var jwt = require('jsonwebtoken');
var config = require(__dirname + '../../config.js');

function get(req, res, next) {
    var token;
    var payload;

    if (!req.headers.authorization) {
        return res.status(401).send({message: 'You are not authorized'});
    }

    token = req.headers.authorization.split(' ')[1];

    try {
        payload = jwt.verify(token, config.jwtSecretKey);
    } catch (e) {
        if (e.name === 'TokenExpiredError') {
            res.status(401).send({message: 'Token Expired'});
        } else {
            res.status(401).send({message: 'Authentication failed'});
        }

        return;
    }

    oracledb.getConnection(
        config.database,
        function(err, connection){
            if (err) {
                return next(err);
            }

            connection.execute(
                'select column1 as "column1" ' +
                'from jsao_protected_things ',
                {},//no binds
                {
                    outFormat: oracledb.OBJECT
                },
                function(err, results){
                    if (err) {
                        connection.release(function(err) {
                            if (err) {
                                console.error(err.message);
                            }
                        });

                        return next(err);
                    }

                    res.status(200).json(results.rows);

                    connection.release(function(err) {
                        if (err) {
                            console.error(err.message);
                        }
                    });
                }
            );
        }
    );
}

module.exports.get = get;

protectedThings.js is different from publicThings.js in two ways. Of course it fetches data from a different table, but in addition, it uses the jsonwebtoken module to ensure that the request has a valid JWT.

With the protectedThings.js in place we just need to update server.js to map the new route through.

var express = require('express');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var publicThings = require(__dirname + '/routes/publicThings.js');
var protectedThings = require(__dirname + '/routes/protectedThings.js');
var app;
var router;
var port = 3000;

app = express();

app.use(morgan('combined')); //logger
app.use(bodyParser.json());

router = express.Router();

router.get('/public_things', publicThings.get);
router.get('/protected_things', protectedThings.get);

app.use('/api', router);

app.listen(port, function() {
    console.log('Web server listening on localhost:' + port);
});

Restart your server and try calling this route like we did the last...

Ouch, that hurts! But at least we know our data is safe... You can try sending fake authorization headers through - they should fail.

Creating Users

This tutorial is about authentication, but before we can authenticate users we have to create some. Add the following users.jsfile in our routes directory.

var oracledb = require('oracledb');
var bcrypt = require('bcrypt');
var jwt = require('jsonwebtoken');
var config = require(__dirname + '../../config.js');

function post(req, res, next) {
    var user = {
        email: req.body.email
    };
    var unhashedPassword = req.body.password;

    bcrypt.genSalt(10, function(err, salt) {
        if (err) {
            return next(err);
        }

        bcrypt.hash(unhashedPassword, salt, function(err, hash) {
            if (err) {
                return next(err);
            }

            user.hashedPassword = hash;

            insertUser(user, function(err, user) {
                var payload;

                if (err) {
                    return next(err);
                }

                payload = {
                    sub: user.email,
                    role: user.role
                };

                res.status(200).json({
                    user: user,
                    token: jwt.sign(payload, config.jwtSecretKey, {expiresInMinutes: 60})
                });
            });
        });
    });
}

module.exports.post = post;

function insertUser(user, cb) {
    oracledb.getConnection(
        config.database,
        function(err, connection){
            if (err) {
                return cb(err);
            }

            connection.execute(
                'insert into jsao_users ( ' +
                '   email, ' +
                '   password, ' +
                '   role ' +
                ') ' +
                'values (' +
                '    :email, ' +
                '    :password, ' +
                '    \'BASE\' ' +
                ') ' +
                'returning ' +
                '   id, ' +
                '   email, ' +
                '   role ' +
                'into ' +
                '   :rid, ' +
                '   :remail, ' +
                '   :rrole',
                {
                    email: user.email.toLowerCase(),
                    password: user.hashedPassword,
                    rid: {
                        type: oracledb.NUMBER,
                        dir: oracledb.BIND_OUT
                    },
                    remail: {
                        type: oracledb.STRING,
                        dir: oracledb.BIND_OUT
                    },
                    rrole: {
                        type: oracledb.STRING,
                        dir: oracledb.BIND_OUT
                    }

                },
                {
                    autoCommit: true
                },
                function(err, results){
                    if (err) {
                        connection.release(function(err) {
                            if (err) {
                                console.error(err.message);
                            }
                        });

                        return cb(err);
                    }

                    cb(null, {
                        id: results.outBinds.rid[0],
                        email: results.outBinds.remail[0],
                        role: results.outBinds.rrole[0]
                    });

                    connection.release(function(err) {
                        if (err) {
                            console.error(err.message);
                        }
                    });
                });
        }
    );
}

The users.js  uses bcrypt to first generate a salt and then use it to hash the password. Once the password is hashed the insertUser function is invoked to do the insert into Oracle Database. The insertUser function demonstrates several features of the Oracle Database Node.js driver, such as the ability to use the returning clause (which always returns arrays) and the autoCommit setting (which was set to true). After the user is inserted, the user data is sent to the client along with a JWT access token that was generated with the jsonwebtoken module.

As we did before, we need to update server.js to map new the route through.

var express = require('express');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var publicThings = require(__dirname + '/routes/publicThings.js');
var protectedThings = require(__dirname + '/routes/protectedThings.js');
var users = require(__dirname + '/routes/users.js');
var app;
var router;
var port = 3000;

app = express();

app.use(morgan('combined')); //logger
app.use(bodyParser.json());

router = express.Router();

router.get('/public_things', publicThings.get);
router.get('/protected_things', protectedThings.get);
router.post('/users', users.post);

app.use('/api', router);

app.listen(port, function() {
    console.log('Web server listening on localhost:' + port);
});

Testing this route is a little trickier than before as we are going to be sending some data to the server. The body of the request will be JSON and we'll need to include the appropriate header to indicate that. Restart your server and give it a shot.

Notice that, when done correctly, we get both the user back (with the new id) and a token. A token! You know what we can do with that! Let's re-test our /api/protected_things route, this time we'll supply the correct authorization header. Note that the value of the authorization header is the word "Bearer," followed by a space, and then the token value.

It's bacon! Typically the token returned would be saved to local storage, assuming the application is a web app, and then added to the HTTP headers of all subsequent requests to the API.

Just in case you were wondering, this is what our new record looks like in our table.

Authenticating Users

The token generated when creating a user will only be valid for 60 minutes (that can be adjusted), after which time requests will receive an error with the message, "Token Expired." At that point, the application can redirect the user to a login screen where they can authenticate themselves to get a shiny new token. We'll create the logins.js in our routes directory to contain this logic.

var oracledb = require('oracledb');
var bcrypt = require('bcrypt');
var jwt = require('jsonwebtoken');
var config = require(__dirname + '../../config.js');

function post(req, res, next) {
    oracledb.getConnection(
        config.database,
        function(err, connection){
            if (err) {
                return next(err);
            }

            connection.execute(
                'select id as "id", ' +
                '   email as "email", ' +
                '   password as "password", ' +
                '   role as "role" ' +
                'from jsao_users ' +
                'where email = :email',
                {
                    email: req.body.email.toLowerCase()
                },
                {
                    outFormat: oracledb.OBJECT
                },
                function(err, results){
                    var user;

                    if (err) {
                        connection.release(function(err) {
                            if (err) {
                                console.error(err.message);
                            }
                        });

                        return next(err);
                    }

                    user = results.rows[0];

                    bcrypt.compare(req.body.password, user.password, function(err, pwMatch) {
                        var payload;

                        if (err) {
                            return next(err);
                        }

                        if (!pwMatch) {
                            res.status(401).send({message: 'Invalid email or password.'});
                            return;
                        }

                        payload = {
                            sub: user.email,
                            role: user.role
                        };

                        res.status(200).json({
                            user: user,
                            token: jwt.sign(payload, config.jwtSecretKey, {expiresInMinutes: 60})
                        });
                    });

                    connection.release(function(err) {
                        if (err) {
                            console.error(err.message);
                        }
                    });
                });
        }
    );
}

module.exports.post = post;

logins.js fetches the user information, including the hashed password, from the database. It then uses the brcypt module to compare the hashed password to the password that was sent in the POST to /api/logins route. If a match is found then a new token is generated and sent to the client.

As before, we need to update server.js to map the new route through.

var express = require('express');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var publicThings = require(__dirname + '/routes/publicThings.js');
var protectedThings = require(__dirname + '/routes/protectedThings.js');
var users = require(__dirname + '/routes/users.js');
var logins = require(__dirname + '/routes/logins.js');
var app;
var router;
var port = 3000;

app = express();

app.use(morgan('combined')); //logger
app.use(bodyParser.json());

router = express.Router();

router.get('/public_things', publicThings.get);
router.get('/protected_things', protectedThings.get);
router.post('/users', users.post);
router.post('/logins', logins.post);

app.use('/api', router);

app.listen(port, function() {
    console.log('Web server listening on localhost:' + port);
});

If you restart your server and test a POST to the /api/logins route with the correct email and password, you should get the user data and a new token. However, if the email or password are wrong you should get an error message.

Image title

Streamlining the Authentication and Authorization

Currently, the authentication code for the /api/protected_things route is embedded in the route's logic. This makes it hard to reuse. Also, it's currently only ensuring that users are authenticated, it's not doing any authorization. We can fix both issues pretty easily. First, we'll remove the authentication logic from protectedThings.js. That's right, strip it out!

var oracledb = require('oracledb');
var config = require(__dirname + '../../config.js');

function get(req, res, next) {
    oracledb.getConnection(
        config.database,
        function(err, connection){
            if (err) {
                return next(err);
            }

            connection.execute(
                'select column1 as "column1" ' +
                'from jsao_protected_things ',
                {},//no binds
                {
                    outFormat: oracledb.OBJECT
                },
                function(err, results){
                    if (err) {
                        connection.release(function(err) {
                            if (err) {
                                console.error(err.message);
                            }
                        });

                        return next(err);
                    }

                    res.status(200).json(results.rows);

                    connection.release(function(err) {
                        if (err) {
                            console.error(err.message);
                        }
                    });
                }
            );
        }
    );
}

module.exports.get = get;

Now we'll create an auth.js file in the routes directory to contain our new, beefier authentication and authorization logic.

var jwt = require('jsonwebtoken');
var config = require(__dirname + '../../config.js');

function auth(role) {
    return function(req, res, next) {
        var token;
        var payload;

        if (!req.headers.authorization) {
            return res.status(401).send({message: 'You are not authorized'});
        }

        token = req.headers.authorization.split(' ')[1];

        try {
            payload = jwt.verify(token, config.jwtSecretKey);
        } catch (e) {
            if (e.name === 'TokenExpiredError') {
                res.status(401).send({message: 'Token Expired'});
            } else {
                res.status(401).send({message: 'Authentication failed'});
            }

            return;
        }

        if (!role || role === payload.role) {
            //pass some user details through in case they are needed
            req.user = {
                email: payload.sub,
                role: payload.role
            };

            next();
        } else {
            res.status(401).send({message: 'You are not authorized'});
        }
    }
}

module.exports = auth;

Notice that the auth function returns a function (middleware) that handles the authentication and authorization. If both checks pass then next is invoked which executes the next handler on the route. How can we use this new middleware? All we have to do is require it into server.js  and invoke it as the first handler for a route that should be protected.

var express = require('express');
var morgan = require('morgan');
var bodyParser = require('body-parser');
var auth = require(__dirname + '/routes/auth.js');
var publicThings = require(__dirname + '/routes/publicThings.js');
var protectedThings = require(__dirname + '/routes/protectedThings.js');
var users = require(__dirname + '/routes/users.js');
var logins = require(__dirname + '/routes/logins.js');
var app;
var router;
var port = 3000;

app = express();

app.use(morgan('combined')); //logger
app.use(bodyParser.json());

router = express.Router();

router.get('/public_things', publicThings.get);
router.get('/protected_things', auth(), protectedThings.get);
router.get('/protected_things2', auth('ADMIN'), protectedThings.get);
router.post('/users', users.post);
router.post('/logins', logins.post);

app.use('/api', router);

app.listen(port, function() {
    console.log('Web server listening on localhost:' + port);
});

Here you see that the original /api/protected_things route still requires authentication (auth is used but not passed a role). There's also a new route, /api/protected_things2, that demonstrates how easy it is to ensure that a user has a certain role. Of course, this logic could be modified to better meet your authentication and authorization needs.

I hope this helps answer some questions regarding local authentication with Oracle Database and JWTs!

Database authentication Node.js Oracle Database JWT (JSON Web Token)

Published at DZone with permission of Dan McGhan, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Nginx + Node.JS: Perform Identification and Authentication
  • Jakarta Security and REST on Cloud: Part 4 Combining JWT With OAuth2
  • 10 Node.js Security Practices
  • Fixing Common Oracle Database Problems

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!