Converting Claims to Windows Tokens and User Impersonation

In a domain environment it is really useful to switch user contexts in a web application.  This could be if you are needing to log in with credentials that have elevated permissions (or vice-versa) or just needing to log in as another user.

It’s pretty easy to do this with Windows Identity Foundation and Claims Authentication.  When the WIF framework is installed, a service is installed (that is off by default) that can translate Claims to Windows Tokens.  This is called (not surprisingly) the Claims to Windows Token Service or (c2WTS).

Following the deploy-with-least-amount-of-attack-surface methodology, this service does not work out of the box.  You need to turn it on and enable which user’s are allowed to impersonate via token translation.  Now, this doesn’t mean which users can switch, it means which users running the process are allowed to switch.  E.g. the process running the IIS application pools local service/network service/local system/etc (preferably a named service user other than system users).

To allow users to do this go to C:\Program Files\Windows Identity Foundation\v3.5\c2wtshost.exe.config and add in the service users to <allowedCallers>:

<windowsTokenService>
  <!--
      By default no callers are allowed to use the Windows Identity Foundation Claims To NT Token Service.
      Add the identities you wish to allow below.
    -->
  <allowedCallers>
    <clear/>
    <!-- <add value="NT AUTHORITY\Network Service" /> -->
    <!-- <add value="NT AUTHORITY\Local Service" /> –>
    <!-- <add value="nt authority\system" /> –>
    <!-- <add value="NT AUTHORITY\Authenticated Users" /> -->
  </allowedCallers>
</windowsTokenService>

You should notice that by default, all users are not allowed.  Once you’ve done that you can start up the service.  It is called Claims to Windows Token Service in the Services MMC snap-in.

That takes care of the administrative side of things.  Lets write some code.  But first, some usings:

using System;
using System.Linq;
using System.Security.Principal;
using System.Threading;
using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.WindowsTokenService;

The next step is to actually generate the token.  From an architectural perspective, we want to use the UPN claims type as that’s what the service wants to see.  To get the claim, we do some simple LINQ:

IClaimsIdentity identity = (ClaimsIdentity)Thread.CurrentPrincipal.Identity;
string upn = identity.Claims.Where(c => c.ClaimType == ClaimTypes.Upn).First().Value;

if (String.IsNullOrEmpty(upn))
{
    throw new Exception("No UPN claim found");
}

Following that we do the impersonation:

WindowsIdentity windowsIdentity = S4UClient.UpnLogon(upn);

using (WindowsImpersonationContext ctxt = windowsIdentity.Impersonate())
{
    DoSomethingAsNewUser();

    ctxt.Undo(); // redundant with using { } statement
}

To release the token we call the Undo() method, but if you are within a using { } statement the Undo() method is called when the object is disposed.

One thing to keep in mind though.  If you do not have permission to impersonate a user a System.ServiceModel.Security.SecurityAccessDeniedException will be thrown.

That’s all there is to it.

Implementation Details

In my opinion, these types of calls really shouldn’t be made all that often.  Realistically you need to take a look at how impersonation fits into the application and then go from there.  Impersonation is pretty weighty topic for discussion, and frankly, I’m not an expert.

Build your own Directory Federation Service

This is more of a random collection of thoughts because earlier today I came to the conclusion that I need something very similar to Active Directory Federation Services, except for non-domain users.  This is relatively easy to do; all I need is to create a Secure Token Service with a user store for the back end. 

The simplest approach is to use ASP.NET Membership and Roles with SqlProvider’s wrapped up by some WIF special sauce.  Turns out Dominick Baier already did just that with StarterSTS.

The problems I have with this is that it’s a pain to manage when you start getting more than a hundred or so users.  Extending user properties is hard to do too.  So my solution is to use something that is designed for user identities… an LDAP directory.  If it’s good enough for Active Directory, it’ll be plenty useful for this situation.

Reasoning
As an aside, the reason I’m not using Active Directory in the first place is because I need to manage a few thousand well known users without CAL’s.  This would amount to upwards of a couple hundred thousand dollars in licensing costs that just isn’t in the budget.  Further, most of these users probably wouldn’t use any of our systems that use Active Directory for authentication, but nevertheless, we need accounts for them.

Also, it would be a lot easier to manage creation and modification of user accounts because there are loads of processes that have been designed to pull user data out of HR applications into LDAP directories instead of custom SQL queries.

So lets think about what makes up Active Directory Federation Services.  It has roles that provides:

  • Token Services
  • A Windows Authentication end-point
  • An Attribute store-property-to-claim mapper (maps any LDAP properties to any claim types)
  • An application management tool (MMC snap-in and PowerShell cmdlets)
  • Proxy Services (Allows requests to pass NAT’ed zones)

That’s a pretty lightweight product when you compare it to the other services in Microsoft’s Identity stack. 

We can simplify it even further by breaking down the roles we need.

Token Services

This is actually pretty easy to accomplish.  Refer back to the WIF magic sauce.

Authentication end-point

This is just (well, you know what I mean) a web page login control.  We can’t do Windows Authentication without Kerberos (or NTLM), and we can’t do Kerberos without Active Directory (technically it could be done, but you’d be crazy to try).

Attribute store-property-to-claim mapper

ADFS can connect to a bunch of different attribute stores, including custom built stores if you provide assemblies.  We only really need to map to a few LDAP properties, and make it easy to map to other properties in the future.

Application management tool

This would be to manage the mapper and a few STS settings like URI names and certificates.  This, I think, would be a relatively simple application if we designed the configuration database properly.

Proxy Services

Proxies are a pain in the butt.  Useful in general, but we don’t really need to think about this at the moment.

Some Warnings

There are some things that are worth mentioning.  We have to be really careful about what we create because we are developing a serious piece of the security infrastructure.  Yes, it is for a group of employees that won’t have much access to anything dangerous (if they need access, they’d be migrated to Active Directory), but nevertheless we are creating the main ingress point for the majority of our employees.  It also needs to be accessible from the internet.

It may sound like I think it’ll be a synch to develop this system and have it work securely, but in reality there is a lot that will need to go into it to protect the network, the employees, and the data this could possibly interact with.  It is tough to develop applications securely.  It is far harder to develop secure applications whose sole responsibility is security related.

Next Steps

The next step is to design the thing.  I know how it will exist in relation to the systems it will be used to provide identity to, but aside from that, the architecture of the thing is still unknown.  With any luck I can accomplish rough designs tomorrow on the train, on my way to visit family for the holiday.

Better yet, maybe while visiting with family. Winking smile