Переход от механизма токенов на основе сеанса к механизму OAuth 2.0

У меня есть приложение Play Framework, выступающее в роли внутреннего сервера, предоставляющего набор REST API.
На стороне клиента у меня есть приложение AngularJS, которое вызывает API с внутреннего сервера через AJAX.

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

Теперь я хочу использовать OAuth 2.0. Причины есть? :

  • Это отличный стандартный способ защитить API, избегая использования хранилища данных (Memcached) для хранения токенов аутентификации на стороне сервера, как я сейчас предоставляю.
  • Я хочу обеспечить лучшую безопасность, чем единственный файл cookie, предоставив некоторые client_secret и одноразовые номера, чтобы избежать некоторых повторных атак и т. д.
  • Я хочу ограничить количество клиентов, способных вызывать даже общедоступный REST API, который я предоставляю, то есть API, который позволяет анонимный вызов, например, список элементов.

Дело в том, что я не привлекаю третью сторону, так как все защищенные ресурсы находятся на моей собственной ответственности.
Я наткнулся на этот статья, объясняющая, как защитить внутренний REST API с помощью OAuth 2.0, реализующего двухстороннее соединение вместо трехстороннего, как обычно.

Однако я не могу понять, как поток Client Credentials может аутентифицировать конкретного пользователя при вызове REST API, для которого требуется аутентификация пользователя.

Действительно, поток учетных данных клиента, по-видимому, основан на глобальных ключах client_id, client_secret (глобальных для приложения, поэтому в моем случае для моего приложения Javascript) и, следовательно, недостаточно специфичен для нацеливания на конкретного пользователя и управления его конкретными правами.

Любая помощь будет здорово.


person Mik378    schedule 17.02.2014    source источник


Ответы (1)


Похоже, вы должны использовать «Предоставление учетных данных владельца ресурса» (http://tools.ietf.org/html/rfc6749#section-4.3). Это очень просто - поместите идентификатор/секрет клиента в заголовок авторизации и поместите имя пользователя/пароль в переменные запроса. Вот пример из RFC:

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=johndoe&password=A3ddj3w

На стороне сервера вы можете проверить как действительность клиента (вашего приложения javascript), так и пользователя. Просто помните, что невозможно защитить учетные данные клиента, поскольку они будут встроены в ваш (загружаемый) код JavaScript. Имя пользователя/пароль вводится непосредственно конечным пользователем.

person Jørn Wildt    schedule 17.02.2014
comment
Я думал об этом режиме, но для API, который требует авторизованного пользователя. Итак, как насчет вызова одного из моих API, который разрешает анонимные вызовы. Действительно, для этого не потребуются какие-либо учетные данные конечного пользователя, поэтому должен ли я использовать поток учетных данных клиента для этих конкретных случаев? Однако это даже не имеет смысла, поскольку Javascript не является конфиденциальным клиентом => любой может получить client_secret через отладчик javascript и использовать его от имени приложения. Как быть с этим требованием? Я строго не хочу, чтобы какой-либо внешний пользователь вызывал мой общедоступный API (например, curl), даже неограниченный. - person Mik378; 17.02.2014
comment
Вы не можете избежать клиентов, вызывающих ваш общедоступный API. Извини. - person Jørn Wildt; 17.02.2014
comment
› таким образом, должен ли я использовать поток учетных данных клиента для этих конкретных случаев? Вы используете только один из четырех потоков один раз при входе в систему - результатом является некий токен, который впоследствии будет использоваться в следующих запросах. Это ничем не отличается от классического использования страницы входа на веб-сайте с последующим сохранением идентификатора сеанса в файле cookie. - person Jørn Wildt; 17.02.2014
comment
Я понимаю. Поэтому не нужно возиться со специфическими элементами OAuth (такими как client_id и client_secret) для любого вызова общедоступного API, поскольку Javascript не является конфиденциальным клиентом. Напротив, все вызовы, для которых требуется аутентифицированный пользователь, будут включать поток предоставления учетных данных пароля владельца ресурса. Я прав? Большое спасибо за твою помощь :) - person Mik378; 17.02.2014
comment
› Напротив, все вызовы, для которых требуется аутентифицированный пользователь, будут включать поток предоставления учетных данных пароля владельца ресурса. Да, но поскольку клиент может не знать, какие вызовы выполнять до входа в систему, ему придется всегда использовать этот поток в качестве первого запроса. - person Jørn Wildt; 17.02.2014