Основные поля
Кратко остановимся на том, какие есть стандартные полях в токене и зачем они нужны:
Forms authentication
Internet explorer
В нашем продукте не требуется поддержка этого браузера, поэтому решение мною лично не тестировалось. Тем не менее, как утверждает гугл, решение для него есть, и оно, пожалуй, самое простое и элегантное из всех. Более того, я нигде не встречал информации, что это решение для браузеров от Microsoft утратило актуальность:
if (document.execCommand("ClearAuthenticationCache")) {
window.location.assign(url);
}
В IE существует метод ClearAuthenticationCache, который сбрасывает «те самые глубинные недра». Просто и элегантно. И никаких плясок со вспомогательной страницей 401. Работает ли данный метод в Edge, не знаю. Скорее всего да.
Token authentication
Следующее поколение способов аутентификации представляет Token Based Authentication, который обычно применяется при построении систем Single sign-on (SSO). При его использовании запрашиваемый сервис делегирует функцию проверки достоверности сведений о пользователе другому сервису. Т. е. провайдер услуг доверяет выдачу необходимых для доступа токенов собственно токен-провайдеру (Identity provider).
Это то, что мы видим, например, входя в приложения через аккаунты в социальных сетях. Вне IT самой простой аналогией этого процесса можно назвать использование общегражданского паспорта. Официальный документ как раз является выданным вам токеном — все государственные службы по умолчанию доверяет отделу полиции, который его вручил, и считает паспорт достаточным для вашей аутентификации на протяжении всего срока действии при сохранении его целостности.
На схеме хорошо видно, как и в какой последовательности приложения обмениваются информацией при использовании аутентификацией по токенам.
На следующей схеме дополнительно отражены те этапы взаимодействия, в которых пользователь принимает непосредственное участие. Этот момент и является недостатком подобной схемы — нам всегда нужен пользователь, чтобы получить доступ к ресурсу.
Авторизация
В цепочке обработчиков запроса авторизация находится ближе к контроллеру. Это позволяет проводить тонкую настройку доступа к ресурсам.
Аутентификация и авторизация
Когда говорят об аутентификации, используя сокращение «auth», речь может идти об одном из двух следующих понятий:
При описании различий этих понятий я обычно использую аналогию из мира Unix. Аутентификация — это вход в систему с использованием имени и пароля. Авторизация — это разрешения на чтение, запись и выполнение, имеющие отношение к конкретным файлам и директориям.
Здесь мы уделим основное внимание аутентификации, так как это, в сравнении с авторизацией, понятие более фундаментальное, и так как прежде чем пользователя можно будет авторизовать, он должен пройти процедуру аутентификации. После того, как на сервере будет реализован механизм аутентификации, оснастить его системой авторизации обычно довольно просто, хотя то, как будет выглядеть система авторизации некоего проекта, очень сильно зависит от особенностей самого проекта.
Взгляд сверху
Обычно в системах встречаются разные компоненты: пользователи, работающие через браузер, пользователи, взаимодействующие с сервером через мобильные приложения, и просто серверные приложения, нуждающиеся в принадлежащих вам данных, хранящихся на других серверах, доступ к которым осуществляется через Web API.
Запрос на аутентификацию
Authentication/Token Request — процесс запроса аутентификации.
В зависимости от того какие области (scopes) запрошены, сервис выдачи токенов вернет:
- Только Identity Token, если запрошены только Identity scopes.
- Identity Token и Access Token, если запрошены также и Resources scopes.
- Access Token и Refresh Token, если запрошeн Offline Access.
Более подробно про процесс аутентификации можно прочесть в разделе «
Кастомные фильтр авторизации
Кастомный фильтр должен быть унаследован от одного из следующих типов:
Следующая диаграмма показывает иерархию классов фильтров:
Клиент
Client — устройство или программа (браузер, приложение), которым требуется либо токен для аутентификации пользователя, либо токен для доступа к какому-то ресурсу (подразумевается, что данный ресурс «знаком» с тем конкретным «
» у которого клиент запрашивает токен для доступа).
Область (scope)
Scope — идентификатор ресурса, к которому клиент хочет получить доступ. Список scope посылается в адрес
в составе
По умолчанию все клиенты имеют возможность запрашивать любые области, но это можно (и нужно) ограничивать в конфигурации сервиса выдачи токенов.
Scopes бывают двух видов:
- Identity scopes — это запрос информации о пользователе. Его имя, профиль, пол, фотография, адрес электронной почты и т. д.
- Resource scopes — имена внешних ресурсо (Web APIs), к которым клиент хочет получить доступ.
Процесс аутентификации
Разбираемся детально ху из ху
В данный момент на слуху следующие протоколы:
- OpenID — для проверки учетных данных пользователя (identification & authentication).
- OAuth — про то, чтобы получать доступ к чему-то.
- OpenID Connect — и про и то, и про другое одновременно.
Сервис выдачи токенов
Open ID Connect Provider — важнейший объект всей конструкции централизованного сервиса аутентификации, он также может называться Security Token Service, Identity Provider authorization server и т. д. Различные источники называют его по-разному, но по смыслу это сервис, который выдает токены клиентам.
Основные функции:
Способ второй: digest authentication
Digest authentication
Способ первый: basic authentication
Basic Authentication
Способ пятый: certificate authentication
. Сертификаты бывают двух типов:
Ниже приведено несколько шагов, как создать Self signed сертификат с помощью утилиты keytool.
generate client and server keyskeytool -genkey -keystore keystore_client -alias clientKeykeytool -genkey -keystore keystore_server -alias serverKey
generate client and server certificateskeytool -export -alias clientKey -rfc -keystore keystore_client > client.certkeytool -export -alias serverKey -rfc -keystore keystore_server > server.cert
import certificates to corresponding truststoreskeytool -import -alias clientCert -file client.cert -keystore truststore_serverkeytool -import -alias serverCert -file server.cert -keystore truststore_client
Теперь полученные сертификаты надо добавить в конфигурацию нашего сервера. В данном, случае используется Tomcat
Способ четвертый: digital signature (public/private key pair)
Идея этого подхода заключается в использовании
. Суть состоит в том что любой может обратится к рест сервису и получить беспорядочный набор символов, а точнее шифрованный ответ от сервера и только владелец приватного ключа сможет его расшифровать.
И так по порядку.
Способ шестой: oauth2 authorization
Ну и на закуску я оставил самый сложны для понимания и реализации способ. Зато он очень гибкий и хорошо подходит для больших порталов. Опять же не буду заниматься копипастом, чтобы почитать, что такое OAuth и как он работает идем
Spring security предоставляет нам класс OAuthTemplate, который значительно облегчает нам жизнь.
Все идеи для реализации своей OAuth имплементации я почерпнул из этой
Токен доступа
Access Token — информация, что конкретному пользователю разрешается делать. Клиент запрашивает Access Token и затем использует его для доступа к ресурсам (Web APIs). Access Token содержит информацию о клиенте и пользователе, если она присутствует. Важно понимать, что есть такие типы авторизации, при которых пользователь в процессе непосредственно не участвует (подробнее об этом в следующей части)
Токен личности
Identity Token — подтверждение аутентификации. Этот токен содержит минимальный набор информации о пользователе.
Токен обновления
Refresh Token — токен, по которому STS вернет новый Access Token. В зависимости от режима работы, Refresh Token может быть многоразовым и одноразовым. В случае с одноразовым токеном, при запросе нового Access Token будет также сформирован готовый Refresh Token, который следует использовать при повторном обновлении. Очевидно, что одноразовые токены более безопасны.
Более подробно о составе токенов в разделе «структура токена».
Установка контекста безопасности
Если ваше приложение выполняет какую-либо логику связанную с аутентификацией, вы должны задать контекст безопасности в двух свойствах:
Следующий код показывает как задать контекст безопасности:
Формат
Заключение
Что ж, я надеюсь мне немного удалось прояснить общую картину и помочь Вам в реализации собственных проектов. Это конечно же не все способы защитить Ваш рест сервис, но есть решения на любой вкус. Примеры реализаций не являются общими решениями, а лишь приведены для полного понимания картины. Вы можете писать свои имплементации в зависимости от нужд проекта.
Перед выбором security для вашего проекта четко решите, что вам надо, взвесьте все за и против. Не стоит усложнять систему, если этого не требует проект.
Надеюсь, Ваши приложения будут безопасными и надёжными.
Заключение первой части
В этой статье мы постарались дать теоретический и терминологический фундамент, который понадобится нам создании работающего решения в следующих статьях.
Stay tuned.
Минимальная реализация интеграция Identity Server в ваше приложение выглядит так:
public void Configuration(IAppBuilder app)
{
var factory = new IdentityServerServiceFactory();
factory.UseInMemoryClients(Clients.Get())
.UseInMemoryScopes(Scopes.Get())
.UseInMemoryUsers(Users.Get());
var options = new IdentityServerOptions
{
SiteName = Constants.IdentityServerName,
SigningCertificate = Certificate.Get(),
Factory = factory,
};
app.UseIdentityServer(options);
}
Минимальная реализация интеграции веб-клиента с Identity Server:
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = Constants.ClientName,
Authority = Constants.IdentityServerAddress,
RedirectUri = Constants.ClientReturnUrl,
ResponseType = "id_token",
Scope = "openid email",
SignInAsAuthenticationType = "Cookies",
});
}
Минимальная реализация интеграции веб-API с Identity Server:
public void Configuration(IAppBuilder app)
{
app.UseIdentityServerBearerTokenAuthentication(
new IdentityServerBearerTokenAuthenticationOptions
{
Authority = Constants.IdentityServerAddress,
RequiredScopes = new[] { "write" },
ValidationMode = ValidationMode.Local,
// credentials for the introspection endpoint
ClientId = "write",
ClientSecret = "secret"
});
app.UseWebApi(WebApiConfig.Register());
}