Dotless 1.4.4 is out

Idle hands do… open source?

During the last few weeks, I’ve done something I’ve wanted to do for a longer time, and stepped up my involvement in Free Software somewhat. It started out as kind of an accident: I was encountering an annoying bug that I attributed to our usage of dotless in one of our projects, and I went to the issue tracker looking for reports of a similar problem. Having looked at the tracker for a moment, I then checked the corresponding code and noted that, yes, dotless does in fact do the correct thing. Then I proceeded to look at my own code, and it took me all of five seconds to spot the obvious bug.

A bit embarrassing, sure, but not useless. Because while I was looking through the issue tracker, I noted that some of the issues were of a fairly simple nature — maybe even something I could fix? I remembered fixing a bug back in ’10, so I then went through the list of closed pull requests, and noted that I had contributed no less than five PRs.

During that weekend, I came down with the flu and skipped work. However, I used some of that downtime to work on dotless — given that I had no time constraints or expectations of efficiency, I could spend a moment here and another there to fix a bug or two. First, I ended up going for the low-hanging fruit. I ended up creating about a dozen pull requests — some with bug fixes, some with actual new features.

After giving things about a week to settle, I then asked the current maintainers if they might accept me as a core contributor, since they didn’t seem to have the time to process the pull requests. Not long after that Daniel granted me contributor access to the project, and off I went, merging the PRs in and cleaning up the issue tracker.

Sweet release

Of course, not everything went perfectly: I intended to release dotless 1.4.3 about a week after having merged the fixes in. And I did — except that I messed up the NuGet packaging so that the standalone dotless compiler was left out of the package. And instead of releasing 1.4.3.1 with the fixed package as I should have, I bumped up the version to 1.4.4. I expect that won’t be much of a problem for anyone, though, so I’m not feeling too bad. After all, I did fix a number of inconsistencies, crashers and things like Bootstrap not compiling when minified. So maybe I can forgive myself a bit of a blunder there. :-)

What next?

The less.js guys are thinking about building a .NET wrapper around less.js. It’s an interesting idea, to be sure: that way, the .NET implementation would never need to play catch-up with the official version. However, I still believe there’s merit in having a “native” .NET implementation, so I’m going to keep at it for now.

For the next release, I’ve already got @import options, variable interpolation improvements, list arguments and improved mixin guards. Porting the less.js test cases to give me a rough idea of how far behind is a logical next step. I’d like to aim for feature parity for 1.5 — on the other hand, maybe more frequent releases with smaller, incremental improvements would better serve the project. At the very least, 1.5 should fully support Bootstrap and KendoUI.

A large slice of my professional history is in line-of-business software with user bases ranging in the dozens or hundreds. It’s exciting and a bit frightening to be taking responsibility of a project that has, over the course of years, been downloaded over 400 000 times from NuGet.org. Time to see if I’m up to the task!

NHibernate TimeoutException with Azure SQL

Recently, I spent nearly three full working days debugging the damndest thing: a simple NHibernate Linq query in an Azure test environment was timing out. Together with the SqlAzure client driver that does transient fault handling by retrying queries this resulted in a situation, where a specific page would never load, causing instead a huge spike in the database resource usage.

Of course, as it tends to be with these things, the same query against a local SQL Server database worked just fine.

Possibly the strangest part was that after obtaining the query through NHProf, I tried running the same query via SQL Server Management studio, and the mean execution time of the query was between 100ms and 200ms. Accordingly, I had a hell of a time believing that the issue was an inefficient query as such.

I even tried creating a raw ADO.NET query that had the same command text and parameter specifications… and it executed in under 200ms.

I was about to give up when I had the idea of running both the slow and the fast query against a local database with the SQL Profiler enabled, because while there was no discernible difference in execution time against the local database, perhaps I’d be able to make out some difference in the way the queries were executed.

At first, it looked like the queries were identical from the server’s perspective, too.

But then, I noticed the difference.

The slow query declared that the single parameter’s size was 4000 whereas the fast version said it was 1.

Realization began to dawn, and I re-ran my raw ADO.NET query against the Azure database, but with the parameter size set to 4000 — and wouldn’t you know it, the timeout manifested itself immediately.

My current hypothesis is that what’s going on underneath it all is that the database is waiting for a value for the parameter and it never shows up, which is what causes the timeout. Another strange factor is that the issue doesn’t reproduce with all Azure SQL servers.

