DarksideCookie

Come to the dark side...we have cookies!

Implementing federated security with Azure Access Control Service

I believe it is time for a really heavy blog post, and if you have ever read one of my other blog posts you are probably getting scared now. My posts are normally big, but this might actually be even bigger… Sorry! But it is an interesting topic with many things cover…

But before we can start looking at code, there are 2 things I want to do. First of all, I want to thank my colleague Robert Folkesson (warning, blog in Swedish) for getting me interested in this topic, and for showing me a great introduction.

And secondly, I want to give a quick run-through of what federated security and claims based authentication means…

Federated security means that an application relies on someone else to handle user authentication, for example Windows Live or Facebook. These identity providers are responsible for authenticating the user, and returning a token to the application, which the application can use to perform authorization.

The token that is returned contains a set of “claims”, which are small pieces of information about the user. It can be the users name, e-mail, username, role and so on. In reality, it can be anything the identity provider feels like providing. The application can then look at the claims and provide authorization based on this.

This is called claims based authentication, and sort of replaces the roles based authentication that we are used to. Why? Well, it is a lot more granular. Instead of giving access to a specific role, we can authorize access based on a whole heap of things, ranging from username to domain to “feature”. Anything we can think of. And on top of that, as long as we trust the identity provider, any provider can issue these claims, making our security much more flexible.

What I am going to be showing today however, is not based on using a provider like Facebook. Instead, I will use a custom Secure Token Service (STS) that implements a protocol called WS-Federation. WS-Federation is the same protocol that for example Active Directory Federation Service (ADFS) implements. The main difference between the custom one I’ll be using, and the “real” thing, is that this simple implementation (that I have actually borrowed) is mostly hardcoded and doesn’t actually do anything except generate a predefined token. But this will work fine for the demo…

But before we can get started, we need to get some pre-requisites installed. First of all, we need to get WIF Foundation installed. On top of that, we need the Windows Identity Framework SDK (WIF SDK) installed as it will help us with some configuration in VS. I will also use some code from a sample project built by Microsoft called Fabrikam Shipping. So that source code is important as well.

Fabrikam Shipping is a demo application developed by Microsoft to show off federated security among other things. It covers much more than this post, but is also much more complicated… The reason to download it is that I will be using bits and pieces from that project…

Now that all of the pre-requisites are installed, we can get started! The first thing on the list of things to do, is to get an STS up and running. Luckily, the Fabrikam demo comes with a simple STS application (as mentioned before). It is in the SelfSTS solution, which can be found in the unpacked “Fabrikam Shipping” folder under “assets\SelfSTS”. Unfortunately it doesn’t come pre-compiled, so you need to open the project and run it, which will produce a screen that looks like this

image

However, before we move any further, we need a new cert to use for signing the token. We could use the existing one, but I will create a new one just to cover that as well.

Creating the cert is easily done by clicking “Generate New..” in the UI, which will generate a new pfx-file in the folder where the SelfSTS.exe file is located. Give the cert a useful name and a password you can remember. That is bin/Debug if you just F5:ed to start the application. The cert is automatically used by SelfSTS…

If you click in the “Edit Claim Types and Values”, you can update the claims that the STS will issue in the token. This isn’t necessary, but the feeling is so much better when the application greets you by your real name instead of Joe (btw, isn’t it normally John Doe, not Joe Doe?)

And yes, before we go on, press the big, green start button.

The newly created cert obviously needs to be available on the machine that is going to run the application that consumes the token for it to work. In this case, that is the local machine. And it needs to be installed in a places where the application user can find it, and has access to it.

In this case, it will be a web application hosted in IIS. And being the lazy person that I am, I installed the cert in the machine store under the Personal container and set the ACL to allow Everyone to read it. In a real scenario you would do this in a safer way…

The actual install of the cert is outside of the scope of this post, but if you Google it you will find a million tutorials on the web. It is easy to do through mmc.exe and the Certificate snap-in.

Ok, STS done! Nice and simple! At least when using SelfSTS… Smile

