Pages

Wednesday, 10 October 2012

WebAPI and Subscriber Authentication by Custom HTTP Headers

Recently I've been experimenting with WebAPI, part of the ASP.NET 4 framework. Whilst providing a great way to provide HTTP services, most HTTP services that are provided by companies are on a subscription basis. With this in mind, how can I best secure my HTTP Services for consumption by a paying subscriber?

The easy answer is to pass in an authentication token or credentials with each call to your HTTP service. How you do this is important, particularly for GET methods.

The best solution I've come up with so far is to add a custom authentication header to calls to my HTTP service, and provide a mechanism in my WebAPI MVC application to check the authentication provided in the header of each call.

First, we need to build our WebAPI MVC application! To do this:

Start Visual Studio and select New Project from the Start page. Or, from the File menu, select New and then Project.

In the Templates pane, select Installed Templates and expand the Visual C# node. Under Visual C#, select Web. In the list of project templates, select ASP.NET MVC 4 Web Application. Name the project "NewsSubscriptionService" and click OK.

In the New ASP.NET MVC 4 Project dialog, select Web API and click OK. For the purposes of this example, don't tick the Create a unit test project box.

Created for you as part of this project will be a default API controller, located in the Controllers folder and called ValuesController.cs. You will need to open this file to create our test GET method.
In the ValuesController.cs file, please replace the class section with:
public class ValuesController : ApiController
    {
        // GET api/values
        [ValidateSubscriber]
        public string Get()
        {
            return "Authenticated";
        }
    }
What does this do? Well, it creates a GET method called Get, which returns a string value. You will see from the code that an attribute has been assigned to the method called ValidateSubscriber. This is what you will create next, and does the job of validating the authentication token passed in the HTTP request to our method. The benefit of this approach is you can secure each HTTP method in your application by applying the attribute as required. 


In your solution, create a folder called Authentication and within this folder create a class file called ValidateSubscriber.cs
In the ValidateSubscriber.cs file, replace the ValidateSubscriber class with:
public class ValidateSubscriber : System.Web.Http.AuthorizeAttribute
    {
        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            
            if (actionContext.Request.Headers.GetValues("authenticationToken") != null)
            {
                // get value from header
                string authenticationToken = Convert.ToString(actionContext.Request.Headers.GetValues("authenticationToken").FirstOrDefault());
                // This is a hard-coded token, but in reality you would do a check against a subscriber database or something of that ilk.
                if (authenticationToken != "326ED626-0E95-4C75-A456-B42E605FF929")
                {
                    HttpContext.Current.Response.AddHeader("authenticationToken", authenticationToken);
                    HttpContext.Current.Response.AddHeader("AuthenticationStatus", "NotAuthorized");
                    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
                    return;
                }

                HttpContext.Current.Response.AddHeader("authenticationToken", authenticationToken);
                HttpContext.Current.Response.AddHeader("AuthenticationStatus", "Authorized");
                return;
            }
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.ExpectationFailed);
            actionContext.Response.ReasonPhrase = "Please provide valid inputs";
            base.OnAuthorization(actionContext);
        }
    }
You will see from the code that requests to any HTTP service secured by this attribute is intercepted and a custom HTTP header value is looked for called authenticationToken. For this example, a hard-coded Guid value is expected, but in reality you would plumb this in to a database or data store call to check the supplied Guid is valid. Each subscriber should have a different Guid too!


This is all you need to secure your HTTP method!
A quick test is to call this secured method in a HTML page:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" src="/Scripts/jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="/Scripts/knockout-2.1.0.js"></script>
    <script type="text/javascript" src="/Scripts/jquery.unobtrusive-ajax.min.js"></script>
    <script type="text/javascript">
        $(function () {
            $(".button").click(function () {
                $.ajax({
                    
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("authenticationToken", "326ED626-0E95-4C75-A456-B42E605FF929");
                    },
                    url: "/api/Values/Get",
                    type: "GET",
                    statusCode: {
                        200: function (result) {
                            $("#Data").html(result);
                        },
                        401: function (result) {
                            $("#Data").html("Access was denied");
                        }
                    }
                });
            });
        });
    </script>