All this is triggered by a change to NHibernate Core where the SqlClientDriver skips setting the parameter size to a meaningful value, and instead sets it to a default of 4000.

Fortunately, the workaround is simple: I extended the client driver code with a very specific special-case workaround that sets the parameter size:

It may eventually turn out that I’ll need to handle more than just the one-character parameter size, but for now, this seems to fix the issue.

Media Services at Global Azure BootCamp Finland

I was at the Global Windows Azure BootCamp in Espoo today, rambling about the coolness of the Microsoft media platform in general and Windows Azure Media Services in particular. The event was hosted at the awesome co-workspaces of AppCampus by Teemu Tapanila and Karl Ots — hats off for organizing the event, it was great fun!

I’m not sure if anyone actually tried them, but I put up some lab exercises on GitHub for playing around with Azure Media Services. If you’re looking for a starting point for working with Azure Media Services, go ahead and take a look. :)

The Anatomy of a Cloud Video Service — My TechDays 2013 talk

So, a few weeks back I was on stage at TechDays 2013 Finland. My topic for the day, titled “The Anatomy of a Cloud Video Service”, was about the Futudent “camera + software + cloud service” solution that I’ve been involved with for quite a while now. I intend to cover the associated technologies in more depth in blog form later, but for now, here’s the video of my presentation.

I spent my hour talking about what the client application does, how we handle video transcoding, what it was like to build the associated video sharing service and all the challenges associated with the entire story.

The talk is in Finnish, so obviously it’s only for a limited audience. Also note that for whatever reason, the video is set to forcibly start at 3:22 and you have to specifically click on “watch the entire video” at the timeline marker in order to get to the first few minutes.

Upcoming breaking changes in Windows Azure Active Directory preview

A moment ago Vittorio Bertocci wrote a post on some upcoming changes to the Developer Preview of WAAD. The changes are of the breaking sort, so if you’re actively using WAAD, this is something you’ll want to react to.

The WAAD MSDN forums have a more detailed announcement about the changes, but at a glance, here are the two key things I picked up on.

The service endpoint names are changing

Your (most likely automatically generated) Web.config settings say something like this now:

      <wsFederation passiveRedirectEnabled="true" 
					issuer="https://accounts.accesscontrol.windows.net/tenant-id/v2/wsfederation" 
					....
					requireHttps="false" />

After the change, that will have to change to:

      <wsFederation passiveRedirectEnabled="true" 
					issuer="https://login.windows.net/tenant-id/wsfed" 
					....
					requireHttps="false" />

The metadata and JWT endpoints are changing too, which may or may not affect you — but if you’re using any of them, you’ll probably know what to do anyway. :-) 

The User Principal Name claim will no longer be included

A while back, the claim that actually names the user principal was changed from EmailAddress to UPN. Now things are changing again, and in the future, the naming claim type will be … name! Which means your web.config settings need to change from

<nameClaimType value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" />

to

<nameClaimType value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" />

That’s pretty much it. And of course, if you can’t get the settings right editing them by hand, you can always run the Visual Studio Wizard again

Hope this helps someone. :-)

Blog move

Just a quick note: I’ve grown tired of Blogger regularly doing a hatchet job with my post markup and the limited options they give me for customizing the look and feel of the site, so I’ve moved to a new host.

I tried my best to not mess with the existing post URLs, but I’m afraid that at least the RSS feed urls will have changed.

Windows Azure Active Directory: Using the Graph API with an Office 365 Tenant

In a previous post I wrote about querying the Graph API for the group memberships of a WAAD user. In yet another post, I detailed setting up a WAAD tenant, but I also noted that you don’t have to do that if you’ve already got an Office 365 subscription, and would prefer to use that instead.

While that statement is technically true, the story is far from complete. As commenter Nick Locke points out, my instructions for using the Graph API don’t work for Office 365 tenants: the code throws an exception while trying to get the authorization token for the request.

After a bit of trial and error, I managed to figure out a fix.

Once again, open up the Microsoft Online Services Module for Windows PowerShell. Run Import-Module MSOnlineExtended -Force to load the module, use Connect-MsolService with admin credentials to establish the connection, and type in:

$adPrincipal = Get-MsolServicePrincipal -AppPrincipalId 00000002-0000-0000-c000-000000000000
$adPrincipal.ServicePrincipalNames

