2017-08-09 6 views
0

Scénario est l'application Angularjs 1.6.5 avec un C# WebApi. L'authentification est effectuée par rapport à AAD avec l'utilisation de angular-adal.js. Jusqu'à présent, tout fonctionne parfaitement, car les utilisateurs peuvent se connecter via AAD et WebApi accepte le jeton.Angularjs Adal et des revendications supplémentaires ou des propriétés pour l'autorisation

Pour cette application spécifique, les rôles sont dans une application externe, à laquelle WebApi a accès. Je suis en mesure d'ajouter les allégations relatives au rôle (après les aller chercher de l'application externe) avec l'utilisation de WindowsAzureActiveDirectoryBearerAuthenticationOptions avec le code suivant à l'intérieur du 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)); 
      } 
     } 
    } 
    } 
}); 

Ainsi, pour chaque httpRequest que AngularJS fait à l'API, la La fonction précédente recherche les rôles pour l'utilisateur et ajoute les revendications de rôle. Avec cette mise en œuvre, je suis en mesure d'utiliser un AuthorizeAttribute dans les méthodes de contrôleur, limitant l'accès aux seuls certains rôles comme ceci:

[CustomAuthorize(Constants.Roles.resourcesAdministrator)] 

Je trouve cette façon très inneficient, car à chaque httpRequest, l'API doit chercher la rôles de l'utilisateur à partir de la base de données (ou quel que soit le mode de persistance implémenté).

Ce que je veux faire est de lire les rôles d'utilisateur juste une fois, et puis pouvoir les utiliser dans l'API avec chaque demande suivante. Existe-t-il un moyen d'ajouter les revendications au jeton APRÈS avoir reçu le jeton pour AAD? Par ailleurs, je pourrais juste ajouter une propriété Roles à chaque modèle, ou quelque chose comme ça, mais ce n'est pas ce que je cherche.

Si vous avez d'autres idées ou suggestions, elles seront grandement appréciées.

Cordialement

+0

'angular' tag est pour' 2 + '' angularjs' balise est pour '1.x' – Kuncevic

+0

Merci pour la mise à jour @Kuncevic. Je garderai cela à l'esprit car nous utilisons Angular 1.x. – aplon

Répondre

1

Le jeton est pas en mesure de modifier puisqu'il est émis. Et puisque les rôles sont stockés dans l'autre application, je ne pense pas qu'il soit possible d'obtenir les rôles sans interroger la base de données.

Dans ce scénario, nous pouvons gérer les rôles à l'aide des rôles de l'application Azure AD &. Ensuite, il émettra la réclamation roles dans id_token.

Par exemple, nous pouvons modifier le manifeste de l'application comme ci-dessous:

"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" 
    } 
    ], 

et attribuer les rôles à l'utilisateur grâce à l'application via le portail Azure comme la figure ci-dessous: enter image description here

Ensuite, nous peut obtenir la requête id_token like ci-dessous (flux de subvention implicite), les rôles doivent être dans le jeton. Et nous pouvons appeler l'API Web en utilisant ce jeton.

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

id_token échantillon: enter image description here

+0

Merci d'avoir parlé le temps de répondre à Fei, donc, je devrais synchroniser les rôles de l'application externe avec les rôles AAD. De cette façon, les deux systèmes partagent les mêmes rôles et j'obtiendrais les rôles dans le jeton. Droite? – aplon

+0

Oui, vous aviez raison. –