Подтвердить что ты не робот

Spring Безопасность и миграция Google OpenID Connect

Вопросы:

1) Какой лучший способ интегрировать аутентификацию OpenID Connect в веб-приложение, использующее Spring Безопасность для аутентификации?

2) Есть ли какой-либо способ - либо из MITREid стороны, либо из стороны в аккаунтах Google - получить фильтр проверки подлинности MITREid OpenID Connect работать с сервисом Google OpenID Connect?

Я уверен, что ответы на эти вопросы будут полезны для любого разработчика, который использует модуль OpenID модуля Spring для аутентификации с Google.

Деталь:

Мой webapp использует Spring модуль безопасности OpenID (<openid-login .../>) для аутентификации с учетными записями Google в качестве поставщика удостоверений. т.е. пользователи аутентифицируются с использованием своего адреса Google Apps или GMail.

В последнее время, когда пользователи аутентифицируются, они получают это предупреждение от учетных записей Google:

Важное замечание: OpenID2 для аккаунтов Google уходит в апреле 20, 2015 г.

Таким образом, Google отказывается от поддержки OpenID, полностью отключит его в апреле 2015 года и заявляет, что вы должны перейти на протокол OpenID Connect, если хотите выполнить аутентификацию с помощью учетных записей Google.

Я надеялся, что Spring У безопасности будет встроенная поддержка OpenID Connect, так же как и встроенная поддержка OpenID. например что-то вроде элемента <openid-connect-login .../>. Но мои поиски не получили такой поддержки.

Лучшим кандидатом, который я нашел до сих пор, является MITREid Connect. Он включает в себя Spring фильтр проверки подлинности безопасности с именем OIDCAuthenticationFilter для OpenID Connect. Проблема в том, что она не взаимодействует с реализацией Google OpenID Connect.

Я попробовал клонирование простого веб-приложения MITREid и настроил его для аутентификации (с помощью OpenID Connect) с учетными записями Google. Но это не сработало, потому что это зависит от nonce, которую не поддерживает реализация Google OpenID Connect. Сообщение об ошибке из аккаунтов Google:

Параметр, не разрешенный для этого типа сообщения: nonce

Далее я попытался подключить собственную реализацию интерфейса MITREid AuthRequestUrlBuilder в конфигурацию MITREid. Единственная разница между моей реализацией и реализацией MITREid заключалась в том, что я не отправил nonce.

Не отправляя незапланированную реализацию Google OpenID Connect счастливой, но MITREid выбрал исключение, если не смог найти nonce в ответе проверки подлинности Google. Сообщение об ошибке:

Ошибка аутентификации: токен идентификатора не содержит требования nonce

Я отслеживал исключение MITREid до этих строк в MITREID OIDCAuthenticationFilter:

// compare the nonce to our stored claim
String nonce = idClaims.getStringClaim("nonce");
if (Strings.isNullOrEmpty(nonce)) {

    logger.error("ID token did not contain a nonce claim.");

    throw new AuthenticationServiceException("ID token did not contain a nonce claim.");
}

Но мне не удастся расширить реализацию MITREid, чтобы игнорировать nonce. Так близко, но пока! Если учетные записи Google согласятся с тем, что nonce или MITREid могут быть настроены на игнорирование nonce, тогда у нас будет решение.

В списке проблем MITREid Connect в github я обнаружил, что другие сталкиваются с подобными проблемами:

1) # 726 - Документация по использованию клиента с Google в качестве поставщика проверки подлинности

2) # 704 - добавьте атрибут useNonce в ServerConfiguration, чтобы указать, принимает ли IdP значение nonce в свои запросы.

Итак, я застрял. Приезжайте в апреле 2015 г. Google завершит проверку подлинности Open ID.

Некоторые релевантные ссылки:

1) https://support.google.com/accounts/answer/6135882

2) https://www.tbray.org/ongoing/When/201x/2014/03/01/OpenID-Connect

3) https://github.com/mitreid-connect

4) https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/blob/master/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java

5) https://github.com/mitreid-connect/simple-web-app

