简体   繁体   中英

How to do role based authorization in Azure with Asp.net webapi backend and front end as Angular

How I can do Azure role based authentication in webapi backend. I see tons of example for Asp.net MVC but none for webapi with front end as Angular. I have hosted my website developed in angular with backend as webapi and hosted it on Azure and enabled the Authentication/authorization as Azure Active directory in Azure website. Also I have done the setup for AD application for roles in its manifest files. After I hit website, I have to authenticate and then after authentication it redirects to my website . During my website load it calls my webapi and the Authentication token with claims is passed to my webapi. In webapi I am checking for InRole or [Authorize(Roles = "admin")] and based on that I am allowing access. However in token roles do not flow by default . So I query graph api to get roles by extracting the information from token and pass it to graph api to get roles. I am doing query in Owin Startup class to fetch role, But I am not able to get success. Is there anything wrong with the code, Please help . The code is copied below. Also I could have used ADAL JS library in Angular to authenticate with AD but I don't need to do so as I have enabled authentication in Azure website using the option "Authentication/Authorization". The layer of Authentication in website will do all token validation and forward it to webapi.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IdentityModel.Tokens;
using System.Linq;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.ActiveDirectory;
using Owin;
using System.Security.Claims;
using System.Net;
using System.Web;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.Owin.Security.OAuth;
using Microsoft.Azure.ActiveDirectory.GraphClient;
using System.Threading.Tasks;

namespace OneMap.Web
{
    public partial class Startup
    {
        // Apply bearer token authentication middleware to Owin IAppBuilder interface.
        private void ConfigureAuth(IAppBuilder app)
        {
            var tenantId = Common.Configuration.GetConfigurationSetting("ida:Tenant");
            // ADAL authentication context for our Azure AD tenant.
            var authenticationContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(
              $"https://login.windows.net/{tenantId}", true, TokenCache.DefaultShared);

            // Secret key that can be generated in the Azure portal to enable authentication of a
            // specific application (in this case our Web API) against an Azure AD tenant.
            var applicationKey = Common.Configuration.GetConfigurationSetting("ida:Password");



            // Root URL for Azure AD Graph API.
            var azureGraphApiUrl = "https://graph.windows.net";
            var graphApiServiceRootUrl = new Uri(new Uri(azureGraphApiUrl), tenantId);
            var clientId = Common.Configuration.GetConfigurationSetting("ida:ClientId");
            // Add bearer token authentication middleware.
            app.UseWindowsAzureActiveDirectoryBearerAuthentication(
              new WindowsAzureActiveDirectoryBearerAuthenticationOptions
              {
                  // The id of the client application that must be registered in Azure AD.
                  TokenValidationParameters = new TokenValidationParameters { ValidAudience = clientId },
                  // Our Azure AD tenant (e.g.: contoso.onmicrosoft.com).
                  Tenant = tenantId,
                  Provider = new OAuthBearerAuthenticationProvider
                  {
                      // This is where the magic happens. In this handler we can perform additional
                      // validations against the authenticated principal or modify the principal.
                      OnValidateIdentity = async context =>
                                {
                                    try
                                    {
                              // 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;

                              // Credential representing the current user. We need this to request a token
                              // that allows our application access to the Azure Graph API.
                              var userUpnClaim = identity.FindFirst(ClaimTypes.Upn);
                                        var userName = userUpnClaim == null
                                ? identity.FindFirst(ClaimTypes.Email).Value
                                : userUpnClaim.Value;
                                        var userAssertion = new UserAssertion(
                                userJwtToken, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);

                              // Credential representing our client application in Azure AD.
                              var clientCredential = new ClientCredential(clientId, applicationKey);

                              // Get a token on behalf of the current user that lets Azure AD Graph API access
                              // our Azure AD tenant.
                              var authenticationResult = await authenticationContext.AcquireTokenAsync(
                                azureGraphApiUrl, clientCredential, userAssertion).ConfigureAwait(false);

                              // Create Graph API client and give it the acquired token.
                              var activeDirectoryClient = new ActiveDirectoryClient(
                                graphApiServiceRootUrl, () => Task.FromResult(authenticationResult.AccessToken));

                              // Get current user groups.
                              var pagedUserGroups =
                                await activeDirectoryClient.Me.MemberOf.ExecuteAsync().ConfigureAwait(false);
                                        do
                                        {
                                  // Collect groups and add them as role claims to our current principal.
                                  var directoryObjects = pagedUserGroups.CurrentPage.ToList();
                                            foreach (var directoryObject in directoryObjects)
                                            {
                                                var group = directoryObject as Group;
                                                if (group != null)
                                                {
                                          // Add ObjectId of group to current identity as role claim.
                                          identity.AddClaim(new Claim(identity.RoleClaimType, group.ObjectId));
                                                }
                                            }
                                            pagedUserGroups = await pagedUserGroups.GetNextPageAsync().ConfigureAwait(false);
                                        } while (pagedUserGroups != null);
                                    }
                                    catch (Exception e)
                                    {
                                        throw;
                                    }
                                }
                  }
              });
        }
    }
}

AFAIK, the roles claim only issued in the id_token. After you change the manifest of app(refer here ), you can using the SPA get the id_token and access the web API according the roles via the id_token.

And there is no need to using the Authentication/authorization since you have protect the web API using the Microsoft.Owin.Security.ActiveDirectory OWIN middleware. To authenticate the SPA you can refer this code sample .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM