Этим постом я хочу открыть ветку статей посвященную IdentityServer4. Начнем мы с основных понятий.
Самым перспективным на текущий момент протоколом аутентификации является OpenID Connect, а протоколом авторизации (предоставления доступа) является OAuth 2.0. IdentityServer4 реализует эти два протокола. Он оптимизирован для решения типичных проблем безопасности.
OpenID Connect — это протокол и стандарт аутентификации, он не дает доступ к ресурсам (Web API), но т.к. он разработан поверх протокола авторизации OAuth 2.0, он позволяет получить параметры профиля пользователя как будто вы получили доступ к ресурсу UserInfo.
JWT (JSON Web Token) представляет собой веб-стандарт, который определяет способ передачи данных о пользователе в формате JSON в зашифрованном виде.
OAuth 2.0 (RFC 6749) — это протокол и стандарт авторизации. Он позволяет приложениям получить доступ к защищенным ресурсам, например к Web API.
Взглянем на диаграмму обращения к защищенному ресурсу и разберемся с основными шагами и принятой терминологией:
Клиент запрашивает у пользователя разрешение пройти авторизацию от его имени. Клиент — это клиентское приложение обращающиеся к защищённым ресурсам от имени владельца ресурсов. Ресурс — это все наши защищенные сервисы Web API.
User разрешает клиентскому приложению пройти авторизацию от его имени, например, вводит логин и пароль. Логин и пароль будут являться грантом авторизации для клиентского приложения. User (владелец ресурса) — программа или человек, который может выдать доступ к защищённым ресурсам, например, путем ввода логина (username) и пароля (password);
Клиентское приложение запрашивает токен доступа у
IdentityServer4
путём предоставления информации о самом себе (client_id
,client_secret
), предоставления разрешения на авторизацию от пользователя (username
,password
) и предоставленияgrant_type
иscope
. Затем сервер авторизации проверяет подлинность клиента и реквизиты владельца ресурса (логин и пароль).
Протокол OAuth 2.0 проводит аутентификации не только пользователя, но и клиентского приложения, осуществляющего доступ к ресурсам. Для этого протокол предусматривает такие параметры как client_id и client_secret.
сlient_id — это идентификатор клиентского приложения, используемыйIdentityServer4
для поиска информации о клиенте.
client_secret является аналогом пароля для клиентского приложения и используется для аутентификации клиентского приложения наIdentityServer4
. Секрет клиента должен быть известен только приложению и API. Исходя из вышесказанного делаем вывод что IdentityServer4 должен знать о своих клиентах.
Если подлинность приложения подтверждена и разрешение на авторизацию действительно,
IdentiryServer4
создаётaccess-токен
(токен доступа) для приложения и необязательный ключ обновления (refresh-токен
). Процесс авторизации завершён. Если запрос недопустимый или несанкционированный, то сервер авторизации возвращает код с соответствующим сообщением об ошибке.
Клентское приложение обращается за данными к защищенному Web API, предоставляя при этом токен доступа для авторизации. Если код ответа сервера ресурсов 401, 403 или 498, то токен доступа, используемый для аутентификации, недействителен или просрочен.
Если токен действителен,
Web API
предоставляет данные приложению.
Типы токенов
Зарегистрированным в IdentityServer4
клиентам позволено запрашивать у IdentityServer4
identity
-токен, access
-токен и refresh
-токен.
- identity-токен (токен идентификации) — результат процесса аутентификации. Содержит идентификатор пользователя и информации о том, как и когда пользователь проходит аутентификацию. Можно расширить своими данными.
- access-токен (токен доступа) — передается защищенному API и используется им для авторизации (разрешения доступа) к своим данным.
- refresh-токен (токен обновления) — необязательный параметр, который сервер авторизации может возвратить в ответ на запрос токена доступа.
Введем еще два понятия:
Authenticatation Server Url — конечная точка для получения ключа доступа. Все запросы на предоставление и возобновление ключей доступа будем направлять на этот URL-адрес.
Resource Url — URL-адрес защищенного ресурса, по которому нужно обращаться, чтобы получить доступ к нему, передавая ему ключ доступа в заголовке авторизации.
Запрос ключа доступа
Для запроса ключа доступа клиент делает POST
запрос к конечной точке IdentityServer4
со следующим заголовком
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Expect': '100-continue'
и передавая следующие параметры:
'grant_type' : 'password',
'username' : login,
'password' : password,
'scope' : 'scope',
'client_id' : 'client_id',
'client_secret' : '{client_secret}'
username
, password
, client_id
и client_secret
были разобраны выше. Разберём остальные параметры:
grant_type — тип гранта или тип разрешения на авторизацию. Тип разрешения на авторизацию зависит от используемого приложением метода запроса авторизации, а также от того, какие типы разрешения поддерживаются со стороны API. В нашем случае он будет иметь значение password
, что согласно спецификации OAuth 2.0
соответствует гранту реквизитов доступа владельца ресурса (авторизация по логину и паролю).
Протокол OAuth 2.0
определяет следующие типы грантов требующие обязательного взаимодействие с пользователям:
- код авторизации (authorization code). Является одним из наиболее распространённых типов разрешения на авторизацию, т.к. хорошо подходит для серверных приложений (server-side applications), где исходный код приложения и секрет клиента не доступны посторонним;
- неявный (implicit). Неявный тип разрешения на авторизацию используется мобильными и веб-приложениями, где конфиденциальность секрета клиента не может быть гарантирована;
И типы грантов, которые могут выполняться без интерактивного взаимодействия с пользователям:
- реквизиты владельца ресурса (resource owner). Этот тип разрешения стоит использовать только в том случае, когда клиентское приложение пользуется доверием пользователя и пользователь спокойно относится к вводу своего логина и пароля. Этот тип разрешения должен использоваться только в том случае, когда другие варианты не доступны. Данный тип разрешения удобен для корпоративных клиентов, которые в рамках своей системы уже использовали учетные данные пользователя и хотят перейти на
OAuth 2.0
. - учетные данные клиента. Используются при доступе приложения к API. Это может быть полезно, например, когда приложение хочет обновить собственную регистрационную информацию на сервисе или URI перенаправления, или же осуществлять доступ к другой информации, хранимой в аккаунте приложения на сервисе, через API сервиса.
scope — это необязательный параметр. Он определяет область видимости. Токен доступа, возвращенный сервером, будет обеспечивать доступ только к тем службам, которые входят в эту область. Т.е. мы можем несколько служб объединить под одним scope и если клиент получает ключ доступа к этому scope он получает доступ ко всем этим службам. Также scope может использоваться для ограничения прав авторизации (например, доступ на чтение или запись)
antonpryamostanov
Статья хорошая, я бы даже сказал отличная. Важное дело делаете — продолжайте освещать эту тему, а то в Интернете каша полная по ней, полнейшая путаница на stack overflow и 90% людей не понимают как это работает и как должно работать. Страшно подумать сколько уязвимостей сейчас существует из-за неправильно настроенной авторизации на сайтах.
И самое печальное, что в 2020 году до сих пор нет готовых решений plug and play, которые не требуют глубоких технических навыков и программирования для внедрения OAuth2 и Open ID Connect. Но есть перспективная тенденция: SECaaS, и например наша некоммерческая организация готовит SECaaS платформу которая в этом году произведёт революцию в этой сфере. И она независима (хоть и поддерживает/совместима) от OAuth2 и Open ID Connect.