6) https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/blob/master/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/PlainAuthRequestUrlBuilder.java

7) https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/issues/726

8) https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/pull/704


2015-02-18 Обновление

Функциональность недавно была добавлена ​​в ветку разработки mitreid-connect для отключения nonce - поэтому делает OIDC-сервер Google счастливым. К счастью, mitreid-connect также предоставил некоторые рекомендации по взаимодействию с Google. К сожалению, изменение "nonceEnabled" пока недоступно в Maven, но, надеюсь, это скоро изменится.

4b9b3361

Ответ 1

AFAIK, нет чистой и легкой Spring миграции безопасности с OpenID на аутентификацию OpenID Connect. Внедрение аутентификации OpenID с помощью Spring Безопасность выполняется с использованием хорошо документированного <openid-login/>, но для OpenID Connect не существует аналога.

альтернатива MITREid все еще находится на ветке разработки и недоступна в Maven Central и, следовательно, не является кандидатом.

В комментариях Чак Мах указывает на Как реализовать OpenID-соединение и Spring Безопасность, где Romain F. предоставляет пример кода.

Образец кода Romain указал мне в правильном направлении. Это время заканчивается, я пошел с романтическим подходом, который должен был написать пользовательский Spring Security AuthenticationFilter, который использует spring -security-oauth2 для запроса oauth2 api конечная точка userinfo (для Google это https://www.googleapis.com/oauth2/v2/userinfo). Предполагается, что если мы сможем успешно запросить конечную точку userinfo, пользователь успешно завершит аутентификацию, чтобы мы могли доверять возвращенной информации - например, адрес электронной почты пользователя.

Когда я впервые начал изучать OpenID Connect, "центральным понятием стала" . Однако, просматривая исходный код spring -security-oauth2, он, похоже, игнорируется. Это приводит к вопросу, какова точка маркера ID, если мы можем аутентифицироваться без него (просто запросив конечную точку oauth2 userinfo)?

Минималистское решение, которое я бы предпочел, просто вернет проверенный токен ID. Не было бы необходимости запрашивать конечную точку userinfo. Но такого решения не существует в виде фильтра проверки подлинности Spring.

Мой webapp не был spring -boot-приложением, таким как romain. spring -boot делает много конфигурации за кулисами. Вот некоторые из проблем/решений, с которыми я столкнулся на этом пути:

  • проблема: статус HTTP 403 - ожидаемый токен CSRF не найден. Срок действия вашего сеанса истек?

    • Решение: java config: httpSecurity.csrf(). disable()
  • проблема: статус HTTP 500 - ошибка при создании bean с именем 'scopedTarget.googleOAuth2RestTemplate': Scope 'session' неактивен для текущего потока;

    • Решение: java config: OAuth2RestTemplate не обязательно должен быть областью сеанса (OAuth2ClientContext уже имеет сеанс и что все, что необходимо)
  • Проблема: HTTP Status 500 - Ошибка при создании bean с именем 'scopedTarget.oauth2ClientContext': Scope 'session' неактивен для текущего потока;

    • solution: web.xml: добавить RequestContextListener
    • : потому что доступ к oauth2ClientContext с сеансом bean осуществляется за пределами области Spring MVC DispatcherServlet (к нему обращаются из OpenIdConnectAuthenticationFilter, который является частью цепочки фильтров Spring).
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    
  • Проблема: org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: для получения одобрения пользователей требуется перенаправление.

    • solution: web.xml: добавьте определение фильтра сразу. PRECEEDING springSecurityFilterChain
    <filter>
        <filter-name>oauth2ClientContextFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>oauth2ClientContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

К сожалению, OpenID Connect не позволяет нам запрашивать область email. Когда наши пользователи прошли аутентификацию с помощью OpenID, они увидели бы экран согласия, например "webapp хотел бы просмотреть ваш адрес электронной почты", с которым им было удобно. Теперь мы должны запросить области openid email, в результате чего появится экран согласия с просьбой предоставить нам общий доступ к нашему общедоступному профилю... который нам действительно не нужен или хочет... и пользователи менее удобны с этим экраном согласия.