Installing LogMeIn on your Windows Azure roles

LogMeIn… I’m assuming everyone knows this great suite of tools. The tools and subscriptions offered by LogMeIn provide you with everything you need regarding remote access and support. What I love the most is that the remote connections are done over simple HTTP traffic and this works through most corporate proxies I’ve encountered (unlike RDP over port 3389).

I rarely need to connect to my Azure instances via RDP, but whenever this happens I get stuck with the same issue. Corporate proxy doesn’t allow traffic other than HTTP. Now in this post I’ll explain how to bypass this issue by installing LogMeIn on your roles to connect over HTTP.

LogMeIn Installer

Start by connecting to your LogMeIn account and choose to add a new computer. When you do, be sure to choose LogMeIn Pro (or the trial). By using LogMeIn Pro you can perform a silent installation but this isn’t supported in LogMeIn Free. I explicitly use the word supported because you could do it. In order to use LogMeIn Free you’ll need to modify the installer (follow this guide).

Download the file but don’t run it yet.

Startup Task

In your project (WebRole or WorkerRole) start by creating a new folder called Startup and add the installer in that folder. Set the Copy to Output Directory property of that file to Copy always.

Create a new file in that same folder called LogMeIn.cmd and also set it to Copy always. The file should contain the following:

Startup\logmein.msi /quiet USERPASSWORD=myLogMeInPassword USERVERIFYPWD=myLogMeInPassword USEREMAIL=myLogMeIn@email.be USERWEBPASSWORD=myLogMeInPassword LicenseType=pro

Finally add the startup task in your ServiceDefinition.csdef:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="MyRole" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole" vmsize="ExtraSmall">
    ...
    <Startup>
      <Task commandLine="Startup\LogMeIn.cmd" executionContext="elevated" taskType="simple" />
    </Startup>
  </WebRole>
</ServiceDefinition>

The solution should look like this:

And you’re done… you can publish now.

Result

Your role is visible in your LogMeIn computers:

And of course, you can connect to your role and also have real time statistics (like CPU and Memory usage). And it’s also very easy to upload files, …

Note that this is great to test things out but I wouldn’t advise on using this in a live environment.

Have fun!

The Belgian eID in Windows Azure – Part 1: Authentication and Identification for your webroles with the eID IdP

If you follow my other blog 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.

