Как стать автором
Обновить

Введение в OAuth и OpenID Connect

Уровень сложностиПростой
Время на прочтение9 мин
Количество просмотров3.3K

Идентификация, аутентификация, авторизация

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

Аутентификация — предоставление доказательств, что вы на самом деле есть тот, кем идентифицировались (от слова “authentic” - истинный, подлинный). В качестве доказательства может использоваться паспорт, для подтверждения личности в банке, либо ввод пароля на сайте.

Авторизация — проверка, что вам разрешен доступ к запрашиваемому ресурсу.

Виды авторизации

  • Ролевая модель доступа (RBAC) - разграничение роли к ресурсу в зависимости от группы, к которой принадлежит пользователь. Суть подхода заключается в создании ролей, повторяющих бизнес-роли в компании, и присваивание их пользователям. На основе этих ролей проверяется возможность выполнения пользователем того или иного действия.

    Пример: В сервисе существует 2 роли - User и Admin. Для некоторых методов существуют ограничения - например, доступ на запись данных есть только у пользователя с ролью Admin.

    Eventlog UseCases.drawio.png
  • Атрибутная модель доступа (ABAC) - разграничение доступа основанное на анализе правил для атрибутов объектов или субъектов и возможных операций с ними. Основное отличие этого подхода в том, что каждая ситуация оценивается не с точки зрения роли пользователя и действия, которое он хочет совершить, а с точки зрения атрибутов, которые к ним относятся. Бизнес-правило, по сути, представляет собой набор условий, в которых различные атрибуты должны удовлетворять предъявляемым к ним требованиям.

    Например, в системе существует бизнес-правило: Менеджер отделения может нанимать сотрудника только в своё отделение. Тогда при найме сотрудника необходимо настроить проверку атрибутов:

    • Субъект.Должность == “Менеджер”

    • Действие == “Найм сотрудника”

    • Объект.Филиал == Субъект.Филиал

    То есть необходимо проверить, что действие “Найм сотрудника” пытается выполнить пользователь с должностью "Менеджер". А также что найм происходит в тот филиал, менеджером которого является пользователь.

SSO/SLO (Single Sign-On/Single Log Out)

Вводные данные

Представим, что в компании есть 2 сервиса - Сервис A и Сервис Б, в которых пользователи могут произвести вход и получить доступ к определенному функционалу, в зависимости от роли. У Сервиса А своё хранилище пользователей и их ролей, у Сервиса Б - другое.

Два сервиса 1.png

Задача: Объединить данные пользователей в двух сервисах

В один день приходит задача о необходимости объединения хранилищ, так как пользователям приходится выполнять двойную работу - регистрироваться в Сервисе А, а потом в Сервисе Б. Данные пользователей, допустим, одинаковые. Отличаются роли, но проблем с переносом возникнуть не должно. Разработчик объединяет хранилище в одно, теперь пользователь регистрируется либо в Сервисе А, либо в Сервисе Б.

Два сервиса 2.png

Задача: Необходимость интеграции

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

Данные о ролях и пользователях хранятся в одном месте, однако возникает сложность с передачей данных между сервисами. Возможно Сервисам А и Б нужны разные данные для авторизации (предоставления доступа к ресурсу), возможно Сервис А использует в качестве токена не тот же тип токена, что и Сервис Б. Может случиться и так, что Сервис А и Сервис Б шифруются по-разному. Во всех этих случаях необходимо передавать токен из одного сервиса в другой и предугадать возможные проблемы с передачей данных аутентифицированного пользователя. Также необходимо продумать механизм, который инициирует выход из обоих приложений.

Решение: Единая точка входа

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

Два сервиса 3.png

Выводы

Данный механизм называется Single Sign-on. Также при помощи Сервиса В можно реализовать Single Log-out - т.к. пользователь закончит свою сессию в Сервисе В и его аутентификационные данные “испортятся” как в Сервисе А, так и в Сервисе Б.

OAuth 2.0 и OpenIdConnect

Что такое OAuth

OAuth 2.0 (Open Authorization) описывает механизм получения доступа одного приложения к другому от имени пользователя. Другими словами - OAuth 2.0 это протокол авторизации, разработанный для предоставления сайту или приложению доступа к ресурсам, размещенным другими веб-приложениями.

Если вернуться к примеру с Сервисом А, Сервисом Б и Сервисом В, то сервисы А и Б будут запрашивать у Сервиса В доступ к ресурсам пользователя для построения своих авторизационных политик.