Next, we need to configure the Azure Access Control Service (ACS), letting it know about our STS. To do this, you have to log into the Azure management portal and click “Service Bus, Access Control & Caching” in the lower left corner. Next, select “Access Control” and click “New”, which will launch this screen

ACS Setup 1

Fill in the namespace, location and subscription you whish to use and click “Create Namespace”. Creating the namespace will then take a couple of minutes…

While that is being created, you can have a long hard think about who would want to steal the namespace “darksidecookie”!? I wanted that for obvious reasons, but it was taken…

Once the namespace is active, select it and press the “Access Control Service” button at the top of the UI

ACS Setup 2

This will bring up a new page where you can configure the access control. It even has a step-by-step of what you need to do to get up and going on the first page… So following that, start by clicking “Identity Providers”.

As you might see, Windows Live provider is already there, and can’t actually be removed… What you want is the “Add” link, which will start a wizard to guide you through setting up a new identity provider.

In this case, we want a WS-Federation provider, and after you have given it a useful name, you need to provide it with an XML file that tells it a bunch of stuff about the STS we are about to use. As our STS is running locally, we can’t give it the address to that. Instead, we choose to upload the XML as a file.

The FederationMetadata.xml can be fetched using a browser. Just point it at http://localhost:8000/STS/FederationMetadata/2007-06/FederationMetadata.xml, where SelfSTS will provide you with what you need. Save the XML to a file and upload it to the Azure ACS.

The login text is irrelevant for this demo, so just put whatever you want in there, and then press “Save”, which should send you back to a page that looks something like this

ACS Setup 3

Ok, so now the ACS knows where to get the token from. The next step is to set up a “Relying Party Application”, which is the name for an application that relies on the ACS for authentication…

To do this, click the “Relying party applications” link and then “Add”. Give your application a useful name, and a realm, which is, as the page explains, the Uri for which the token is valid. If you are running locally, http://localhost/ will do just fine.

The token format should be “SAML 2.0”, and encryption should be turned off for this demo, as we don’t need it… Token lifetime is up to you, I left it at 600…

Next, you want to make sure that your new identity provider is ticked, as well as “Create new rule group”. And also make sure that you generate a new signing key before clicking “Save”.

After we got our “Relying party application” set up, we are almost done. However, we need to look at the rules for this application first.

Click “Rule Groups” and then the “Default Rule Group for XXX”, which will bring up a screen that shows you all the rules for the application. In this case it should be empty as we are in the middle of setting up our first application. But you can easily fill it up with the rules you need by clicking “Generate”. This will look through the configuration XML you uploaded for the STS, and automatically add “passthrough rules” for each of the claims issued by the SelfSTS service.

ACS Setup 4

“Passthtrough” means that the claims issued by SelfSTS will just pass through the Azure ACS and get delivered to the application. You can change the rules to limit what is passed to the client, remap values and modify the claims in a bunch of ways. I will talk a little bit more about this later…

Ok, now the Azure ACS is configured for our application, and we can focus on creating the actual application, which will be a new ASP.NET MVC 3 application (I guess MVC is the way to go…) in VS2010.

Next, we need to set up a new host in the hosts file and map it to 127.0.0.1. We also have to create a new website in IIS, pointing towards the project folder of the new MVC application and using the host header we just added to the hosts file.

You also need to make sure that you update the application pool configuration to use .NET 4.0 instead of 2.0, which is the default. You could also configure it to run under a specific user account and only give that user access to the certificate that I previously set up to allow access for Everyone.

Now that we have a MVC 3 application project set up, with IIS hosting, it is time to configure it to use federated security, which is really easy when you have the WIF SDK installed. Just right-click your project and choose “Add STS reference...”.

In the wizard that opens, give it the URL to the site, as defined in the hosts file, and press “Next”. Ignore the potential warning that pops-up, it is just telling you that you are trying to use cool security stuff without using SSL. In this case that is actually ok…

Next, select “Use an existing STS”. The location of the metadata document is available in the ACS configuration website under “Application Integration”, under “WS-Federation Metadata”.

