Angularjs 授权的附加声明或属性

Angularjs Adal and additional claims or properties for Authorization

场景是 Angularjs 带有 c# WebApi 的 1.6.5 应用程序。使用 angular-adal.jsAAD 进行身份验证。到目前为止,一切正常,因为用户可以通过 AAD 登录并且 WebApi 接受令牌。

对于这个特定的应用程序,角色位于外部应用程序中,WebApi 可以访问该应用程序。我已经能够使用 WindowsAzureActiveDirectoryBearerAuthenticationOptions 添加角色声明(在从外部应用程序获取它们之后),并在 ConfigureOAuth(IAppBuilder app) 中使用以下代码:

app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
   TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
   {
       ValidAudience = clientId
   },
   //Audience = ConfigurationManager.AppSettings["ida:ClientID"],
   Tenant = tenant,


   Provider = new OAuthBearerAuthenticationProvider
   {
       OnValidateIdentity = async context =>
     {
         // Retrieve user JWT token from request.
         var authorizationHeader = context.Request.Headers["Authorization"];
         var userJwtToken = authorizationHeader.Substring("Bearer ".Length).Trim();

         // Get current user identity from authentication ticket.
         var authenticationTicket = context.Ticket;
         var identity = authenticationTicket.Identity;

         if (identity.FindFirst(System.Security.Claims.ClaimTypes.Role) == null)
         {
             var user = identity.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn").Value;

             Cis.bll.Xrm.bllSystemUserRoles bllSystemUserRoles = new Cis.bll.Xrm.bllSystemUserRoles();
             var su = bllSystemUserRoles.getByEmail(user);
             //var roleClaim = new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, su.stringRoles);
             foreach (var item in su.Roles)
             {
                 identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, item.xrmName));
             }
         }
     }
   }
});

因此对于 Angularjs 对 API 执行的每个 httpRequest,前面的函数查找用户的角色并添加角色声明。通过此实现,我可以在 Controller 方法中使用 AuthorizeAttribute,将访问权限限制为仅某些角色,如下所示:

[CustomAuthorize(Constants.Roles.resourcesAdministrator)]

我发现这种方式非常低效,因为对于每个 httpRequest,API 必须从数据库中获取用户的角色(或任何实现的持久化方式)。

我想做的是只读取用户角色一次,然后能够在 API 每个后续请求中使用它们。有没有办法在我们收到 AAD 的令牌后将声明添加到令牌?

顺便说一句,我可以为每个模型添加一个角色 属性 或类似的东西,但这不是我想要的。

如果您有任何其他想法或建议,我们将不胜感激。

此致

令牌已颁发,无法修改。而且由于角色存储在其他应用程序中,我认为不查询数据库就不可能获得角色。

在这种情况下,我们可以通过 Azure AD 应用程序角色和角色声明来管理角色。然后它将在 id_token 中发出 roles 声明。

例如,我们可以像下面这样修改应用程序的清单:

"appRoles": [
    {
      "allowedMemberTypes": [
        "User"
      ],
      "displayName": "Writer",
      "id": "d1c2ade8-98f8-45fd-aa4a-6d06b947c66f",
      "isEnabled": true,
      "description": "Writers Have the ability to create tasks.",
      "value": "Writer"
    },
    {
      "allowedMemberTypes": [
        "User"
      ],
      "displayName": "Observer",
      "id": "fcac0bdb-e45d-4cfc-9733-fbea156da358",
      "isEnabled": true,
      "description": "Observers only have the ability to view tasks and their statuses.",
      "value": "Observer"
    },
    {
      "allowedMemberTypes": [
        "User"
      ],
      "displayName": "Approver",
      "id": "fc803414-3c61-4ebc-a5e5-cd1675c14bbb",
      "isEnabled": true,
      "description": "Approvers have the ability to change the status of tasks.",
      "value": "Approver"
    },
    {
      "allowedMemberTypes": [
        "User"
      ],
      "displayName": "Admin",
      "id": "81e10148-16a8-432a-b86d-ef620c3e48ef",
      "isEnabled": true,
      "description": "Admins can manage roles and perform all task actions.",
      "value": "Admin"
    }
  ],

并通过应用程序通过 Azure 门户将角色分配给用户,如下图所示:

然后我们可以得到像下面的id_token请求(隐式授权流程),角色应该在令牌中。我们可以使用此令牌调用网络 API。

Get:https://login.microsoftonline.com/{tenant}/oauth2/authorize?response_type=id_token&client_id={clientId}&redirect_uri={redirect_uri}&nonce={nonce}

id_token 示例: