Home | My Disclaimer | Who am I? | Search...| Log in

The Basics of Building a Security Token Service

by Steve Syfuhs / October 29, 2010 04:00 PM

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

by Steve Syfuhs / October 28, 2010 04:00 PM

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.

Minor Change to TechDays Presentation

by Steve Syfuhs / October 19, 2010 04:00 PM

Just a quick update to let everyone know that Miguel Carrasco and I are switching sessions so he can get back home for a prior engagement.  As such, I will now be doing OPT315: Microsoft Visual Studio 2010 Tips and Tricks. This session is on the 2nd day at 3:40pm - 4:45pm.

Presenting a TechDays Local Flavours Track Session!

by Steve Syfuhs / October 13, 2010 04:00 PM

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

Techdays 2010 Presentation: Build Websites Fast with Visual Studio 2010

by Steve Syfuhs / September 12, 2010 04:00 PM

Joey Devilla has graciously offered me the opportunity to present at Techdays in Toronto this year!  The Toronto event is October 27th-28th.

Here is the session abstract:

DEV355: Build Web Sites Fast with Microsoft Visual Studio 2010 (click for more information)

Day 1 - 1:00pm - 2:05pm

Learn about the new Web developer innovations in Visual Studio 2010. Visual Studio 2010 makes development of standards-based Web sites better than ever with new support for CSS 2, HTML code snippets, powerful dynamic Intellisense for Javascript, and more! Visual Studio 2010 also makes it easy to deploy applications from development to test and production environments with new support for Web Configuration Transforms and integration with the IIS Web Deployment Tool.

For more details:

*Early Bird discount ($349.99 + taxes) expires on September 16, 2010.
Toronto October 27-28, 2010
Metro Toronto Convention Centre
255 Front Street West
Toronto ON M5V 2W6

Show Map

Get Directions
Register Now!

Pictures from Techdays and FailCamp in Toronto

by Steve Syfuhs / October 12, 2009 04:00 PM

After getting my camera back from Mitch Garvis after Techdays and FailCamp in Toronto, I decided to upload photos from the events, and to my surprise there were some pretty good shots.  Here is what I came back with:

4007417044

4006643533

4007406358

4006631995

4007393754

4006623627

4006616273

4007373722

4006582013

4006587385

4007358462

4006597103

4007340130

ASP.NET WebForms are NOT Being Overthrown by MVC

by Steve Syfuhs / October 05, 2009 04:00 PM

It’s always a fun day when the man himself, ScottGu responds to my email.  Basically it all started last week at Techdays in Toronto (pictures to follow, I promise). 

Quite a few people asked me about MVC, and whether or not it will replace Web Forms.  My response was that it wouldn’t, but I didn’t have any tangible proof.  I discussed new features in .NET 4.0, and how the development is still going strong for future releases.  Some didn’t buy it.

So, earlier today I emailed Scott and asked him for proof.  This was his response:

Hi Steve,

Web Forms is definitely not going away – we are making substantial improvements to it with ASP.NET 4.0 (I’m doing a blog series on some of the improvements now).  ASP.NET MVC provides another option people can use for their UI layer – but it is simply an option, not a replacement.

In terms of the dev team size, the number of people on the ASP.NET team working on WebForms and MVC is actually about equal.  All of the core infrastructure investments (security, caching, config, deployment, etc) also apply equally to both.

Now, MVC is new.  MVC is powerful.  MVC is pretty freakin cool in what it can do.  But it won’t replace WebForms.  Frankly, I like WebForms.  MVC does have it’s place though.  I can see a lot benefits to using it.  It alleviates a lot of boilerplate code in certain development architectures, and that is never a bad thing.

Long Live WebForms!

Presenting at Techdays 2009!

by Steve Syfuhs / July 15, 2009 04:00 PM

Still working out session details, but it looks like I will be presenting in Ottawa and Montreal for Techdays 2009.  I will be loitering around at the Toronto event soaking up all the techie-goodness, so come find me at any of the three events.  We can talk shop, shoot the breeze, or just mill about having a good time.

I promise I won’t embarrass anyone.  Except maybe myself.  But that’s a warning for all occasions.

Here are the dates of the events across Canada.  Buy your tickets before the early-bird deal runs out!

City Date Venue
VANCOUVER SEPTEMBER 14-15 Vancouver Convention Centre
TORONTO SEPTEMBER 29-30 Metro Toronto Convention Centre
HALIFAX NOVEMBER 2-3 World Trade & Convention Centre
CALGARY NOVEMBER 17-18 Calgary Stampede
MONTREAL DECEMBER 2-3 Mont-Royal Centre
OTTAWA DECEMBER 9-10 Hampton Inn & Convention Centre
WINNIPEG DECEMBER 15-16 Winnipeg Convention Centre

The Early Bird price is $299.  The regular Price is $599.

I will post more on the sessions I will be presenting at a later date when I get the full details.

See you there!

About

Steve is a bit of a Renaissance Kid when it comes to technology. He spends most of his time in the security stack.