B
B
Boogie19892016-09-03 23:57:59
JavaScript
Boogie1989, 2016-09-03 23:57:59

How to properly organize web service authorization on Express?

I want to use Express as a web service for my Angular application. How to properly organize authorization? As I understand it, standard sessions and cookies will not work, or will they? How about jwt? If you use jwt then how to set a specific user in req?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
M
Maxim, 2016-09-04
@maxfarseer

How about jwt?

Behind! Comfortable, I like it.
In short - send standard registration data, the server issues you a token. Next, add the token to the request headers.
In principle, in Google there is enough information on the issue. Look at the site itself (jwt.io), from there a link to the package for node
I will copy here pieces of code from my api server, but I will say right away that I am not very strong in node, if there are comments from those who know, I will only be glad. I won’t give the angular code either, because I have the client code on react.
Here the file uses callbacks, maybe there are better options. In other application routes, I played somewhere through async, somewhere through promise.
My router auth
const express = require('express')
const router = express.Router()
const User = require('../models/user')
const v4 = require('node-uuid').v4
const jwt = require('jsonwebtoken')

router.post('/signup', (req, res, next) => {

  req.check('email', 'Please enter a valid email').len(1).isEmail()
  req.check('password', 'Please enter a password with a length between 4 and 34 digits').len(4, 34)

  const errors = req.validationErrors()

  if (errors) {
    return res.status(400).json({ errors })
  } else {
    User.hashPassword(req.body.password, (err, passwordHash) => {
      if (err) {
        return res.status(400).json({ error: err.message })
      }

      const user = new User({
        name: req.body.name,
        nickname: req.body.nickname,
        email: req.body.email,
        password: req.body.password,
      })

      user.passwordHash = passwordHash
      user.save((err, item) => {
        if (err) {
          return res.status(400).json({ error: err.message })
        }
        const payload = {
          _id: item._id,
          iss: 'http://localhost:3000',
          permissions: 'poll',
        }
        const options = {
          expiresIn: '7d',
          jwtid: v4(),
        }
        const secret = new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64')
        jwt.sign(payload, secret, options, (err, token) => {
          return res.json({ data: token })
        })
      })
    })
  }
})

router.post('/signin', (req, res, next) => {

  req.check('email', 'Please enter a valid email').len(1).isEmail()
  req.check('password', 'Please enter a password with a length between 4 and 34 digits').len(4, 34)

  const errors = req.validationErrors()
  const password = req.body.password

  if (errors) {
    return res.status(400).json({ errors })
  } else {
    User.findOne({ email: req.body.email }, (err, user) => {
      if (err) {
        return res.status(400).json({ error: err.message })
      }
      if (!user) {
        return res.status(400).json({ error: 'User not found' })
      }
      User.comparePasswordAndHash(password, user.passwordHash, (err, areEqual) => {
        if (err) {
          return res.status(400).json({ error: err.message })
        }
        if (!areEqual) {
          return res.status(400).json({ error: 'Wrong password' })
        }
        const payload = {
          _id: user._id,
          iss: 'http://localhost:3000',
          permissions: 'poll',
        }
        const options = {
          expiresIn: '7d',
          jwtid: v4(),
        }
        const secret = new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64')
        jwt.sign(payload, secret, options, (err, token) => {
          return res.json({ data: token })
        })
      })
    })
  }
})

module.exports = router;

user model
const mongoose = require('mongoose')
const bcrypt = require('bcrypt')
const Schema = mongoose.Schema
let bcrypt_cost = 12

const userSchema = new Schema({
  name: { type: String, required: true },
  email: { type: String, required: true },
  passwordHash: String,
})

userSchema.statics.hashPassword = (passwordRaw, cb) => {
  if (process.env.NODE_ENV === 'test') {
    bcrypt_cost = 1
  }
  bcrypt.hash(passwordRaw, bcrypt_cost, cb)
}

userSchema.statics.comparePasswordAndHash = (password, passwordHash, cb) => {
  bcrypt.compare(password, passwordHash, cb)
}

const User = mongoose.model('User', userSchema)

module.exports = User

There is AUTHO_CLIENT in the router code - since I originally took the implementation from AUTH0 , by the way, might you like it? Everything is convenient for them ... But for myself, for the purpose of learning, I rewrote it on my own. (some link they have about angular cookies vs token )
I like that I can take some information directly from the token (for example, access level - in my example - poll)

I
Ivan, 2016-09-04
@LiguidCool

To express, sort of like passport js scrolls.

P
planc, 2016-09-06
@planc

read the mean machine pdf
here is the code from the book:
https://github.com/scotch-io/mean-machine-code

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question