title: Nuxt login issue - Returning 401 Unauthorized - Cannot get info from serverside onfrontend
body: <p>I've been trying to get the frontend to log in the user, get the information sent from the backend (which works perfectly using postman) and keep it stored in the store until log out.</p>
  <p>Backend is using server middleware and not separate. Just /api/user for all user related end points, like login. Backend is NodeJs, Express and database is Mongodb.</p>
  <p>Backend returns data like so:</p>
  <pre><code>{
      &quot;userId&quot;: &quot;USERID&quot;,
      &quot;email&quot;: &quot;EMAIL&quot;,
      &quot;message&quot;: &quot;Auth successful&quot;,
      &quot;token&quot;: &quot;TOKEN&quot;
  }
  </code></pre>
  <p>I am using jwt (jsonwebtoken) for tokens in the backend.</p>
  <p>My attempt is as follows:
  script on my admin/auth.vue (where the login is located)</p>
  <pre><code>&lt;script&gt;
      export default {
          data() {
              return {
                  email: '',
                  password: '',
                  mode: 'login',
                  error: null,
              };
          },
          methods: {
              async submitForm() {
                  const actionPayload = {
                      email: this.email,
                      password: this.password,
                  };
                  try {
                      await this.$store.dispatch('login', actionPayload);
                      const redirectUrl = '/' + (this.$route.query.redirect || 'admin');
                      this.$router.replace(redirectUrl);
                  } catch (err) {
                      this.error = err.message || 'Failed to authenticate, try later.';
                  }
              },
          },
      };
  &lt;/script&gt;
  </code></pre>
  <p>I have this in layouts/default.vue to check if the user is authenticated:</p>
  <pre><code>&lt;script&gt;
      export default {
          computed: {
              isAuthenticated() {
                  return this.$store.getters.isAuthenticated;
              },
          },
      };
  &lt;/script&gt;
  </code></pre>
  <p>As for my store, here's the files for those (under modules/admin):
  index.js</p>
  <pre><code>import mutations from './mutations.js';
  import actions from './actions.js';
  import getters from './getters.js';
  
  export default {
      state() {
          return {
              userId: null,
              token: null,
              didAutoLogout: false,
          };
      },
      mutations,
      actions,
      getters,
  };
  </code></pre>
  <p>actions.js</p>
  <pre><code>let timer;
  
  export default {
      async login(context, payload) {
          return context.dispatch('auth', {
              ...payload,
              mode: 'login',
          });
      },
      async auth(context, payload) {
          const url = 'http://localhost:3000/api/user/login';
  
          const response = await fetch(url, {
              method: 'POST',
              body: JSON.stringify({
                  email: payload.email,
                  password: payload.password,
              }),
          });
  
          const responseData = await response.json();
  
          if (!response.ok) {
              const error = new Error(
                  responseData.message || 'Failed to authenticate. Check your login data.'
              );
              throw error;
          }
  
          const expiresIn = +responseData.expiresIn * 5000;
          // const expiresIn = 5000;
          const expirationDate = new Date().getTime() + expiresIn;
  
          localStorage.setItem('token', responseData.token);
          localStorage.setItem('userId', responseData.userId);
          localStorage.setItem('tokenExpiration', expirationDate);
  
          context.commit('setUser', {
              token: responseData.token,
              userId: responseData.userId,
          });
      },
      tryLogin(context) {
          context.commit('setUser', {
              token: responseData.token,
              userId: responseData.userId,
          });
          if (token &amp;&amp; userId) {
              context.commit('setUser', {
                  token: token,
                  userId: userId,
              });
          }
      },
  };
  </code></pre>
  <p>getters.js</p>
  <pre><code>export default {
      userId(state) {
          return state.userId;
      },
      token(state) {
          return state.token;
      },
      isAuthenticated(state) {
          return !!state.token;
      },
      didAutoLogout(state) {
          return state.didAutoLogout;
      },
  };
  </code></pre>
  <p>mutations.js</p>
  <pre><code>export default {
      setUser(state, payload) {
          state.token = payload.token;
          state.userId = payload.userId;
          state.didAutoLogout = false;
      },
      setAutoLogout(state) {
          state.didAutoLogout = true;
      },
  };
  </code></pre>
  <p>and my regular index.js for the store:</p>
  <pre><code>import Vuex from 'vuex';
  import Vue from 'vue';
  import adminModule from './modules/admin/index.js';
  
  Vue.use(Vuex);
  
  export default () =&gt;
      new Vuex.Store({
          state: () =&gt; ({}),
          mutations: {},
          actions: {},
          modules: {
              auth: adminModule,
          },
      });
  </code></pre>
  <p>And when I hit log in, it returns:</p>
  <pre><code>POST http://localhost:3000/api/user/login 401 (Unauthorized)
  </code></pre>
  <p>I've spent 2 days on this and still cannot get it right (I'm used to doing this with firebase, but I wanted to do it in mongodb instead), any help at all is very appreciated!</p>
  <p>I did try using nuxt auth but hit a wall as I could not get the store to pick up on the token stored in the browser. If anyone has a nuxt auth approach that might work, I would be willing to attempt it!</p>
  <p>For the backend code (that works in postman):</p>
  <pre><code>const express = require('express');
  const app = express();
  const morgan = require('morgan');
  const bodyParser = require('body-parser');
  const mongoose = require('mongoose');
  
  app.use((req, res, next) =&gt; {
          res.header('Access-Control-Allow-Origin', '*');
          res.header(
              'Access-Control-Allow-Headers',
              'Origin, X-Requested-With, Content-Type, Accept, Authorization'
          );
          if (req.method === 'OPTIONS') {
              res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET');
              return res.status(200).json({});
          }
          next();
      });
      app.use('/user', userRoutes);
          
          app.use((req, res, next) =&gt; {
              const error = new Error('Not found');
              error.status = 404;
              next(error);
          });
          
          app.use((error, req, res, next) =&gt; {
              res.status(error.status || 500);
              res.json({
                  error: {
                      message: error.message,
                  },
              });
          });
  </code></pre>
  <p>then I have routes/user.js</p>
  <pre><code>const express = require('express');
  const router = express.Router();
  
  const UserController = require('../controllers/user');
  const checkAuth = require('../middleware/check-auth');
  
  router.post('/signup', UserController.user_signup);
  
  router.post('/login', UserController.user_login);
  
  router.delete('/:userId', checkAuth, UserController.user_delete);
  
  module.exports = router;
  </code></pre>
  <p>then I have the user controller (controllers/user.js):</p>
  <pre><code>const mongoose = require('mongoose');
  const bcrypt = require('bcrypt');
  const jwt = require('jsonwebtoken');
  
  const User = require('../models/user');
  
  exports.user_login = (req, res, next) =&gt; {
      User.find({ email: req.body.email })
          .exec()
          .then((user) =&gt; {
              if (user.length &lt; 1) {
                  return res.status(401).json({
                      message: 'Auth failed',
                  });
              }
              bcrypt.compare(req.body.password, user[0].password, (err, result) =&gt; {
                  if (err) {
                      return res.status(401).json({
                          message: 'Auth failed',
                      });
                  }
                  if (result) {
                      const token = jwt.sign(
                          {
                              email: user[0].email,
                              userId: user[0]._id,
                          },
                          process.env.JWT_KEY,
                          {
                              expiresIn: '1h',
                          }
                      );
                      return res.status(200).json({
                          userId: user[0]._id,
                          email: user[0].email,
                          message: 'Auth successful',
                          token: token,
                      });
                  }
                  res.status(401).json({
                      message: 'Auth failed',
                  });
              });
          })
          .catch((err) =&gt; {
              console.log(err);
              res.status(500).json({
                  error: err,
              });
          });
  };
  </code></pre>
  <p>And the check auth js is here:</p>
  <pre><code>const jwt = require('jsonwebtoken');
  
  module.exports = (req, res, next) =&gt; {
      try {
          const token = req.headers.authorization.split(' ')[1];
          const decoded = jwt.verify(token, process.env.JWT_KEY);
          req.userData = decoded;
          next();
      } catch (error) {
          return res.status(401).json({
              message: 'Auth failed',
          });
      }
  };
  </code></pre>
  <p>Full code here in case anyone wants to check it: <a href="https://github.com/codeechic/issue-28392832" rel="nofollow noreferrer">https://github.com/codeechic/issue-28392832</a></p>
  <p>I do have an env variable for JWT_KEY</p>