Generating Federation Metadata Dynamically

In a previous post we looked at what it takes to actually write a Security Token Service.  If we knew what the STS offered and required already, we could set up a relying party relatively easily with that setup.  However, we don’t always know what is going on.  That’s the purpose of federation metadata.  It gives us a basic breakdown of the STS so we can interact with it.

Now, if we are building a custom STS we don’t have anything that is creating this metadata.  We could do it manually by hardcoding stuff in an xml file and then signing it, but that gets ridiculously tedious after you have to make changes for the third or fourth time – which will happen.  A lot.  The better approach is to generate the metadata automatically.  So in this post we will do just that.

The first thing you need to do is create a endpoint.  There is a well known path of /FederationMetadata/2007-06/FederationMetadata.xml that is generally used, so let’s use that.  There are a lot of options to generate dynamic content and in Programming Windows Identity Foundation, Vitorrio uses a WCF Service:

[ServiceContract]
public interface IFederationMetadata
{
    [ServiceBehavior]
    [webGet(UriTemplate = "2007-06/FederationMetadata.xml")]
    XElement FederationMetadata();
}

It’s a great approach, but for some reason I prefer the way that Dominick Baier creates the endpoint in StarterSTS.  He uses an IHttpHandler and a web.config entry to create a handler:

<location path="FederationMetadata/2007-06">
<system.webServer>
<handlers>
<add
        name="MetadataGenerator"
        path="FederationMetadata.xml"
        verb="GET"
        type="Syfuhs.TokenService.WSTrust.FederationMetadataHandler" />
</handlers>
</system.webServer>
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>

As such, I’m going to go that route.  Let’s take a look at the implementation for the handler:

using System.Web;

namespace Syfuhs.TokenService.WSTrust
{
    public class FederationMetadataHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ClearHeaders();

            context.Response.Clear();
            context.Response.ContentType = "text/xml";

            MyAwesomeTokenServiceConfiguration
.Current.SerializeMetadata(context.Response.OutputStream);
        }

        public bool IsReusable { get { return false; } }
    }
}

All the handler is doing is writing metadata out to a stream, which in this case is the response stream.  You can see that it is doing this through the MyAwesomeTokenServiceConfiguration class which we created in the previous article.  The SeriaizeMetadata method creates an instance of a MetadataSerializer and writes an entity to the stream:

public void SerializeMetadata(Stream stream)
{
    MetadataSerializer serializer = new MetadataSerializer();
    serializer.WriteMetadata(stream, GenerateEntities());
}

The entities are generated through a collection of tasks:

private EntityDescriptor GenerateEntities()
{
    if (entity != null)
        return entity;

    SecurityTokenServiceDescriptor sts = new SecurityTokenServiceDescriptor();

    FillOfferedClaimTypes(sts.ClaimTypesOffered);

    FillEndpoints(sts);
    FillSupportedProtocols(sts);
    FillSigningKey(sts);

    entity = new EntityDescriptor(new EntityId(string.Format("https://{0}", host)))
    {
        SigningCredentials = this.SigningCredentials
    };

    entity.RoleDescriptors.Add(sts);

    return entity;
}

The entity is generated, and an object is created to describe the STS called a SecurityTokenServiceDescriptor.  At this point it’s just a matter of sticking in the data and defining the credentials used to sign the metadata:

private void FillSigningKey(SecurityTokenServiceDescriptor sts)
{
    KeyDescriptor signingKey
= new KeyDescriptor(this.SigningCredentials.SigningKeyIdentifier)
{
Use = KeyType.Signing
};

    sts.Keys.Add(signingKey);
}

private void FillSupportedProtocols(SecurityTokenServiceDescriptor sts)
{
    sts.ProtocolsSupported.Add(new System.Uri(WSFederationConstants.Namespace));
}

private void FillEndpoints(SecurityTokenServiceDescriptor sts)
{
    EndpointAddress activeEndpoint
= new EndpointAddress(string.Format("https://{0}/TokenService/activeSTS.svc", host));
    sts.SecurityTokenServiceEndpoints.Add(activeEndpoint);
    sts.TargetScopes.Add(activeEndpoint);
}


private void FillOfferedClaimTypes(ICollection<DisplayClaim> claimTypes)
{
    claimTypes.Add(new DisplayClaim(ClaimTypes.Name, "Name", ""));
    claimTypes.Add(new DisplayClaim(ClaimTypes.Email, "Email", ""));
    claimTypes.Add(new DisplayClaim(ClaimTypes.Role, "Role", ""));
}

That in a nutshell is how to create a basic metadata document as well as sign it.  There is a lot more information you can put into this, and you can find more things to work with in the Microsoft.IdentityModel.Protocols.WSFederation.Metadata namespace.

