Saturday, September 12, 2015

Implement Basic Authentication in ASP.Net Web API at Host level (IIS)


In our previous discussion, we discussed what are different ways to implement security in ASP.Net web-api. Before you proceed, I would recommend to go through that article on the link below first, as that will act as a kind of base for where and how we will implement the security.
In this discussion, we will be implementing basic authentication in web-api at the host level. 
As per MSDN, basic authentication is:



As per the above description, there is one limitation to the use of IIS as the host and implementing basic authentication at IIS level. This means, IIS uses Windows credentials to authenticate the users. So this implementation is suitable for any intranet applications, where the users have to access the application within the domain. 

To start with, we will create a new empty project using Empty ASP.Net Web -API template project. Let's name it as BasicAuthenticationIIS.


Next, we add a controller called as SampleController and inherit it from ApiController, to make it a WebAPI controller type. Also, we add a method named GetCurrentDateTime which will return current date and time as string to the user. So our controller will look like:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace BasicAuthenticationIIS.Controllers
{
    public class SampleController : ApiController
    {
        public String GetCurrentDateTime()
        {
            return DateTime.Now.ToString();
        }
    }
}


Next, we simply host the application in IIS. So open IIS, select " Default Web Site", right click and select the option "Add Application". Provide an Alias name to it and provide the physical path to the application directory. 

Browse the application and enter the path of the webapi and see the results. 
So this was without any security. Anyone who is not authenticated, can access the method. Let's add the authentication to the api. So we start by adding the settings in the config file. So we add the authentication mode to the web.config as Windows. 

<system.web>
    <authentication mode="Windows"></authentication>
</system.web>

Next, add the [Authorize] attribute on the method for which we need to add the security. So our method will look like:


[Authorize]
public String GetCurrentDateTime()
{
            return DateTime.Now.ToString();
}

Build the application. Next, go to IIS and select the option "Authentication".

Within this, select the Basic Authentication option, right click and Enable it.
That's it. Restart the application in IIS and browse the application. It asks for credentials. 
Cancel it and it says Un-Authorized.

Let's refresh and enter windows account credentials. 

Press Ok and see the results.

We can also create a sample application and test it. Create a new a Console application and write the following code:

WebRequest req = WebRequest.Create("http://localhost/BasicAuthSample/api/sample/GetCurrentDateTime");
req.Method = "GET";
req.ContentType = "text/xml";
byte[] authBytes = Encoding.UTF8.GetBytes("emailAddress:Password".ToCharArray());
req.Headers.Add("Authorization", "BASIC " + Convert.ToBase64String(authBytes));
System.Net.WebResponse response = req.GetResponse();
System.IO.StreamReader reader = new StreamReader(response.GetResponseStream());
string str = reader.ReadToEnd();


Run the application and see the results:



In case you do not send the credentials, it will throw an error of type WebException, which you can catch and check status code. The complete code will be like the following:


class Program
    {
        static void Main(string[] args)
        {
            try
            {
                WebRequest req = WebRequest.Create("http://localhost/BasicAuthSample/api/sample/GetCurrentDateTime");
                req.Method = "GET";
                req.ContentType = "text/xml";
                Byte[] authBytes = Encoding.UTF8.GetBytes((ConstantStruct.UserName + ":" + ConstantStruct.Password));
                req.Headers.Add("Authorization", "BASIC " + Convert.ToBase64String(authBytes));
                req.Headers.Add("test", "test");

                System.NetWebResponse response = req.GetResponse();
                System.IOStreamReader reader = new StreamReader(response.GetResponseStream());
                Console.Write(reader.ReadToEnd());
            }
            catch (WebException ex)
            {
                var statusCode = ((HttpWebResponse)ex.Response).StatusCode;
                if (statusCode == HttpStatusCode.Unauthorized)
                {
                    Console.Write("Authorization failed.");
                }
            }
            Console.Read();
        }
    }

So this is how we can implement the host level (i.e. IIS), basic authentication in a web-api. Hope you enjoyed reading it. Happy coding...!!!

1 comment: