如何在消费者使用声明身份验证时保护 API

How to secure an API when the consumer uses claims authentication

背景

我正在构建一个 .NET MVC 企业 Web 应用程序,它必须能够对来自不同公司的用户进行身份验证。其中一项主要要求是确保用户无需创建和记住新凭据即可使用该应用程序,相反,他们应该继续使用他们用于访问公司内联网中的应用程序的任何凭据。

由于应用程序将托管在 Extranet 上并且需要处理针对多个域(即多个 Active Directory)的身份验证,我们希望每个客户端都设置应用程序可以连接的安全令牌服务 (AD FS)用于实施声明身份验证。

MVC 应用程序将检查用户是否已通过身份验证,如果未通过身份验证,则启动以 MVC 应用程序结束的工作流,该应用程序将获得与用户关联的 SAML 声明。

问题

此时,用户已通过身份验证并获得对 MVC 应用程序的访问权限。但是,该应用程序本身是一个现代 Web 应用程序,它使用相当多的 JavaScript 来使用处理大部分业务逻辑的 .NET Web API。 我的主要问题是如何保护这个 API。我想确保发送到此服务器的唯一请求是从有效来源发送的,并且使用该服务的用户有权这样做。

当前解决方案

我可以采用两种方法来使用 API:

  1. 直接来自JavaScript(首选解决方案)
  2. 通过 MVC 服务器路由请求,然后将其转发到 API。

为了选择一种方法,我首先需要找到一种方法来保护 API。

HMAC 认证

我发现的最直接的解决方案是 HMAC 身份验证 - http://bitoftech.net/2014/12/15/secure-asp-net-web-api-using-api-key-authentication-hmac-authentication/。但是,此方法要求所有 API 请求直接来自 MVC 服务器,因为密钥需要位于 MVC 服务器上。

OAuth 2.0

我可以实施的第二种方法是 OAuth 2.0 的某种风格。我熟悉的口味可以在这里找到 http://alexbilbie.com/guide-to-oauth-2-grants/:

授权码授予

这不是我想要采用的方法。 MVC 应用程序已经收到用户的声明 - 他们不应该仅仅因为 API 需要声明而再次这样做。 (我有一个后续问题询问我是否可以简单地将声明传递给 API 服务器)

隐式授权

我喜欢这种方法听起来的方式,因为我将能够在客户端执行 API 请求(即 JavaScript 代码),但是它遇到与第一种方法相同的问题.

资源所有者凭据授予

这种方法是不可能的 - 我不希望 MVC 应用程序或 API 保留用户的凭据。

客户端凭据授予

此方法是列出的唯一合理的 OAuth 方法 - 但是我看不出此方法与上面详述的 HMAC 身份验证之间的主要区别。

问题

  1. 我是否正确设置了 MVC 应用程序的身份验证结构?具体来说,在这种情况下,让 AD FS 处理身份验证并使用代表用户声明的 SAML 令牌进行响应是否合适?
  2. 我计划将用户数据存储在服务器的会话中。我还可以在会话中存储用户的声明,然后以某种方式将其发送到 API 进行身份验证吗?
  3. 如果我可以将声明从MVC服务器传递给API服务器,并且API服务器可以正确验证请求,是吗安全地将声明传递给客户端(浏览器/JS 代码)以便使用 API 可以绕过 MVC 服务器?
  4. HMAC 身份验证方法是最好的方法吗?
  1. 是的,使用 ADFS 或任何 IdP 产品作为应用程序的 IdP 是实施 SSO 的好方法。这样做可以帮助您将所有联合访问管理以及声明规则委派给 ADFS。
  2. 是的,您可以在会话中存储声明并以某种方式将它们发送到 WebAPI。请注意,如果您使用的是 WIF,它已将声明存储在 Thread.CurrentPrincipal 中作为 ClaimsPrincipal 对象。另一件事是,我假设您只想以某种方式仅发送声明,而不是整个 SAML2 令牌。
  3. 我会说它与您用来保护客户端令牌的机制一样安全。查看 https://auth0.com/blog/ten-things-you-should-know-about-tokens-and-cookies/ and https://security.stackexchange.com/questions/80727/best-place-to-store-authentication-tokens-client-side 了解更多详情。
  4. 我不能说它是否最适合您,但它似乎是一种可行的方式,因为您也可以控制 WebAPI。但是,似乎使用 JWT 令牌会更容易:https://vosseburchttechblog.azurewebsites.net/index.php/2015/09/19/generating-and-consuming-json-web-tokens-with-net/. Talking about JWT token, you can also ask ADFS to issue it for you: https://blogs.technet.microsoft.com/maheshu/2015/05/26/json-web-token-jwt-support-in-adfs/.