The Basics of Building a Security Token Service

Last week at TechDays in Toronto I ran into a fellow I worked with while I was at Woodbine.  He works with a consulting firm Woodbine uses, and he caught my session on Windows Identity Foundation.  His thoughts were (essentially—paraphrased) that the principle of Claims Authentication was sound and a good idea, however implementing it requires a major investment.  Yes.  Absolutely.  You will essentially be adding a new tier to the application.  Hmm.  I’m not sure if I can get away with that analogy.  It will certainly feel like you are adding a new tier anyway.

What strikes me as the main investment is the Security Token Service.  When you break it down, there are a lot of moving parts in an STS.  In a previous post I asked what it would take to create something similar to ADFS 2.  I said it would be fairly straightforward, and broke down the parts as well as what would be required of them.  I listed:

  • 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)

These aren’t all that hard to develop.  With the exception of the proxy services and token service itself, there’s a good chance we have created something similar to each one if user authentication is part of an application.  We have the authentication endpoint: a login form to do SQL Authentication, or the Windows Authentication Provider for ASP.NET.  We have the attribute store and something like a claims mapper: Active Directory, SQL databases, etc.  We even have an application management tool: anything you used to manage users in the first place.  This certainly doesn’t get us all the way there, but they are good starting points.

Going back to my first point, the STS is probably the biggest investment.  However, it’s kind of trivial to create an STS using WIF.  I say that with a big warning though: an STS is a security system.  Securing such a system is NOT trivial.  Writing your own STS probably isn’t the best way to approach this.  You would probably be better off to use an STS like ADFS.  With that being said it’s good to know what goes into building an STS, and if you really do have the proper resources to develop one, as well as do proper security testing (you probably wouldn’t be reading this article on how to do it in that case…), go for it.

For the sake of simplicity I’ll be going through the Fabrikam Shipping demo code since they did a great job of creating a simple STS.  The fun bits are in the Fabrikam.IPSts project under the Identity folder.  The files we want to look at are CustomSecurityTokenService.cs, CustomSecurityTokenServiceConfiguration.cs, and the default.aspx code file.  I’m not sure I like the term “configuration”, as the way this is built strikes me as factory-ish.

image

The process is pretty simple.  A request is made to default.aspx which passes the request to FederatedPassiveSecurityTokenServiceOperations.ProcessRequest() as well as a newly instantiated CustomSecurityTokenService object by calling CustomSecurityTokenServiceConfiguration.Current.CreateSecurityTokenService().

The configuration class contains configuration data for the STS (hence the name) like the signing certificate, but it also instantiates an instance of the STS using the configuration.  The code for is simple:

namespace Microsoft.Samples.DPE.Fabrikam.IPSts
{
    using Microsoft.IdentityModel.Configuration;
    using Microsoft.IdentityModel.SecurityTokenService;

    internal class CustomSecurityTokenServiceConfiguration
: SecurityTokenServiceConfiguration
    {
        private static CustomSecurityTokenServiceConfiguration current;

        private CustomSecurityTokenServiceConfiguration()
        {
            this.SecurityTokenService = typeof(CustomSecurityTokenService);
            this.SigningCredentials =
new X509SigningCredentials(this.ServiceCertificate);
            this.TokenIssuerName = "https://ipsts.fabrikam.com/";
        }

        public static CustomSecurityTokenServiceConfiguration Current
        {
            get
            {
                if (current == null)
                {
                    current = new CustomSecurityTokenServiceConfiguration();
                }

                return current;
            }
        }
    }
}

It has a base type of SecurityTokenServiceConfiguration and all it does is set the custom type for the new STS, the certificate used for signing, and the issuer name.  It then lets the base class handle the rest.  Then there is the STS itself.  It’s dead simple.  The custom class has a base type of SecurityTokenService and overrides a couple methods.  The important method it overrides is GetOutputClaimsIdentity():

protected override IClaimsIdentity GetOutputClaimsIdentity(
IClaimsPrincipal principal, RequestSecurityToken request, Scope scope)
{
    var inputIdentity = (IClaimsIdentity)principal.Identity;

    Claim name = inputIdentity.Claims.Single(claim =>
claim.ClaimType == ClaimTypes.Name);
    Claim email = new Claim(ClaimTypes.Email,
Membership.Provider.GetUser(name.Value, false).Email);
    string[] roles = Roles.Provider.GetRolesForUser(name.Value);

    var issuedIdentity = new ClaimsIdentity();
    issuedIdentity.Claims.Add(name);
    issuedIdentity.Claims.Add(email);

    foreach (var role in roles)
    {
        var roleClaim = new Claim(ClaimTypes.Role, role);
        issuedIdentity.Claims.Add(roleClaim);
    }

    return issuedIdentity;
}