</head>
<body>
    <div id="Data"></div>
    
    <input type="submit" class="button" value="test" />
    
</body>
</html>

What this does is create a request to our HTTP method and display the string value that is returned by the method. You can test the authentication by changing the Guid value added to the request in the beforeSend function.
An example solution is available for download here

Tuesday, 7 August 2012

MVC - SSL, Testing and Production

I recently had a conversation with a colleague about SSL and how a login page for an MVC application could be forced over SSL, to ensure credentials supplied in the login form are sent over an encrypted channel.

The answer is quite easy: there is a flag that can be set for your controller method called RequireHttps

However..

During my time as a developer, one problem I have seen and witnessed many times is the one of development code being published to a production environment. The consequences of which can range from minor embarrassment (Response.Write() anyone?) to dangerous security holes.

When debugging an application, having the RequireSSL flag set for a controller method can cause all sorts of issues and the temptation is to comment out this flag for debugging. The danger here of course is that this flag is not then un-commented for deploying to a production environment.

There are several ways to ensure this doesn't happen:

1.You could use IIS and a self-signed certificate when testing locally, but this depends on the level of admin access you have to your development PC.
2. Use conditional compilation. For example:


#if !DEBUG
[RequireHttps] 
#endif


You could argue that this leads to messy code, however my main concern is that it doesn't mitigate against a debug version of a DLL making it's way to a product environment. Trust me, this is more common than you might think.

3. Use a derived flag from RequireHttpsAttribute. This last option is by far my favourite, and the safest option.


using System;
using System.Web.Mvc;


    public class RemoteRequireHttps : RequireHttpsAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            if (filterContext.HttpContext != null && filterContext.HttpContext.Request.IsLocal)
            {
                return;
            }
            base.OnAuthorization(filterContext);
        }
    }

When you need to force a controller method over SSL, use the RemoteRequireHttps flag you have created above. When testing locally, the IsLocal flag will prevent SSL being required. When deployed to a production environment, the method will be forced over SSL.

With security, nothing can be left to chance and the mitigation of an accidental release of development code into a production environment needs to be considered at all times. 


Tuesday, 31 July 2012

Entity Framework 4.3 Seeding Data Using int as Identity Column Type

When seeding data using EF 4.3 code first, there is a gotcha when seeding data in identity columns. Let me explain.


In a recent project, I had two tables as part of my model. The first one was called Questions, and the code looked like:

    [Table("Questions", Schema = "Forms")]
    public class Question
    {

        public int QuestionID { get; set; }

        [Required(ErrorMessage = "The question is required")]
        [MaxLength(400)]
        public string QuestionText { get; set; }

        public string Marker { get; set; }

    }

The next table was a relationship table to link Question records to a table with Form records. I had used a linking table as I needed a display order column:

    [Table("FormsQuestions", Schema = "Forms")]
    public class FormsQuestions
    {

            [Key, ForeignKey("Form"), Column(Order = 0)]
            public int FormID { get; set; }
            public virtual Form Form { get; set; }

            [Key, ForeignKey("Question"), Column(Order = 1)]
            public int QuestionID { get; set; }
            public virtual Question Question { get; set; }

            public int DisplaySequence { get; set; }
    }

As you can see, I am using int as my type for the identity column in the Questions table, a fairly common thing. When seeding the data for these two tables, I can set the value of QuestionID in the Questions table..or can I? I ran across this gotcha when I made a mistake with seeding the Question table:

var questions = new List<Question>
            {
                new Question { QuestionID = 1, QuestionText = "Question text one", Marker = "<<one>>"},
                new Question { QuestionID = 3, QuestionText = "Question text two", Marker = "<<two>>"}
            };
            questions.ForEach(s => context.Questions.Add(s));
            context.SaveChanges();

As you can see, the second record should have a QuestionID with the value 2. However, as I was setting the QuestionID column values (or so I thought), I didn't think this would be a problem. There are a lot more questions being seeded in the actual code, however I've trimmed the data for the example in this post.


If I seed the joining table for questions with QuestionIDs 1 and 2 from above, I have something like:

