diegohaz / rest

REST API generator with Node.js, Express and Mongoose
MIT License
1.79k stars 310 forks source link

Passport local strategy login #113

Closed awojtczyk closed 6 years ago

awojtczyk commented 7 years ago

Don't know if that will help, but for my small mobile app i needed passport-local strategy. So, I've added following:

auth/index.js:

import { password, master, facebook, google, local } from '../../services/passport'

...

router.post('/local',
  local(),
  login)

services/passport/index.js

export const local = () => (req, res, next) =>
  passport.authenticate('local', { session: false }, (err, user, info) => {
    if (err && err.param) {
      return res.status(400).json(err)
    } else if (err || !user) {
      return res.status(401).end()
    }
    req.logIn(user, { session: false }, (err) => {
      if (err) return res.status(401).end()
      next()
    })
  })(req, res, next)

...

passport.use('local', new LocalStrategy(localOptions,(email, password, done) => {
  const userSchema = new Schema({ email: schema.tree.email, password: schema.tree.password })

  userSchema.validate({ email, password }, (err) => {
    if (err) done(err)
  })

  User.findOne({ email }).then((user) => {
    if (!user) {
      done(true)
      return null
    }
    return user.authenticate(password, user.password).then((user) => {
      done(null, user)
      return null
    }).catch(done)
  })
}))

This should be helpfull for everyone who will need this generator for using together with mobile apps etc. Basically this is for everyone who don't the master key feature.

I can create some doc, where i can describe 'getting rid' of masterkey functionality if that would be needed.

maustand commented 7 years ago

:+1:

iojanis commented 5 years ago

I'm sorry but when implementing this, my REST Req: curl -X POST http://0.0.0.0:3333/api/auth/local -i -d "email=test@example.com&password=123456" still won't work. What am I doing wrong?

It says:

HTTP/1.1 401 Unauthorized X-Powered-By: Express Access-Control-Allow-Origin: * Date: Wed, 30 Jan 2019 00:12:58 GMT Connection: keep-alive Transfer-Encoding: chunked

jackkum commented 5 years ago

@iojanis

curl -i \
  -H "Accept: application/json" \
  -H "Content-Type:application/json" \
  -X POST http://0.0.0.0:3333/api/auth/local \
  -d '{"email": "test@example.com","password":"123456"}'
iojanis commented 5 years ago

Thanks for the quick response! I already tried that after some research... But I got the same response.

curl -i \
-H "Accept: application/json" \ -H "Content-Type:application/json" \ -X POST http://0.0.0.0:3333/api/auth/local \ -d '{"email": "test@example.com","password":"123456"}' HTTP/1.1 401 Unauthorized X-Powered-By: Express Access-Control-Allow-Origin: * Date: Wed, 30 Jan 2019 00:23:53 GMT Connection: keep-alive Transfer-Encoding: chunked

To be more precise:

I removed "localOptions" from the original code, because it was undefined. And imported the "passport-local" package using import { Strategy as LocalStrategy } from 'passport-local'.

I get no errors, everything seems fine. The User exists and the basic authentication still works. Actually I had the same error yesterday and I thought to try it again today, from a fresh installation. Still no progress. :(

LocalAuth is a must have for me, because I want to use it with nuxt-auth!

EDIT:

This is how my passport.js looks like:

import passport from 'passport'
import { Schema } from 'bodymen'
import { BasicStrategy } from 'passport-http'
import { Strategy as LocalStrategy } from 'passport-local'
import { Strategy as BearerStrategy } from 'passport-http-bearer'
import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt'
import { jwtSecret, masterKey } from '../../config'
import User, { schema } from '../../api/user/model'

export const password = () => (req, res, next) =>
  passport.authenticate('password', { session: false }, (err, user, info) => {
    if (err && err.param) {
      return res.status(400).json(err)
    } else if (err || !user) {
      return res.status(401).end()
    }
    req.logIn(user, { session: false }, (err) => {
      if (err) return res.status(401).end()
      next()
    })
  })(req, res, next)

export const master = () =>
  passport.authenticate('master', { session: false })

export const token = ({ required, roles = User.roles } = {}) => (req, res, next) =>
  passport.authenticate('token', { session: false }, (err, user, info) => {
    if (err || (required && !user) || (required && !~roles.indexOf(user.role))) {
      return res.status(401).end()
    }
    req.logIn(user, { session: false }, (err) => {
      if (err) return res.status(401).end()
      next()
    })
  })(req, res, next)

export const local = () => (req, res, next) =>
  passport.authenticate('local', { session: false }, (err, user, info) => {
    if (err && err.param) {
      return res.status(400).json(err)
    } else if (err || !user) {
      return res.status(401).end()
    }
    req.logIn(user, { session: false }, (err) => {
      if (err) return res.status(401).end()
      next()
    })
  })(req, res, next)

passport.use('local', new LocalStrategy((email, password, done) => {
  const userSchema = new Schema({ email: schema.tree.email, password: schema.tree.password })

  userSchema.validate({ email, password }, (err) => {
    if (err) done(err)
  })

  User.findOne({ email }).then((user) => {
    if (!user) {
      done(true)
      return null
    }
    return user.authenticate(password, user.password).then((user) => {
      done(null, user)
      return null
    }).catch(done)
  })
}))

passport.use('password', new BasicStrategy((email, password, done) => {
  const userSchema = new Schema({ email: schema.tree.email, password: schema.tree.password })

  userSchema.validate({ email, password }, (err) => {
    if (err) done(err)
  })

  User.findOne({ email }).then((user) => {
    if (!user) {
      done(true)
      return null
    }
    return user.authenticate(password, user.password).then((user) => {
      done(null, user)
      return null
    }).catch(done)
  })
}))

passport.use('master', new BearerStrategy((token, done) => {
  if (token === masterKey) {
    done(null, {})
  } else {
    done(null, false)
  }
}))

passport.use('token', new JwtStrategy({
  secretOrKey: jwtSecret,
  jwtFromRequest: ExtractJwt.fromExtractors([
    ExtractJwt.fromUrlQueryParameter('token'),
    ExtractJwt.fromBodyField('token'),
    ExtractJwt.fromAuthHeaderWithScheme('Bearer')
  ])
}, ({ id }, done) => {
  User.findById(id).then((user) => {
    done(null, user)
    return null
  }).catch(done)
}))

I guess the auth/index.js is not necessary.