Аутентификация маркера REST API
Я только начал разработку моего первого REST API в .NET. Поскольку он будет неактивен, я буду использовать токены для аутентификации:
Основная идея (System.Security.Cryptography):
- AES для шифрования + HMACSHA256 для целостности
- данные токена будут содержать объект со свойствами: имя пользователя, дату выдачи и тайм-аут
- будет храниться имя пользователя, хешированный пароль и хеш HMAC
Логин:
- проверьте правильность учетных данных (имя пользователя, сравнение хешированного пароля с значением db)
- если true, зашифровать объект данных
- использовать HMAC для сгенерированного токена и хранить его в базе данных
- вернуть токен (без HMAC) пользователю (cookie/string)
Запрос метода, требующего проверки подлинности:
- пользователь отправляет токен с каждым запросом
- расшифровывается токен
- если он истек, ошибка
- если не истек срок использования HMAC и сравнить имя пользователя + сгенерированный хеш с значениями db
- Если проверка db действительна, пользователь аутентифицирован
Как я вижу, этот подход имеет следующие преимущества:
- даже если db компрометируется, он не содержит фактического токена (хеш нельзя отменить...)
- даже если у злоумышленника есть токен, он не может увеличить срок действия, обновляя поля, так как дата истечения срока находится в самом маркере
Теперь, во-первых, мне интересно, действительно ли это хороший подход.
Кроме того, я до сих пор не понял, где хранить ключи AES и SHA256 на сервере (должен ли я просто жестко кодировать их? Если я помещаю их в web.config или использую машинный ключ, то у меня есть проблема в случае загрузки сбалансированные серверы,...).
И наконец, где я храню векторы AES IV, поскольку Crypto.CreateEncryptor требует его для дешифрования? Означает ли это, что пользователи должны отправлять токен + IV с каждым запросом?
Надеюсь, это имеет смысл, и я благодарю вас за ответы заранее.
UPDATE:
Хорошо, теперь я сделал еще несколько исследований и пришел с этим решением:
- токен будет содержать первоначально указанные данные (имя пользователя, дата выдачи и тайм-аут).
- сгенерирован с encrypt-then-mac (он включает в себя зашифрованные данные AES, вектор IV + тег этих двух значений для аутентификации, сгенерированный с помощью HMACSHA265)
- токен тега будет записан в db
- пользователь будет аутентифицирован, если:
-
Тег
- действителен (аутентификация по токенам)
- данные могут быть дешифрованы
- токен еще не истек
Тег
- соответствует тому, что написано в базе данных
- пользователь не заблокирован в базе данных (недействительность маркера по запросу)
Клавиши - будут сохранены в отдельном разделе web.config. Эти же ключи должны быть на каждом сервере (для каждого приложения, конечно)
Я не использовал FormsAuthenticationTicket, потому что в .NET возникают следующие проблемы:
Ответы
Ответ 1
Это продолжение из потока комментариев в вопросе.
Кажется, вы немного смущены тем, что именно, OAuth, так что, надеюсь, я смогу прояснить это здесь.
OAuth - это не веб-сервис или что-то, что вы потребляете. Это протокол, который описывает способ, которым сайт может аутентифицировать пользователя против службы, не позволяя сайту знать, что такое учетные данные пользователя. В качестве побочного преимущества большинство поставщиков OAuth также имеют веб-службу для запроса пользовательской информации, и разрешение на это может быть предоставлено в то же время.
Как правило, вы заинтересованы в реализации OAuth с точки зрения сайта (например, AcmeWidgets.com), чтобы пользователь мог войти в систему через Facebook или Google или что-то в этом роде. Тем не менее, вы также можете реализовать сторону обслуживания (например, где обычно будет Facebook) и разрешить другим пользователям аутентифицироваться против ВАС.
Итак, скажем, у вас есть веб-сервис, позволяющий сторонним сайтам предоставлять виджеты Acme-брендов для пользователей. Ваш первый сторонний разработчик - популярный MyBook.org. Поток будет выглядеть примерно так:
- Кто-то приглашает пользователя использовать приложение "Acme Widgets" в своем профиле MyBook.
-
Пользователь нажимает кнопку, которая перенаправляется на AcmeWidgets.com. URL-адрес выглядит примерно так:
http://acmewidgets.com/oauth/user?r=http%3A%2F%2Fmybook.org%2Foauth%2Fclient&appid=12345
- Пользователь спрашивает, хотят ли они разрешить MyBook получать доступ к своим данным и виджетам.
- Пользователь нажимает "Да", после чего Acme Widgets отмечает, что пользователь разрешил его.
-
Пользователь перенаправляется обратно в MyBook по адресу, подобному этому:
http://mybook.org/oauth/client?token=ABCDEFG
-
MyBook, на стороне сервера, теперь берет этот токен и помещает вызов веб-службы BACK в AcmeWidgets:
http://acmewidgets.com/oauth/validate?token=ABCDEFG&appid=12345&appsecret=67890
- AcmeWidgets отвечает конечным маркером идентификации, идентифицирующим пользователя.
- В противном случае он терпит неудачу, что означает, что пользователь пытается подделать токен, или они отказали в разрешении или в каком-либо другом случае отказа.
-
MyBook с маркером теперь может вызывать API-интерфейсы AcmeWidgets:
http://acmewidgets.com/api/provision?appid=12345&token=ABC123&type=etc
Это все известно как танец OAuth. Обратите внимание, что здесь существует ряд определенных функций реализации, таких как URL-адреса, способы кодирования различных токенов, могут ли токены истекать или отменяться и т.д.
Надеюсь, это очистит все для вас!