var formsquestions = new List<FormsQuestions>
            {
                new FormsQuestions { QuestionID = 1, FormID = 1, DisplaySequence = 10},
                new FormsQuestions { QuestionID = 3, FormID = 1, DisplaySequence = 20}
            };
            formsquestions.ForEach(s => context.FormsQuestions.Add(s));
            context.SaveChanges();

However, this is going to fail! When inserting the data, values 1 & 2 have been used for the question records, not 1 & 3.


It transpires that whatever value I set for the QuestionID column when seeding the data is ignored and this set value is not inserted with the record. Instead, the next available value is assigned and there doesn't seem to be a command in EF that's equivalent to setting IDENTITY_INSERT <table_name> ON.

Special mention must go to my friend Luke Baughan for putting me in the right direction when I ran across this issue! Please read his blog at: http://ilovedevelopment.blogspot.co.uk/


Friday, 29 June 2012

ASP.NET DropDownList Postback: The jQuery AJAX Replacement for MVC

It was handy in ASP.NET WebForms to have the AutoPostback property and use the SelectedIndexChanged event, to allow other parts of your WebForm to be updated depending on user selection!

With MVC and Razor you can achieve the same functionality, but it has to be done using some other way that fits in with a View. Recently I had a requirement to render a list of checkboxes on a user form; the catch was that the list of checkboxes to be rendered was dependant on a drop down list option the user selected on the same form...

With this senario, we have three main components to any solution:

1. We need to fire a method when the drop down list selection changes.
2. This method needs to take the value of the selected item in the drop down list and return output based on that value.
3. The returned output needs to be rendered in the view.

With the requirement I had, I needed to query a database to return the data needed to render the checkboxes. The solution I used utilised jQuery AJAX and JSON.

I had an MVC Web Application with the latest version of jQuery installed, however I also needed the json2 library from http://www.json.org/ (this can also be downloaded via NuGet).

With these libraries referenced, I needed to wire up a a method to fire on the change event of the dropdownlist using jQuery:


    $(document).ready(function () {

        $('#OrganisationId').change(getReceivers);

    });


My getReceivers method makes an ajax call using JSON data to a controller action in my MVC application:

function getReceivers() {
        $.ajax({
            url: '/Person/ListRecievers',
            data: "{'organisationId':'" + $('#OrganisationId').val() + "', 'personId':'@Model.Person.Id'}",
            type: 'POST',
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function (result) {
                $('#receiversResponse').empty();
                $.each(result, function (person) {
                    var isChecked;
                    if (this.selected) {
                        isChecked = 'checked=\'checked\'';
                    }
                    else {
                        isChecked = '';
                    }
                    $('#receiversResponse').append(
                            '   <label class=\'checkbox\'>'
                            + '     <input type=\'checkbox\' name=\'Receivers\' ' + isChecked + ' value=\'' + this.id + '\'>' + this.name + ' at ' + this.organisationName + ''
                            + ' </label>'
                        );
                });
            },
            error: function () {

            }
        });
    }


URL: the path to my controller action to get the data back for generating the checkbox HTML

Data: this is data I need to pass to my controller action. I have two inputs, organisationId and personId. It is important to remember that these are passed in the ajax call as strings - if the organisationId is a Guid (for example), you will need to convert this to a Guid once it is passed into your controller action

Success: This takes the returned data (in JSON) and iterates through to generate HTML for the checkboxes. The HTML is written to a div I have in my view with an ID of "receiversResponse".


My controller action that is called to return the data I need in JSON is:



        public ActionResult ListRecievers(string organisationId, string personId)
        {
            var selectedOrganisation = db.Organisations.Where(p => p.Id == new Guid(organisationId)).Single();
                var people = db.People.ToList();
                var peopleList = from p in people
                                 select (new {
                                     id = p.Id,
                                     name = p.Name,
                                     organisationName = p.Organisation.Name,
                                     selected = db.People.Include("Receivers").Where(n => n.Id == new Guid(personId) && n.Receivers.Any(r => r.Id == p.Id)).Count() == 1
                                 }
                                     );
                return Json(peopleList.ToList(), JsonRequestBehavior.AllowGet);  
        }



I hope the solution to this problem helps someone else to dynamically display HTML based on user selection of a dropdownlist option value. You don't have to just display checkboxes with this either!


