DEV Community

loading...

Auth in Nuxt for 5 years old

aneesshameed profile image aneesshameed Updated on ・3 min read

If you are having a tough time understanding oAuth in nuxt here is a short writeup about it. We are going to implementing oAuth with local strategy using cookie storage.

Everything starts with nuxt config.

auth: {
    strategies: {
      local: {
        endpoints: {
          login: {
            url: '/api/auth/login',
            method: 'post'
          },
          user: { url: '/api/user', method: 'get', propertyName: 'user' }
        },
        tokenRequired: false,
        tokenType: false
      }
    }
  },

In the config file, I am describing two endpoints. The first endpoint describes were the auth start. And the second endpoint says from where the app gets the data about the logged-in user. Both the URLs are required for the setup to start working. You can't test the app by adding only login URL and then trying to login. It throws an error. The user logs into the app using an email and a password. When the authorization is a success the server returns success and then the user will be taken to "/" route of the nuxt app. Since we are using cookies in our strategy to store the user information, the same will be stored on the server-side. Every time now when the user refreshes the app, a request to "/api/user" will be triggered and the server sends back a refreshed information about the user by checking emailId stored in the cookie.

Now, let's look at the login page. In my login page, when the user clicks on a LOGIN button loginLocal function will be called. If the login is a success the app will be redirected to the home page as said earlier, else the error message provided by the server will be logged to the console. In real app, you make a snackbar out of it.

loginLocal: async function() {
      try {
        await this.$auth.loginWith('local', {
          data: {
            email: this.email
            password: this.password
          }
        })
        this.$router.push('/')
      } catch (err) {
        console.log(err.response.data)
      }
    },

Okay, that's done, Now let's look at the server-side. My server folder in nuxt app has the following structure.

-Server
  -models
    -user.js
  -routes
    -auth.js
    -user.js
  index.js

In my index.js I have the following code.

const express = require('express')
...
...

async function start() {
...
...
/**********************************/
  const cookieSession = require('cookie-session') //you need to install this
  app.set('trust proxy', 1) // trust first proxy
  app.use(
    cookieSession({
      name: 'session'
    })
  )
/********************************/

/**/
mongoose
/**/

/**/
body-parser
/**/

const authRouter = require('./routes/auth')
app.use('/api/auth', authRouter)

const userRouter = require('./routes/user')
app.use('/api/user', userRouter)

 app.listen(port, host)
  consola.ready({
    message: `Server listening on http://${host}:${port}`,
    badge: true
})
}
start()

And in my auth.js file, I compare the email and password. If success I store the user email in a session cookie, and then sends a success JSON. If error I send a status 500, which will be caught by my loginLocal function.

const express = require('express')
...
...
router.post('/login', async (req, res, next) => {
  try {
    const body = req.body
    const doc = await User.findOne({
      email: body.email
    })

    if (doc == null) throw new Error('You are not registered')

    doc.comparePassword(body.password, function(err, isMatch) {
      if (err) {
        throw new Error('Incorrect password')
      }
      if (isMatch) {
        doc.lastLogin = new Moment().toISOString()
        req.session.email = body.email
        doc.save()
        res.json(true)
        res.end()
      } else {
        res.status(422).json('Incorrect password')
        res.end()
      }
    })
  } catch (err) {
    res.status(500).json(err.message)
    res.end()
  }
})

Now the user is logged in. Once the user is logged in, the app takes the user to home route "/". At this point the app sends a new request to get the details of the user. When ever a user refreshes the page, the app sends another request to get the user details. In my user.js file, when the app hits "api/user", the app gets user email from cookie and then finds out the user. This user data will then be send to the front end. This data will then be stored in nuxt's $auth.user object

const express = require('express')
...
...
router.get('/', (req, res, next) => {
  try {
    User.findOne({
      email: req.session.email
    })
      .then((doc) => {
        res.json({ user: doc.toJSON() })
        res.end()
      })
      .catch((err) => {
        res.status(500).json(err.message)
        res.end()
      })
  } catch (err) {
    res.status(500).json(err.message)
    res.end()
  }
})

Next, we will look at token-based oAuth which is the preferred way for local login strategy.

Discussion

pic
Editor guide
Collapse
jpliukaitis profile image
jpliukaitis

res.status(500).json('Incorrect password')

I would recommend you to change 500 error to 422 error (Validation) in case of bad password or non existing user, as 500 errors should only come up when your server encoutners unexpected conditions and can not fulfill request.

Collapse
aneesshameed profile image
aneesshameed Author

Ah, thanks for the tip. Updated the same. :D

Collapse
slidenerd profile image
slidenerd

mind sharing a link to the code? also does it work with express-session