Как создать безопасность группы пользователей для REST API с использованием промежуточного программного обеспечения - PullRequest
1 голос
/ 11 апреля 2019

Для защиты REST API я использую промежуточное программное обеспечение для проверки на наличие токена JWT пользователя и разрешаю этому конкретному пользователю только доступ к его собственным данным.

В auth.js

const jwt = require('jsonwebtoken')
const User = require('../models/user')

const auth = async (req, res, next) => {
    try {
        const token = req.header('Authorization').replace('Bearer ', '')
        const decoded = jwt.verify(token, process.env.JWT_SECRET)
        const user = await User.findOne({ _id: decoded._id, 'tokens.token': token })

        if (!user) { // If no user is found
            throw new Error()
        }

        // if there's a user
        req.token = token
        req.user = user
        next()
    } catch (e) {
        res.status(401).send({ error: 'Please authenticate.' })
    }
}

module.exports = auth

В одном из маршрутизаторов get / update

router.get('/itemShipmentStatus', auth, async (req, res) => {
   // Get the items shipment status from db.
})

Однако я заметил, что мне нужно создать нового пользователя-администратора (например, admin 1, admin2) для получения и обновления itemShipmentStatus для всех пользователей.Есть ли способ достичь аутентификации группы пользователей через промежуточное ПО (auth.js?)

Обновление:

Единственное решение, которое я могу придумать, - это добавить еще одно "userGroup "поле для документа пользователя при создании нового пользователя.Затем в промежуточном программном обеспечении auth.js добавьте еще одно условие, чтобы проверить, принадлежит ли пользователь группе администраторов.

if (!user || user.userGroup !== 'Admin') { // If no user is found
    throw new Error()
}

Это обычный способ сделать это?

Ответы [ 2 ]

2 голосов
/ 18 апреля 2019

Я бы предложил добавить массив permissions, хранящийся у пользователя.Таким образом, вы более гибки.Тогда

const auth = (allowedPermission) => (async (req, res, next) => {
    try {
        const token = req.header('Authorization').replace('Bearer ', '')
        const decoded = jwt.verify(token, process.env.JWT_SECRET)
        const user = await User.findOne({ _id: decoded._id, 'tokens.token': token })

        if (!user) { // If no user is found
            throw new Error()
        }
        if (!user.permissions.includes(allowedPermission)){
            throw new Error() // Forbidden 403
        }


        // if there's a user
        req.token = token
        req.user = user
        next()
    } catch (e) {
        res.status(401).send({ error: 'Please authenticate.' })
    }
})

и на маршруте

router.get('/itemShipmentStatus', auth([admin, user]), async (req, res) => {
   // Get the items shipment status from db.
})

Тогда будет необходимо определить правильный код для запуска.

Я бы предложил рассмотреть вопрос о разделенииapi.Публичный API и API администратора.Это связано с тем, что концептуально пользователь может захотеть быть администратором и получить доступ к своему собственному itemShipmentStatus.Таким образом, наличие

router.get('/itemShipmentStatus', auth([admin, user]), async (req, res) => {
   // Get the items shipment status from db.
})
router.get('/admin/itemShipmentStatus', auth([admin]), async (req, res) => {
   // Get the items shipment status from db of all user.
})

Это позволяет пользователю с правами администратора протестировать API как обычный пользователь и получить весь статус администратора.

0 голосов
/ 22 апреля 2019

Более традиционный способ сделать это - создать AuthRouter, который расширяет значение по умолчанию express.Router и проверяет наличие разрешенных ролей, поэтому не будет необходимости использовать промежуточное ПО для каждого маршрута.

Расширение express.Router для проверки ролей:

const express = require('express');
const jwt = require('jsonwebtoken');
const User = require('../models/user');

export default class AuthRouter extends express.Router {
  addRoles(...roles) {
    return this.use(checkAccessForRoles(...roles));
  }
}

const checkAccessForRoles = (...roles) => async (req, res, next) => {
  const token = req.header('Authorization').replace('Bearer ', '');
  const decoded = jwt.verify(token, process.env.JWT_SECRET);
  const user = await User.findOne({ _id: decoded._id, 'tokens.token': token });

  if (!roles.includes(user.role)) throw new Error('Forbidden');

  req.user = user;

  return next();
};

Использование AuthRouter для ADMIN роли пользователя:

const adminRouter = new AuthRouter({
  prefix: '/admin',
})
  .addRoles(['ADMIN']);

adminRouter.get('/itemShipmentStatus', async (req, res) => {
  // Get the items shipment status from db.
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...