Pages

Wednesday, 1 January 2014

Securing WebApi with Live Id authentication token

I wanted to create a small Windows Store App which would save data using a custom WebApi. I didn’t want to ask the user to register and create a new account, so I opted to use Windows Live with wl.signin as the scope to implement a single sign-on solution.

I will be using the User Identifier as a unique identifier for user specific data to show only the relevant data to the user. I do not want to store any personal details as the app will allow users to add, edit and delete only their own data and profile data will not be required to do this.

I wanted to implement the WebApi as a MVC5 WebApi2 solution which would allow me to create a web client that consumes the same WebApi at a later stage. This approach would also allow me to learn about the implementation of OWIN authentication middleware.

Getting to the bottom of how I would authorise access to the WebApi resources using the OWIN pipeline took me much longer than I anticipated and decided to create this blog post to help others that want to do the same.

I don’t know if this is the best way or even the correct way of implementing this and I will be researching this a lot more to be sure it is secure and implemented correctly. Please feel free to comment on this approach and let me know if it should be changed or can be improved.

Please note I have simplified the example code significantly for brevity and have no error handling, please use the code as an example only.

If you want to follow this tutorial please create a solution as follow:

1.) Create a new Windows Store App using this Blank App (XAML) template

image

2.) It is very important to associate the app with your store account. This will update the app manifest to allow us to use the Live Connect APIs LiveAuthClient to sign users in.

image

3.) Add the WebApi project to the solution

image

image

4.) Change the authentication to ‘No Authentication’

image

Signing the user in with Live SDK in the Windows Store App

The first thing we want to do is to get an authentication token that will be used to authorise requests to the WebApi. I opted to use the Nuget package to reference the Live Connect APIs instead of installing the SDK.

Add the LiveSDK package using the Package Manage Console:

PM> Install-Package LiveSDK
Installing 'LiveSDK 5.5'.
Successfully installed 'LiveSDK 5.5'.
Adding 'LiveSDK 5.5' to SignMeIn.
Successfully added 'LiveSDK 5.5' to SignMeIn.

It is important that we specify a redirect domain for the app, configure your app and specify a redirect domain.


Create a method in the MainPage class file to authenticate the user

private async Task<string> AuthenticateAsync()
{
try
{
var auth = new LiveAuthClient(“<<The redirect domain for the app>>”);
var loginResult = await auth.LoginAsync(new[] { "wl.signin" });
// ToDo: add code here to handle Login failure
if (loginResult.Status == LiveConnectSessionStatus.Connected)
{
return loginResult.Session.AuthenticationToken;
}
}
catch (Exception)
{
// ToDo: add code here to handle Login failure
throw;
}
return string.Empty;
}

It is worth reading up and understanding the core concepts of the Live Connect APIs


Next we add a method to retrieve data from the WebApi, I am using the Microsoft.AspNet.WebApi.Client Nuget package for this.

PM> Install-Package Microsoft.AspNet.WebApi.Client

Create the GetData method in the MainPage class file, the authentication token we got from the AuthenticateAsync method is set as the bearer token in the the auhorization header. The bearer token will be used by the WebApi to authorize access to the requested resource. At this stage the WebApi does not enforce any authorization and all requests will be allowed.

private async Task<string> GetData(string authenticationToken)
{
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("<<The root URL for your web application>>");
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", authenticationToken);

var respone = await httpClient.GetAsync("/api/values");

var content = await respone.Content.ReadAsStringAsync();

return content;
}

Authorising the WebApi requests


We will be using OWIN Middleware to validate the bearer token passed in the authorization header and create a ClaimsIdentity with the claims issued by the Microsoft Live service to authorize requests to resources. The authentication token issued by Microsoft Live is a JsonWebToken which we need to unpack and validate the signature to ensure the token is tamper proof.


This can be done using OAuthBearerAuthenticationMiddleware by configuring it with the UseJwtBearerAuthentication extension method.


First of all we need to install the Microsoft.Owin.Host.SystemWeb and  Microsoft.Owin.Security.Jwt nuget packages.

Install-Package Microsoft.Owin.Security.Jwt

Install-Package Microsoft.Owin.Host.SystemWeb

Now we need to configure the OAuthBearerAuthenticationMiddleware by adding it to the OWIN pipeline. We do this by adding a Startup.cs class with an OwinStartupAttribute.

using Microsoft.Owin;

[assembly: OwinStartup(typeof(SignMeIn.Web.Startup))]

namespace SignMeIn.Web
{
using System.Security.Cryptography;
using Microsoft.Owin.Security.Jwt;
using Owin;

public class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}

private void ConfigureAuth(IAppBuilder app)
{
// Create the signing key that will be used to validate the token
// This is based on the application secret
var sha256 = new SHA256Managed();
var secretBytes = System.Text.Encoding.UTF8.GetBytes("<< Your App Secret >>" + "JWTSig");
byte[] signingKey = sha256.ComputeHash(secretBytes);

app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AllowedAudiences = new[] { "<<the audience allowed>>" },
IssuerSecurityTokenProviders =
new[]
{
new SymmetricKeyIssuerSecurityTokenProvider(
"urn:windows:liveid", signingKey)
}
});
}
}
}