Более простой пример - на сайтах нередко можно встретить кнопки по типу “Войти через аккаунт Google”, “Войти через аккаунт Яндекс”, после чего выводится окно, где перечисляется к каким данным пользователя приложение хочет получить доступ. После подтверждения согласия, приложение получит доступ к запрошенной информации пользователя.

Untitled

Это и есть реализация протокола, так как приложение или сайт получает от внешнего сервиса информацию о пользователе.

OpenIdConnect

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

OpenId Connect (OIDC) - протокол идентификации и аутентификации, построенный на основе OAuth 2.0. Он позволяет клиентским приложениям (веб- или мобильные клиенты) проверять личность пользователя через доверенного Identity provider’а и получать базовую информацию о пользователе при помощи claim’ов в токене. Тут приведен список стандартных claims.

Кто принимает решение какие claim’ы будут в токене?

  • Identity provider сам определяет, какие claim’ы предоставлять;

  • Scope - при запросе токена, клиент также может указать какие данные ему нужны;

  • User consent - пользователь может согласиться или запретить передачу некоторых данных.

Для взаимодействия при помощи OIDC, необходимо передать scope openid, тогда, к примеру, при использовании authorization code flow в ответе от token endpoint вернется не только access_token, но и id_token, который содержит в себе только аутентификационные данные пользователя.

Предоставление данных пользователя клиенту

При помощи OAuth 2.0 клиент (приложение или сайт), получает доступ к информации пользователя (resource owner), которую предоставляет сервер авторизации.

Untitled

В данном случае сервис “Дзен” запрашивает у сервера авторизации номер телефона пользователя example.mail. Стоит отметить, что в данном примере номер телефона является опциональной информацией для сервиса “Дзен”, т.е. если пользователь example.mail не захочет предоставлять доступ к номеру телефона, то авторизация пройдёт. В отличие от электронной почты, т.к. если пользователь не захочет предоставлять сервису “Дзен” свой адрес электронной почты, авторизация завершится с ошибкой.

Получение токена

После того, как пользователь предоставит информацию клиенту, клиент получает токен. Существуют разные способы получения токена доступа (access_token), которые называются Grant’ами или Authorization flow.

Client Credentials

В ситуации, когда одному клиенту необходимо получить доступ к ресурсам другого, следует использовать Client Credentials gran type, так как сервер авторизации выдаёт токен на основании client_id (логин клиента) и client_secret (пароль клиента), который не содержит вообще никаких данных о пользователе от лица которого будет действовать клиент.

Клиент - ПО (сервис, приложение), которое запрашивает токены у сервера авторизации либо для аутентификации пользователя (запрашивает identity токен), либо для доступа к ресурсу (запрашивает access токен).

💡 Клиент должен быть зарегистрирован в сервере авторизации, чтобы получить доступ к данным пользователя

Сервер авторизации — это сервис, который валидирует входящие данные и принимает решение о выдаче доступа. В данном случае он принимает решение выдавать ли access token клиенту.

Access token используется для предоставления доступа к ресурсу. При помощи access token’а можно получить данные клиента для построения авторизационных политик. Обычно access token представляет собой JWT токен, который считается самодостаточным, так как payload содержит все необходимые данные (claims). В некоторых случаях можно встретить access token в виде некоего набора символов. Такой тип токена называется reference. По этой строке можно получить данные клиента, используя специальный эндпоинт connect/introspect.

Client Credentials flow.drawio.drawio.png

В данном случае клиент передаёт свой client_id и secret в обмен на access_token

Когда использовать:

  • Для приложений, действующих от своего имени (без пользователя)

  • Используется в серверных приложениях и микросервисах

Resource Owner Password Credentials

В данном случае User (Resource owner) даёт клиенту - приложению, которому необходимо действовать от лица пользователя, свои учётные данные. Клиент отправляет их серверу авторизации (сервис, который отвечает за выдачу токенов), после чего сервер авторизации в ответе отдаёт клиенту токен.

Resource owner — это человек, предоставляющий доступ к некоторой части своей учетной записи. Ресурсами в этом случае могут быть данные (фотографии, документы, контакты), услуги (размещение записи в блоге, перевод средств) или любой другой ресурс, требующий ограничения доступа. Любая система, желающая действовать от имени пользователя, должна сначала получить от него разрешение.

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

Сервис авторизации при данном flow, валидирует не только данные клиента (client_id и secret), но и учётные данные пользователя - username и password.

При данном флоу, сервер авторизации может выдать не только access token, но и два новых типа токена - identity token и refresh token.

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

