Есть ли способ программно генерировать cookie CouchDB?

99
9

Я работаю над приложением, которое будет использовать CouchDB для хранения некоторых данных для пользователей. Но я не хочу, чтобы пользователи входили в CouchDB напрямую.


У меня будет клиент приложения (mobile/web), сервер приложений и сервер CouchDB. Клиентское приложение будет аутентифицироваться на сервере приложений, тогда мой идеальный сценарий будет для моего сервера приложений аутентифицировать пользователей программным путем, а затем отправить только 10-минутный файл cookie в клиентское приложение.


То есть, я бы хотел, чтобы сервер приложений запрашивал Cookie с сервера CouchDB от имени пользователя приложения, а затем отправлял только файл cookie клиенту приложения.


Сервер приложений может просто POST для _session от имени аутентифицированного пользователя, но для этого требуется:


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

По соображениям безопасности, # 3 кажется лучшим, но это похоже на дополнительную работу, и это дополнительное путешествие туда-обратно к БД (хотя и не дорогое). Поэтому мой вопрос: есть ли какой-либо администратор способ создания cookie от имени пользователя без использования пароля пользователя?


Это также потенциально может позволить мне полностью отклонить запросы на _session, за исключением моего сервера приложений, в качестве дополнительной меры безопасности.


И ради полноты, я также упомянул, что посмотрел на эти другие варианты и нашел, что они хотят:


    Proxy Auth


    Тот факт, что x_auth_token никогда не истекает, беспокоит меня. Это означает, что скомпрометированный токен предоставит навсегда доступ к пользовательским данным. И AFAICT, токен не может быть даже признан недействительным без изменения имени пользователя или секретности сервера (что фактически лишает законных прав всех остальных токенов). Но, может быть, я что-то пропустил?


    OAuth auth


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


спросил(а) 2021-01-25T19:38:38+03:00 4 месяца, 3 недели назад
1
Решение
132

Я не следую вашим точным целям. Кажется, вы подразумеваете, что у пользователей могут быть пароли ( "сервер приложений, аутентифицирующий пользователей программным способом" ), но вы не хотите, чтобы пользователи "когда-либо знали свой пароль CouchDB". Какую аутентификацию вы хотите?


Есть два (и полтора) общих подхода, которые я использовал для аутентификации с помощью CouchDB:


    "Человек-в-середине [ware]" подход, где у меня есть тонкое промежуточное ПО перед CouchDB. Это промежуточное программное обеспечение пересылает имя пользователя/пароль на "/_session", что дает коды cookie или ошибки, основанные на базе данных CouchDB _users. Средство связывания копирует этот файл cookie из CouchDB на свой собственный HTTP-ответ обратно клиенту (или отображает сообщение в случае ошибки). Затем по последующим запросам, которым нужен доступ к базе данных, он пересылает cookie (теперь из клиентского запроса) обратно в базу данных.


    Традиционный подход, когда вы просто используете CouchDB в качестве хранилища данных и поддерживаете свои собственные "пользовательские" записи/индексы. Убедитесь, что вы используете современные рекомендации для хранения/обработки паролей или используете библиотеку, которая занимается этими деталями. Среднее связывание соединяется с базой данных как "сама" и обрабатывает разрешения на чтение и запись с собственной логикой на основе собственной обработки сеанса.


    Или - вид гибридного подхода - вы можете использовать API "/_session" только для того, чтобы убедиться, что CouchDB принимает имя пользователя + пароль как действительный. Если это так, создайте отдельный сеанс промежуточного программного обеспечения для этого пользователя. (В основном вы используете базу данных CouchDB _user как "библиотеку обработки паролей", а остальная часть - это традиционный подход, когда управление доступом реализовано в промежуточном программном обеспечении, а не в базе данных.)


В реальных продуктах для производства я обычно использовал только последние два (или один с половиной с учетом ранней нумерации...) - первый способ - это весело, но CouchDB не имеет документально- как правило, означает, что предоставление пользователям почти прямого доступа к серверу базы данных на практике является несостоятельным.

ОБНОВЛЕНИЕ: теперь возникает вопрос, что вы хотите, чтобы клиентское приложение говорило напрямую с обоими серверами: приложение (ранее "промежуточное" ) сервер и CouchDB (базы данных). Я оставляю содержимое выше, потому что я думаю, что он все еще несколько полезен и предоставляет немного фона/контекста для этого обновления.


