如何检查调用者是否属于 WebAPI 层中的 AD 安全组?

How to check caller is part of AD Security group in WebAPI layer?

我有一个网站 (WebApp),我从那里对接受 JWT Bearer Token 身份验证的 WebAPI 层进行 Ajax 调用。我已经将 Adal.js 集成到我的前端脚本层中,配置值如下所示。

var config = {
instance: "https://login.microsoftonline.com/",
tenant: "tenant.com",
clientId: "CLIENT_ID OF THE PORTAL APP", // Web-Portal app
redirectUri: "http://localhost:8241/",
popUp: true,
cacheLocation: "localStorage" };

WebApiConfig 如下所示:

var webApiConfig = {
    resourceId: "CLIENT_ID OF API APP", // Web-API app
    resourceBaseAddress: "http://localhost:9020/"
};

一切正常,我能够 authenticate/authorize 并通过隐式 oauth 流的访问令牌调用我的 webapi。

现在我希望能够检索登录用户的用户安全组成员值,以便 在 WebAPI 层 ,我可以作为授权逻辑的一部分,确保用户属于特定的安全组。因此,我在 Azure AD 的应用程序清单 xml 中设置了 GroupMembershipClaims: "SecurityGroup"(我首先为 WebApi 应用程序清单执行此操作,但随后也在 WebApp 应用程序清单中)。

但是,GroupMembershipClaims 似乎只包含在 idtoken 中, accessToken。鉴于它是发送到 WebAPI 的 accessToken,我无法在该层进行此检查。我想我可以在 WebApp 层进行检查,但是考虑到这个 WebApi 层将从许多其他前端应用程序(不属于我,我主要是 "API provider")调用,这不是一个安全的解决方案.

那我该如何解决呢?我想一种方法是使用 WebApi 层上的 "on-behalf-of" 流来调用 Graph API 来找出这个?恐怕这将需要比用户范围内可用的权限更多的权限。

谢谢!

这是个好问题。

我的第一个想法是 "well you can get them from Graph API",但我看你已经想到了 :)

如果你想这样做,你可以像你说的那样使用On-behalf-of,在MS Graph API上使用这个操作:https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/user_getmembergroups。 您将需要这些委托权限:User.Read 和 Group.Read.All。 因此,除了基本 User.Read.

之外,您还需要获得读取所有组的权限

还有其他几个选项。

您可以在 API 中定义角色。 我写了一篇关于如何做到这一点的文章:Defining permission scopes and roles offered by an app in Azure AD。 因此,如果您在 API 的清单中定义这样的角色:

{
  "appRoles": [
    {
      "allowedMemberTypes": [
        "User"
      ],
      "displayName": "Administrator",
      "id": "179c1dc0-4801-46f3-bc0d-35f059da1415",
      "isEnabled": true,
      "description": "Administrators can access advanced features.",
      "value": "admin"
    }
  ]
}

您需要为每个角色设置唯一的 GUID,您可以为此使用在线生成器或 PowerShell [System.Guid]::NewGuid()

然后可以将这些角色分配给用户,如果您至少拥有 Azure AD Basic,则可以将它们分配给组。 角色包含在访问令牌中,因此您可以在 API.

中轻松检查这些内容

我的另一个想法是让 API 和 front-end 在 Azure AD 中使用相同的注册应用程序。 通过这种方式,您可以将 Id 令牌而不是访问令牌传递给 API,并且您将获得这些组。 但由于您可能还有其他 front-end,我怀疑这是否适合您。