1

I have started building my first NodeJs app. I am usinf AdonisJs framework.

I have created a simple user registration page from where user gets registered successfully. After that when I go to login page to log that user in, it's request.auth.attempt(email, password) method won't authenticate the existing user. Here's what I have coded so far:

config/auth.js

authenticator: 'session',

  /*
  |--------------------------------------------------------------------------
  | Session Authenticator
  |--------------------------------------------------------------------------
  |
  | Session authenticator will make use of sessions to maintain the login
  | state for a given user.
  |
  */
  session: {
    serializer: 'Lucid',
    model: 'App/Model/User',
    scheme: 'session',
    uid: 'email',
    password: 'password'
  },

routes.js

const Route = use('Route')

// Register
Route.get('register', 'AuthController.showRegisterPage')
Route.post('register', 'AuthController.register')

// Login
Route.get('login', 'AuthController.showLoginPage')
Route.post('login', 'AuthController.login')

// Logout
Route.get('logout', 'AuthController.logout')

AuthController.js/register

/**
     * Handle user registration
     */
    * register(request, response) {

        // validate form input
        const rules = {
            name: 'required',
            username: 'required|unique:users',
            email: 'required|email|unique:users',
            password: 'required|confirmed|min:6'
        }

        const messages = {
            'name.required': 'Name field is required.',
            'username.required': 'Username field is required.',
            'username.unique': 'Username field must have a unique value.',
            'email.required': 'Email field is required.',
            'email.unique': 'Email field must have a unique value.',
            'password.required': 'Password field is required.',
            'password.confirmed': 'Password/Confirm Password fields does not match.'
        }

        const validation = yield Validator.validateAll(request.all(), rules, messages)

        // show error messages upon validation fail
        if (validation.fails()) {
            yield request
                .withAll()
                .andWith({ errors: validation.messages() })
                .flash()

            return response.redirect('back')
        }

        const user = new User()
        user.name = request.input('name')
        user.username = request.input('username')
        user.email = request.input('email')
        user.password = yield Hash.make(request.input('password'))
        yield user.save()

        yield response.sendView('auth.register', {message: {type: 'success', text: 'Registration successful. You can login now.'} })

    }

AuthController.js/login

/**
     * Handle user authentication
     */
    * login(request, response) {

        const email = request.input('email')
        const password = request.input('password')

        // validate form input
        const rules = {
            email: 'required|email',
            password: 'required'
        }

        const messages = {
            'email.required': 'Email field is required.',
            'password.required': 'Password field is required.'
        }

        const validation = yield Validator.validateAll(request.all(), rules, messages)

        // show error messages upon validation fail
        if (validation.fails()) {
            yield request
                .withAll()
                .andWith({ errors: validation.messages() })
                .flash()

            return response.redirect('back')
        }

        try {

            yield request.auth.attempt(email, password)
            response.route('/')

        } catch (e) {

           yield response.sendView('auth.login', {message: {type: 'error', text: 'Invalid credentials. Please try again.'} })

        }

    }

app/Model/User

'use strict'

const Lucid = use('Lucid')
const Hash = use('Hash')

class User extends Lucid {

  static boot () {
    super.boot()

    /**
     * Hashing password before storing to the
     * database.
     */
    this.addHook('beforeCreate', function * (next) {
      this.password = yield Hash.make(this.password)
      yield next
    })
  }

  apiTokens () {
    return this.hasMany('App/Model/Token')
  }

}

module.exports = User

Every time I try to log in, it always executes the catch part in login method. I don't have any idea what's going on. Somebody please help me.

1 Answer 1

3

This is because you are hashing the password twice.

If you look at your User Model there's a hook to hash the password with bcrypt before creating it into the database.

On your registration workflow you are also hashing the password.

const user = new User()
user.name = request.input('name')
user.username = request.input('username')
user.email = request.input('email')
user.password = yield Hash.make(request.input('password')) // here
yield user.save().

This is why it doesn't work.
You must remove the hashing part on your controller method.

As a side note that Adonis 4.0 is released so if you start a new project you may want to use this version instead of using 3.2.

Sign up to request clarification or add additional context in comments.

1 Comment

You're a genius. Thanks a lot :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.