Node.js Аутентификация API безстоящих /cookieless сессий

Я создаю API и пытаюсь выяснить аутентификацию в нескольких контекстах.

Сеансы и аутентификация пароля

API должен обслуживать клиентские приложения, которые мы создаем и развертываем, и обрабатывать аутентифицированные запросы с использованием пароля. Не стоит посылать пароль с каждым запросом, поэтому имеет смысл сначала нажать конечную точку входа и получить идентификатор сеанса. Webapp, о котором идет речь, написан в AngularJS и должен отслеживать свой собственный сеанс в локальном хранилище, чтобы уменьшить захват сеанса и удалить зависимость от файлов cookie для отслеживания сеансов.

Webapp должен будет отправить идентификатор сеанса с каждым запросом и в настоящее время делает это в теле запроса. Этот фрагмент довольно легко и тесно связан с API. Я бы скорее передал всю информацию об аутентификации одним способом - через заголовок, предпочтительно - вместо нескольких полей, расположенных по всему телу запроса, url и заголовкам.

Хранилище сеансов

Redis - это, конечно, удивительно. Хранилище сеансов является простым и автоматически собирает мусор. К сожалению, сеансов в redis сложно управлять: я не могу легко отменить все сеансы для данного пользователя. Добавление этой возможности путем хранения сеансов в истинной redis-datastructure вместо глобального пространства ключей устраняет возможность добавления TTL с ключевыми ключами. Мое текущее решение состоит в том, чтобы хранить список сеансов в пользовательской коллекции MongoDB и мусор-сбор истекших сеансов активности сеанса (например, вход/выход из системы).

Сессии хранятся в redis с connect-redis, но по мере их отправки с каждым запросом не включены в файлы cookie. На данный момент у меня есть небольшая часть промежуточного программного обеспечения, которая выводит идентификатор сеанса из тела запроса и помещает его в объект req.cookies.

var express = require('express');
var RedisStore = require('connect-redis')(require('connect'));

var app = express();
app.use(function(req, res, next) {
  req.cookies = {session: req.body.session};
});
app.use(express.session({
  store: new RedisStore({
    client: redisClient,
    prefix: 'session:'
  }),
  key: 'session',
  secret: 'all mine'
});

Этот подход работает отлично, за исключением того, что express.session заканчивает настройку файла cookie, когда экспресс отвечает, и что это не желаемое поведение.

Как настроить это правильно в контексте Express?

Ключи API

Наш API также должен поддерживать ключи API для сторонних приложений, чтобы получить ограниченный и контролируемый доступ к нашей системе. Самый распространенный механизм, который я знаю для этого, - это распространять ключи API для заинтересованных разработчиков, а разработчик передает ключ API как часть запроса. Это приводит к той же дилемме, что и проверка подлинности на сеанс/пароль: каждый API ожидает ключ API в другой части запроса, от тела до URL-адреса в заголовках.

Расширение и открытые стандарты

В то время как мы не планируем поддерживать стандарты Open аутентификации, такие как OpenAuth и OpenID при первоначальном выпуске, мы хотим создать структуру, в которой добавление указанных стандартов является простым. Частью этого может быть унификация того, как авторизационные полномочия авторизации передаются API, как с аутентификацией сеанса/пароля и аутентификации API Key.

Другой вопрос спрашивает, является ли настройка заголовка HTTP Authorization хорошей идеей или если пользовательский заголовок - лучшая идея.

Поддержка CRUD

Чтобы поддерживать парадигму CRUD для API RESTful, имеет смысл не предоставлять информацию об аутентификации в теле, поскольку это ограничивало бы все запросы API для запросов POST, тогда как CRUD рекомендует использовать различные методы HTTP.

TL;DR

Две вещи:

  • Как мы можем использовать модуль, например connect-redis без использования сеансов на основе файлов cookie.
  • Как нам настроить информацию аутентификации для максимальной гибкости и функциональной совместимости?

Ответ 1

Как указано, вопрос невозможен. Сессия - состояние. Поэтому вы не можете выполнять сеансы без учета состояния.

Если вы действительно хотите аутентификацию без учета состояния, то у вас не может быть сеансов, и вы должны использовать механизм HTTP Authentication.

Если вам действительно нужны сеансы, но вы не хотите передавать токен состояния в заголовок Cookie, тогда вы должны использовать механизм OAuth, который позволяет использовать заголовка авторизации или параметра запроса для хранения токена согласованного состояния.

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

Самый простой и лучший способ сделать это - использовать их для начала. Не заново изобретайте колесо. OAuth2 спроектирован таким образом, чтобы его можно было легко реализовать в нескольких случаях использования и иметь собственный механизм расширения, если вам нужно больше.

Ответ 2

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

Вы можете создать зашифрованный токен с хешем, содержащим, по крайней мере, идентификатор пользователя, дату истечения срока действия и секрет сервера. Вам даже не нужно включать пароль, как только вы проверяете пользователя в запросе на вход.

Маркер будет передан в заголовке Authorization, избегая использования файлов cookie или любого другого параметра запроса.

С помощью этого токена вы можете идентифицировать пользователя и проверить дату истечения срока действия, не требуя хранения на сервере, поэтому нет состояния сеанса. Вам понадобится только магазин, если вам нужно будет выдать аутентифицированные токены по требованию.