Thursday, 7 June 2012

MVC: Security Best Practises for Entity Framework 4.3 Code First and SQL Server

With Entity Framework, using code first development is a real time saver - however there are several best practises to consider when using SQL Server as your data store.


1. The user credentials you specify in the web.config when developing your application must have elevated privileges to drop/create the database depending on the database initialiser you are using for development. The use of web.config transforms for specifying different configurations for different build environments is essential, so that a connection string for a production build has user credentials with the lowest possible privileges.


2. Use DataAnnotations to specify schemas. In most of the examples I have seen, objects are created in the dbo schema. An example of how to specify a schema for your entity is:


[Table("Course", Schema = "Students")]
    public class Course
    {
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }
        public virtual ICollection<Enrollment> Enrollments { get; set; }
    } 


Why do this? Well, when the database and the user login are created (see item 3), the database user created for the login can then only be set explicit permissions for the schema(s) it needs to. 


3. When publishing to a production server for the first time, create the database manually and use Code First Migrations in Entity Framework 4.3 to publish an SQL script that can be run separately in the context of your database by a user with the correct privileges. This prevents your application requiring elevated privileges on your database; potentially disastrous if your the production server hosting your application is compromised.


I will add other best practises as I encounter them, however these are some things I have noted so far. Please add your own best practises below or comment on the above!










Wednesday, 30 May 2012

MVC - Displaying CheckBoxLists for Generic Lists

When developing an application, you may encounter a scenario where you have, for example, a customer record and that customer may be a member of several (but not all) customer lists in your application. 


All fairly straightforward. In an ASP.NET WebForms application for a customer management page where you want to select or un-select the lists a customer is in, you would typically bind the available customer lists to a CheckBoxList and in the DataBound event for this CheckBoxList control you would then mark checkboxes as checked for the lists your customer is in.


Depending on how you structure your application, this could involve two calls to your data store - one to get the available customer lists and one to get the customer details.


With MVC, the approach to this scenario takes a little adjustment!


The MVC Approach



There are several ways to handle displaying checkbox lists, however when I am developing MVC applications  I prefer to work solely with the strongly typed ViewModel I have created for my view. When doing this however, it is important to get the data in your ViewModel in a certain way.


Taking the example scenario above, in my application I want a customer edit view where I can edit the customer details and select or un-select the lists the customer is a member of. My customer entity looks something like:


    public class Customer
    {


        public Guid Id { get; set; }


        [Required(ErrorMessage = "A first name is required"), Display( Name = "First name")]
        public string Firstname { get; set; }


        [Required(ErrorMessage = "A surname is required"), Display(Name = "Surname")]
        public string Surname { get; set; }


        [Required(ErrorMessage = "An email address is required"), Display(Name = "Email address")]
        public string EmailAddress { get; set; }


        [Display(Name = "Added on")]
        public DateTime AddedOn { get; set; }


        [Display(Name = "Modified on")]
        public DateTime ModifiedOn { get; set; }


        [Display(Name = "Customer lists")]
        public List<CustomerList> Lists { get; set; }
    }

As you can see, I am including the lists a customer is a member of when I return an instance of a customer. My CustomerList entity is:



    public class CustomerList
    {


        public Guid Id { get; set; }


        [Required(ErrorMessage = "A name is required"), Display(Name = "Name")]
        public string Name { get; set; }


        [Display(Name = "Created on")]
        public DateTime CreatedOn { get; set; }


        [Display(Name = "Modified on")]
        public DateTime ModifiedOn { get; set; }


        public bool Checked { get; set; }
    }



In my customer repository, I have a GetCustomerById method to return a customer entity populated with the details for the customer:


        public Customer GetById(Guid id, string connectionString)
        {
            Customer customer = null;
            SQLQuery query = new SQLQuery("Customers.GetById", CommandType.StoredProcedure, connectionString);
            query.AddParameter("@Id", SqlDbType.UniqueIdentifier, id, ParameterDirection.Input);
            DataTableReader reader = query.ExecuteDataSet().Tables[0].CreateDataReader();


            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    customer = new Customer
                                   {
                                       AddedOn = (DateTime) reader["AddedOn"],
                                       EmailAddress = (string) reader["EmailAddress"],
                                       Firstname = (string) reader["Firstname"],
                                       Id = new Guid(reader["Id"].ToString()),
                                       ModifiedOn = (DateTime) reader["ModifiedOn"],
                                       Surname = (string) reader["Surname"], 
                                       Lists = GetListsByCustomerId(id, connectionString)
                                   };
                }
            }
            return customer;
        }

