0

My application is a Node.js API with a client inside the same application.

I'm trying to implement a simple auth login that uses a JWT token generated by a Node.js API.

My logic is as follows:

  1. Client: User submits login information to /auth/login route.
     $.ajax({
        url: "/auth/login",
        type: "POST",
        data: formData,
        dataType: "json",
        success: function(data, textStatus, jqXHR) {
            if (typeof data.redirect == "string") {
                window.location = data.redirect; 
            }
        },
        error: function(data) {
            if (typeof fail === "function") fail(data);
        }
    });
  1. API: Verify user and on success generates JWT and sends back to the client.
router.post("/login", async (req, res) => {

    var login = { UID: req.body.UID, password: req.body.password };
    AU.manualLogin(login)
        .then(result => {

            res.header("x-auth-token", result.token).json({
                status: 200,
                message: "success",
                data: result.data,
                redirect: "/dashboard" 
            });

        })
        .catch(err => next({ status: 400, message: err.message }));
});
  1. Client: Saves JWT to the header and checks for redirect - In this case, I use window.location to direct to /dashboard after successful login. (this part I'm not sure about)

  2. API: Middleware checks valid JWT on protected routes.

module.exports = function auth(req, res, next) {

    const token = req.headers["x-auth-token"];
    if (!token)
        return res.status(401).send("Access denied. No token provided.");

    try {
        const decoded = jwt.verify(token, "jwtPrivateKey");
        req.user = decoded;
        next(); //pass control to next middleware
    } catch (ex) {
        res.status(400).send("Invalid token.");
    }
};

The Problem:

The token is definitely being sent from API -> Client. But I have no idea how to handle the token from the client-side. I think the issue might be to do with the window.location redirect as at this point it does not seem to be sending the x-auth-token to the API.

What I have tried

I have tested the solution with Postman from end-to-end and it works fine. That probably proves that it isn't the API side that has the issue.

I've also tried these sources:

Justin
  • 954
  • 4
  • 22
  • 44
  • I would suggest before redirecting, save the token in local storage or in a cookie – Dark Lord Jun 13 '18 at 06:31
  • @DarkLord I've heard from multiple sources that saving to local storage or cookies isn't a good idea but then again I'm quite new to this still. Can it even be done without local storage and cookies? – Justin Jun 13 '18 at 06:33

1 Answers1

1

You need kind of a storage to keep the token. Otherwise the user has always to login again after he closes the browser/tab. So it's quite common to keep the token in local or session storage.

Approach 1: Use a single page application (SPA) framework like angular, vue.js, react etc. to protect your routes client-side

Approach 2: You can request only html and css (view) from your backend and then store the token after a login procedure. With a valid token, fetch the (protected) data with ajax requests. Redirect to the login page if a ajax request returns the status code 401 (unauthorized) or a user wants to access the protected route without having a token stored. This is perhaps the most suitable for you.

Approach 3: Use Node.js with a backend framework like express and store auth information in a server side session

index.js

const express = require('express');
const session = require('express-session');
const app = express();
app.use(require("cookie-parser")());
app.use(session({ secret: 'aslwezoweasdfasdlkfalksdfhweelaerfcv', resave: false, saveUninitialized: true}));

routes/protectedRoutes.js

const express = require('express');
const router = express.Router();
router.all("/*", util.handleAuthenticate); // check auth on every request
// other routes

indexController.js (login functionality)

module.exports.login = function(req, res) {
    if(!req.session.name) {
        // check username/password --> db lookup
        // if valid:
        req.session.name  = ...
        // redirect to home or backref
        // else: redirect to login
    }
}

util/security.js

function isLoggedIn(req) {
    return !!req.session.name;
}

function handleAuthenticate(req, res, next) {
    if(isLoggedIn(req))
    {
        next();
    }
    else
    {
    // redirect to login page
    }
}
momo
  • 3,313
  • 2
  • 19
  • 37
  • How do I use that code into the initial request in number 1 (above) ? I tried adding this after but it didn’t work. – Justin Jun 13 '18 at 06:59