Каков наилучший способ реализации аутентификации на токенах для restify.js?

Я пытаюсь создать RESTful api с restify.js, но я не хочу раскрывать api всем. И я собираюсь использовать аутентификацию на основе токенов. Процесс в моем сознании подобен этому, я не уверен, разумно ли это.

  • пользователь отправляет имя пользователя/пароль на api для получения токена.

  • этот токен должен быть включен в запрос на вызовы всех других api.

Если это разумно, есть ли какая-либо библиотека node.js, которую я могу использовать?

Кроме того, как мне защитить токен? Если кто-то перехватит HTTP-запрос с токеном, тогда этот человек получит api url и токен. Затем он может отправить запрос по своему усмотрению. Есть ли способ избежать этого?

Спасибо большое!

Ответ 1

Основная аутентификация доступа

Рестайдинг поставляется с плагином authorizationParser. authorizationParser разобрать Authorization. Когда плагин используется, он сделает доступными свойства req.username и req.authorization. Формат последнего:

{
  scheme: <Basic|Signature|...>,
  credentials: <Undecoded value of header>,
  basic: {
    username: $user
    password: $password
  }
}

Серверу необходимо будет выборочно перехватить запросы, требующие проверки подлинности, и подтвердить учетные данные пользователя.

Вот пример сервера, который потребует аутентификации для всех вызовов:

var restify = require('restify'),
    server;

server = restify.createServer();

server.use(restify.authorizationParser());

server.use(function (req, res, next) {
    var users;

    // if (/* some condition determining whether the resource requires authentication */) {
    //    return next();
    // }

    users = {
        foo: {
            id: 1,
            password: 'bar'
        }
    };

    // Ensure that user is not anonymous; and
    // That user exists; and
    // That user password matches the record in the database.
    if (req.username == 'anonymous' || !users[req.username] || req.authorization.basic.password !== users[req.username].password) {
        // Respond with { code: 'NotAuthorized', message: '' }
        next(new restify.NotAuthorizedError());
    } else {
        next();
    }

    next();
});

server.get('/ping', function (req, res, next) {
    res.send('pong');

    next();
});

server.listen(8080);

Самый простой способ тестирования - использовать curl:

$ curl -isu foo:bar http://127.0.0.1:8080/ping

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 6
Date: Fri, 12 Dec 2014 10:52:17 GMT
Connection: keep-alive

"pong"

$ curl -isu foo:baz http://127.0.0.1:8080/ping

HTTP/1.1 403 Forbidden
Content-Type: application/json
Content-Length: 37
Date: Fri, 12 Dec 2014 10:52:31 GMT
Connection: keep-alive

{"code":"NotAuthorized","message":""}

Restify поставляется с встроенным JsonClient, который поддерживает базовую аутентификацию, например

var restify = require('restify'),
    client;

client = restify.createJsonClient({
    url: 'http://127.0.0.1:8080'
});

client.basicAuth('foo', 'bar');

client.get('/ping', function(err, req, res, obj) {
    console.log(obj);
});

OAuth 2.0

Если вы предпочитаете аутентификацию маркера, вы можете использовать restify-oauth2 пакет, который реализует Client Credentials аутентификационный поток, который является тем, что вам нужно.

На странице документации поэтапно описано, как настроить такую ​​аутентификацию, включая роли каждой конечной точки, а в своем репозитории есть пример кода.

Резюме

Независимо от выбранного вами способа аутентификации, все они требуют использования HTTPS. Разница в том, что если имя пользователя/пароль скомпрометировано, пользователю необходимо будет изменить свои учетные данные. Если токен взломан, пользователь должен будет запросить новый токен. Последнее может быть выполнено программно, в то время как первое обычно использует жестко заданные значения.

Боковое примечание. При производстве учетные данные должны считаться "скомпрометированными", если они передаются по меньшей мере один раз по небезопасному каналу, например. скомпрометированный HTTPS, как в случае ошибки SSL, например Heartbleed.