It gets the authenticated user, grabs all the roles from the RolesProvider, and generates a bunch of claims then returns the identity.  Pretty simple.

At this point you’ve just moved the authentication and Roles stuff away from the application.  Nothing has really changed data-wise.  If you only cared about roles, name, and email you are done.  If you needed something more you could easily add in the logic to grab the values you needed. 

By no means is this production ready, but it is a good basis for how the STS creates claims.

Token Request Validation in ASP.NET

Earlier this week during my TechDays presentation on Windows Identity Foundation, there was a part during the demo that I said would fail miserably after the user was authenticated and the token was POST’ed back to the relying party.  Out of the box, ASP.NET does request validation.  If a user has submitted content through request parameters it goes through a validation step, and by default this step is to break on anything funky such as angle brackets.  This helps to deter things like cross site scripting attacks.  However, we were passing XML so we needed to turn off this validation.  There are two approaches to doing this.

The first approach, which is what I did in the demo, was to set the validation mode to “2.0”.  All this did was tell ASP.NET to use a less strict validation scheme.  To do that you need to add a line to the web.config file:

<system.web>
<httpRuntime requestValidationMode=”2.0” />
</system.web>

This is not the best way to do things though.  It creates a new vector for attack, as you’ve just allowed an endpoint to accept trivial data.  What is more preferred is to create a custom request validator.  You can find a great example in the Fabrikam Shipping demo.

It’s pretty straightforward to create a validator.  First you create a class that inherits System.Web.Util.RequestValidator, and then you override the method IsValidRequestString(…).  At that point you can do anything you want to validate, but the demo code tries to build a SignInResponseMessage object from the wresult parameter.  If it creates the object successfully the request is valid.  Otherwise it passes the request to the base implementation of IsValidRequestString(…).

The code to handle this validation is pretty straightforward:

    public class WSFederationRequestValidator : 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))
            {
                SignInResponseMessage message =
                     WSFederationMessage.CreateFromFormPost(context.Request) 
                     as SignInResponseMessage;

                if (message != null)
                {
                    return true;
                }
            }

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

Once you’ve created your request validator, you need to update the web.config file to tell .NET to use the validator.  You can do that by adding the following xml:

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

You can find the validation code in FabrikamShipping.Web\Security\WSFederationRequestValidator.cs within the FabrikamShipping solution.

Free Code Sample Request Service from Microsoft

Just came across this on the Decrypt my World blog.  It seems a lot of Microsoft developers are asked for code samples and for lots of valid reasons they can’t provide them.  So Microsoft is fixing that by opening up a service where you can request code samples for any Microsoft technologies.

Here is the official word on what it is:

Developers are encouraged to submit code sample requests dealing with any Microsoft development technologies to our site. At the same time, developers can now vote for newly submitted or existing code sample topics. Here’s the exciting part! Microsoft engineers will then pick the requests with the highest number of votes and provide the code samples. It’s all FREE!

You can find the full write-up here: http://1code.codeplex.com/wikipage?title=NEW%2c%20FREE%20Code%20Sample%20Request%20Service%20from%20Microsoft%20All-In-One%20Code%20Framework

Managing Identity in SharePoint

Yet another presentation on the docket!  I submitted an abstract to SharePoint Summit 2011 and they accepted!  I will be presenting on SharePoint and how it manages Identity.  More specifically, how SharePoint 2010 uses WIF to handle Claims based authentication and Federation.

Here are the details

Event: SharePoint Summit 2011, January 31st 2011 – February 2nd, 2011

When: 11:30 a.m. - 12:45 p.m. February 1st, 2011

Where: Four Seasons Hotel, Toronto

Abstract: Managing identities within an organization is relatively easy. However, as business changes, we need to be able to adapt quickly. Identity is something that often gets overlooked in adaptation. In this session we will discuss the Windows Identity Foundation and how SharePoint uses it to adapt easily to change.

Link: http://www.sharepointsummit2011.com/Toronto/conference_day2.htm#session_7_3

Changing the Identity Game with the Windows Identity Foundation

Similar to the TVBUG presentation, I will be presenting on the Windows Identity Foundation to the Metro Toronto .NET User Group.

Here are the details:

When: November 10th, 2010

Where: KPMG, 333 Bay Street, 10th Floor, Toronto

Abstract: Identity is a tricky thing to manage. These days every application requires some knowledge of the user, which inevitably requires users to log in and out of the applications to prove they are who they are as well as requiring the application to keep record of the accounts. With the Windows Identity Foundation, built on top of a Claims-based architecture, there is a fundamental shift in the way we manage these users and their accounts. In this presentation we will take a look at the why's and dig into the how's of the Windows Identity Foundation by building an Identity aware application from scratch.

