Azure AD多租户应用程序-如何实施令牌验证?

时间:2018-09-15 18:47:23

标签: azure oauth oauth-2.0 azure-active-directory azure-web-sites

我在Azure广告中注册了一个多租户 Web应用/ API ,并且已将其连接到API应用。 API应用具有Active Directory身份验证设置。目前,只有一个租户需要访问api。我通过将https://sts.windows.net/<third party tenant>/放在发行者URL 中来确保只有他们才能访问。我的问题是:我应该如何让第二个(或更多)租户访问api?我再也无法在发行人URL 中添加租户ID,所以我有点不知所措

谢谢

1 个答案:

答案 0 :(得分:2)

您当前使用的方法仅适用于单个租户方案,即通过设置IssuerURL自动验证租户仅适用于单个租户方案。

对于多租户应用程序,该应用程序负责存储和验证所有可能的发行者。这是设计目的,有关Microsoft有关此主题的确切指南,请参见此处:

Work with claims-based identities in Azure AD: Issuer Validation

  

对于单租户应用程序,您只需检查发行者是否为   您自己的租户。实际上,OIDC中间件会自动执行此操作   默认情况下。在多租户应用中,您需要允许多个   发行人,对应于不同的租户。这是一般   使用方法:

     
      
  • 在OIDC中间件选项中,将ValidateIssuer设置为false。这将关闭自动检查。
  •   
  • 租户签署后,将租户和发行方存储在用户数据库中。
  •   
  • 无论何时用户登录,都要在数据库中查找发行人,如果未找到发行人,则意味着租户尚未注册。您   可以将他们重定向到注册页面。
  •   
  • 您还可以将某些租户列入黑名单;例如,针对未付费订阅的客户。
  •   

因此,在基于.NET的Web应用程序中,启动类中的代码将更改为类似的内容。.请注意 new TokenValidationParameters {ValidateIssuer = false

Authenticate using Azure AD and OpenID Connect

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions {
    ClientId = configOptions.AzureAd.ClientId,
    ClientSecret = configOptions.AzureAd.ClientSecret, // for code flow
    Authority = Constants.AuthEndpointPrefix,
    ResponseType = OpenIdConnectResponseType.CodeIdToken,
    PostLogoutRedirectUri = configOptions.AzureAd.PostLogoutRedirectUri,
    SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme,
    TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false },
    Events = new SurveyAuthenticationEvents(configOptions.AzureAd, loggerFactory),
});

一旦您禁用了验证发行者,您将需要自己处理验证。这是一个示例,其中包含一些有关如何自己进行验证的指南

Update your code to handle multiple issuer values

在让呼叫通过之前,您至少需要对照您自己的有效租户ID列表检查捕获“ Azure AD租户ID”的“ tid”声明。

  

当单个租户应用程序验证令牌时,它会检查   根据元数据中的签名密钥对令牌进行签名   文档,并确保令牌中的发行者值与   在元数据文档中找到的。

     

由于/ common端点与租户不对应,因此不是   发行者,当您检查元数据中的/ common发行者值时   它具有模板网址,而不是实际值:

     

https://sts.windows.net/ {tenantid} /

     

因此,多租户应用程序不能仅通过以下方式验证令牌   将元数据中的发行者值与   令牌。多租户应用程序需要逻辑来决定哪个发行者   值是有效的,而无效的则基于的租户ID部分   发行人的价值。

     

例如,如果多租户应用程序仅允许从   签署了服务的特定租户,则必须   检查令牌中的发行者值或tid声明值以   确保租户在其订户列表中。如果一个   多租户应用程序仅与个人打交道,而不会   任何基于租户的访问决策,那么它都可以忽略发行者   完全有价值。

(编辑)有关验证令牌的更多信息 我正在尝试通过此处的评论回答您的问题。

  1. 这是示例代码,它执行手动验证JWT令牌的任务。 Manually validating a JWT access token in a web API

enter image description here

有用的摘录。

  

验证声明,当应用程序收到访问令牌时   用户登录后,还应针对   在访问令牌中声明。这些验证包括但不包括   限于:

     

受众声明,以验证是否打算提供ID令牌   到您的申请之前并没有“到期时间”声明,以验证   该ID令牌尚未过期的发行人声明,以验证   令牌是由v2.0端点随机数作为令牌发布给您的应用的   重播缓解攻击建议您使用标准库   诸如JwtSecurityTokenHandler.ValidateToken方法的方法   (JwtSecurityToken)做大部分上述繁重的工作。您   通过基于以下因素做出决策,可以进一步扩展验证过程   令牌中收到的索赔。例如,多租户应用程序   可以通过检查tid的值来扩展标准验证   针对一组预先选择的租户声明(租户ID),以确保他们   只能从他们选择的租户中荣誉令牌。

  1. 样本访问令牌,仅用于理解:访问令牌和Id_token都是简单的base64编码的JSON Web令牌(JWT)。您可以对它们进行解码以找到声明,然后对其进行验证。我正在共享一个示例,该示例具有执行此操作的代码。在此之前,这里是来自Microsoft Docs的示例访问令牌。我只是以here
  2. 为例

实际值:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1N ...(长编码字符串继续) 解码值(您可以使用https://jwt.io之类的网站轻松检查此内容):

{
  "aud": "https://service.contoso.com/",
  "iss": "https://sts.windows.net/7fe81447-da57-4385-becb-6de57f21477e/",
  "iat": 1388440863,
  "nbf": 1388440863,
  "exp": 1388444763,
  "ver": "1.0",
  "tid": "7fe81447-da57-4385-becb-6de57f21477e",
  "oid": "68389ae2-62fa-4b18-91fe-53dd109d74f5",
  "upn": "frankm@contoso.com",
  "unique_name": "frankm@contoso.com",
  "sub": "deNqIj9IOE9PWJWbHsftXt2EabPVl0Cj8QAmefRLV98",
  "family_name": "Miller",
  "given_name": "Frank",
  "appid": "2d4d11a2-f814-46a7-890a-274a72a7309e",
  "appidacr": "0",
  "scp": "user_impersonation",
  "acr": "1"
}

如您所见,解码后的值包含许多要验证的声明,包括“ tid”。

希望这会有所帮助!