If your Office 365 setup is like ours, the result will look a lot like this:

00000002-0000-0000-c000-000000000000
AzureActiveDirectory/graph.windows.net
AzureActiveDirectory/directory_s5.windows.net
AzureActiveDirectory/directory_s4.windows.net
AzureActiveDirectory/directory_s3.windows.net
AzureActiveDirectory/directory_s2.windows.net
AzureActiveDirectory/directory_s1.windows.net
AzureActiveDirectory/directory.windows.net
AzureActiveDirectory/Directoryapi.microsoftonline.com

Looking at this list, it occurred to me that the problem might be related to the fact that we construct Realm Names for our application using the GUID 00000002-0000-0000-c000-000000000000 and the domain name graph.windows.net — the result looking like: 00000002-0000-0000-c000-000000000000/graph.windows.net@your-app-principal-id. So I figured I’d change my app to use the string AzureActiveDirectory instead of the GUID, and wouldn’t you know it, I got past the authorization token error. Only now I ended up with another error: validating the token didn’t work.

After a bit of head-scratching and web-searching, I thought I had it backwards: it wasn’t my app that was misconfigured, it was the Office 365 tenant. Suppose that the Graph API service actually identifies itself as 00000002-0000-0000-c000-000000000000/graph.windows.net and not AzureActiveDirectory/graph.windows.net, and that’s why things are failing.

I repeated the commands above in a MSOL PowerShell session that was connected to the WAAD domain I created before, and noted that indeed, the Service Principal Names for Microsoft.Azure.ActiveDirectory were otherwise identical, but AzureActiveDirectory was replaced by 00000002-0000-0000-c000-000000000000. So I cooked up this PowerShell bit:

I then ran it against the Office 365 MSOL PowerShell session and tried again. And wouldn’t you know, it worked!

Apparently, we’re not the only ones with this problem, so let’s hope this helps save someone else the trouble!

Windows Azure Active Directory: Using Group Memberships for Authorization

This is the fifth installation in my series on WAAD. So far, we’ve managed to create a WAAD tenant domain, set up an application to use WAAD for Single-Sign On authentication and read the current user’s group memberships using the Active Directory Graph API. Oh, and let’s not forget fixing a problem where the current user’s name is null. Now that we’re here, let’s complete the picture by converting our group memberships to roles and using those roles for authorization.

Staking a claim

One of the interesting changes in .NET 4.5 that hasn’t received much attention is the fact that under the covers, all authentication providers are now claims-based. Of course, Windows Identity Foundation has been claims-based from the start – the real change is that all the common infrastructure supports claims as well. For ASP.NET MVC development, this means that all we need to do to support roles using the [Authorize(Roles = "RoleName")] attribute syntax is get role claims from somewhere. The bad news is that WAAD authentication only gives us an identity claim. The good news is we can make up our own role claims pretty easily. Our enabler is a class called System.Security.Claims.ClaimsAuthenticationManager:

Defines the base implementation for a claims authentication manager. The claims authentication manager provides a place in the claims processing pipeline for applying processing logic (filtering, validation, extension) to the claims collection in the incoming principal before execution reaches your application code.

Let’s put that to use. Create a new class and call it GroupToRoleClaimAuthenticationManager. Paste in this code:


Then configure the application to use the manager by adding this under system.identityModel/identityConfiguration in Web.config:

<claimsAuthenticationManager type="WAADDemo.GroupToRoleClaimAuthenticationManager, WAADDemo" />

Create groups

Log in to the WAAD administration portal, open up “users & groups” and switch to the “security groups” view:

waad-groups

Create a group called “Administrators” and add your WAAD administrator user to that group. Then, create a new user:

waad-create-user-1

You don’t have to specify any additional details if you don’t want to. Click on “next” and you’ll get a page asking about user roles. Notably, you most likely don’t want to specify any roles here, as the roles are fixed and specific to WAAD:

waad-create-user-2

The next page in the wizard will ask about assigning licenses. This is a feature that is specific to Office 365, so you can skip it and click “next”. Finally, the wizard will ask whether you want the generated password for your new user to be sent to someone via email. Whether you do that or not, the password will be displayed to you on the next page, so note the password down somewhere and complete the wizard.

Restricting access