Presenting a TechDays Local Flavours Track Session!

Earlier this morning I got an email from John Bristowe congratulating me on being selected to present a session for the local flavours track at TechDays in Toronto!  This bumps up my count to 2.  Needless to say I am REALLY excited.

I was a little disappointed to find out there weren’t any sessions on the Windows Identity Foundation, so that just meant I had to submit my own to the local flavours track…and they accepted it!  Here are the details:

October 27, 3:40 PM to 4:45 PM

Breakout | LFT330: Windows Identity Foundation Simplified: All the Scary Things Made Un-Scary

The Windows Identity Foundation helps simplify user access for developers by externalizing user access from applications via claims and reducing development effort with pre-built security logic and integrated .NET tools. This presentation is an intimate discussion on the basics of the Windows Identity Foundation and its claims model. In this session, you’ll learn how to refactor an existing sample set of applications to use WIF, to connect identities to the Cloud, and to remove the burden of managing multiple disparate user stores.

Location: Metro Toronto Convention Centre - South Building (255 Front Street West, Toronto)

Room: TBA

image

Presentation: Changing the Identity Game with the Windows Identity Foundation

Rob Windsor and TVBUG are letting me present on November 8th on Claims-Based Authentication and Identification.  Here are the details:

Location: Room 1, Library, 2nd floor, North York Public Library

Date: Monday, November 8, 2010

Time:
6:30 to 6:50 (Pizza - Meet and Greet)
6:50 to 7:00 (Group Business)
7:00 to 9:00 (Presentation)

Topic: Changing the Identity Game with the Windows Identity Foundation

Abstract: Identity is a tricky thing to manage. These days every application requires some knowledge of the user, which inevitably requires users to log in and out of the applications to prove they are who they are as well as keep a record of their accounts. With the Windows Identity Foundation, there is a fundamental shift in the way we manage these users and their accounts. In this presentation we will take a look at the why's and dig into the how's of the Windows Identity Foundation by building an Identity aware application from scratch.

Directions

All TVBUG meetings are held at the North York Public Library or North York Memorial Hall. Both are located in the same building at Yonge Street and Park Home Avenue (North of the 401 between Sheppard and Finch across from Empress Walk). If you are taking the Subway get off at the North York Centre Station. The library meeting rooms are on the 2nd Floor. Memorial Hall meeting rooms are on the Concourse Level near the food court.

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.

Converting Bootstrap Tokens to SAML Tokens

there comes a point where using an eavesdropping application to catch packets as they fly between Secure Token Services and Relying Parties becomes tiresome.  For me it came when I decided to give up on creating a man-in-the-middle between SSL sessions between ADFS and applications.  Mainly because ADFS doesn’t like that.  At all.

Needless to say I wanted to see the tokens.  Luckily, Windows Identity Foundation has the solution by way of the Bootstrap token.  To understand what it is, consider how this whole process works.  Once you’ve authenticated, the STS will POST a chunk of XML (the SAML Token) back to the RP.  WIF will interpret it as necessary and do it’s magic generating a new principal with the payload.  However, in some instances you need to keep this token intact.  This would be the case if you were creating a web service and needed to forward the token.  What WIF does is generate a bootstrap token from the SAML token, in the event you needed to forward it off to somewhere.

Before taking a look at it, let's add in some useful using statements:

using System;
using System.IdentityModel.Tokens;
using System.Text;
using System.Threading;
using System.Xml;
using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Tokens.Saml11;

The bootstrap token is attached to IClaimsPrincipal identity:

SecurityToken bootstrapToken = ((IClaimsPrincipal)Thread.CurrentPrincipal).Identities[0].BootstrapToken;

However if you do this out of the box, BootstrapToken will be null.  By default, WIF will not save the token.  We need to explicitly enable this in the web.config file.  Add this line under <microsoft.IdentityModel><service><securityTokenHandlers>:

<securityTokenHandlerConfiguration saveBootstrapTokens="true" />

Once you’ve done that, WIF will load the token.

The properties are fairly straightforward, but you can’t just get a blob from it:

image

Luckily we have some code to convert from the bootstrap token to a chunk of XML:

SecurityToken bootstrapToken = ((IClaimsPrincipal)Thread.CurrentPrincipal).Identities[0].BootstrapToken;

StringBuilder sb = new StringBuilder();

using (var writer = XmlWriter.Create(sb))
{
     new Saml11SecurityTokenHandler(new SamlSecurityTokenRequirement()).WriteToken(writer, bootstrapToken);
}

string theXml = sb.ToString();

We get a proper XML document:

image

That’s all there is to it.