Статьи

Федерация идентичности и OpenId

На данный момент федерация идентичности является горячей темой, по крайней мере, для моего клиента.

Все началось достаточно невинно: кому-то, кто не принадлежал к организации, нужно было получить доступ к приложению. «Не проблема», давайте зарегистрируем его. Спустя год потребности в тысячах пользователей исчисляются, и управление идентификацией переросло свои возможности: программное обеспечение было разработано для организации, а не для множества сторонних пользователей. И все же, партнеры, клиенты и поставщики имеют веские причины для доступа к внутренним приложениям, но все же должны быть идентифицированы и предоставлены права (аутентификация и авторизация), как и любой другой пользователь.

Это один из тех случаев, когда федерация идентичности подходит. Что такое федерация идентичности? Википедия определяет это как:

«Процесс аутентификации пользователя в нескольких ИТ-системах или даже организациях».

Я бы лучше определил это как аутентификацию пользователя в нескольких доменах. Домен может относиться безразлично к крупнозернистым или мелкозернистым системам.

Другие варианты использования федерации идентификации включают в себя:

  • стартап, который не желает вкладывать средства в какое-либо программное обеспечение для управления идентификацией (приобретенное или разработанное) и предпочитает делегировать его третьей стороне
  • организация, которая нуждается в «свежей» информации о личности, будет делегирована третьей стороне, где эта «свежесть» почти гарантирована, будь то по юридическим причинам или просто потому, что
  • децентрализованная организация, которая делегирует аутентификацию своим подразделениям, но все еще нуждается в совместимости приложений
  • и т.п.

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

В любом случае, в настоящее время федерация идентичности приобретает все большее значение, даже если предыдущие технологии предоставляли некоторые возможности, ориентированные на нее. Я думаю о LDAP здесь, где вы можете разместить некоторую ветку вашего дерева LDAP на другом LDAP. Однако это ограничено, поскольку мастер и делегат должны по-прежнему использовать одну и ту же схему (если я хорошо помню, я давно не играл с LDAP).

С такой растущей потребностью в федерации идентификации вполне естественно, что существует множество решений, но нет четкого стандарта, ни нормализованного, ни фактического . Доступные технологии включают (но не ограничиваются ими): CAS , Shibboleth и OpenId . Недавно я заинтересовался последним, не потому, что он лучше других (я новичок в этой области, и у меня недостаточно информации для вынесения такого суждения), а потому, что Google является поставщиком OpenId перед собственным управлением идентификаторами Google или Google. Приложения . Это означает, что вы можете управлять своими личностями в инфраструктуре Google (и это бесплатно до 50 учетных записей) и аутентифицировать своих пользователей с помощью OpenId!

Аутентификация с помощью OpenId — это многоэтапный процесс:

  1. Приложение получает доступные конечные точки аутентификации от провайдера
  2. Приложение перенаправляет пользователя на одну из таких конечных точек аутентификации
  3. Пользователь аутентифицирует себя в инфраструктуре провайдера
  4. Провайдер перенаправляет поток в приложение, если успешно
  5. Наконец, приложение проверяет, прошла ли аутентификация успешно

К счастью, в Java доступен проект OpenSource, который прекрасно оборачивает мельчайшие детали OpenId внутри API. Этот проект называется OpenId4Java и работает как шарм.

Первые два шага обрабатываются с помощью следующего кода:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

try {
// API entry point
ConsumerManager manager = new ConsumerManager();

// Get available endpoints
List<?> discoveries = manager.discover("https://www.google.com/accounts/o8/id");

// Bind to endpoint
DiscoveryInformation discovered = manager.associate(discoveries);

// Create the auth request, providing return URL
AuthRequest authReq = manager.authenticate(discovered, request.getRequestURL().toString());

// Redirects to provider login page
response.sendRedirect(authReq.getDestinationUrl(true));

} catch (Exception e) {

throw new ServletException(e);
}
}

Просто попробовав предыдущий код, вы попадете на страницу входа Google! Как только пользователь аутентифицирован, он отправляется обратно в наше приложение: нам просто нужно управлять токеном, чтобы проверить его целостность. OpenId4Java также делает свое дело (предыдущий код должен быть немного изменен, вы найдете его в исходниках):

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

ParameterList openidResp = new ParameterList(request.getParameterMap());

DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute("discovered");

StringBuffer receivingURL = request.getRequestURL();

String queryString = request.getQueryString();

if (queryString != null && queryString.length() > 0) {

receivingURL.append("?").append(request.getQueryString());
}

try {

VerificationResult verification = manager.verify(receivingURL.toString(), openidResp, discovered);

Identifier verified = verification.getVerifiedId();

if (verified != null) {

AuthSuccess authSuccess = (AuthSuccess) verification.getAuthResponse();

request.getRequestDispatcher("/WEB-INF/page/welcome.jsp").forward(request, response);

} else {

request.getRequestDispatcher("/").forward(request, response);
}

} catch (Exception e) {

throw new ServletException(e);
}
}

Более того, Google поддерживает расширение OpenId, расширение Attribute Exchange (AX). Это позволило нам запрашивать информацию о пользователе у провайдера OpenId, если, конечно, мы получаем согласие пользователя. OpenId4Java легко интегрируется с таким расширением, нам просто нужно несколько обновить наш запрос и наш ответ:

FetchRequest fetch = FetchRequest.createFetchRequest();

fetch.addAttribute("Email", "http://schema.openid.net/contact/email", true);
fetch.addAttribute("FirstName", "http://axschema.org/namePerson/first", true);
fetch.addAttribute("LastName", "http://axschema.org/namePerson/last", true);
fetch.addAttribute("Country", "http://axschema.org/contact/country/home", true);
fetch.addAttribute("Lang", "http://axschema.org/pref/language", true);

authReq.addExtension(fetch);
if (authSuccess.hasExtension(OPENID_NS_AX)) {

MessageExtension ext = authSuccess.getExtension(OPENID_NS_AX);

if (ext instanceof FetchResponse) {

FetchResponse fetch = (FetchResponse) ext;

request.setAttribute("EMAIL", fetch.getAttributeValue("Email"));
request.setAttribute("FIRST_NAME", fetch.getAttributeValue("FirstName"));
request.setAttribute("LAST_NAME", fetch.getAttributeValue("LastName"));
request.setAttribute("COUNTRY", fetch.getAttributeValue("Country"));
request.setAttribute("LANG", fetch.getAttributeValue("Lang"));
}
}

С OpenId и OpenId4Java использование федерации удостоверений действительно занимает считанные минуты!

Здесь вы найдете источники примера проекта в формате Eclipse / Maven.

Чтобы идти дальше:

От http://blog.frankel.ch/identity-federation-and-openid