Once it has loaded that metadata, it will complain about the STS using a self-signed cert, which we actually know. Just disable certificate chain validation…

On the next screen however, we want to make sure to tell it that the token is encrypted, and select the self issued certificate that was imported earlier in the post.

After that, it is next, next, finish…

This will add a bunch of configuration in web.config, as well as a FederationMetadata folder with the meta data for the STS.

Ok, security configured! Time to create a view. First up, the index view!

The Home controller has very little code. For index() it uses this

public ActionResult Index()
{
var claimsIdentity = (IClaimsIdentity)this.HttpContext.User.Identity;
return View(claimsIdentity);
}

It basically just casts the current identity to an IClaimsIdentity and uses that as the model.

The view is almost as simple

@using Microsoft.IdentityModel.Claims
@model IClaimsIdentity
@{
ViewBag.Title = "Index";
}

@if (Model != null && Model.IsAuthenticated)
{

<h2>Hello @Model.Name! How is your life as a @Model.Claims.Where(c => c.ClaimType == "http://schemas.xmlsoap.org/claims/Group").First().Value?</h2>

<span>Your claims:<br />
@foreach (var claim in Model.Claims)
{
@claim.ClaimType @:: @claim.Value<br />
}
</span>
}

What the view does is pretty simple. If the user is authenticated, it writes out a greeting consisting of the name of the user and the group he/she belongs to. It then iterates through each claim and prints it on the screen.

That should be it! However, pressing F5 give you an error saying “A potentially dangerous Request.Form value was detected…”. The reason for this error is fairly simple. ASP.NET validates all incoming form posts and makes sure that no “<” characters are posted to the application in due to security issues. I will get back to why we are getting a “<” posted, but for now all we need to do is either turn off validation, or change the validation.

Turning it off is as simple as adding the following to you web.config

<configuration>
<system.web>
<pages validateRequest="false" />
</system.web>
</configuration>

If you still want validation, you will have to change the validation that is going on. Luckily, the Fabrikam Shipping solution has already done this. Just copy the “WSFederationRequestValidator.cs” file from “FabrikamShipping.Web\Security” to your project, add a reference to Microsoft.IdentityModel to your project and add the following to your web.config

<configuration>
<system.web>
<httpRuntime requestValidationType="Microsoft.Samples.DPE.FabrikamShipping.Web.Security.WSFederationRequestValidator" />
</system.web>
</configuration>

Ok…time to go F5 again… This time it should work, and you should see something like this

F5 2

Ok, so we have obviously got it all going! But what is really happening? Well, you might see that the screen flickers a bit as the page is loaded. The reason for this is that as soon as you try to reach the site, it sees that you have no token and redirects you to the ACS, which in turn redirects you to the SelfSTS, which returns a token to the ACS, which takes those claims and returns them in a token to IIS.

Ehh…what? Well, it is easy to see what is happening in Fiddler

Fiddler

It might be a bit hard to see, but the first row is a 302 from the IIS (I am using www.securesite.com in my hosts file). The 302 redirects to xxxxxx.accesscontrol.windows.net over SSL. The return from the ACS is a page that causes a redirect to http://localhost:8000/ (SelfSTS). SelfSTS in turn replies with a page that contains an HTML form containing the token, as well as a JavaScript that posts the form back to the ACS. The ACS then takes the claims and repackage them in a token that is passed back to the client, which sends them to the IIS.

At least I think that is the flow. It gets a little complicated. The important part is that the token arrives and the user is authenticated!

Ok, now that security seems to work, it is time to start tweaking it a bit. I want to make sure that whenever a user is part of the group “Developers”, I want to add another claim to the token, something that is really easy with the ACS.

Open the ACS configuration page and click on “Rule groups” and then the default group from earlier. Click “Add” to add a new rule. In this case, I want the issuer to be the ACS and the input claim to be a “http://schemas.xmlsoap.org/claims/Group”. As you can see, it is open for you to input whatever you want as well…very flexible! The input claim value should be “Developers”, making sure that this rule is only applied when there is a group claim with the value “Developers”.

