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
Step 1: Web Site Registration in Azure Active Directory
1. In the MS Azure ->Azure Active Directory click on App 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.
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(AuthenticationFailedNotificationcontext) { 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 TaskIndex() { 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.
Please provide your inputs or topics you want to have blog or help required.