Now right click the webrole and choose Add STS reference, fill in the application URI (in our case this is http://127.0.0.1 – this is the address that was assigned by the devfabric). Choose to use an existing STS: https://www.e-contract.be/eid-idp/endpoints/ws-federation/metadata/auth-ident-metadata.xml, this endpoint will authenticate you (by asking your pincode) and identify you (get your information).

To get things working you’ll need to disable the request validation mode (see my previous post):

<httpRuntime requestValidationMode="2.0"/>

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:

Download the code: WebRoleWitheIDIdP.zip
Or try it yourself (will stay online for a few days): http://eid-idp-demo.cloudapp.net

Enjoy!

A few tips to get up and running with the Azure AppFabric Access Control Service

If you plan to use the Azure AppFabric Access Control Service (ACS) you might bump into some challenges to get everything working correctly. Let me give you an overview of issues that might arise and how you can quickly solve them.


Setting up your environment

ACS is based on Windows Identity Foundation and this doesn’t come by default with the .NET Framework. If you want to use ACS you’ll need to install the WIF runtime (and you might also want to install the SDK):

A potentially dangerous Request.Form value was detected from the client (wresult=”<t:RequestSecurityTo…”).

You’ll get this error after a successful login when the identity provider redirects the user to your action. The reason is the following: when redirecting the user to the application the identity provider also passes some extra data containing the information regarding the user.

Take a look at what Fiddler is picking up, there’s a bunch of XML in the wresult key. ASP.NET sees this as a potentially dangerous value and will throw an exception.

Now to solve this you have a few options. First you could choose to turn off validation:


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

    <!-- For .NET 4.0 -->
    <httpRuntime requestValidationMode="2.0" />
  </system.web>

But that’s not such a good solution since this could make your application vulnerable to cross-site scripting attacks. A better way to solve this issue would be to write a custom WIF RequestValidator. The goal of a RequestValidator is to let you override the default ASP.NET validation if you think the request is not unsafe. In our case, if the request contains a sign in response we want the request to be valid and we’ll skip the default validation.

using System;
using System.Web;
using System.Web.Util;

using Microsoft.IdentityModel.Protocols.WSFederation;

namespace Sandrino.SomeAzureApplication
{
    public class AccessControlRequestValidator : RequestValidator
    {
        protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
        {
            validationFailureIndex = 0;

            if (requestValidationSource == RequestValidationSource.Form && collectionKey.Equals(WSFederationConstants.Parameters.Result, StringComparison.Ordinal))
            {
                var message = WSFederationMessage.CreateFromFormPost(context.Request) as SignInResponseMessage;
                if (message != null)
                    return true;
            }

            return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
        }
    }

}

Note that you’ll need a reference to the WIF assembly: Microsoft.IdentityModel.dll

To use this RequestValidator you’ll also need to modify your web.config:


  <system.web>
     <httpRuntime
        requestValidationType="Sandrino.SomeAzureApplication.AccessControlRequestValidator"/>
  </system.web>

Now you’ll be able to login through your identity provider and be redirected to your application without any error. And maybe even more important, without making your application vulnerable to XSS attacks.

More information on TechNet.

Allowing anonymous users on some parts of your application

When you add an STS reference in Visual Studio and start the application you’ll notice that you are immediately required to logon. This might be acceptable for some applications but sometimes you’ll want to implement a homepage where a user could register, see more information, …

Remove the following lines from the web.config:

<system.web>
    <authorization>
      <deny users="?" />
    </authorization>
    ...
  </system.web>

Removing the authorization element will cause the application to be freely accessibly by everyone. Then for each action you want to secure, you should add the Authorize attribute to it.

Example:

    public class CustomerController : Controller
    {
        [Authorize]
        public ActionResult Index()
        {
            return View();
        }
    }

Updating your realm

Once you start using ACS in real projects you’ll notice a small annoyance: the audience Uris and the realm. When you add an STS reference in Visual Studio you’ll notice that the web.config gets filled up with all kinds of elements:

<microsoft.identityModel>
    <service>
      <audienceUris>
        <add value="http://localhost:5100/" />
      </audienceUris>
      <federatedAuthentication>
        <wsFederation passiveRedirectEnabled="true" issuer="https://....accesscontrol.windows.net/v2/wsfederation" realm="http://localhost:5100" requireHttps="false" />
        <cookieHandler requireSsl="false" />
      </federatedAuthentication>
      ...
    </service>
  </microsoft.identityModel>

Now it’s great that we don’t have to fill up the web.config manually but on the other hand this will cause some problems once we start deploying. The relying parties in ACS have a specific return URL set that the user will be redirected to after a successful login. If we do our local, staging and production tests with the same realm we’ll always be redirected to the same page (this might be the production page for example).

You could start playing with forwarding, your hosts file, … but a better way to do this is by updating the realm based on the current url of the application. So if the application runs on http://localhost:90 the realm will also be set to this Uri. And if you create a relying party with this realm in ACS you could set it to forward to http://localhost:90/Customer/Detail for example.

Time for some code:

    public class MvcApplication : System.Web.HttpApplication
    {
        ...

        private void WSFederationAuthenticationModule_RedirectingToIdentityProvider(object sender, RedirectingToIdentityProviderEventArgs e)
        {
            // Get the request url.
            var request = HttpContext.Current.Request;
            var requestUrl = request.Url;

            // Build the realm url.
            var realmUrl = new StringBuilder();
            realmUrl.Append(requestUrl.Scheme);
            realmUrl.Append("://");
            realmUrl.Append(request.Headers["Host"] ?? requestUrl.Authority);
            realmUrl.Append(request.ApplicationPath);
            if (!request.ApplicationPath.EndsWith("/"))
                realmUrl.Append("/");
            e.SignInRequestMessage.Realm = realmUrl.ToString();
        }

        ...
    }

This code is pretty straightforward: each time the WSFederationAuthenticationModule is ready to redirect to the identity provider (ACS) we intercept this call to update the realm of the sign in request. You’ll see other examples where the Reply is updated instead of the Realm. I prefere not doing this to be able to configure the Reply Uri in ACS.

To make this work just add the function with that exact name in your global.asax file.

At runtime you might also experience the following error:

The AudienceRestrictionCondition was not valid because the specified Audience is not present in AudienceUris.

To solve this issue you could change the mode to Never or add each Uri to the list of audienceUris (both in the web.config). Here is an example of the latter:

      <audienceUris>
        <add value="https://localhost:5100/" />
        <add value="https://something.cloudapp.net" />
        <add value="https://something.com" />
      </audienceUris>

Server Error in ‘/’ Application.

When you deploy your application to Azure you might see the following yellow screen of death:

This might be a pain to debug, unless you use the Remote Desktop module. If you get this error and you connect to an instance using Remote Desktop you’ll see the following error in the Event Viewer:

Exception message: Could not load file or assembly ‘Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′ or one of its dependencies. The system cannot find the file specified. (E:\sitesroot\0\web.config line 33)

To solve this error, set Copy Local to true for the assembly: Microsoft.IdentityModel:

Server Error in ‘/’ Application when using multiple instances in Windows Azure

The same error we saw previously could also happen “sometimes” when you use more than 1 instance in Windows Azure, and this is caused because WIF uses DPAPI for encryption and decryption. This is the error you might see in Event Viewer:

[CryptographicException: Key not valid for use in specified state.]
   System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope) +450
   Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Decode(Byte[] encoded) +150

