Всё гениальное просто. Но до этой простоты нужно перечитать тысячи мануалов. Поэтому, разобравшись, мне захотелось написать quick start по тому, как сделать прозрачную авторизацию в Web-приложении для пользователя, авторизованного в AD, и поделиться своим тестовым проектом. Интересен взгляд со стороны.
Для начала немного теории. SSO, она же прозрачная авторизация, это идея, по которой пользователь раз вводит логин/пароль своей учётной записи в Active Directory при входе на компьютер, и дальше, открывая Web-приложение (не только, но речь о нём) уже автоматически авторизуется с данными своей учётки.
В браузерах для этого заложен принцип — получая в ответ на свой Get-запрос HTTP-код 401 «Not Authorized», и в HTTP-заголовках <WWW-Authenticate: Negotiate>, он, браузер, делает запрос в KDC (Key Distribution Center — одна из служб AD) на получение специального SPNEGO-токена для данного Web-сервиса. Если учётки для такого Web-сервиса нет в AD, то браузер берёт стандартный ответ для авторизации по NTLM. Но в данном случае мы считаем, что что-то пошло не так.
Итак, браузер, в случае корректных настроек данного Web-сервиса в AD, на ответ 401 вновь отправляет Get-запрос, но уже с заголовком вида <Authorization: YIIJvwYGKw… > Если токен начинается так, с «YII», значит это Kerberos-закодированный тикет, содержащий данные для авторизации.
Kerberos — это просто тип шифрования, но поскольку он в основном используется для SSO, эти понятия тесно связаны.
Далее Web-сервис, получив токен, с помощью kerberos-клиента отправляет его в KDC на проверку. И, в случае успеха, получает имя пользователя в AD. Которое дальше уже можно использовать для поиска данных о пользователе (например, групп, в которых он состоит) уже через другой сервис доступа к AD — LDAP.
Наиболее наглядно описывает этот процесс схема из официальной документации Microsoft. И, надо сказать, на удивление именно их документация дала наибольшее понимание предмета.
Отсюда
Таким образом, помимо создания Web-приложения, нужны следующие действия:
Что требуется сделать на стороне администраторов AD
— задать в AD SPN-имя для Web-сервиса (вида HTTP/webservice.example.com@EXAMPLE.COM). Это позволит клиентским браузерам запрашивать токен для данного сервиса и передавать его в HTTP-заголовке Web-сервису, а Kerberos-клиенту через данный сервис на основе ключа проверять подлинность пользователей,
— сформировать для этого сервиса ключ krb5.keytab, который будет использоваться в Kerberos-клиенте для проверки подлинности пользователей.
Дополнительные действия на сервере Web-сервиса
— потребуется установить Kerberos-клиент (в Windows он уже есть, в случае Linux — например, для RedHat команда для установки: yum install krb5-workstation krb5-libs krb5-auth-dialog krb5-devel);
— для него нужно будет настроить файл конфигурации krb5.conf для доступа к KDC (как — администраторы AD назовут правильные настройки, главный параметр — kdc);
— а также подложить файл ключа /etc/krb5.keytab.
В Web-приложении
— устанавливается модуль kerberos, для работы с kerberos-клиентом,
— и модуль activedirectory, для выполнения LDAP-запросов.
Один неприятный момент — для Windows модуль kerberos предоставляет отдельный API, и использовать его не вышло. Если у кого-то есть решение — это была бы неоценимая помощь.
Для Linux модуль kerberos предоставляет два основных метода, которые нужны в работе:
— authGSSServerStep — отправка токена на проверку,
— authUserKrb5Password — авторизация по логин/пароль, на случай если прозрачная авторизация не сработала.
Документации по использованию методов нет, но есть толковые комментарии в файле lib\kerberos.js.
Вот основной кусок кода, проверяющий пришедший от браузера токен:
→ Ссылка на тестовый проект на GitHub
В коде есть бонус — фильтр для поиска всех групп пользователя, работающий при большом числе групп на порядок быстрее метода, предложенного в модуле activedirectory.
В результате при открытии страницы, если всё сделано верно, должно быть
Ожидаемые ограничения:
— адрес Url не может быть в виде ip:port, а только с указанием DNS-имени (связано с регистрацией Web-сервиса в AD),
— данная авторизация работает только при определённых настройках IE, но это настройки по умолчанию («Автоматический вход в сеть только в зоне интрасети», «Разрешить встроенную проверку подлинности Windows»). Chrome использует настройки IE. В остальных браузерах возможно потребуются свои настройки.
Для начала немного теории. SSO, она же прозрачная авторизация, это идея, по которой пользователь раз вводит логин/пароль своей учётной записи в Active Directory при входе на компьютер, и дальше, открывая Web-приложение (не только, но речь о нём) уже автоматически авторизуется с данными своей учётки.
В браузерах для этого заложен принцип — получая в ответ на свой Get-запрос HTTP-код 401 «Not Authorized», и в HTTP-заголовках <WWW-Authenticate: Negotiate>, он, браузер, делает запрос в KDC (Key Distribution Center — одна из служб AD) на получение специального SPNEGO-токена для данного Web-сервиса. Если учётки для такого Web-сервиса нет в AD, то браузер берёт стандартный ответ для авторизации по NTLM. Но в данном случае мы считаем, что что-то пошло не так.
Итак, браузер, в случае корректных настроек данного Web-сервиса в AD, на ответ 401 вновь отправляет Get-запрос, но уже с заголовком вида <Authorization: YIIJvwYGKw… > Если токен начинается так, с «YII», значит это Kerberos-закодированный тикет, содержащий данные для авторизации.
Kerberos — это просто тип шифрования, но поскольку он в основном используется для SSO, эти понятия тесно связаны.
Далее Web-сервис, получив токен, с помощью kerberos-клиента отправляет его в KDC на проверку. И, в случае успеха, получает имя пользователя в AD. Которое дальше уже можно использовать для поиска данных о пользователе (например, групп, в которых он состоит) уже через другой сервис доступа к AD — LDAP.
Наиболее наглядно описывает этот процесс схема из официальной документации Microsoft. И, надо сказать, на удивление именно их документация дала наибольшее понимание предмета.
Отсюда
Таким образом, помимо создания Web-приложения, нужны следующие действия:
Что требуется сделать на стороне администраторов AD
— задать в AD SPN-имя для Web-сервиса (вида HTTP/webservice.example.com@EXAMPLE.COM). Это позволит клиентским браузерам запрашивать токен для данного сервиса и передавать его в HTTP-заголовке Web-сервису, а Kerberos-клиенту через данный сервис на основе ключа проверять подлинность пользователей,
— сформировать для этого сервиса ключ krb5.keytab, который будет использоваться в Kerberos-клиенте для проверки подлинности пользователей.
Дополнительные действия на сервере Web-сервиса
— потребуется установить Kerberos-клиент (в Windows он уже есть, в случае Linux — например, для RedHat команда для установки: yum install krb5-workstation krb5-libs krb5-auth-dialog krb5-devel);
— для него нужно будет настроить файл конфигурации krb5.conf для доступа к KDC (как — администраторы AD назовут правильные настройки, главный параметр — kdc);
— а также подложить файл ключа /etc/krb5.keytab.
В Web-приложении
— устанавливается модуль kerberos, для работы с kerberos-клиентом,
— и модуль activedirectory, для выполнения LDAP-запросов.
Один неприятный момент — для Windows модуль kerberos предоставляет отдельный API, и использовать его не вышло. Если у кого-то есть решение — это была бы неоценимая помощь.
Для Linux модуль kerberos предоставляет два основных метода, которые нужны в работе:
— authGSSServerStep — отправка токена на проверку,
— authUserKrb5Password — авторизация по логин/пароль, на случай если прозрачная авторизация не сработала.
Документации по использованию методов нет, но есть толковые комментарии в файле lib\kerberos.js.
Вот основной кусок кода, проверяющий пришедший от браузера токен:
//cut phrase "Negotiate "
var ticket = req.headers.authorization.substring(10);
//init context
kerberos.authGSSServerInit("HTTP", function(err, context) {
//check ticket
kerberos.authGSSServerStep(context, ticket, function(err) {
//in success context contains username
res.set( 'WWW-Authenticate', 'Negotiate ' + context.response);
res.send(context.username);
});
});
→ Ссылка на тестовый проект на GitHub
В коде есть бонус — фильтр для поиска всех групп пользователя, работающий при большом числе групп на порядок быстрее метода, предложенного в модуле activedirectory.
В результате при открытии страницы, если всё сделано верно, должно быть
Ожидаемые ограничения:
— адрес Url не может быть в виде ip:port, а только с указанием DNS-имени (связано с регистрацией Web-сервиса в AD),
— данная авторизация работает только при определённых настройках IE, но это настройки по умолчанию («Автоматический вход в сеть только в зоне интрасети», «Разрешить встроенную проверку подлинности Windows»). Chrome использует настройки IE. В остальных браузерах возможно потребуются свои настройки.