The Lists property of my Customer entity is populated by another method called GetListsByCustomerId, which takes the Id of the customer and returns a list of CustomerLists to populate my Customer Lists property:


        public List<CustomerList> GetListsByCustomerId(Guid id, string connectionString)
        {
            List<CustomerList> lists = new List<Domain.Entities.CustomerList>();
            SQLQuery query = new SQLQuery("Customers.GetListsByCustomerId", CommandType.StoredProcedure, connectionString);
            query.AddParameter("@Id", SqlDbType.UniqueIdentifier, id, ParameterDirection.Input);
            DataTableReader reader = query.ExecuteDataSet().Tables[0].CreateDataReader();


            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    CustomerList customerList = new Domain.Entities.CustomerList
                    {
                        CreatedOn = (DateTime)reader["CreatedOn"],
                        Name = (string)reader["Name"],
                        Id = new Guid(reader["Id"].ToString()),
                        ModifiedOn = (DateTime)reader["ModifiedOn"],
                        Checked = Convert.ToBoolean(reader["CustomerInList"])
                    };
                    lists.Add(customerList);
                }
            }
            return lists;
        }


Note: The SQLQuery object in the above sample is a custom SQLQuery component - if you are wanting to copy this code, you will need to change this appropriately to your own code to return a DataTableReader.

You'll have noticed in my CustomerList object, I have a property called Checked. This is because in my stored procedure to return the lists for a customer, I am returning all lists and not just the lists for that customer. In my stored procedure I am returning a value to indicate whether the customer is in the list or not, and setting the Checked property appropriately from my query value CustomerInList. This allows for the available lists and the lists a customer is in to be returned in one recordset, saving a database call. My stored procedure is:


DECLARE @temp TABLE ( Id uniqueidentifier, Name nvarchar(50), CreatedOn datetime, ModifiedOn datetime, CustomerInList bit)
INSERT INTO @temp (Id, Name, CreatedOn, ModifiedOn, CustomerInList)
SELECT 
Lists.Id, 
Lists.Name, 
Lists.CreatedOn, 
Lists.ModifiedOn,
(SELECT COUNT(Id) FROM Customers.CustomerLists WHERE ListId = Lists.Id AND CustomerId = @Id)
FROM Customers.Lists

SELECT * FROM @temp




The MVC View

In my Edit view, I now want to display my list of CustomerLists as checkboxes, with lists my customer is in marked as checked.


The best way to do this is with a PartialView and include this in your edit page:

                @model Services.ViewModels.EditCustomer 



                @foreach (var list in Model.Details.Lists)
                {
                    @Html.EditorFor(x => list, "CustomerLists")
                }
                <div>@Html.ValidationMessageFor(m => m.Details.EmailAddress)</div>

Note: The EditCustomer model is myViewModel which has a property of details. My populated customer entity is returned in this property

My CustomerList partical view is:


@model Domain.Entities.CustomerList


@Html.HiddenFor(x => x.Id)
@Html.HiddenFor(x => x.Name)
<div>
    @Html.CheckBoxFor(x => x.Checked)
    @Html.LabelFor(x => x.Checked, Model.Name)
</div>




When the view is rendered, I will now have a list of checkboxes, with one for each of my CustomerLists, and checked if my customer is a member of that list.


Hope this helps - you can download a sample MVC3 application from here





Friday, 25 May 2012

MVC3 - Securing with Authentication and Anti-forgery by Default

Following on from my post about securing MVC3 application by use of global filters, I have released today a package on nuget.org that can be installed to do this automatically.


In addition to requiring to set explicit anonymous access for controller actions you want to be accessible anonymously, there is also ad additional filter for anti-forgery tokens. The additional filter requires you to pass an anti-forgery token in every form post.


Please download the package and let me know what you think! 


