The Belgian eID in Windows Azure – Part 1: Authentication and Identification for your webroles with the eID IdP
You might have noticed that I'm really into the Belgian eID. Needless to say I had to look at how we can use the Belgian eID in Windows Azure. In this series I'll show you how you can integrate it with your existing or future cloud projects.
We'll start by taking a look at the eID Identity Provider (or eID IdP), an open source project hosted on code.google.com:
http://code.google.com/p/eid-idp/. The IdP runs in JBoss and uses a relational database (like MySQL, PostgreSQL, ...). To keep things simple, we won't be looking at how you can install the IdP. Besides running the eID IdP yourself, you can also use the hosted version on the
e-Contract website (managed by Frank Cornelis, one of the contributors of the eID IdP project). The following page shows the supported protocols:
https://www.e-contract.be/eid-idp/main
Since we're going to use Windows Identity Foundation, these metadata endpoints seem to be the most appropriate:
If you look at the claims offered by the WS-Federation Authentication and Identification endpoint, it seems we can get access to some useful information:
schemas.xmlsoap.org/ws/2005/05/identity/claims/name
schemas.microsoft.com/ws/2008/06/identity/claims/role
schemas.xmlsoap.org/ws/2005/05/identity/claims/surname
schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname
schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier
schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress
schemas.xmlsoap.org/ws/2005/05/identity/claims/locality
schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode
schemas.xmlsoap.org/ws/2005/05/identity/claims/gender
schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth
be:fedict:eid:idp:nationality
be:fedict:eid:idp:pob
be:fedict:eid:idp:photo
be:fedict:eid:idp:age
Enough chitchat, show me some code!
Setting up the web application
We're going to build a webrole that will use the eID IdP for authentication and identification. To build this application you'll need the Azure SDK, ASP.NET MVC3, the WIF SDK and the WIF runtime:
Create a new Windows Azure project, add an ASP.NET MVC 3 web role and choose the Internet Application template. Now if you run the application and you'll see that you can view the application without having to login, but this isn't what we want. We would like to have an application that requires you to login using the eID IdP. This way we'll know the user is authenticated without having to do the management of usernames, passwords, security, ... And we're actually externalizing the authentication.
Claims! Claims! Claims!
Before we can run the application we'll write some code to make everything go well and to display the claims we received from the eID IdP. It's important to know that this IdP uses the realm URI as the return URL after a successful login. This means if you used
http://127.0.0.1 as realm, you'll be redirected here. But this isn't what we want...
What we want is that the user gets redirected to an action like /Account/Display after a successful login (to show the user's claims). To achieve this you'll need to add the following code in the Global.asax file:
protected void Application_Start()
{
...
FederatedAuthentication.ServiceConfigurationCreated += OnServiceConfigurationCreated;
}
private void OnServiceConfigurationCreated(object sender, ServiceConfigurationCreatedEventArgs e)
{
FederatedAuthentication.WSFederationAuthenticationModule.SignedIn += new EventHandler(WSFederationAuthenticationModule_SignedIn);
}
private void WSFederationAuthenticationModule_SignedIn(object sender, EventArgs e)
{
HttpContext.Current.Response.Redirect("/Account/Display");
}
Ok this is a good starting point. Now, after a successful login, the user will be redirected to /Account/Display. This means we'll need to write the required code in the AccountController. Let's start with some helper functions that will allow us to get all the claims available for the current identity and an other function that will help us read the value for a specific claim:
private ClaimCollection GetClaims()
{
var claimsPrincipal = Thread.CurrentPrincipal as IClaimsPrincipal;
var claimsIdentity = (IClaimsIdentity)claimsPrincipal.Identity;
return claimsIdentity.Claims;
}
private string GetClaimValue(ClaimCollection claims, string claim)
{
var claimRecord = claims.FirstOrDefault(o => o.ClaimType == claim);
if (claimRecord != null)
return claimRecord.Value;
else
return null;
}
Now with this code it will become very easy to write the required actions: Display and Photo. This Display action maps the claims to the UserInfo model and displays it in the view:
public ActionResult Display()
{
var claims = GetClaims();
var user = new UserInfo();
user.NameIdentifier = GetClaimValue(claims, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
user.Name = GetClaimValue(claims, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name");
user.StreetAddress = GetClaimValue(claims, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress");
user.Nationality = GetClaimValue(claims, "be:fedict:eid:idp:nationality");
user.POB = GetClaimValue(claims, "be:fedict:eid:idp:pob");
user.Locality = GetClaimValue(claims, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/locality");
user.Surname = GetClaimValue(claims, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname");
user.Gender = GetClaimValue(claims, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender") == "1" ? "Male" : "Female";
user.GivenName = GetClaimValue(claims, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname");
user.DateOfBirth = GetClaimValue(claims, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth");
user.PostalCode = GetClaimValue(claims, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode");
user.Age = GetClaimValue(claims, "be:fedict:eid:idp:age");
user.AuthenticationMethod = GetClaimValue(claims, "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod");
return View(user);
}
In the Display view we'll simply show all properties of the model, but we'll also show something else...
<img style="float: right;" src="/Account/Photo" alt="" width="140" height="200" />
Yes... that's right. We'll show the user's photo. One of the claims is the be:fedict:eid:idp:photo claim. This claim contains your picture encoded using standard Base64 encoding. And knowing this makes it very easy to build the Photo action:
public ActionResult Photo()
{
var photo = GetClaims().FirstOrDefault(o => o.ClaimType == "be:fedict:eid:idp:photo");
if (photo != null)
{
var stream = new MemoryStream(Convert.FromBase64String(photo.Value));
return new FileStreamResult(stream, "image/jpg");
}
else
{
return new EmptyResult();
}
}
The result
When you start the application, you'll be redirected to the eID IdP:
After entering the PIN code the Java applet will start reading the eID and the eID IdP will redirect to the realm URI (in this case 127.0.0.1). Since we made that small change in the Global.asax file we'll be redirected to /Account/Display after a successful login:
Enjoy!
Azure AppFabric ACS - Unauthorized: Logon failed due to server configuration
While I was playing around with Azure AppFabric ACS I got the following error:
Error message 401.2: Unauthorized: Logon failed due to server configuration. Verify that you have permission to view this directory or page based on the credentials you supplied and the authentication methods enabled on the Web server. Contact the Web server's administrator for additional assistance.

This error only occured when using ACS in a regular Web Forms application in IIS. But for ASP.NET MVC applications everything worked perfectly. To get my Web Forms application working I had to to turn a Windows feature on: IIS Metabase and IIS 6 configuration compatiblity

After updating the IIS installation the Web Forms application worked perfectly using Azure AppFabric ACS authentication. If you're doing this on Windows Server 2008 you can simply modify the Web Role.
Enjoy
Federated Authentication with Azure AppFabric ACS v2.0: Part 1 - Setup
Yesterday and today I've been teaching the Azure introduction training for MIC Belgium. Even though Azure AppFabric ACS wasn't part of this course it was a hot topic. I showed a demo and we did a small exercise all together, but I promised to create a detailed guide that allows you to create your own applications using federated authentication.
Prerequisites
Before we get started you need a few things on your machine. I was surprised to notice that two of the participants were still running on Windows XP. If you're trying to develop with Azure or WIF then XP is a NO GO. So here is what you need to get started:
To my surprise the WIF SDK does not contain the runtime, so you'll need to install that first.
For the IIS Metabase you'll need to go to Control Panel and choose to turn Windows features on or off:

Creating a simple ASP.NET Website
Start Visual Studio 2010 as Administrator and choose new project to create a normal ASP.NET website. You could use a cloud project but this guide will work with a regular ASP.NET website. After you see the project in the Solution Explorer right click the project and select properties. You'll need to adapt the Web settings to configure IIS.

We're doing this because you might have some problems with Cassini (development webserver) when working with regular (non-MVC) sites and ACS.
- Go to the web tab
- Choose Use Local IIS Web Server
- Click Create Virtual Directory
Now your application should be linked to IIS and if you press F5 everything should work correctly.
Creating an Azure AppFabric ACS namespace
Now that we have a working application it's time to configure Azure AppFabric ACS. ACS will allow us to use identity providers for authentication in our application without having to worry about the management of the identities. One of the goals of federated authentication is that we outsource the identity management. You'll see soon enough what I mean.
Connect to the Management Portal (http://windows.azure.com) and go to the AppFabric tab

Click the Access Control node in the left menu and choose New Namespace. A namespace will allow you to define identity providers and link them to relying party applications (more on this later). Here is an example of how you would create the namespace:

You'll get to set up the name (single word in lower case), choose your subscription and also choose in which datacenter the namespace will be hosted. Before you can create the namespace you need to click the Check Availablity button so see if the namespace you entered has already been taken or not. Click the Create Namespace button and wait a few seconds until the namespace is created.
When the status changes to Active you'll need to select the newly created namespace and click the Access Control Service button. This will forward you to the ACS configuration page and this is where you'll do the actual configuration.

Configuring the relying party application
A relying party application would be your site for example. This site would use ACS to implement federated authentication. But in the end your relying party application will be using claims that come from the identity providers you configure in ACS. You should see a claim as a piece of information about someone's identity. This could be a person's name, function or birthdate for example.
Before defining the relying part application we need to see if the identity providers have been set up correctly. Go to the Identity Providers tab and you should see Windows Live ID to be active be default. Lets leave this how it is for now.

Now go to the Relying party applications tab and choose to add a new one. For the realm and the return URL you should use the URL of your website (for the Visual Studio project that is still open you can just press F5 and you'll see the url of the application). For the application I'm creating this is http://localhost/Sandrino.Labs.ACS/

Besides that you should also select the identity provider(s), but since we only have Windows Live ID (and this is selected by default) you won't need to do anything here for now. Later on the article I'll show you how to add other identity providers, but that's not important for now. Press the Save button and the relying party application will be created.

Now in the left menu click the Rule groups tab. This tab allows you to define the mappings between claims from different identity providers and your relying party application. You should have a default rule group that was created for your relying party application. For my current project this rule group is named Default Rule Group for Labs ACS. Click the name of the rule group to open it.
Press the Generate button, choose Windows Live ID and you'll see that a rule was added matching the nameidentifier claim.

That's it for the ACS configuration for now. The relying party application we configured will now be using Windows Live ID as identity provider and we also have a claim (nameidentifier) that will be accessible from our ASP.NET application. Let's now see how we can use ACS in our application.
Using ACS in our ASP.NET application
If you installed WIF and the WIF SDK correctly you should see the Add STS reference option when you right click the project:

Click this options and you'll see a wizard popping up. On the first page you'll need to configure the Application URI like you configured it in the cloud. This is how I did it:

Before you can continue to the next step you'll need to go back to the ACS configuration page. Click the Application Integration tab and copy the following URL. You need to paste this URL ond the "Use Existing STS" part of the following wizard step.

Now go back to the STS reference wizard and press Next. You'll see the warning message "The application is not hosted on a secure https connection." because you're running on regular HTTP. Ignore this for now by pressing No, but understand that you should always use HTTPS for production applications. On the next page paste the URL you copied from ACS:

Finally press Next until the wizard disappears. This means that both encryption and validation will be disabled but that is ok for now (since we're just developing and exploring ACS). Remember that in an actual production environment your security should be optimal.
If you take a closer look at your project you'll see a new directory called FederationMetadata which contains the referenced FederationMetadata.xml file.
Start your application and see what happens. If everything went we'll you might see a Windows Live ID homepage where you can enter your credentials and after logging in you'll get a nasty ASP.NET error. Should your Windows Live ID password be saved you might not even see the Windows Live ID homepage but see the error immediately.
Fixing the errors
You might run into a few errors, so let's fix these before we continue.
A potentially dangerous Request.Form value was detected from the client (wresult="<t:RequestSecurityTo...").
To solve this problem we simply need to change the request validation mode. Open the web.config and add the following line before the end of the system.web element:

Load User Profile errors
If you're running IIS 7.5 you might run into Load User Profile errors. This is easy to fix: find which application pool your website is using and adapt this pool to support loading of user profiles.
When you select the application pool you need to choose the advanced settings. Here you can see how I'm editing the ASP.NET v4.0 (this should be the one by default) application pool:

This should solve most of your problems. Now try to run your application again, log in to Windows Live and you should be redirected back to your application. You're done! The ASP.NET application you built requires the user to be authenticated and since the relying party application configured in ACS only supports Windows Live ID you'll be forwarded automatically to Windows Live.
Let's see how you can add other identity providers (like Google).
Adding more identity providers
Go back to the ACS configuration page and click the Identity Providers tab. In this example you'll need to add both Google and Yahoo as identity provider. When you add these providers you'll see that the default values of these providers will automatically link these identity providers to your relying party application.

Now to be able to use these identity providers you'll need to configure the claims. Go to the rule groups tab and choose the current rule group (for me this is Default Rule Group for Labs ACS). Now press the Generate button. Pressing the Generate button will make sure ACS automatically generates a list of available claims for the chosen identity providers. The result is clear:

You'll see that we have different types of rules. Each identity provider has a nameidentifier (which we could use as unique key to identify the current user, more on this later). Besides that you can also see that both Google and Yahoo also give you access to other metadata of the identity like the email address or the name.
The identity providers have been added in ACS (and also automatically added in our relying party application) and the claims have been set up. Remember if you are using ADFS or any other system you can modify the rules (under the Rules Group tab) to start mapping claims. This is an important job because your application could/should work with a fixed set of claims independent of the identity provider. That's why we need to do the mappings in ACS (if required).
Final test
When you ran the application the last time you saw that you were forwarded automatically to a Windows Live login page. Now we changed the configuration in ACS to also allow authentication from Google and Yahoo. Please start the application without changing anything and I'm sure you'll be surprised by the result:

Isn't this great? Without changing anything to your code you just allowed users from Yahoo! and Google to use your application. And since ACS also provides support for Active Directory Federation Services you could also allow access from your corporate domain accounts. This last example will be important when you decided to host enterprise applications in the cloud and you need your domain users to access the application.
What's next?
Try these steps for yourself. In the next article I'll show you how you can leverage the Windows Identity Foundation API to access the claims and their values to create a real application using ACS.
Enjoy...