Now we can add the AuthorizeAttribute to our ApiControllers to limit access to requests that have a valid bearer token and retrieve the uid claim from the ClaimsIdentity.

public IEnumerable<string> Get()
{
var identity = this.User.Identity as ClaimsIdentity;
var uid = identity.Claims.First(c => c.Type == "uid");

return new string[] { "value1", "value2" };
}

If you have any issues with getting this to work, make sure you turn tracing on for OWIN by adding the following to the Web.Config. This will allow you to see any warings in the Dbug Output window

<system.diagnostics>
<switches>
<add name="Microsoft.Owin" value="Verbose" />
</switches>
</system.diagnostics>

Ensure that both applications start when you debug by setting the solution properties to multiple startup projects when you are testing this.


image

Sunday, 20 May 2012

Hosting RavenDB on Azure under a worker role

We decided to use RavenDB as the store for the new codewrap internet application, as we decided to use Azure as our PaaS we had to find a solution to run RavenDB on Azure. I found a really good post by Mike Hanley on RavenDB Running in Windows Azure. We now have a really good starting point and a base platform to build on.

The next steps are to secure access to RavenDB more and I will be making some changes to run the endpoints as Internal instead of Input. This should be sufficient for now, as we are still actively in the development phase and data will be dropped and recreated on a regular basis.

I ran into two problems when I followed Mike’s blog, and they were mainly due to my lack of knowledge on Azure.

You need to configure your “StorageAccount” as a connection with YOUR storage account details, to allow the mounting of the cloud drive when deployed to Azure

image

I also had to set the executionContext to elevated as mentioned in the comments to allow RavenDB to listen for HTTP request. You can do this by editing the SeviceDefinition.csdef file.

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="........." xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WorkerRole name="raven.worker" vmsize="Small">
<Runtime executionContext ="elevated" />
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
<Endpoints>
<InternalEndpoint name="Raven" protocol="http" port="8080" />
</Endpoints>
<LocalResources>
<LocalStorage name="RavenCache" cleanOnRoleRecycle="false" sizeInMB="1024" />
</LocalResources>
<ConfigurationSettings>
<Setting name="StorageAccount" />
</ConfigurationSettings>
</WorkerRole>
</ServiceDefinition>

We are now in a good position to evaluate RavenDB on Windows Azure and start some RnD using it as our primary data store.

Sunday, 6 May 2012

Using bind prefix in ASP.NET MVC with overlays

Lets say you want to build an application where you add friends and hobbies to your profile using Ajax. The approach I would take is to include the markup for the friend and hobby forms as part of the profile page markup to make the UI more responsive when the overlays are shown. By doing this you could end up with duplicate element names and ids which can break UI behaviour or if the elements are in a form will not bind correctly when you submit it.

Models:

Here is the view model for the profile page, note that I added the friend and hobby edit models as properties, this is not required but my view is that it important to make it clear that the view for the profile page depends on the friend and hobby models.

public class ProfileViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public FriendModel FriendModel { get; set; }
public HobbyModel HobbyModel { get; set; }
}

public class HobbyModel
{
public int Id { get; set; }
public string Name { get; set; }
}

public class FriendModel
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
}

Views with no bind prefix


When you render the partial views with no prefix the Name elements will have the same name and id, creating duplicate elements in the markup.

<div id="friendOverlay" class="overlay">
@Html.Partial("_AddFriend", Model.FriendModel)
</div>

<div id="hobbyOverlay" class="overlay">
@Html.Partial("_AddHobby", Model.FriendModel)
</div>

Html rendered with no bind prefix


Note the id and name attributes are the same for both input elements.

FriendModel:
<div class="editor-field">
<input class="text-box single-line" id="Name" name="Name" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
</div>

HobbyModel:
<div class="editor-field">
<input class="text-box single-line" id="Name" name="Name" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
</div>

Views with bind prefix


Note the HtmlFieldPrefix is a property on the TemplateInfo property of the ViewDataDictionary that is passed to the Partial method.


The code is not the most elegant, you could create a html helper to improve this.

<div id="friendOverlay" class="overlay">
@Html.Partial("_AddFriend", Model.FriendModel, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "friend" } })
</div>

<div id="hobbyOverlay" class="overlay">
@Html.Partial("_AddHobby", Model.HobbyModel, new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "hobby" } })
</div>

Html rendered with bind prefix


Note the id and name attributes of the input elements are now prepended with the prefix specified.

FriendModel:
<div class="editor-field">
<input class="text-box single-line" id="friend_Name" name="friend.Name" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="friend.Name" data-valmsg-replace="true"></span>
</div>

HobbyModel:
<div class="editor-field">
<input class="text-box single-line" id="hobby_Name" name="hobby.Name" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="hobby.Name" data-valmsg-replace="true"></span>
</div>

Binding the form to the model:


The final change we need to make is to tell the model binder to use the relevant prefix when binding the forms data to the model on post back. We do this by simply adding the BindAttribute to the property of the action we are posting to.

public ActionResult AddFriend([Bind(Prefix = "friend")] FriendModel model)
{
// code to process the model
// code to return result
}

public ActionResult AddHobby([Bind(Prefix = "hobby")]HobbyModel model)
{
// code to process the model
// code to return result
}