Angularjs Adal and Additional Claims or Properties for Authorization

The script is an Angularjs 1.6.5 app with C # WebApi. Authentication is performed by AAD

using angular-adal.js

. Everything works fine so far, as users can connect via AAD and WebApi accepts the token.

For this particular application, the roles are in an external application that WebApi has access to. I was able to add role claims (after downloading them from External app) using WindowsAzureActiveDirectoryBearerAuthenticationOptions

with the following code inside 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));
             }
         }
     }
   }
});

      

So, for every HTTPRequest Angularjs makes for the API, the previous function looks at the roles for the user and adds the requirements for the role. With this implementation, I can use the AuthorizeAttribute on the Controller methods, restricting access to only certain roles, for example:

[CustomAuthorize(Constants.Roles.resourcesAdministrator)]

      

I find this way very time consuming because with each httpRequest the API has to fetch the user roles from the database (or any other way to implement it).

What I want to do is read the user's roles only once, and then use them in the API with each subsequent request. Is there a way to add claims to the token AFTER we receive the token for AAD?

BTW, I could just add a Roles property for each model or something like that, but that's not what I'm looking for.

If you have any other ideas or suggestions they will be greatly appreciated.

Hello

0


source to share


1 answer


The token cannot be changed from the moment of its release. And since the roles are stored in another application, I don't think it is possible to get the roles without querying in the database.

In this case, we can manage roles using the roles and roles of the Azure AD application. Then it issues a claim roles

to id_token.

For example, we can change the application manifest as shown below:

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

      



And assign roles to the user through the app through the Azure portal as shown below: enter image description here

Then we can get the id_token as below request (implicit grant flow), the roles must be in the token. And we can call the web API using this token.

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

      

id_token sample: enter image description here

+1


source







All Articles