Scope - это механизм, разрешающий доступ приложения к определенной области учетной записи пользователя (resource). Например, если запросить scope “email”, то сервер авторизации вернет токен, который содержит email пользователя. Через параметр scope передаются “области видимости”, к которым клиент хочет получить доступ. Строгого требования к именованию scope нет, обязательным для протокола OIDC является только openid. Многие современные серверы авторизации поддерживают следующие scope:

  • email - возвращает email аутентифицированного пользователя;

  • profile - персональные данные пользователя (например ФИО), которые передаются в identity токене;

  • phone - номер телефона;

  • address - адрес пользователя

Refresh токен - это строка, которая используется для получения нового токена доступа по истечении срока действия токена доступа. Для того, чтобы получить данный тип токена, необходимо в запрашиваемых scope’ах указать offline_access.

Resource owner password flow.drawio.png

Пользователь вводит в клиентском приложении логин и пароль (1), после чего инициирует вход в систему. Клиент отправляет на сервер авторизации запрос с данными клиента (client id, client secret) и введенные данные пользователя (2). Сервер авторизации проверяет данные клиента и пользователя (3). После успешной проверки, клиент получит токен доступа (4).

В данном запросе передаётся сам логин и пароль пользователя.

Если открыть сайт Microsoft с описанием данного flow, то сразу бросается в глаза надпись:

Untitled

Это предупреждение актуально только в контексте разговора об OAuth и OpenIdConnect. Может случится так, что между клиентским приложением и авторизационным сервером, который выдает токены, может появиться третье приложение, которое получит доступ к логину и паролю пользователя. Из-за того, что в данном флоу используются данные пользователя, не рекомендуется его использовать в браузерных (и любых других публичных) клиентах. Данный флоу рекомендуется для десктопных или консольных приложений.

Когда использовать:

  • Для доверенных приложений, где пользователь вводит учетные данные напрямую

  • Менее безопасен, рекомендуется избегать, если возможно

Implicit flow

Implicit flow.drawio.png

При помощи данного флоу можно делегировать аутентификацию пользователя на сторону сервера авторизации. Пользователя (Resource owner’а) (1) перенаправляет на страницу аутентификации на стороне сервера авторизации (2). Сервер авторизации проверяет client_id и secret клиента, после чего даёт пользователю ввести свои учётные данные (3). При успешном прохождении этапа аутентификации. Далее идёт опциональный шаг данного флоу - запрос у пользователя разрешения на предоставление клиенту данных пользователя (4). Если согласие было получено, то клиент получает access_token и id_token (5), если такой был запрошен (в запросе был передан scope profile). Не стоит путать implicit flow и resource owner password flow, т.к. в данном случае клиент не получает доступ к логину и паролю пользователя.

Когда использовать:

  • Подходит для SPA (Single Page Applications)

  • Менее безопасен, чем Authorization Code Flow

  • Не поддерживает обновление токенов

Authorization code flow

Authorization code flow.drawio.png

Данный flow отличается от imlicit тем, что появляется новый тип ответа сервера авторизации - autentification code. Код авторизации — это промежуточный токен, используемый для получения access_token’а в потоке серверного приложения. Инициируем запрос на сервер (2), который генерирует ссылку для перехода на сервер авторизации, UI получает ее (3) и осуществляет переход (4). После аутентификации пользователя (5-6), сервер авторизации инициирует обратный редирект на клиента, с authorization code (7). Далее этот код, вместе с данными клиента (client_id, client_secret, redirect_uri) (9) обменивается на access-, id- и (если был запрошен) refresh токены (11). На 10-м шаге сервер авторизации проводит проверку, что клиенту с указанным client_id был выдан именно этот authorization code. Данный флоу считается одним из самых надёжных, так как позволяет избежать появления в браузере данных пользователя (id_token), refresh токена и секрета приложения.

Когда использовать:

  • Лучше всего для веб-приложений с серверной частью

  • Обеспечивает высокую безопасность

  • Позволяет обновлять токены доступа

Ссылки

OAuth 2.0 and OpenID Connect (in plain English): OAuth 2.0 and OpenID Connect (in plain English)

Diagrams of All The OpenID Connect Flows: Diagrams of All The OpenID Connect Flows

Обзор способов и протоколов аутентификации в веб-приложениях: Обзор способов и протоколов аутентификации в веб-приложениях

What is OpenID Connect: How OpenID Connect Works - OpenID Foundation

OpenId Connect Standard Claims: Final: OpenID Connect Core 1.0 incorporating errata set 2

Теги:
Хабы:
-1
Комментарии2

Публикации