Неверное состояние на лазурном, но работает локально

У меня есть клиент Azure Active Directory, с которым я хочу пройти аутентификацию из своего приложения Node.js, работающего в экземпляре службы приложений Azure. Для этого я использую passportjs и passport-azure-ad.

Локально все отлично работает. Я могу пройти проверку подлинности с клиентом Azure AD, и он вернется на мою страницу правильно. Однако в Azure происходит сбой с ошибкой:

authentication failed due to: In collectInfoFromReq: invalid state received in the request

Моя конфигурация точно такая же (кроме redirectUrl), что я использую тот же клиент для локального тестирования, как и в Azure, но все равно не удается. Я настроил правильные URL-адреса ответа, и аутентификация возвращается к моему приложению.

Вот мой конфиг:

{
  identityMetadata: `https://login.microsoftonline.com/${tenantId}/.well-known/openid-configuration`,
  clientID: `${clientId}`,
  responseType: 'id_token',
  responseMode: 'form_post',
  redirectUrl: 'https://localhost:3000/auth/oidc/return',
  allowHttpForRedirectUrl: false,
  scope: [ 'openid' ],
  isB2C: false,
  passReqToCallback: true,
  loggingLevel: 'info'
}

Я использую стратегию OIDC.

Мое промежуточное ПО аутентификации:

passport.authenticate('azuread-openidconnect', {
  response: res,
  failureRedirect: '/auth/error',
  customState: '/'
});

Я сравнил закодированное состояние на authorizerequest против возвращенного ответа, и они отличаются так же локально, как и в Azure, однако Azure - единственная жалоба. Примеры того, как различаются состояния:

Azure:
Request state:  CUSTOMEwAuZcY7VypgbKQlwlUHwyO18lnzaYGt%20
Response state: CUSTOMEwAuZcY7VypgbKQlwlUHwyO18lnzaYGt

localhost:
Request state:  CUSTOMTAYOz2pBQt332oKkJDGqRKs_wAo90Pny%2F
Response state: CUSTOMTAYOz2pBQt332oKkJDGqRKs_wAo90Pny/

Я также попытался полностью удалить customState, но все равно не получилось.

Кто-нибудь знает, что здесь происходит? Я неправильно его настраиваю?

Изменить: Похоже, что это не может быть проблемой с passport-azure-ad. Я еще не уверен, но некоторая отладка показала, что в запросе на вход в мое приложение нет заголовка set-cookie. Сеанс создан, но файл cookie не установлен, поэтому возвращающий ответ не может найти информацию о сеансе, включая состояние, и сравнить их. В результате он сообщает о недопустимом состоянии, поскольку не может получить данные из сеанса.

2 ответа

Решение

Оказывается, проблема была в том, что сеанс никогда не создавался должным образом, поэтому не было состояния для process-azure-ad сравнивать. Причиной этого было то, что я настроил express-session использовать безопасные сеансовые файлы cookie при условии, что, поскольку я подключался через адрес https://...azurewebsites.net, соединение было безопасным. Технически это не так, хотя.

Azure запускает балансировщик нагрузки перед веб-приложением, эффективно проксируя подключения извне к моему приложению. Этот прокси-сервер обеспечивает безопасное соединение, после чего трафик направляется в мое приложение в незашифрованном виде.

Browser -(HTTPS)> Load balancer -(HTTP)> Application

В результате узел не сообщил о безопасном соединении, если не задан параметр конфигурации. trust proxy:

app.set('trust proxy', true);

Когда эта опция установлена, экспресс проверит X-Forwarded-Proto заголовок, для которого был использован протокол для подключения к прокси-серверу (в данном случае балансировщик нагрузки). Этот заголовок содержит http или https в зависимости от протокола соединения.

Однако для Azure этого еще недостаточно. Балансировщик нагрузки Azure не устанавливает X-Forwarded-Proto заголовок тоже. Вместо этого он использует x-arr-ssl, Это не большая проблема, хотя, поскольку iisnode (среда выполнения, которую я использую для запуска узла в IIS в Azure), имеет опцию под названием enableXFF это обновит X-Forwarded-Proto заголовок на основе внешнего протокола соединения. Установка обоих этих параметров позволяет express-session установить безопасный cookie, сохраняя сеанс и позволяя passport-azure-ad хранить и сравнивать информацию о состоянии аутентификации.

PS: Большое спасибо блогу Скотта Смита + комментарии за предоставление ответа: http://scottksmith.com/blog/2014/08/22/using-secure-cookies-in-node-on-azure/

Это известная проблема кодирования с модулем passport-azure-ad, Увидеть:

  • "State" gets encoded and causes "collectInfoFromReq: invalid state received" #309
  • "invalid state received in the request" causing infinite loop on Login #247

Вы можете обновить версию модуля до v3.0.7 или более новый, чтобы исправить это.

Другие вопросы по тегам