In the “Then” section, tell it to add an output claim with a type of “MyOwnClaimThingy” or whatever you want. The value can be whatever, as long as you input one. I chose “Dude!”. Finally press “Save”.

Go back to VS and re-run the application. Remember that the token might still be active (and in a cookie), so you might have to close the browser and re-start it.

When you load up the screen, there is no new claim…ok…simple reason. The SelfSTS is configured to issue the group claim with a value of “Sales” (I think…). So open the SelfSTS window (might have been minimized to Systray…) and stop it. Then edit the claims to make sure that the group claim says “Developer”.

Restart the browser again to get the new result, which should now be contain a claim called “MyOwnClaimThingy”, or whatever you called it, with whatever value you chose.

Ok, but what if you don’t want the authorization to be active everywhere? Maybe only a part of the site needs authorization. Well, simple! It is all based around the regular ASP.NET security. Just open the web.config and change the regular <authorization /> element

<configuration>
<system.web>
<authorization>
<allow users="*" />
<!--<deny users="?" />-->
</authorization>
</system.web>
</configuration>

The above configuration will effectively turn it off completely. You might want to do something else using <location /> elements or something. However, in my case, I want to be able to set the authorization on my controller or individual controller actions instead.

Normally you would just add an Authorize attribute to do this. However, that attribute is based around users or roles, not claims. Luckily, it is ridiculously easy to repurpose it to handle claims. Just add a class that looks like this

public class ClaimsAuthorize : AuthorizeAttribute
{
private readonly string _group;

public ClaimsAuthorize(string group)
{
_group = group;
}

protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
if (!httpContext.User.Identity.IsAuthenticated)
return false;

var identity = httpContext.User.Identity as IClaimsIdentity;
if (identity == null)
return false;

var claim = identity.Claims.Where(c => c.ClaimType == "http://schemas.xmlsoap.org/claims/Group").FirstOrDefault();
if (claim == null)
return false;

if (!claim.Value.Equals(_group, StringComparison.OrdinalIgnoreCase))
return false;

return true;
}
}

It overrides the AuthorizeCore() method with logic that looks for the claims. But before looking for the claim I want, I make sure the user is authenticated and that authentication has produced an IClaimsIdentity.

Next, I can mark any method or controller with this attribute to force authorization…

public class HomeController : Controller
{
public ActionResult Index()
{
var claimsIdentity = (IClaimsIdentity)this.HttpContext.User.Identity;

return View(claimsIdentity);
}

[ClaimsAuthorize("Developer")]
public ActionResult Authorized()
{
var claimsIdentity = (IClaimsIdentity)this.HttpContext.User.Identity;

return View(claimsIdentity);
}
}

As you can see, I have created a new action called Authorized, which requires you to be logged in. If you aren’t, it automatically redirects you to the login page, which in this case is the ACS which just requests a token from SelfSTS and then returns it to the application, which renders the page.

Ok, so the actual implementation needs some tweaking, making sure that you get sent to a log in page and so on, but it works. However, it is up to the STS to give you a way to authenticate. The application just redirects you to the ACS, which in turn redirects you to another page. That page should have log in abilities, and make sure you are who you are, before redirecting you back with a valid token.

So…that is my introduction to federated security using Azure ACS. It is fairly complicated with a lot of moving parts, but once it is up and going, it is pretty neat. I hope my introduction has made it a little easier to follow. If not, tell me so and I will try to do better… Smile

I have a little bit of source code for the web app I was using. It is however dependent on a whole bunch of other stuff as you can see from the post. But I thought I would put it up here anyway… So here it is: DarksideCookie.Azure.FederatedSecurity.zip (71.00 kb)

The source contains the config I was using, however that namespace does not exist anymore. So you will have to configure your own…

Posted: Nov 08 2011, 13:55 by ZeroKoll | Comments (1) |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: Azure | Security
Manage post: :)

Comments (1) -

Luc Bos Netherlands said:

Another great post, thx!

# December 26 2011, 10:01
Comments are closed