Azure 上的状态无效,但在本地工作

Invalid state on azure, but working locally

我有一个 Azure Active Directory 租户,我希望通过 Azure 应用服务实例上的 Node.js 应用程序 运行 对其进行身份验证。我正在使用 passportjs 和 passport-azure-ad 来执行此操作。

本地一切正常。我可以使用 Azure AD 租户进行身份验证,它 returns 正确返回我的页面。但是在 Azure 上它失败并显示错误:

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

我的配置完全相同(除了 redirectUrl),因为我使用相同的租户进行本地测试以及在 Azure 中,但它仍然失败。我已经设置了正确的回复 url 和身份验证 returns 回到我的应用程序。

这是我的配置:

{
  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'
}

我正在使用 OIDCStrategy。

我的认证中间件:

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

我比较了 authorize 请求的编码状态与返回的响应,它们在本地和 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 header。 session 已创建,但未设置 cookie,因此返回响应无法查找 session 信息(包括状态)并进行比较。结果是它报告无效状态,因为它无法从 session.

检索数据

这是模块 passport-azure-ad 的一个已知编码问题。参见:

您可以将模块版本升级到 v3.0.7 或更高版本来修复它。

原来问题是 session 从未正确创建,因此 process-azure-ad 没有状态可供比较。这样做的原因是我已将 express-session 配置为使用安全 session cookie,因为我是通过 https://...azurewebsites.net 地址连接的,所以连接是安全的。但这在技术上并非如此。

Azure 运行 是 Web 应用程序前面的负载平衡器,有效代理从外部到我的应用程序的连接。此代理是安全连接终止的地方,然后流量未加密地路由到我的应用程序。

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

结果是节点没有将连接报告为安全连接,除非设置配置选项 trust proxy:

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

设置此选项后,express 将检查 X-Forwarded-Proto header 使用哪个协议连接到代理服务器(在本例中为负载平衡器)。此 header 包含 http 或 https,具体取决于连接协议。

对于 Azure,这仍然不够。 Azure 负载均衡器也不设置 X-Forwarded-Proto header。相反,它使用 x-arr-ssl。这不是一个大问题,因为 iisnode(运行我在 Azure IIS 上使用 运行 节点的时间)有一个名为 enableXFF 的选项,它将更新 X-Forwarded-Proto header 基于连接的外部协议。设置这两个选项可以让 express-session 设置安全 cookie,保持 session 存储并允许 passport-azure-ad 存储和比较身份验证状态信息。

PS:非常感谢 Scott Smiths 的博客和提供答案的评论: http://scottksmith.com/blog/2014/08/22/using-secure-cookies-in-node-on-azure/