https://nuget.org/packages/ValidationAndAuthenticationByDefault.MVC3/1.0.0 

Wednesday, 2 May 2012

Securing Your MVC Intranet Applications - Security by Default

The standard way to secure your MVC Intranet applications is to use the [Authorize] attribute for controller actions you want to secure. The controller is the resource you're actually trying to protect and any security decisions should be done at the controller level rather than at the route level.


For example using the default Intranet Application template in MVC3, you will have a Home Controller that looks like the following:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;


namespace MvcAuthenticationSample.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";


            return View();
        }


        public ActionResult About()
        {
            return View();
        }
    }
}

To force users to log on when they access /Home/, you would add the [Authorize] attribute to your Index ActionResult, like this:

[Authorize]

public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";


            return View();
        }

If you are using the built in Membership provider included in the Intranet Application template and set the [Authorize] attribute on the Index() ActionResult above, your users will be redirected to the LogOn action in your Account Controller. If a user accesses /Home/About/, they will not be redirected.


Hopefully you can see the flaw in this approach for an Intranet Application as a controller action may be created where the [Authorize] attribute is not set where it should be. You might think this will be mitigated by testing, but it can be easily overlooked.


The best way to secure your MVC Intranet Application is to require have all controller actions by default  require authorisation. You can then open up access to controller actions you want users to be able to access anonymously, which leads to a much better approach to security.


One way of doing this is to create a base controller with the [Authorize] attribute set, and have all your controllers derive from this base controller. However, with this approach there is nothing to stop a controller being created that doesn't derive from the base controller you have created.


A much better way to do this is to use Global Filters. This allows you to set a global filter for all controllers in your application, which means they will have the [Authorize] attribute set by default, whether or not they derive from a base controller. Coupled with this, you can then create a custom attribute which you set explicitly for controller actions that do not require authorisation.


To do this, first you need to create your custom allow anonymous attribute:


using System;


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class AllowAnonymousAttribute : Attribute { }

You will also need to create a filter that derives from AuthorizeAttribute:

public sealed class LogonAuthorize : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
            if (!skipAuthorization)
            {
                base.OnAuthorization(filterContext);
            }
        }
    }

You will then need to register this new filter in RegisterGlobalFilters in global.asax:

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new LogonAuthorize());
        }

And voila! Your controllers will require authorisation by default. However...