To solve this issue we need to take a few steps. First you should start by creating a new certificate and adding it to the hosted service:

Write down the thumbprint and add it to the certificates of your service definition. If you don’t add it to the service definition you might bump into the following error on the server:

ID1039: The certificate’s private key could not be accessed. Ensure the access control list (ACL) on the certificate’s private key grants access to the application pool user.
Thumbprint: ’0FD1AC13BB1F1B19997DAD5413EA138AC47471F0′

Now in the web.config you should add the following block in the microsoft.identityModel element:

  <microsoft.identityModel>
    <service>
      ...
      <serviceCertificate>
        <certificateReference x509FindType="FindByThumbprint"
          findValue="0FD1AC13BB1F1B19997DAD5413EA138AC47471F0" />
      </serviceCertificate>
    </service>
  </microsoft.identityModel>

To use this service certificate you’ll need to overwrite the FederatedAuthentication‘s default behavior in the global.asax file:

        protected void Application_Start()
        {
            ...
            FederatedAuthentication.ServiceConfigurationCreated += OnServiceConfigurationCreated;
        }

        private void OnServiceConfigurationCreated(object sender, ServiceConfigurationCreatedEventArgs e)
        {
            var sessionTransforms = new List<CookieTransform>(new CookieTransform[]
            {
                new DeflateCookieTransform(),
                new RsaEncryptionCookieTransform(e.ServiceConfiguration.ServiceCertificate),
                new RsaSignatureCookieTransform(e.ServiceConfiguration.ServiceCertificate)
            });

            var sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());
            e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
        }

And that’s all I have to say about this. Hopefully you’ll manage to get everything running with all this information. Shouldn’t this be enough you can always take a look at the following resources:

Enjoy!

Welcome to the Fabric Controller blog

Windows AzureHi and welcome to my new blog on the Windows Azure platform.

My name is Sandrino Di Mattia and I’m a Technical Consultant at RealDolmen. The last few years I’ve been active in the community mainly by writing articles on my blog, on CodeProject, writing for MSDN Magazine, presenting some sessions, … regarding many different technologies (going from WCF to SharePoint to Dynamics CRM).

RealDolmenBut with this blog I want to dive deeper in a technology I truly love: the Windows Azure platform. It has been a little more than a year ago since I started working with Windows Azure (mainly thanks to RealDolmen with our Windows Azure MVP Maarten Balliauw) and I’ve been passionate about the platform ever since.

Because of this decision I felt I had to do one more thing: start a new blog and find a good name for it. First I wanted to go with something cloudy (like nimb.us, strat.us, cumul.us, cumulus.com, …) but none of the domain names seemed available. After looking at even more (and longer) cloud names like pyrocumulonimbus I decided to go from something cloudy to something “Azurey” to finally end up with: ‘Fabric Controller.

That was it, now it’s time to take care of some content for this blog. I hope you’ll enjoy reading my posts as much as I’ll enjoy writing them…

Sandrino