GA4

Tuesday, July 11, 2017

Authentication of Web API from the Client Side by using Azure Active Directory

We are global so as our Web APIs. Sometime our APIs are exposed to the different client applications through the cloud service. There are scenarios where we want to know who is accessing our API for tracking purposes which requires authentication at Web API . Here, I have taken an example of MS Azure, where, my client application and my web API both are hosted on MS Azure platform and I want to know who is calling my web API.



Step 1: Web Site Registration in Azure Active Directory


1. In the MS Azure ->Azure Active Directory click on App Registration

2. Click on “New application registration”

3. Create

4. Once you have created the site, you can check some of the values which you will be using in you web site codding. (in a green Box)






5. Check and Add Reply URLs. You can also add it later once you know the return URLs.


6. Create a key and copy it in the secure location to be used during the client application. Remember: Once you move from the keys tab than the value will be marked as “Hidden’ and you won’t be able to copy it. Therefore, copy the value before moving away from the “Keys” tab.


7. In the Required Permissions section Make sure in the Windows Azure Directory….. you have the following permission added. This Windows Directory API is added by default. Do not currently worry about adding the other API. We’ll revisit later.



Step 2: API Registration in Azure Active Directory

1. Click again on “New application registration”, and create the new app which we’ll use for authentication of our API with the similar steps which are above but no key creation will be required here.
 2. Refer Below properties: Note: Copy the App ID URI and store it somewhere to use it during code.


3. Check Reply URLs 




Above are the steps which needs to be performed before you start with you actual coding.


Now, let’s look at the code side.

Step 3: Working on the WebSite - client side code: I have created MVC project through Visual Studio 2017.

1. Once you create you WebSite project as a client. Add nugget packages mention in the package.config file. – Refer attached project

2. After that open the Startup.Auth.cs from the path /App_Start
3. Replace the default code with the following:

public partial class Startup
    {
        private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
        private static string appKey = ConfigurationManager.AppSettings["ida:AppKey"];
        private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
        private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
        private static string redirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];

        public static readonly string Authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

        string myApiResourceId = ConfigurationManager.AppSettings["ida:MyAPI"];

        // For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864
        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = clientId,
                    Authority = Authority,
                    PostLogoutRedirectUri = redirectUri,
                    RedirectUri = redirectUri,

                    Notifications = new OpenIdConnectAuthenticationNotifications()
                    {
                        //
                        // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                        //
                        AuthorizationCodeReceived = OnAuthorizationCodeReceived,
                        AuthenticationFailed = OnAuthenticationFailed
                    }

                });
        }

        private Task OnAuthenticationFailed(AuthenticationFailedNotification context)
        {
            context.HandleResponse();
            context.Response.Redirect("/Home/Error?message=" + context.Exception.Message);
            return Task.FromResult(0);
        }

        private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
        {
            var code = context.Code;

            ClientCredential credential = new ClientCredential(clientId, appKey);
            string userObjectID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
            AuthenticationContext authContext = new AuthenticationContext(Authority, true);

            // If you create the redirectUri this way, it will contain a trailing slash.  
            // Make sure you've registered the same exact Uri in the Azure Portal (including the slash).
            Uri uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));

            AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, uri, credential, myApiResourceId);
            HttpContext.Current.Session["apiToken"] = result.AccessToken;
        }
    }

4. The web.config should have the following appSettings:


    
    
    
    
      //Application ID of the web site
    
    
    
    
    
  

    ......
    
    .......
  



5. Your Controllers should be decorated with [Authorize] so that web site is aware that this particular controller will be authorized. Your controller code should be like below. This is just an example on how to call web API from the controller using the same bearer token.

   [Authorize]
    public class HomeController : Controller
    {
        
        private string todoListResourceId = ConfigurationManager.AppSettings["ida:MyAPI"];
        private string todoListBaseAddress = "https://myapi.azurewebsites.net";
        private const string TenantIdClaimType = "http://schemas.microsoft.com/identity/claims/tenantid";
        private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
        private static string appKey = ConfigurationManager.AppSettings["ida:AppKey"];

        public async Task Index()
        {

            String responseString = null;

            try
            {
                //
                // Retrieve API Method.
                //
                HttpClient client = new HttpClient();
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, todoListBaseAddress + "/api/userinfo/name");
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", Session["apiToken"].ToString());
                HttpResponseMessage response = await client.SendAsync(request);

                //
                // Return user to the view.
                //
                if (response.IsSuccessStatusCode)
                {
                    responseString = await response.Content.ReadAsStringAsync();

                    ViewBag.User = responseString;
                }
            }
            catch(Exception ex)
            {
                throw ex;
            }
            
            return View();

        }
   }


6. Now you client is ready.

Step 4: Create the Web API. I have used the standard MVC Web API for the PoC.

1. Once you create the web API project, Add nugget packages mention in the package.config file. – Refer attached project.
2. After that open the Startup.Auth.cs from the path /App_Start
3. Replace the default code with the following:


 public partial class Startup
    {
        // For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864
        public void ConfigureAuth(IAppBuilder app)
        {
            app.UseWindowsAzureActiveDirectoryBearerAuthentication(
                      new WindowsAzureActiveDirectoryBearerAuthenticationOptions
                      {
                          Audience = ConfigurationManager.AppSettings["ida:Audience"],
                          Tenant = ConfigurationManager.AppSettings["ida:Tenant"],

                      });
        }
    }

4. The web.config of API project should have the following appSettings:


     //Registered API - APP ID URI
     //Active Directory ID
  

5. Your API class example is as follows:

    [Authorize]
    [RoutePrefix("api/userinfo")]
    public class ValuesController : ApiController
    {
        //GET api/
        [Route("name")]
        [HttpGet]
        public string GetMyAPIUser()
        {
            //return "Charan";
            return ClaimsPrincipal.Current.Identity.Name;
        }
    }

6. Compile and publish your API to MS Azure and do the following configuration in the MS Azure.        
     a. Open the API Application on cloud which is jut hosted above.
     
     b. Click on Authentication / Authorization and make sure you have changed it to “Log in with Azure Active Directory” and also change other values as show in the screen shot.



    c. Click on Configured(Advance) – Highlighted in Yellow and do the following configurations.



7. Now you can run your web site and you will be able to see the user who has called the Web API. You can use the token information to store into your database from the Web API Method.



I hope you have enjoyed reading above blog on how to authenticate Web API from client side by using Azure Active Directory.

Please provide your inputs or topics you want to have blog or help required. 

No comments: