2017-08-09 88 views
0

情景是Angularjs 1.6.5应用程序,带有c#WebApi。使用angular-adal.jsAAD进行验证。到目前为止,一切正常,因为用户可以通过AAD登录,并且WebApi接受令牌。Angularjs Adal以及授权的其他声明或属性

对于此特定应用程序,角色位于WebApi具有Access的外部应用程序中。我已经能够增加角色的权利要求与使用WindowsAzureActiveDirectoryBearerAuthenticationOptionsConfigureOAuth(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)); 
      } 
     } 
    } 
    } 
}); 

因此,对于每一个HTTPRequest,它Angularjs确实给API时,上一个函数查找用户的角色并添加角色声明。有了这个实施,我能够在控制器的方法来使用AuthorizeAttribute,限制只能访问特定的角色,像这样:

[CustomAuthorize(Constants.Roles.resourcesAdministrator)] 

,我觉得这种方式非常inneficient,因为每个的HttpRequest,该API具有获取用户从数据库中的角色(或实施任何持久性方式)。

我想要做的就是只读取一次用户角色,然后在随后的每个请求中都可以在API中使用它们。在我们收到AAD标记后,是否有方法将标记添加到标记中?

顺便说一句,我可以只为每个模型添加一个角色属性,或类似的东西,但它不是我正在寻找。

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

Regards

+0

'angular'标签是用于'2 +''angularjs'标签是用于'1.x' – Kuncevic

+0

感谢您的更新@Kuncevic。当我们使用Angular 1.x时,我会牢记这一点。 – aplon

回答

1

令牌自发布以来无法修改。由于角色存储在另一个应用程序中,我不认为有可能在不查询数据库的情况下获取角色。

在这种情况下,我们可以通过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的门户应用这些角色分配给用户像下图: enter image description here

然后我们可以在下面获得类似id_token的请求(隐式授权流程),角色应该在令牌中。我们可以使用此令牌调用We​​b API。

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

id_token样品: enter image description here

+0

感谢您说出回答Fei的时间,所以我应该将外部应用程序中的角色与AAD角色同步。这样,两个系统共享相同的角色,我将获得令牌中的角色。对? – aplon

+0

是的,你是对的。 –