With this filter registered, you will not be able to log on! This is where you need to set you AllowAnonymous attribute in your Account Controller to allow users to access actions associated with logging in to your application:

        [AllowAnonymous]
        public ActionResult LogOn()
        {
            return View();
        }

        //
        // POST: /Account/LogOn

        [HttpPost]
        [AllowAnonymous]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (Membership.ValidateUser(model.UserName, model.Password))
                {
                    FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "The user name or password provided is incorrect.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

I would personally like to see future version of MVC intranet application templates implement a secure by default approach to controllers. Inadvertently creating security holes in applications can be a big problem that is difficult to rectify.

A sample project can be downloaded from here.



Monday, 23 April 2012

Custom WCF Authentication Using Message Contract

When you create a WCF Service or Web Service, you may want to implement subscription based access to this service. This allows you to have many customers consuming the service, with each customer having their own account and credentials to access.

When creating ASP.NET Web Services, implementing subscription based access can be done by using the SOAP header to add credentials particular to the customer consuming the web service. In a WCF service, this is done using the Message Contract.

For this post, I have created a test WCF service application which is used to return account data for a customer. The interface has one operations contract called GetAccountsData which returns a message contract called accounts info. As the accounts info message contract has sensitive information, I am also specifying the EncryptAndSign attribution on the properties on the message contract. 

The Interface:

[ServiceContract]
    public interface IAccountsService
    {
        [OperationContract]
        AccountsInfo GetAccountsData(CustomerCredential cCredential);
    }


The message contract:

    [MessageContract]
    public class AccountsInfo
    {
        [MessageBodyMember(Order = 1, ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        public string CustomerID;

        [MessageBodyMember(Order = 2, ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        public string AccountNumber;

        [MessageBodyMember(Order = 3, ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        public double CurrentBalance;
    }

You'll notice the use of another message contract in the GetAccountsData method - CustomerCredential. This method contract is used to pass authentication information from the client when GetAccountsData is called.

    [MessageContract]
    public class CustomerCredential
    {
        [MessageHeader(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        public string SecurityToken;

        [MessageBodyMember(Order = 1, ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        public string CustomerID;

    }

I also have a class that implements IAccountsService and contains GetAccountsData. For the purposes of this example, I have hard-coded an authentication token and have continued if the correct token is passed through, however this is where you would make a call to your data store to authenticate the token and validate the client accessing the service.

public AccountsInfo GetAccountsData(CustomerCredential credentials)
        {
            if (!string.IsNullOrEmpty(credentials.SecurityToken))
            {
                if (!credentials.SecurityToken.Equals("7DB8B334-8F1A-4EF0-8586-1FF7C279502F"))
                {
                    throw new FaultException("You are not authorised to access the method");
                }
                else
                {
                    // A database/data store call would be made here to get the data and return based on the customer ID.
                    // You could also do further security checks such as the customer requiring to enter a PIN
                    if (credentials.CustomerID.Equals("C123"))
                    {
                        return new AccountsInfo { CustomerID = "C123", AccountNumber = "987654321", CurrentBalance = 1000 };
                    }
                    else
                    {
                        return new AccountsInfo { CustomerID = "N/A", AccountNumber = "N/A", CurrentBalance = 0 };
                    }
                }
            }
            else
            {
                throw new FaultException("Security information not provided");
            }
        }


To consume this service, I have created an empty MVC3 Web Application which has just one controller returning an action result - I didn't want to overcomplicate for the example, but you should be able to see how this example can be extended and built upon.

The Index ActionResult of my HomeController has the following code:

CustomerAccount account = new CustomerAccount();
            try
            {
                ChannelFactory<IAccountsService> factory = new ChannelFactory<IAccountsService>("WSHttpBinding_IAccountsService", new EndpointAddress("http://localhost:8013/AccountsService.svc"));
                IAccountsService proxy = factory.CreateChannel();
                CustomerCredential credentials = new CustomerCredential();
                credentials.SecurityToken = "7DB8B334-8F1A-4EF0-8586-1FF7C279502F";
                credentials.CustomerID = "C123";
                AccountsInfo accountDetails = proxy.GetAccountsData(credentials);
                
                account.CustomerID = accountDetails.CustomerID;
                account.AccountNumber = accountDetails.AccountNumber;
                account.CurrentBalance = accountDetails.CurrentBalance;

            }
            catch (Exception ex)
            {
                throw ex;
            }

The CustomerAccount is my model, and I am calling my WCF service to return data in the model which is passed to the view.

You'll notice the endpoint of http://localhost:8013 - this is where I published my WCF service and the address I used to add the service reference to my MVC3 application. If you download the attached sample, be sure to either change references to http://localhost:8013 to the URL you published the WCF service to.

To pass in the credentials, I am creating a CustomerCredential object, which we defined in the service. Here I am passing in my hard coded token, however in reality you would issue a token to each client consuming your service for them to pass in at this stage. Your service would then validate the token used as described above.

The test WCF service and MVC3 Web Application used for this post are available from here - www.web-architecture.com/files/WCFSample.zip




Thursday, 19 April 2012

UAC Administrator Access on a Windows Server 2008 Development Server

Windows Server 2008 R2 has UAC build-in and turned on by default. With a server hosting your applications that is exposed to the outside world, you definitely want to keep this feature turned on!


On an internal development server however, you may wish to disable UAC for the administrator users group as with it turned on you will find barriers when testing that can slow things down - one example is changing a value in an exe.config file in the programs directory as you won't be able to save the config file back to the same location without running the editing program in Administrator mode.


To disable UAC for the administrators group, follow these simple steps:


1. On your server, go to "Administrative Tools" > "Local Security Policy"
2. Expand the "Local Policies" > "Security Options" node and find the "User Account Control: Run all administrators in Admin Approval Mode" policy in the main window.



3. Open the policy and select the "Disabled" option. Click OK and reboot your server.



Again, I would stress that you should never contemplate doing this on a production server, even to allow items to be dropped in the GAC. An installer should always be created for adding DLLs to the GAC on a production server in Windows 2008 R2.


Wednesday, 18 April 2012

SQL Server: Insert, Update and Delete Data in a Single Execution by Using MERGE


With the release of SQL Server 2008, insert, update, or delete operations can be performed in a single statement using MERGE. Prior to SQL Server 2008, each insert, update or delete had to be run separately. The MERGE statement allows you to join a data source with a target table or view, and then perform multiple actions against the target based on the results of that join. 


The following example is taken from TechNet, and the original example can be found at http://technet.microsoft.com/en-us/library/bb522522(v=sql.105).aspx This example uses MERGE to insert, update, or delete rows in a target table based on differences with the source data.


Example
==================


Consider a small company with five departments, each with a department manager. The company decides to re-organise its departments. To implement the re-organisation results in the target table dbo.Departments, the MERGE statement must implement the following changes:


  • Some existing departments will not change.
  • Some existing departments will have new managers.
  • Some departments are newly created.
  • Some departments will not exist after the reorganization.

The following code creates the target table dbo.Departments and populates it with managers.


Transact-SQL

USE AdventureWorks2008R2;
GO
IF OBJECT_ID (N'dbo.Departments', N'U') IS NOT NULL 
    DROP TABLE dbo.Departments;
GO
CREATE TABLE dbo.Departments (DeptID tinyint NOT NULL PRIMARY KEY, DeptName nvarchar(30), 
    Manager nvarchar(50));
GO
INSERT INTO dbo.Departments 
    VALUES (1, 'Human Resources', 'Margheim'),(2, 'Sales', 'Byham'), 
           (3, 'Finance', 'Gill'),(4, 'Purchasing', 'Barber'),
           (5, 'Manufacturing', 'Brewer');


The organizational changes to be made to the departments are stored in the source table dbo.Departments_delta. The following code creates and populates this table:


Transact-SQL

USE AdventureWorks2008R2;
GO
IF OBJECT_ID (N'dbo.Departments_delta', N'U') IS NOT NULL 
    DROP TABLE dbo.Departments_delta;
GO
CREATE TABLE dbo.Departments_delta (DeptID tinyint NOT NULL PRIMARY KEY, DeptName nvarchar(30), 
    Manager nvarchar(50));
GO
INSERT INTO dbo.Departments_delta VALUES 
    (1, 'Human Resources', 'Margheim'), (2, 'Sales', 'Erickson'),
    (3 , 'Accounting', 'Varkey'),(4, 'Purchasing', 'Barber'), 
    (6, 'Production', 'Jones'), (7, 'Customer Relations', 'Smith');
GO


Finally, to reflect the company reorganization in the target table, the following code uses the MERGE statement to compare the source table, dbo.Departments_delta, with the target table dbo.Departments. The search condition for this comparison is defined in the ON clause of the statement. Based on the results of the comparison, the following actions are taken.


Departments that exist in both tables are updated in the target table with new names, new managers, or both in table Departments. If there are no changes, nothing is updated. This is accomplished in the WHEN MATCHED THEN clause.


Any departments in Departments_delta that don't exist in Departments are inserted into Departments. This is accomplished in the WHEN NOT MATCHED THEN clause.


Any departments in Departments that do not exist in the source table Departments_delta are deleted from Departments. This is accomplished in the WHEN NOT MATCHED BY SOURCE THEN clause.


Transact-SQL

MERGE dbo.Departments AS d
USING dbo.Departments_delta AS dd
ON (d.DeptID = dd.DeptID)
WHEN MATCHED AND d.Manager <> dd.Manager OR d.DeptName <> dd.DeptName
    THEN UPDATE SET d.Manager = dd.Manager, d.DeptName = dd.DeptName
WHEN NOT MATCHED THEN
    INSERT (DeptID, DeptName, Manager)
        VALUES (dd.DeptID, dd.DeptName, dd.Manager)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE
OUTPUT $action, 
       inserted.DeptID AS SourceDeptID, inserted.DeptName AS SourceDeptName, 
       inserted.Manager AS SourceManager, 
       deleted.DeptID AS TargetDeptID, deleted.DeptName AS TargetDeptName, 
       deleted.Manager AS TargetManager;