Home > Net >  React Axios save jwt token
React Axios save jwt token

Time:02-05

I am having troubles implementing the signin side of an authentication system with React, Axios and Express (the signup functionality works fine), I have already taken a look at multiple similar questions with different answers but none seem to work, my approach is the following:

In my Node backend I have:

router.post('/sign-in', async (req, res) => {
    let email = req.body.email;
    let password = req.body.password;
    let user = await User.findOne({ email: email });
    
    if (user && bcryptjs.compareSync(password, user.password)) {
        jwt.sign({ user_id: user.user_id }, config.app.secretKey, { expiresIn: 60 * 60 * 24 * 7 }, (err, token) => {
            console.log(token);
            return res.send(token);
        });
    } else {
        return res.send({ "error": "Wrong email or password." });
    }
});

function isAuthenticated(req, res, next) {
    const bearerHeader = req.headers['Authorization'];
    console.log(bearerHeader);
    if (typeof bearerHeader !== 'undefined') {
        req.token = bearerToken;
        next();
    } else {
        res.sendStatus(401);
    }
}

In the React I have a sign-in component with a signin method:

signin() {
    let email = document.getElementById("email").value;
    let password = document.getElementById("password").value;
    let account = { email, password };

    axios.post("http://localhost:4000/auth/sign-in", account).then((token) => {
        localStorage.setItem("token", token.data);
        console.log(token.data);
        axios.defaults.headers.common['Authorization'] = token.data;
        
        //window.location = "/";
    });
}

I am checking if the authentication works by executing the following code:

componentDidMount() {
  console.log(localStorage.getItem("token"));
  const token = localStorage.getItem("token");
  if (token) {
    axios.defaults.headers.common['Authorization'] = localStorage.getItem("token");
    axios.get("http://localhost:4000/authorized",{withCredentials:true}).then((response)=>{
      console.log(response);
    });
  }
}

The /authorized api is the following:

app.get("/authorized", auth.isAuthenticated, (req,res)=>{
    res.send("Authorized!");
});

This is the server app:

const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const mongoose = require('mongoose');
const config = require('./config');

mongoose.connect(config.database.host); // { autoIndex: false } set this to false in production to disable auto creating indexes
mongoose.Promise = global.Promise;

const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const mongoose = require('mongoose');
const config = require('./config');

mongoose.connect(config.database.host); // { autoIndex: false } set this to false in production to disable auto creating indexes
mongoose.Promise = global.Promise;

const app = express();

app.use(helmet());
app.use(cors( { origin:'http://localhost:3000', credentials:true } ));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

const auth = require('./services/authentication');

app.use("/auth", auth.router);

app.get("/authorized", auth.isAuthenticated, (req,res)=>{
    res.send("Authorized!");
});

app.listen(4000,()=>{
    console.log('Server started...');
});

The problem is the following: when the user sends a request to /sign-in it correctly receives the token and stores it in localStorage (at the moment I am storing it in the localStorage maybe later on I will probably store it in a cookie), but when the token is sent to the server for authorization purposes the server executes the isAuthenticated method which replies with a 401 status, I have tried almost everything but I cannot manage to find a solution.

This is what I get when logging req.headers:

{
   host: 'localhost:4000',
   connection: 'keep-alive',
   pragma: 'no-cache',
   'cache-control': 'no-cache',
   'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"',
   accept: 'application/json, text/plain, */*',
   'sec-ch-ua-mobile': '?1',
   'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Mobile Safari/537.36',
   'sec-ch-ua-platform': '"Android"',
   origin: 'http://localhost:3000',
   'sec-fetch-site': 'same-site',
   'sec-fetch-mode': 'cors',
   'sec-fetch-dest': 'empty',
   referer: 'http://localhost:3000/',
   'accept-encoding': 'gzip, deflate, br',
   'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7'
}

CodePudding user response:

You are using isAuthenticated method as a middleware I suppose. It is supposed to be called after sign-in. In the router.post('/sign-in') I don't think you need this middleware isAuthenticated to be executed. remove the middleware from the signing router. It should be working fine after that. Signing in the user will generate a token which you store in the header to authenticate the user. Not signing router itself. Hope you find this helpful. Best of luck.

CodePudding user response:

On server side, update CORS code like so :-

app.use(cors( { origin:'http://localhost:3000', credentials:true } ));

On client side, add withCredentials:true like so :-

componentDidMount() {
    console.log(localStorage.getItem("token"));
    axios.get("http://localhost:4000/authorized",{withCredentials:true}).then((response)=>{
        console.log(response);
    }).catch((error)=>{
        console.log(error);
    });
}
  •  Tags:  
  • Related