Now we’ve got groups and our groups have members in them. We also have a bunch of code in our application that converts those memberships into role claims. The last thing we need to do is use that to restrict access within our application. Add a new controller action – for example, in the HomeController of the Internet Application app template:

[Authorize(Roles = "Administrators")]
public ActionResult AdminOnly() {
 return View();
}

Create a matching view, and run the application. When the application asks for you to log in, do that with the credentials of the user you just created. Since this is the first time you are logging in, instead of immediately directing you back to the application, WAAD will ask you to change the user’s password:

waad-password-change

Change the password and log in again with the new password. Navigate to https://localhost:44302/Home/AdminOnly (substituting the port and protocol you’re actually using) and you should be greeted with a 401:

iis-express-unauthorized

To verify that administrators can see the admin features, log out of your session by closing the browser session, re-launch the browser and log in again – this time, using your admin credentials – and the application will let you through:

waad-app-with-admin-user

You’ll probably also want to hide links to administrative features from users that don’t have the required privileges – that’s easily done with IPrincipal.IsInRole().

Phew! We’ve covered a lot of ground and come pretty far. I hope you found all this useful. As usual, questions and comments are welcome!

Windows Azure Active Directory Authentication: User Principal Name is Suddenly Null

Last week, after I had already written my guide on setting up your ASP.NET MVC web application to use WAAD authentication, Microsoft changed the configuration of WAAD in a way that broke my demo application: logging in worked, but the user principal had “null” for its name.

After looking into the problem for a moment, I realized that the application was configured to expect an email address claim from the identity provider. The configuration is in web.config:

<add type="System.IdentityModel.Tokens.Saml2SecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
	<samlSecurityTokenRequirement>
		<nameClaimType value="http://schemas.xmlsoap.org/claims/EmailAddress" />
	</samlSecurityTokenRequirement>
</add>

This configuration says that the thing that names our user principal is the email address claim. After the update, we no longer get that claim, so the configuration needs to change to this:

<add type="System.IdentityModel.Tokens.Saml2SecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
	<samlSecurityTokenRequirement>
		<nameClaimType value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" />
	</samlSecurityTokenRequirement>
</add>

This does make more sense: the new claim is a “upn” or “user principal name”, which makes sense because, well… it’s the name of our user principal.

After this change, you’ll also want to add this line somewhere, most likely your Application_Start event handler:

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Upn;

This ensures that your anti-forgery tokens keep functioning.

What sucks about this is that I didn’t receive any kind of notification about the change. I hope this helps someone avoid the headache of debugging through the issue. Smile

Windows Azure Active Directory: Querying the Graph API for group memberships

This is the third part in my series of posts on Windows Azure AD. In this post I go through the steps required to get your application talking to the AD Graph API, and the things that stumped me along the way. The reason we’re interested in the Graph API to begin with is that WAAD Authentication provides us with the user’s identity, but doesn’t tell us anything else about them. If we want more details, such as group memberships, we need to do some extra work.

Dependencies

We begin this part by adding a new Service Reference to the project. For the address of the service, type http://graph.windows.net/offbeatdemo.onmicrosoft.com (replacing offbeatdemo.onmicrosoft.com with your own tenant domain name) and click “Go”. After a moment of waiting, Visual Studio should generate the necessary metadata files. Here you can give your service a namespace – remember, it’s relative to your project’s default namespace, so let’s call it “ActiveDirectoryGraph”.

vs-graph-reference

Once you hit OK, the service reference is generated as per usual. This is where the fun begins. Go to the References node in your project, right-click and select “Manage NuGet Packages…”. Select “Online” from the left, click on the search box and type in “Microsoft.WindowsAzure.ActiveDirectory.Authentication” and you should see a single matching package.

vs-nuget-aal

Click on “Install” to have NuGet fetch the library for you. The library in question is the Windows Azure Authentication Library, or AAL for short. It has all kinds of features, but the reason we need it is to authenticate our application so it can make Graph API requests. Somewhat counterintuitively, AAL depends on System.Windows.Forms of all things, so before your code will compile, you will need to add that as a reference to your project.

Using the API

Create a new class in your project – you can call it what you like, but I’m calling mine “GraphClient”. Paste in the following code – you may have to change some namespaces, but if you’ve added the service reference and the AAL package correctly, it should compile as is:


I’m not going to go through the implementation details of the class now – if you’ve got questions or feedback, leave a comment here or in the gist at GitHub. In order to use this class, what you need to do is find out some details about your tenant domain and Service Principal. It’s not entirely obvious why, but the only place where I’ve found the tenant id so far is the FederationMetadata.xml file (as documented in the article Integrating Multi-Tenant Cloud Applications with Windows Azure Active Directory) – note that the file I linked to is the federation metadata for my demo tenant domain, so you need to change the URL to get your own metadata. Locate the entityId attribute on the EntityDescriptor tag.

federation-metadata-tenantid

The entityId attribute looks like this: spn:00000001-0000-0000-c000-000000000000@a071bf68-ee1d-46aa-ac6d-cfddf3826050 – the emphasized part after the @ sign is the tenant id. Yours will be different from mine of course – copy the id somewhere handy, because you will need it soon. You’re also going to need the app principal id of the service principal you created in the previous installment. Finally, you’ll need to grant your application the right to read the directory, and create a symmetric key known to both WAAD and your application – it’s a key you will use to sign your requests, so WAAD will know it’s you making them. Here’s how you do all that: open the MSOL module for PowerShell and use Connect-MsolService to connect to your WAAD tenant. Run Import-Module MSOnlineExtended –Force to make all the commandlets available, and then run Get-MsolServicePrincipal | select DisplayName,AppPrincipalId to list your service principals.

PS C:\Windows\system32> Get-MsolServicePrincipal | select DisplayName,AppPrincipalId

DisplayName                             AppPrincipalId
-----------                             --------------
Microsoft.Azure.ActiveDirectory         00000002-0000-0000-c000-000000000000
Microsoft.Azure.ActiveDirectoryUX       0000000c-0000-0000-c000-000000000000
WAADDemo App                            e8a3050f-0c61-46bd-9808-ff7dd5dcdb4b

The resulting list will show you the app principal id (in this case, e8a3050f-0c61-46bd-9808-ff7dd5dcdb4b) – copy it somewhere handy. Next, we use that to create a new symmetric key with New-MsolServicePrincipalCredential:

PS C:\Windows\system32> New-MsolServicePrincipalCredential -AppPrincipalId e8a3050f-0c61-46bd-9808-ff7dd5dcdb4b
The following symmetric key was created as one was not supplied JH0QbohY5/+IW25zzukjuwPjr6mpnMhgicgVA4SfF9A=

Save the symmetric key somewhere too. As far as I know, there is no way to restore the value if you lose it – you’ll have to create a new key instead. You’ve got everything your application needs, but there’s still one more thing left to do: granting privileges.

PS C:\Windows\system32> Add-MsolRoleMember -RoleName "Service Support Administrator" `
 -RoleMemberType ServicePrincipal -RoleMemberObjectId 3dc125e6-d518-40d2-9392-87a03dac8f68

The “Service Support Administrator” role grants read-only access to the directory. The RoleMemberType switch is needed to inform WAAD that we’re granting the privilege to an application instead of a user or a group, and the RoleMemberObjectId switch identifies the Service Principal. Note that the Object Id is different from the AppPrincipalId we used earlier – if you don’t have the Object Id written down anywhere, you can use Get-MsolServicePrincipal | select DisplayName,ObjectId to get it. Now, you can use the collected values to create an instance of GraphClient and use it. Add this to a controller action:

var client = new GraphClient("offbeatdemo.onmicrosoft.com""a071bf68-ee1d-46aa-ac6d-cfddf3826050",
 "e8a3050f-0c61-46bd-9808-ff7dd5dcdb4b""JH0QbohY5/+IW25zzukjuwPjr6mpnMhgicgVA4SfF9A=");
 
var groups = client.GetUserGroups(User.Identity.Name);

return View(groups);

Now you should be able to display your user’s group memberships in the view:

waad-app-with-groups

Wrapping up

None of this was particularly difficult to do from a programming perspective – the trick is finding all the information you need! It doesn’t much help that most of the examples out there deal with either SaaS applications that are registered in the Seller Dashboard or applications that use ACS instead of WAAD. The steps are largely the same, but the places where you look for IDs and keys are wildly different. Merely listing the user’s group memberships isn’t very interesting. Now that we’ve got them, we could use them for authorization within the application – which is what we’re doing in the next part of this series.

1 2 3 14