首页 > 解决方案 > 如何使用 Open ID Connect 和 Azure AD 对站点和两个可重用的 Web 服务进行身份验证?

问题描述

我正在使用 ASP.NET Core Web 应用程序(顺便说一下,在 Blazor 中)构建一个系统,我们将其称为“站点”,以及一些域 Web 服务(有朝一日可能会被其他站点使用),其中一个称为“CustomerService” ”。

遵循有关如何使用 Open ID Connect 和 Azure Active Directory 为该系统设置身份验证的各种指南和文章,我看到了以下可能的不同身份验证和授权方法,尤其是关于 AJAX 请求:

  1. Site-only auth, passthrough:服务信任站点;站点对用户进行身份验证。
  2. Service-only auth, passthrough:服务对用户进行身份验证;站点通过所有 AJAX 请求。
  3. Service-only auth,CORS服务通过 CORS 提供站点客户端数据,带有身份验证;站点根本不处理 AJAX 请求。
  4. Service and site auth, passthrough:服务和站点都验证用户;站点通过一些 AJAX 请求。

这些似乎都存在重大的实际问题。 是否有第五种方法,或者我应该考虑的一种变化?

这是我对这些方法的详细说明。

(1)服务信任本站;网站验证用户

(1a) 设置 Site.Server 以使用 Open ID Connect 进行用户身份验证,在 Site.Server 上实施所有必要的授权,将 Web API 调用传递给 CustomerService,并设置 CustomerService 以信任来自 Site.Server 的请求。这看起来是个坏主意,因为这样任何用户都可以欺骗 Site.Server 并拥有对应在 CustomerService 上保护的操作的完全访问权限。此外,CustomerService 将无法强制执行授权;我们会相信 Site.Server 能把它做好,这似乎不是最理想的。

(1b) 与 (1a) 相同,但 Site.Server 会知道一个秘密的 API 密钥,该密钥将在标头或 API 调用的查询字符串或正文中传递给 CustomerService。这似乎不太好,因为 API 密钥永远不会改变,然后任何用户都可以发现和欺骗。尽管如此,这仍然可行,因为 API 密钥可以保密,我们可以使用双方的秘密服务器来检索它。但是 CustomerService 仍然无法强制执行授权;我们会相信 Site.Server 能把它做好,这似乎不是最理想的。

(1c) 与 (1b) 相同,但我们提出了一种偶尔轮换 API 密钥的机制。这似乎不太好,因为 API 密钥会更改,然后可能被任何用户发现和欺骗。尽管如此,这仍然可行,因为 API 密钥可以保密,我们可以使用双方的秘密服务器来检索它。但是 CustomerService 仍然无法强制执行授权;我们会相信 Site.Server 能把它做好,这似乎不是最理想的。

(2)服务对用户进行身份验证;站点通过所有 AJAX 请求:避免在 Site.Server 上进行任何身份验证,而是仅通过 Open ID Connect+Azure AD 对 CustomerService 执行授权/身份验证。Site.Server 必须将包括标头在内的请求传递给 CustomerService。这样做的好处是将安全性放在正确的位置,但这似乎不可行,因为用户没有直接使用 CustomerService,因此用户无法在 CustomerService 上进行身份验证;他们的 AJAX 请求仍然发送到 Site.Server。

(3)服务通过 CORS 提供站点客户端数据,并进行身份验证;站点根本不处理 AJAX 请求:避免在 Site.Server 上进行任何身份验证,而是使用 CORS 允许用户的浏览器直接连接到 CustomerService,只需要通过 Open ID Connect+Azure AD 进行身份验证。这样做的好处是将安全性放在正确的位置,但是用户如何在 AJAX 请求上进行身份验证而不首先以人类可浏览的方式进行身份验证呢?我的 AJAX 请求无法重定向到 microsoftonline 并提示用户,可以吗?另外,CORS 总体上似乎是个坏主意——我们希望摆脱跨站点的任何东西;对用户来说,看起来 Site.Server 应该同时提供 AJAX 调用和 HTML 页面请求,对吧?

(4)服务和站点都验证用户;站点通过一些 AJAX 请求。使用相同的应用 ID 在 Site.Server 和 CustomerService 上进行身份验证,使它们在 Azure AD 所知的情况下显示为同一个站点。Site.Server 可以进行自己的身份验证并限制某些服务调用访问 CustomerService,或者它可以将请求(包括标头)传递给 CustomerService,然后它也可以拒绝或授予访问权限。这是我们决定做的,但我现在质疑它,好像我添加了第二个服务,现在它必须再次拥有相同的应用程序 ID 才能保持这种方法。

这些方法似乎都没有达到目标。我是否错过了我应该考虑的另一种方法?还是有我遗漏的变化?

标签: asp.net-coreauthenticationarchitectureazure-active-directoryopenid-connect

解决方案


以下是我对选项 5 的看法:

网页界面

代码在浏览器中运行并与授权服务器交互以对用户进行身份验证。诸如OIDC Client之类的库会为您完成安全工作。

提供最佳可用性和最简单的代码。UI 使用访问令牌来调用跨域 API。不过,更新令牌很棘手,而且浏览器安全需要一些尽职调查。

网页后端

仅是静态内容,部署在世界各地靠近最终用户的地方 - 可能通过 Azure CDN。必须执行零代码。提供最佳性能。

WEB UI 与移动 UI 相同

实际上,您的 Web UI 以与移动 UI 相同的方式运行,并且相当简单,对 cookie + 双跳的需求更少。

入口点 API

浏览器 UI 与为 UI 消费者定制的入口点 API 交互。此 API 通过下载 Azure AD 令牌签名密钥来验证令牌。它在授权请求方面也有第一发言权。

入口点 API 协调对核心 API 和 Azure API(如 Graph)的调用。Web UI 使用单一令牌范围为入口点 API,您可以严格控制 UI 的权限。同时,API 可以使用 Azure AD 的“代表”功能来获取下游 API 的令牌,因此 UI 不需要处理这个问题。

域 API

这些通常在锁定的私有云中运行,不会被外界直接调用。这使您可以更密切地控制哪些类型的调用者可以调用哪些高权限操作。

我的博客文章

我的博客的索引页面包含有关这些模式及其背后目标的更多信息。也许浏览一下 SPA 目标和 API 平台架构帖子。

此页面上有一些工作代码示例。在我的情况下,托管使用 AWS 而不是 Azure,尽管概念是相同的。


推荐阅读