Вы правы в своих подозрениях, что Прокси-аутентификация - это неправильное решение: оно не предназначено для использования конечным пользователем, но действительно для замены часть "трюк" для пересылки файлов cookie №1 выше. То есть аутентификация прокси-сервера - это когда вы полностью доверяете одной стороне (т.е. Вашему промежуточному программному обеспечению) предоставлять информацию о пользователе, поскольку она работает от имени пользователя. Но вы хотите, чтобы пользователи напрямую разговаривали с базой данных, и вы не можете доверять им с помощью X-Auth-CouchDB-Token.


Я отложу ваше решение по опции OAuth. Я думаю, что это ближе, чем хотите, но ясно, что каким-то образом вы аутентифицируете пользователей в отношении другой службы и не нуждаетесь в хранении для каждого пользователя в CouchDB. Подписание запроса, требуемое OAuth 1.0, означает, что вам понадобится поддержка в вашей HTTP-библиотеке клиентского приложения.


Я вижу несколько вариантов, не создавая настраиваемый CouchDB-плагин, который может позволить вашему приложению передать токен аутентифицированным пользователям, которые ваш сервер базы данных примет:


    Прокси в конце концов! То есть, скройте свой сервер базы данных за сервером приложений или другим легким пользовательским обратным прокси. Все это промежуточное программное обеспечение должно быть выполнено, это проверить существующий сеанс клиентского приложения (cookie или другой заголовок аутентификации), и если он действителен, установите внутренний прокси-серверы auth что CouchDB примет - затем он пересылает остальную часть запроса/ответа дословно.

    Детерминированный пароль, для каждого пользователя, если вам станет лучше. Настройте свой сервер приложений на секрет, известный только ему, затем установите для каждого пользователя пароль что-то вроде HMAC(username, app_server_secret). Теперь, когда вы хотите создать токен для пользователя, ваш сервер приложений может генерировать пароль для каждого пользователя. Обратите внимание, что это действительно не более безопасно, чем просто использование app_server_secret в качестве пароля для каждого пользователя. CouchDB уже солевым и хэширует каждый пользовательский пароль независимо, поэтому, если кто-то получает доступ к базе данных, но не к вашим настройкам конфигурации приложения, злоумышленник не могли рассказать обо всем. В обоих случаях предотвращение несанкционированного использования базы данных полностью зависит от сохранения секретности app_server_secret.


    Восстановите алгоритм генерации текущего файла cookie CouchDB. Алгоритм cookie CouchDB (источник просмотра) в основном data = username + ':' + timestamp; base64(data + ':' + sha_mac(data, secret)). Где secret - это значение couch_httpd_auth.secret плюс значение пользователя salt. Вы можете сообщить серверу своего приложения couchdb_httpd_auth/secret значение, и он может следовать тем же самым шагам, чтобы создать действительный файл cookie, который вы предоставляете клиентскому приложению, и CouchDB примет его как свое. Этот файл cookie будет действителен до отметки времени + настроенный couch_httpd_auth/timeout. Как "взломанный", как кажется, это, вероятно, ближе всего к тому, что вы просите, хотя вам все равно необходимо установить/отключить фактические пароли пользователей.


ответил(а) 2021-01-25T19:38:38+03:00 4 месяца, 3 недели назад
64

Расширение блестящего ответа natevw. У меня были подобные проблемы, и я бы никогда не понял, что вариант 3 возможен, не наткнувшись на этот ответ.


Вот моя реализация python3 для создания cookie (использует pycouchdb для взаимодействия с кушеткой):

def generate_couchdb_cookie(couchAddress, couchSecret, username):

timestamp = format(int(time.time()), 'X')
data = username + ":" + timestamp

server = pycouchdb.Server(couchAddress)
db = server.database("_users")
doc = db.get("org.couchdb.user:" + username)
salt = doc["salt"]
secret = couchSecret + salt

hashed = hmac(secret.encode(), data.encode(), sha1).digest()
inbytes = data.encode() + ":".encode() + hashed
result = base64.urlsafe_b64encode(inbytes)

return "AuthSession=" + (result.decode("utf-8")).rstrip('=')

ответил(а) 2021-01-25T19:38:38+03:00 4 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема