Authentication (JWT) works in local but not in Heroku?

Viewed 499

I have a project builded in MEVN stack that works properly in local, I deployed my backend in Heroku successfully and I tested it with Postman and everything works very well, but when I tried to login with my client(local) i have a "GET https://invoicing-wmb.herokuapp.com/api/user 401 (Unauthorized)". any idea what could be wrong ?...

In addition I've been testin with console.log("") and the code works until before this line in User:

const claims = jwt.verify(cookie, 'secret')

Note: The only thing that is not working is the user auth everything else is working good.

This is the mi index.js in the backend.

const express = require('express')
const mongoose = require('mongoose')
const cors = require('cors')
const cookieParser = require('cookie-parser')
mongoose.set('useCreateIndex', true)

mongoose.connect('mongodb+srv://markselin:PASSWORD123@cluster0.uaau3.mongodb.net/myFirstDatabase?retryWrites=true&w=majority', {

    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true
}, () => {
    console.log('connected to the database')
})

const routes = require('./routes/routes')

app = express()

app.use(cookieParser())
app.use(cors({

    credentials: true,
 
    origin: ['https://invoicing-wmb.herokuapp.com', 'http://localhost:8080'] //CLOUD
}))


app.use(express.json())

app.use('/api', routes)

//testing main /
app.get('/', function(peticion, respuesta){
    respuesta.send('WECOME TO OUR API [WBM]')
})
app.get('/api', function(peticion, respuesta){
    respuesta.send('INVOICING API [WMB]')
})


app.listen(process.env.PORT || 8000)

This is my User in router.js

router.get('/user', async (req, res) => {

    try {
        
        
        const cookie = req.cookies['jwt']
        

        const claims = jwt.verify(cookie, 'secret')
        
        if (!claims) {

            res.send({message:'NO AUTENTICADO'})
        }
        
        const user = await User.findOne({_id: claims._id})
        
        const {pass, ...data} = await user.toJSON()
        console.log('AUTENTICADO'+data)
        res.json(data)
    } catch (e) {
        return res.status(401).send({
            message: 'unauthenticated'
        })
    }
})

Login method in client

  methods: {
    
    async handleSubmit() {

      try {
 
        const respons = await axios.post("login", {
         
          email: this.email,
          pass: this.pass,
        });

     
        localStorage.setItem("token", respons.data.token);
      
      
        const response = await axios.get("user");
         
     
        this.$store.dispatch("user", response.data);
       

        this.$router.push({name:'Inicio'})
      } catch (e) {
        console.log(e)
       
      }
    },

and axios.js

import axios from 'axios'
    axios.defaults.baseURL = 'https://invoicing-wmb.herokuapp.com/api/'     //CLOUD
    axios.defaults.headers.common['Authorization'] = 'Bearer' + localStorage.getItem('token')
    axios.defaults.withCredentials = true;

and finally this is the logs from Heroku when I tried to Login logs Heroku

2 Answers

It seems that you're using cookies to hold the user's tokens. My guess is that the cookie isn't sent because of domain mixup. When you test it on localhost then the domain for your frontend and backend is the same so cookies work. When you test in postman you probably send the token directly, or set cookies manually so that works as well. Once you're in the browser it will limit which cookies can be used by which websites.

You would have to check what properties your cookies currently have. E.g. is the secure flag used and are you using https connections? Most importantly have a look at the Same-Site property as in your case it should be set to lax or none. Another option would be to run frontend and backend on the same domain.

Make sure you've enabled ACM (Automated Certificate Management) at Heroku. You'll need to update your app above the free tier to do so.

This may be your problem in that using "Secure" in the Set-Cookie cannot be used at Heroku unless you are entering via https which requires a cert. I had this -- my auth cookies were not persisting past the main page.

  1. enable ACM
  2. connect via HTTPS
  3. use Chrome Dev Inspector, Networking tab to verify cookies are present.

Enjoy!

Related