- PVSM.RU - https://www.pvsm.ru -
Пускать или не пускать? Вот в чем вопрос…
Сейчас на многих сайтах мы видим возможность зарегистрироваться или войти с помощью соцсетей, а некоторые сайты предлагают использовать внешние ключи безопасности или отпечатки пальцев. Что это? Стандарты с хорошо проработанной безопасностью или проприетарные реализации? Можем ли мы доверять этим технологиям и использовать их для разработки сайтов и в повседневной жизни? Давайте разбираться. Итак, сейчас существуют несколько стандартов и технологий для идентификации пользователей OAuth 2.0,OpenID Connect, WebAuthn, SAML 2.0, Credential Management API и др. В статье я расскажу о трех наиболее перспективных протоколах OAuth 2.0, OpenID Connect и WebAuthn. И чтобы понять как их применять на практике, сделаем три лабораторные работы. В качестве платформ для идентификации пользователей будем использовать GitHub и Google, на которых у большинства есть аккаунты.
Начнем с самого известного протокола OAuth 2.0. Он был опубликован в 2012 году, как RFC 6749: The OAuth 2.0 Authorization Framework [1].
С помощью OAuth 2.0 пользователь разрешает определенному сайту получить свои закрытые данные из соцсетей, но без передачи сайту своих логинов / паролей. Например, когда вы регистрируетесь на сайте через Facebook, то как раз и предоставляете этому сайту разрешение получить из Facebook ваше имя, e-mail адрес и другие закрытые данные.
Давайте разберемся с технической реализацией. Для простоты я буду называть любой сайт, который хранит идентификационные данные пользователя Соцсетью. А MySite буду называть любой сайт или приложение, которое хочет получить данные пользователя из Соцсети.
Стандарт определяет следующие роли:
Теперь сам процесс. Детали конкретных реализаций могут различаться, но общая логика будет всегда следующая:
Существует множество инструкций, как реализовать OAuth 2.0 авторизацию, используя соцсети. Мне лично понравилась следующая статья: Authentication using GitHub OAuth 2.0 with NodeJS [2] В ней подробно описаны шаги и приведена тестовая программа. Но, чтобы действительно осознать алгоритм, лучше пройти все шаги руками (http запросами из браузера или вызовами curl). Поехали.
Для начала регистрируем свое приложение на GitHub: github.com/settings/applications/new [3]
Задаем параметры:
Чтобы авторизация работала в рамках собственного сайта адреса должны быть реальными, но для лабораторной работы это не обязательно.
Получаем от GitHub:
Разумеется во всех лабораторных работах все значения фейковые.
Так выглядит получение Client ID и Secret на сайте GitHub:
Теперь начинаем авторизацию. Считаем, что Шаг 1 уже пройден: пользователь зашел на MySite и выбрал “Войти с помощью GitHub ”. Шаг 2 из call flow — это вызов в REST формате:
https://github.com/login/oauth/authorize?client_id=ab8ec08a620c2
В результате этого вызова GitHub показывает окно для авторизации:
Шаг 3: Вводим логин/пароль для доступа на GitHub
Шаг 4: GitHub перенаправляет запрос на Homepage, в этом запросе мы видим code:
http://MySite/home?code=a29b348f63d21
По данному адресу нет работающего сайта, но для нас главное знать присланный code, чтобы сформировать следующий Шаг 5:
https://github.com/login/oauth/access_token?client_id=ab8ec08a620c2&
client_secret=e6fdd52b0a99e8fbe76b05c1b7bb93c1e&
code=a29b348f63d21
Шаг 6: В ответ получили access token:
access_token=31b71cbd372acdbb20ec1644b824f3dd0&scope=&token_type=bearer
Шаг 7: Вставляем access_token в заголовок запроса и вызоваем GitHub API:
curl -H "Authorization: token 31b71cbd372acdbb20ec1644b824f3dd0" https://api.github.com/user
Шаг 8: В ответ получаем JSON с полезной информацией обо мне, которую можно использовать для формирования профиля на MySite:
{
"login": "AlexeySushkov",
"html_url": "https://github.com/AlexeySushkov",
"repos_url": "https://api.github.com/users/AlexeySushkov/repos",
"name": "Alexey Sushkov",
"blog": "http://sushkov.ru",
"location": "St.Petersburg, Russia",
"email": "alexey.p.sushkov@gmail.com",
и т.д.
}
На самой деле, мы рассмотрели только один сценарий работы OAuth 2.0. Существует несколько сценариев, каждый из которых используется в зависимости от приложения, соображений безопасности, способу развертывания и т.д. Описание всех сценариев можно найти, например, тут: OAuth 2.0 in a Nutshell [6].
С OAuth 2.0 немного разобрались. Теперь выясним зачем нужен OpenID Connect, который является надстройкой над OAuth 2.0:
Давайте посмотрим на стандарт с технической стороны.
OpenID Connect (OIDC) — открытый стандарта OpenID, который разрабатывает консорциум OpenID Foundation [7]. OIDC расширяет OAuth 2.0 следующими основными возможностями:
Диаграмма взаимодействия в OpenID Connect выглядит так же, как и в случае OAuth. Единственная разница в содержимом запросов:
Теперь посмотрим, чем нас по данной теме порадует Google. Есть подробная инструкция по конфигурации и использованию OpenID Connect от Google [8] и “песочница” по использованию Google API: Google OAuth 2.0 Playground [9].
Здесь, как и в случае с OAuth 2.0, мы пройдем путь по шагам и посмотрим на приходящие данные. Аналогично считаем, что приложение зарегистрировано, Client ID и Client Secret получены, Шаг 1 пройден. Шаг 2 из call flow — это вызов в REST формате:
https://accounts.google.com/o/oauth2/v2/auth?
response_type=code&
client_id=140797064495-b8b79j42m97nkkrlndfstikv8.apps.googleusercontent.com&
scope=openid%20email&
redirect_uri=http%3A//c18529.shared.hc.ru/wp-login.php&
state=765439764
У Google немного посложнее, т.к. безопасности они уделяют больше внимания:
Шаг 3: Форма ввода пароля отсутствует, т.к. я уже был залогинен в Google.
Шаг 4: Google перенаправляет запрос на Homepage, в этом запросе мы видим code:
http://MySite?state=123&code=4/xAFkcMzhyJhUErRJYwIyntSYN-WeJjfZHLiwWL4IaT-WkHzMU18xABlPmev-M_87wVbqTkQ1y93w6GB5&scope=email+openid+https://www.googleapis.com/auth/userinfo.email&authuser=0&prompt=none
Также как и в случае с GitHub по данному адресу нет работающего сайта, но это и не надо, нам главное знать code, чтобы сформировать следующий Шаг 5. Тут тоже немного посложнее, т.к. Google требует запрос POST, а не GET:
curl -d "code=4/xAFkcMzhyJhUErRJYwIyntSYN-WeJjfZHLiwWL4IaT-WkHzMU18xABlPmev-M_87wVbqTkQ1y93w6GB5&client_id=140797064495-b8b79j42m97nkkrlndfstikv8.apps.googleusercontent.com&
client_secret=HMVctrTicW6RC1Q8T&
redirect_uri=http%3A//c18529.shared.hc.ru/wp-login.php&
grant_type=authorization_code"
-H "Content-Type: application/x-www-form-urlencoded" -X POST https://oauth2.googleapis.com/token
Шаг 6: В ответ получили access_token и id_token:
{
"access_token": "ya29.Il_AB0KeKnjBJx0dhjm2nCLt1B-Mq0aQBW5T302JnlZfsxW1AXqLFfDJZRMi2R2WKG4OX4msKLjx4E4CSl4G_4ajAy3aqrf4pM0ic0jJr092pA67H9aktJktCbx",
"expires_in": 3327,
"scope": "openid https://www.googleapis.com/auth/userinfo.email",
"token_type": "Bearer",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjE3ZDU1ZmY0ZTEwOTkxZDZiMGVmZDM5MmI5MWEzM2U1
………………………………много_букв…………………………………………………….._4mUTiMNSAHljap1hLD2hAzgOZWuQ"
}
Что теперь делать с этим богатством?
Шаг 7: C access_token все понятно: включаем его в вызов API, например GMail:
curl -H "Authorization: Bearer ya29.a0Adw1xeWvFoxHKNICHnV6vFFj5TZdPQVlYD98h8wjW95ZEbHVui_pk7HGRoq3Q7MlVLV23xkVM0yyjSP8ClSlvfUy3b_IqvKQW5Lvwj38QzJhee-aH1grerB4pRpMzn_FGueigG_RGI56pKPgFBTr49cpynQy" https://www.googleapis.com/gmail/v1/users/alexey.p.sushkov@gmail.com/profile
Шаг 8: В ответ получаем JSON с полезной информацией:
{
"emailAddress": "alexey.p.sushkov@gmail.com",
"messagesTotal": 372543,
...
}
Теперь давайте проверим утверждение, что в id_token содержится информация для аутентификации пользователя и поддержания сессии. Для этого надо расшифровать содержимое. Самый простой способ сделать это, обратиться к Google API по адресу
oauth2.googleapis.com/tokeninfo [10] и в качестве параметра указать полученный id_token:
https://oauth2.googleapis.com/tokeninfo?id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjE3ZDU1ZmY0ZTEwOTkxZDZiMGVmZDM5MmI5MWEzM2U1NGMwZTIxOGIiLCJ0eXAiOi
………………………много_букв……………………………...
SVQ5GQni3irfOzOXYEiqijp6TjGa_a-3jKcEsU5TbasZmAIejsdVcNy2_4mUTiMNSAHljap1hLD2hAzgOZWuQ
Получили JSON:
{
"iss": "https://accounts.google.com",
"email": "alexey.p.sushkov@gmail.com",
"email_verified": "true",
"iat": "1583257010",
"exp": "1583260610",
"typ": "JWT"
...
}
Видим, что в id_token содержится информация о логине пользователя, времени получения и времени жизни токена. Можно сделать вывод, что OpenID Connect от Google работает, и его можно применять для соответствующих сценариев.
Web Authentication API [11] (also known as WebAuthn):
По сравнению с OAuth 2.0 в WebAuthn добавляются роли:
Authenticator: внешний ключ безопасности (физический носитель или сканер отпечатков пальцев), который позволяет аутентифицировать пользователя, использую различные технологии, такие как BlueTooth/NFC/USB. Служит для:
Для взаимодействия с браузером Authenticator использует протокол CTAP (Client to Authenticator Protocols).
Relying Party: выполняет ту же функцию, что и “Authorization Server” в OAuth 2.0, а именно проверяет идентификационные данные пользователя. Только в OAuth 2.0 это были логин/пароль, а в WenAuthn — public key credentials.
User Agent: объединяет браузер и сетевое приложение, служит для тех же целей, что и Client в OAuth 2.0, а именно — с одной стороны взаимодействует с пользователем и предоставляет ему GUI, а с другой стороны взаимодействует с системами, в которых хранятся идентификационные данные пользователя.
Перед началом процесса аутентификации, также как и в OAuth 2.0, надо совершить подготовительные действия, только в OAuth 2.0 мы регистрировали приложение, а в WebAuth 2.0 регистрируем пользователя. В Web Authentication API специфицировано два вызова:
Соответственно, для регистрации надо вызвать navigator.credentials.create.
В результате этого в Authenticator-е пользователя сохранится закрытый ключ для определенного сайта, а в Relying Party сохранится открытый ключ.
После этого процесс аутентификации будет таким:
Для закрепления материала делаем лабораторную работу:
Для реализации WebAuthn только http запросами не обойтись, т.к. нужно вызывать браузерное API для взаимодействия с Authenticator-ом. Но и тут Google радует, сделали песочницу с пошаговой инструкцией: Your first WebAuthn [13].
В результате выполнения работы получится JS клиент-серверное приложение, которое реализует аутентификацию с помощью отпечатка пальца. Работающая дема находится по адресу [14].
Если ее запустить на смартфоне с датчиком отпечатков пальцев, то можно посмотреть результат работы. Как обычно, сначала подготовка — регистрируем пользователя:
Создаем логин / пароль и далее привязываем отпечаток пальца:
После этого программа показывает какой открытый ключ привязан к этому отпечатку:
Теперь можно начинать сценарий по аутентификации. Как обычно, считаем, что Шаг 1 пройден и мы находимся на сайте. Чтобы перейти к Шагу 2 надо нажать “Try Reauth”. Браузер выполнит Шаг 3 и вступит во взаимодействие с Authenticator-ом, который на Шаге 4 попросит приложить палец:
И если приложен зарегистрированный палец, то Шаги 5 и 6 успешно пройдут и на Шаге 7 приложение опять покажет окно с соответствующим открытым ключом:
Итак, мы рассмотрели три наиболее распространенных и перспективных протокола для идентификации пользователей: OAuth 2.0, OpenID Connect, WebAuthn. Поняли области их применимости:
It's only the beginning!
Для полноты картины перечислю остальные актуальные протоколы и технологии, используемые для идентификации пользователей:
Зрелый протокол 2005 года, но имеет ограниченный набор сценариев для построения систем SSO. Использует формат данных на основе XML. Подробнее можно посмотреть в статье: “Кто использует протокол аутентификации SAML 2.0” [15]
Разработкой занимается та же организация, что и WebAuthn — W3C. Стандарт Credential Management [16] позволяет:
Пример реализации Credential Management API, известный всем — это диспетчер паролей в Google: passwords.google.com [17]
OATH Resources [18]
Автор: Алексей Сушков
Источник [22]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/informatsionnaya-bezopasnost/348799
Ссылки в тексте:
[1] The OAuth 2.0 Authorization Framework: https://tools.ietf.org/html/rfc6749
[2] Authentication using GitHub OAuth 2.0 with NodeJS: https://medium.com/shriram-navaratnalingam/authentication-using-github-oauth-2-0-with-nodejs-be1091ce10a7
[3] github.com/settings/applications/new: https://github.com/settings/applications/new
[4] MySite/home: http://MySite/home
[5] MySite/callback: http://MySite/callback
[6] OAuth 2.0 in a Nutshell: https://dzone.com/articles/oauth-20-in-a-nutshell
[7] OpenID Foundation: https://openid.net/connect/
[8] OpenID Connect от Google: https://developers.google.com/identity/protocols/OpenIDConnect
[9] Google OAuth 2.0 Playground: https://developers.google.com/oauthplayground/
[10] oauth2.googleapis.com/tokeninfo: https://oauth2.googleapis.com/tokeninfo
[11] Web Authentication API: http://www.w3.org/TR/webauthn
[12] HTTP, HTML, XML и многие другие: https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D1%81%D0%BE%D1%80%D1%86%D0%B8%D1%83%D0%BC_%D0%92%D1%81%D0%B5%D0%BC%D0%B8%D1%80%D0%BD%D0%BE%D0%B9_%D0%BF%D0%B0%D1%83%D1%82%D0%B8%D0%BD%D1%8B#%D0%A1%D1%82%D0%B0%D0%BD%D0%B4%D0%B0%D1%80%D1%82%D1%8B,_%D1%83%D1%82%D0%B2%D0%B5%D1%80%D0%B6%D0%B4%D1%91%D0%BD%D0%BD%D1%8B%D0%B5_W3C
[13] Your first WebAuthn: https://codelabs.developers.google.com/codelabs/webauthn-reauth
[14] Работающая дема находится по адресу: https://webauthn-codelab.glitch.me/
[15] “Кто использует протокол аутентификации SAML 2.0”: https://habr.com/ru/company/1cloud/blog/463775/
[16] Стандарт Credential Management: https://www.w3.org/TR/credential-management-1/
[17] passwords.google.com: https://passwords.google.com/
[18] OATH Resources: https://openauthentication.org/about-oath/
[19] User-Managed Access (UMA) Profile of OAuth 2.0: https://docs.kantarainitiative.org/uma/rec-uma-core.html
[20] User-Managed Access (UMA) 2.0 Grant for OAuth 2.0 Authorization: https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html
[21] Ссылка на W3C стандарт: https://indieauth.spec.indieweb.org/
[22] Источник: https://habr.com/ru/post/491116/?utm_source=habrahabr&utm_medium=rss&utm_campaign=491116
Нажмите здесь для печати.