Creating a Asp.Net Web Api application and securing it using Forms Authentication

Introduction

What is the need of Securing a Web API

The web API can be deployed IIS after successful creation. Now this can be accessed by any one who knows the URL of the API.This creates a lot of security issues and for public-facing web sites this is acceptable but for most web applications this is undesirable as they have restricted or limited access.That is why minimum need is to authenticate the users.

There are many ways of authenticating users.For an ASP.NET web application is targeted exclusively for an enterprise user base a great option is Windows Active Directory–based authentication. But if the user base is extend further then a good choice is Forms Authentication. In this type of authentication user credentials are stored in database and user is validated/authenticated against it.

What is Forms Authentication

The mechanism used for Forms authentication is a ticket-based mechanism. At the time of user login, an authentication ticket gets created and it is saved in to the cookie. This cookie is now sent back to the browser. Now the browser keeps sending the cookie with the ticket in all subsequent requests until the cookie expires. The user is considered an authenticated user, as long as the cookie is sent by the browser and the cookie contains the valid ticket.

Let’s create our first ASP.NET Web API and consume it.

Open visual studio and create a new web project as shown in below figure.Let’s name it as DemoWebApi

Now select the web API template in the next screen, as shown in below figure.By default the view engine is “RAZOR“.

You can now see that the “ValuesController” added by Visual Studio by default . So Let’s delete it and create a new WebAPI controller. To achieve this right click on controller folder. Then select Add Controller from the menu item.

We will select “Empty API” Controller as Template from the Options and give it a name “ProductsController“.

Now let’s do some coding in it.Below is the code :

public class ProductsController : ApiController
    {
        // Return a single product 
        public Product Get(int id)
        {
            return new Product()
            {
                Id = id,
                Name = "Apple",
                Category = "Fruits"
            };
        }

        // Return all Products
        public IEnumerable<Product> GetAllProducts()
        {
            return new Product[]
            {
                new Product()
                {
                    Id = 786,
                    Name = "Orange",
                    Category = "Fruits"
                },
              new Product()
              {
                  Id = 787,
                  Name = "Cabbage",
                  Category = "Vegetables"
              }
            };
        }
    }

We have two action methods defined in ProductsController:

First is to handle GET on a specific product using an identifier i,e Product 
Second is to handle GET requests on all products with corresponding return types i,e IEnumerable<Product>

But before that create “Product” class under Models folder. Below is the code :

 public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
    }

By default Visual Studio creates a HomeController within Index action method.
We will change the code to show the Products in a List on View/Home/Index.cshtml. Below is the code :

<div id="body">
    <section class="featured">
        <div class="content-wrapper">
            <hgroup class="title">
                <h1>Welcome to ASP.NET Web API!</h1>
            </hgroup>
        </div>
    </section>
    <section class="content-wrapper main-content clear-fix">
        <div>
            <h1>Products Listing
            </h1>
            <input id="search" type="button" value="Get" />
        </div>
        <div>
            <ul id="products" />
        </div>
    </section>
</div>

@section scripts{
    <script type="text/javascript">
        $(document).ready(function () {
            $('#search').click(function () {
                $('#products').empty();
                $.getJSON("/api/products", function (data) {
                    $.each(data, function (i, product) {
                        var content = product.Id + ' : ' + product.Name;
                        content = content + ' : ' + product.Category;
                        $('#products').append($('<li/>', { text: content }));
                    });
                });
            });
        });
    </script>
}

Now if we go to /Home/Index of the application and click the Get button, it will get the JSON data from Web API /api/products and show the data in the browser.

Now it’s time to secure our Web Api using forms authentication:

By default the the mode attribute of the authentication element defined in Web.config is “none”.
<authentication mode=”None” />
It means ASP.NET will not authenticate the user.

To enable forms authentication, we have to make sure FormsAuthenticationModule(a specific IIS module),
has to be added into the life cycle of the ASP.NET application. This can be achieved by removing the default authentication element and change it to :

<authentication mode="Forms">
  <forms loginUrl="Login"/>
</authentication>

Similarly to deny access to anonymous users and make authentication mandatory, we have add this to the web config :

<authorization>
  <deny users="?"/>
</authorization>

To know more about the above to configuration please visit :
http://support.microsoft.com/kb/316871

Now the user provides the credentials (user ID and password) and submits the form. LoginController validates the credentials, creates the ticket, and writes the cookie into response.

The browser, on receiving this cookie, starts to send the cookie in all subsequent requests. FormsAuthenticationModule reads the cookie and establishes the identity based on the authentication ticket in the cookie.

Now we will add an empty MVC controller with the name LoginController. Below is the code :

       public ActionResult Index(string returnurl)
        {
           return View(); 
        }

        [HttpPost]
        public ActionResult Index(string userId, string password)
        {
            if (!userId.Equals(password)) 
            return View();

            // Create the ticket and put it in a cookie
            FormsAuthentication.SetAuthCookie("Smruti", false);
            return RedirectToAction("Index", "Home");
        }

The actual authentication (i.e, comparing the user-entered credentials against the stored credentials) happens inside the action method that handles HTTP POST. If credentials are valid, an authentication ticket gets created
and stored into a cookie through the call to FormsAuthentication.SetAuthCookie(). For simplicity the authentication I’m doing is just making sure the user ID and password are the same.

Now let’s create a View for this and this will be our login page. It gets the user ID and password from the user and posts it back to itself. Below is the code :

<h1>Sign In</h1>
<h4>Enter same userid and password</h4>
@section scripts{
    <script type="text/javascript">
        $(document).ready(function () {
            $('.editor-label').css({
                fontSize: 20,
                fontfamily: "Arial",
                marginLeft: 20
            });
            $('.editor-field').css({
                marginLeft: 20
            });
            $('#btnPwd').css({
                marginLeft: 270
            });

        });
    </script>
}

@using (Html.BeginForm())
{
    <div class="editor-label">
        @Html.Label("UserId")
    </div>
    <div class="editor-field">
        @Html.TextBox("userId")
    </div>
    <div class="editor-label">
        @Html.Label("Password")
    </div>
    <div class="editor-field">
        @Html.Password("password")
    </div>
    <input type="submit" id="btnPwd" value="Login" />
}

Now as the changes has been done the application is no longer a free-for-all application i,e it can’t be accessed through the URL only . When you go to Home/Index, which is the home page, you get redirected to the login page. On entering the right credentials (in this  case any string as user ID and the same as password), you come back to the home page. If you then click Get button, the view makes a call to ASP.NET Web API and displays the list of products correctly.

So we are done with the securing thing now. Now let’s see how it works. You can download the code attached and debug it.

Points of Interest

Please note that a cookie is not mandatory for forms authentication and it is possible to send the ticket in a query string, but it is not better form security point of view. Feel free to add any comments/suggestion to improve the article. And one thing , I have attached the project for download form here DemoWebApi code


Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.