Monday, February 15, 2010

Securing WCF Data Services using WIF

This questions comes up every once in a while..

Since WCF Data Services is just a normal WCF service (using the web programming model), all the typical security APIs and extensibility points apply.

That said, depending on your scenario you might have to be a little more creative for REST-style services. Here’s a quick walkthrough:

Enabling WIF in the Data Service
The easiest way to get WIF wired up is by writing a custom service host factory. You simply have to derive from DataServiceHostFactory, override CreateServiceHost and call FederatedServiceCredentials.ConfigureServiceHost before you return the host to the plumbing.

This gives you the standard WIF integration for all standard HTTP credential types (Basic, Integrated etc…) and the typical extensibility points like ClaimsAuthorizationManager.

For accepting and converting more advanced token types like SWT or SAML, you need to plugin your own token handling. I gave it a try for SWT tokens (see here for the general SWT integration story).

public class ProtectedDataServiceHostFactory : DataServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(
      Type serviceType, Uri[] baseAddresses)
    {

        var host = base.CreateServiceHost(serviceType, baseAddresses);

        host.Authorization.ServiceAuthorizationManager = new
          SimpleWebTokenAuthorizationManager(
             acsAddress,
             expectedAudience,
             acsKey);
        host.Authorization.PrincipalPermissionMode =
          PrincipalPermissionMode.Custom;

        return host;
    }
}

This uses my SWT plumbing to turn incoming SWT tokens into an IClaimsPrincipal. You could easily do the same thing for SAML (but be aware that SAML tokens can become quite big – and you typically want to transmit them using an HTTP header for this scenario).

You could now use the resulting claims for authorization as well as WCFDS interceptors, e.g.:

[QueryInterceptor("Users")]
public Expression<Func<Users, bool>> OnQueryUsers()
{
    var principal = Thread.CurrentPrincipal as IClaimsPrincipal;
    var customer = principal.GetClaimValue("http://claims/customerName");

    return user => user.Applications.ApplicationName == customer;
}

Sending a token header to the Data Service
The next step is to send a token to the Data Service. This can be achieved by handling the SendingRequest event on the DataServiceContext derived client plumbing, e.g.:

class ProviderEntitiesWithToken : ProviderEntities
{
    string _token;
    string _tokenHeader = "Authorization";
 
    public ProviderEntitiesWithToken(Uri address, string token) : base(address)
    {
        _token = token;
        SendingRequest += OnSendingRequest;
    }
 
    void OnSendingRequest(object sender, SendingRequestEventArgs e)
    {
        e.RequestHeaders[_tokenHeader] =
          SimpleWebToken.GetAuthorizationHeader(_token);
    }
}

Using the Data Service
The usage pattern is the same as without any tokens or WIF. New up your derived class, set the token and use e.g. LINQ to query the Data Service.

static void Main(string[] args)
{
    var token = RequestToken();
    var service = new ProviderEntitiesWithToken(new Uri(dataServiceAddress), token);
   
    var users = from u in service.Users
                select u;
 
    users.ToList().ForEach(u => Console.WriteLine(u.UserName));
}

HTH


IdentityModel
Monday, February 15, 2010 1:48:40 PM UTC  #   
 Monday, February 08, 2010

Integrating Simple Web Tokens (SWT) with WCF REST Services using WIF

The Simple Web Token (SWT) is a new & simple token format that was created by Microsoft, Google and others. See here for specs. The Azure platform App Fabric Access Control service e.g. uses this token type.

Why yet another token type? Well – the advantages of SWT are that it is simple to construct (form encoded key value pairs), that only simple crypto is needed (SHA256 HMACs) and that it is compact on the wire which allows easy embedding in HTTP headers or query strings.

The downsides are – it is not a widely adopted token format (current spec version is 0.9.5.1) and the lack of asymmetric signatures (e.g. X.509 based).

Since I had to do some ACS work recently, I crafted up a simple SWT integration for WCF based REST services (works in ASP.NET as well). The plumbing looks for a SWT token either on the Authorization or X-Authorization header as well as on the query string. Using the power of WIF, it is simple to transform the SWT token into an IClaimsPrincipal.

From that point on, you have all the unified identity representation benefits of WIF.

Download here.


IdentityModel
Monday, February 08, 2010 2:30:41 PM UTC  #   
 Friday, February 05, 2010

Using SAML as a Client Credential Type in WCF (updated to WIF RTM)

A reader has asked me to update the Client SAML sample to WIF RTM (for background and motivation please read here first).

The main work was in the SAML security token handler Validate method, this looks now like this:

public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
{
    if (token == null)
    {
        throw new ArgumentNullException("token");
    }       

    var samlToken = token as SamlSecurityToken;
    if (samlToken == null)
    {
        throw new ArgumentException("token");
    }
    if (samlToken.Assertion == null)
    {
        throw new ArgumentException("token");
    }
   
    var assertion = samlToken.Assertion as Saml11Assertion;
    this.ValidateConditions(samlToken.Assertion.Conditions, false);

    // extract claims from token
    var identity = new ClaimsIdentity("ClientSaml");
    ProcessStatement(assertion.Statements, identity, "Client");
   
    // call authentication and filtering logic
    IClaimsIdentity newIdentity;

    try
    {
        if (ValidateUser(identity, out newIdentity))
        {
            return new ClaimsIdentityCollection(new IClaimsIdentity[] { newIdentity });
        }
        else
        {
            throw new SecurityTokenValidationException("Authentication failed");
        }
    }
    catch (Exception ex)
    {
        throw new SecurityTokenValidationException("Security token validation failed", ex);
    }
}

You would then derive from the base handler and implement the ValidateUser method. This method does some sort of authentication based on the incoming claims and returns an IClaimsIdentity containing the claims that should get passed through to the service code, e.g.:

// sample implementation - do not use for production ;)
protected override bool ValidateUser(ClaimsIdentity id, out IClaimsIdentity newIdentity)
{
    newIdentity = null;
    var usernameClaim = id.Claims.First(c => c.ClaimType == WSIdentityConstants.ClaimTypes.Name);
    var passwordClaim = id.Claims.First(c => c.ClaimType == _passwordClaimType);
    var customerIdClaim = id.Claims.First(c => c.ClaimType == _customerIdClaimType);
   
    if (usernameClaim.Value == passwordClaim.Value)
    {
        newIdentity = new ClaimsIdentity(new Claim[]
        {
            usernameClaim,
            customerIdClaim
        }, "ClientSaml");

        return true;
    }

    return false;
}

You can find the complete source code here.


IdentityModel
Friday, February 05, 2010 6:44:39 AM UTC  #   
 Wednesday, February 03, 2010

StarterSTS V1.0 Beta 1

OK – I finally was able to carve out some time…This is the first feature complete release of the StarterSTS!

New features include:

  • client certificate support for WS-Fed and WS-Trust endpoints
  • new relying party configuration
    • allows specifying an explicit reply to address
    • allows relying parties without encryption
  • refactoring of web site / STS code.

Still no docs – sorry. Please contact me via the Codeplex forum if you have any questions.

Some brief migration remarks:

  • relying parties are now configured in relyingParties.config. Move the RP entries from certificates.config to this new config file
  • userMappings.config allows mapping client certificates to membership users
  • profile configuration has been moved to profile.config

On the todo list:

  • documentation
  • simplified installation
  • IIS InetMgr integration for all configuration aspects

What I need from you:

  • testers!
  • input and feedback
  • volunteers for completing the todos

Have fun!

download here: http://startersts.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=39891


IdentityModel
Wednesday, February 03, 2010 9:22:22 PM UTC  #   
 Monday, February 01, 2010

Testing Security Code with Moles

I am by far no (unit) testing expert. But I always found it odd that I sometimes have to re-structure code to make it explicitly unit-testable.

One typical example is code that relies on some sort of context – e.g. Thread.CurrentPrincipal. I personally like this pattern in the .NET Framework – but it is not ideal for testing.

Recently I ran across Moles which is a mocking and stubs framework from Microsoft Research which has some features that can help here. Inspired by this video – I gave it a try.

The following code allows “faking” Thread.CurrentPrincipal:

using System.Security.Principal;
using System.Threading.Moles;
using Microsoft.Moles.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[assembly: MoledType(typeof(System.Threading.Thread))]

namespace SecurityTest
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        [HostType("Moles")]
        public void TestSecurityCode()
        {
            MThread.CurrentPrincipalGet = () =>
                new GenericPrincipal(new GenericIdentity("dominick"), null);


            var security = new SecurityCode();
            var user = security.SomeMethod();

            Assert.AreEqual("dominick", user);
        }
    }

    public class SecurityCode
    {
        public string SomeMethod()
        {
            // simulates context
            Thread.CurrentPrincipal = new GenericPrincipal(
              new GenericIdentity("bob"), null);

            return Thread.CurrentPrincipal.Identity.Name;
        }
    }
}


Misc
Monday, February 01, 2010 10:36:20 AM UTC  #   

A Guide to Claims-Based Identity and Access Control

Get it here!!!

http://msdn.microsoft.com/en-us/library/ff359115.aspx


IdentityModel
Monday, February 01, 2010 7:48:16 AM UTC  #   
 Tuesday, January 05, 2010

Claims Identity Guide – Release Candidate

The last six months we were working on finalizing the P&P guide to claims based identity and access control. We finally have a release candidate!

Eugenio has all the details here. As always, feedback is welcome!

Enjoy!


IdentityModel
Tuesday, January 05, 2010 5:37:21 AM UTC  #   
 Thursday, December 24, 2009

Beware of WIF HTTP Modules and Default Configuration

Most samples I know of – as well as FedUtil generated configuration set a preCondition="managedHandler" for the WIF HTTP modules.

This means that the modules (and thus the protection of the requested resource) only kicks in for “managed” content like .aspx files. Not for static content like .xml etc.

If you like to protect static content using WIF, you have to remove the preCondition in web.config. Also add the runAllManagedModulesForAllRequests attribute to the modules section in system.webServer if you are using ASP.NET URL Authorization. Subtle security hole…


IdentityModel
Thursday, December 24, 2009 10:49:24 AM UTC  #   

WIF Configuration – Part 3: Extensibility

Some of the WIF configuration elements support extensibility. This means that you can attach arbitrary XML child elements to the configuration elements. When this is the case, the WIF configuration system creates the piece of plumbing in question using a special ctor that takes an XmlNodeList representing the custom configuration. You can then parse the XML and configure the class accordingly. Examples are:

IssuerNameRegistry

<issuerNameRegistry type="ConfigurationBasedIssuerNameRegistry, ...">
  <
trustedIssuers>
    <
add name="foo"
        
thumbprint="xxx" />
  </
trustedIssuers>
</
issuerNameRegistry>

ClaimsAuthorizationManager
(see here)

<claimsAuthorizationManager type="PolicyBasedAuthorizationManager">
  <
policy resource="Directory"
         
action="Browse">
    <
claim claimType="…"
          
claimValue="Users" />
  </
policy>
</
claimsAuthorizationManager>

SecurityTokenHandler
(see here)

<add type="Saml11SecurityTokenHandler, ...">
  <
samlSecurityTokenRequirement issuerCertificateRevocationMode="Online"
                               
issuerCertificateValidationMode="ChainTrust" />
</
add>


IdentityModel
Thursday, December 24, 2009 8:38:32 AM UTC  #   
 Wednesday, December 23, 2009

WIF Configuration – Part 2: SecurityTokenHandlerConfiguration

The workhorse of WIF are security token handler. Again token handler can be use independently of the WIF configuration system – or together.

The “stand-alone” use case
You can simply new up a token handler (e.g. the SAML 1.1 handler) in an arbitrary application.

var saml11Handler = new Saml11SecurityTokenHandler();

But a token handler needs more information to do its work (issuer name registry, audience URIs, certificate validation etc.). This information is all encapsulated in the SecurityTokenHandlerConfiguration class. You can reach into that class from the token handler’s Configuration property. Configuration is null by default and must be newed up and set manually.

Handler collections
Another option is to group a bunch of token handlers into a collection. This is useful when you have to deal with a number of in/output token types or need to chain token handlers (e.g. for encryption or compression). Collections also allow to share token handler configuration across contained handlers.

When you new up a SecurityTokenHandlerCollection you have the choice of passing in a SecurityTokenHandlerConfiguration instance, or you use a default configuration (not sure if these values are documented – use reflector ;). When you add a handler to a collection, the collection checks if the handler already has some configuration set (by checking if Configuration is not null). If this is not the case, then handler inherits the collection configuration.

var samlHandlers = new SecurityTokenHandlerCollection(new SecurityTokenHandler[]
    {
        saml11Handler,
        new Saml2SecurityTokenHandler()
    });

Another way to new up a handler collection is to use the static CreateDefaultSecurityTokenHandlerCollection method on the collection. This creates a collection with all default token handlers shipping with WIF. Again you have the option to pass in a configuration object.

Using configuration
Token handler configuration is typically an ideal candidate for configuration files. When you want to support that, you have two choices. Either copy the values from configuration, or use the configuration system to create and configure the handler.

Copying from configuration can be handy sometimes. To do that use the approach shown in my previous post to load the service configuration manually.

The WIF security token handler configuration section also has the concept of named handler collections. There is always a default token handler collection, but you can have additional ones – each with their own configuration, e.g.:

<securityTokenHandlers>
  <!--
default token handlers - inherit global configuration settings -->
 
  <
securityTokenHandlerConfiguration>
    <!--
override with local configuration -->
   
    <
audienceUris>
      <
add value="http://bar" />
    </
audienceUris>
  </
securityTokenHandlerConfiguration>
</
securityTokenHandlers>

<
securityTokenHandlers name="AccessToken">
  <!--
named token handler collection - inherit global configuration settings -->
  <
securityTokenHandlerConfiguration>
    <!--
override with local configuration -->
   
    <
audienceUris mode="Always">
      <
add value="http://custom/*" />
    </
audienceUris>
    <
tokenReplayDetection enabled="true" />
   
    <
certificateValidation>
      <
certificateValidator type="AccessCertValidation, ..."/>
    </
certificateValidation>
  </
securityTokenHandlerConfiguration>

  <
clear />
  <
add type="AccessSecurityTokenHandler, …" />
  <
add type="CompressedSecurityTokenHandler, …" />

</
securityTokenHandlers>

Programmatically, you can get to the standard token handler collection using the SecurityTokenHandlers property on ServiceConfiguration.

To get to the named token handlers, you use the SecurityTokenHandlerCollectionManager, e.g. like this:

var accessHandlers = config.SecurityTokenHandlerCollectionManager["AccessToken"];

So as a rule of thumb: when you new up handlers or collections yourself, you are responsible for programmatic configuration. When you use ServiceConfiguration, the config file settings are applied automatically.


IdentityModel
Wednesday, December 23, 2009 5:38:38 PM UTC  #   
 Tuesday, December 22, 2009

WIF Configuration – Part 1: ServiceConfiguration

WIF supports a flexible configuration system and various ways to programmatically interact with that configuration.

This flexibility comes in two ways:

  • Named configuration elements that you can selectively load (service & token handler configuration)
  • Configuration extensibility (e.g. for token handlers, issuer name registries or claims authorization)

In this first part I’ll focus on the service configuration.

The WIF configuration can have several service elements. Services can be named, the unnamed element becomes the default configuration:

<microsoft.identityModel>
  <
service>
    <!--
default configuration -->
  </
service>

  <
service name="alternateConfiguration">
    <!--
alternate configuration -->
  </
service>
</
microsoft.identityModel>

You can get a handle to the configuration by newing up a ServiceConfiguration object. The ctor allows to optionally pass in the name of the service. From there on you have an OM that represents the various configuration options.

This is useful when you build your own integration, but for WCF and ASP.NET there is already an infrastructure in place.

How to couple configuration with a relying party
By default the standard hosting plumbing uses the default service configuration, but there are various ways to make this dynamic (e.g. for different environment like dev, staging etc).

In ASP.NET you can subscribe to the ServiceConfigurationCreated event of the FederatedAuthentication class. This event gets fired during initialization and gives you the chance to load an arbitrary configuration and pass that back via the ServiceConfigurationCreatedEventArgs.
You can then access the current configuration at any point via FederatedAuthentication.ServiceConfiguration (since creating a configuration is expensive, this class takes also care of caching).

In WCF you wire up WIF with by calling FederatedServiceCredentials.ConfigureServiceHost(…). This call allows you to either pass in an instance of ServiceConfiguration or the stringified name of the service. Another option is to use the ConfigureServiceHostBehavior from configuration. Again this behavior has a parameter called serviceName.

You can then access the current configuration either by

  • finding the FederatedServiceCredentials behavior from the ServiceHost description (if you have access to the ServiceHost)
  • obtain it from a MessageProperty called ServiceConfiguration.

HTH


ASP.NET | IdentityModel | WCF
Tuesday, December 22, 2009 9:34:59 AM UTC  #   
 Thursday, December 10, 2009

Troopers10

The annual Troopers conference takes place in my home town – Heidelberg – this year. nice ;)

If you wanna know more about all things security wrt e.g. Blackberry, SSL/TLS, outsourcing, rootkits, botnets, SAP, cloud computing, you name it. This is the place to be.

I will do a talk about the opportunities and risks of federated identity. See you there!


Conferences
Thursday, December 10, 2009 7:49:52 AM UTC  #   
 Wednesday, December 02, 2009

Baier & Weyer on WIF

We had the pleasure to have a chat with Richard and Carl about what’s nearest and dearest to my heart – WIF ;) Enjoy…

http://www.dotnetrocks.com/default.aspx?showNum=503


IdentityModel
Wednesday, December 02, 2009 8:21:15 PM UTC  #   
 Thursday, November 26, 2009

Thinktecture.IdentityModel v0.6

This version is compiled against WIF RTM.

Some stuff is still experimental. But feel free to play around ;)


IdentityModel
Thursday, November 26, 2009 12:28:47 PM UTC  #   
 Wednesday, November 18, 2009

IDFX to Zermatt to Geneva … to … WIF RTM!

It’s been a long way….

http://msdn.microsoft.com/en-us/evalcenter/dd440951.aspx

I love it!


IdentityModel
Wednesday, November 18, 2009 8:02:15 AM UTC  #   
 Wednesday, November 11, 2009

StarterRP v0.95 (for WIF RC)

Updated StarterRP to go with the 0.95 release of the StarterSTS.

Changes include:

  • added more SOAP endpoints to the WCF RP
    • message, mixed mode, simple (for Silverlight clients)
  • added a Silverlight client that can retrieve tokens and send them to RPs
  • added OpenID bridge test to the ASP.NET RP

Same disclaimer as here applies.


IdentityModel
Wednesday, November 11, 2009 8:06:30 AM UTC  #   
 Tuesday, November 10, 2009

StarterSTS v0.95 (for WIF RC)

I uploaded an interim release of the StarterSTS to codeplex.

This release is not fully tested – and is mainly available to provide compatibility with WIF RC. There are some new features – and I hope I have not introduced any regression bugs. Please contact me via the codeplex forum when you have questions.

Some new features:

  • added a simple HTTP and SOAP based endpoint to request token
  • added support to bridge OpenID logons to WS-Federation
    • you can specify a separate signing key for bridged authentication, so RPs can distinguish between native and bridged authentication
  • config changes to accomodate the various endpoints
    • WS-Trust (message security)
    • WS-Trust (mixed mode security)
    • simple HTTP
    • simple SOAP
    • OpenID bridge
    • WS-Federation metadata
  • did some refactoring to allow easier pluggability and customizations
    • retrieving certificates (CertificateProvider)
    • retrieving claims (ClaimsProvider)
    • analyzing an RST (PolicyOptions and PolicyScope)
    • validating the request against configured policy (PolicyValidator)
  • added optional confirmation screen after login
    • when enabled, the user has to confirm before StarterSTS issues the token
    • this is an additional countermeasure against one-click attacks

Have fun.


IdentityModel
Tuesday, November 10, 2009 6:07:02 PM UTC  #   
 Sunday, November 08, 2009

Thinktecture.IdentityModel updated for WIF RC

download here.


IdentityModel
Sunday, November 08, 2009 12:40:48 PM UTC  #   
 Wednesday, October 28, 2009

Using Silverlight to Access WIF secured WCF Services

This topic comes up quite often recently – so I hope the title is search engine friendly.

Disclaimer: At the time of this writing, the current version of Silverlight is v3 and WIF is in beta 2. Hopefully this will be a non-issue soon.

I talk a lot about claims, tokens and WIF/ADFS 2 to customers. All is good and fine and they like it. Another technology that comes up very often is Silverlight – and especially the “story” of Silverlight and WCF/WIF. Now this is not an easy question to answer.

When thinking about Silverlight and back-end security in general – there are two fundamental scenarios – short of really good names – I call them “passive” and “active”.

Passive
With passive I mean, that the browser has already established a security context with the back-end system the Silverlight .XAP uses (and typically is also hosted at). An example would be that the user first authenticates with the web application and then starts the Silverlight app from there. In this case all the authentication related work was done by browser beforehand and all back-end requests simply re-transmit authentication headers, cookies and the like.

This is not different with WIF secured ASP.NET applications. Eugenio has a good example of this here. This approach works fine while running in the browser and using “application-local” resources only.

Active
This is the scenario I really want to talk about. In this case the .XAP comes from some server down to the client (in or out-of-browser) and wants to communicate with some back-end service on a different machine. This back-end service requires an issued token from a STS.

Those of you with WCF background will say: “that’s what the federation bindings in WCF are for”. But there is no federation binding in Silverlight.

If you need to enable such a scenario, you have to use several workarounds.

Requesting a Token
Since Silverlight has no support for WS-Trust, we must find another way to request a token from a STS. Thanks to WIF this is not hard to do when you control the token service. You could add a simple REST or SOAP head that returns tokens. I wrote about this approach here.

Some remarks here:

  • Since you cannot do the proof of possession crypto in Silverlight, you need to request bearer tokens from the STS.
  • The STS roundtrip is a cross-domain request. This means that the STS needs a client access policy (see here).
  • You have to somehow authenticate with the STS. Silverlight has no support for Kerberos or client certificates. Basically you are stuck with some kind of userid/secret credential. I wrote about that here.

Sending the token to the Service
This is the slightly more complicated part. Since Silverlight has no support for issued tokens, you have to manually embed the token in the outgoing SOAP security header. This is not as scary as it sounds.

There is the so called Basic Security Profile in WS-Security which allows sending a simple security header with a timestamp and a token over SSL. This can be encapsulated in a MessageHeader derived class.

public class SecurityMessageHeader : MessageHeader
{
    string _token;
    string _nsUtility = "...";


    public SecurityMessageHeader(string token)
    {
        _token = token;
    }

    protected override void OnWriteHeaderContents(
      XmlDictionaryWriter writer, MessageVersion messageVersion)
    {
        DateTime now = DateTime.UtcNow;
        string created = XmlConvert.ToString(
          now, "yyyy-MM-ddTHH:mm:ss.fffZ");
        string expires = XmlConvert.ToString(
          now.AddMinutes(5), "yyyy-MM-ddTHH:mm:ss.fffZ");

        writer.WriteStartElement("Timestamp", _nsUtility);
        writer.WriteAttributeString("Id", _nsUtility, "_0");
        writer.WriteElementString("Created", _nsUtility, created);
        writer.WriteElementString("Expires", _nsUtility, expires);
        writer.WriteEndElement();
       
        writer.WriteNode(XmlReader.Create(
          new StringReader(_token)), false);
    }

    public override string Name
    {
        get { return "Security"; }
    }

    public override string Namespace
    {
        get { return "..."; }
    }
}

Afterwards you can attach the header to outgoing calls:

var factory = new ChannelFactory<ServiceContract>("client");
var proxy = factory.CreateChannel();

using (var scope = new OperationContextScope(proxy as IContextChannel))
{
    OperationContext.Current.OutgoingMessageHeaders.Add(
      new SecurityMessageHeader(token));
   
    proxy.BeginOperation(result =>
        {
           ...
        }, null);
}

The binding on the client side is a binding with no client credential but SSL (the binary encoder is not required and used only for performance):

<customBinding>
  <
binding name="BearerTokensOverTransport">
    <
binaryMessageEncoding />
    <
httpsTransport />
  </
binding>
</
customBinding>

On the service side, you need a binding that accepts bearer tokens over transport security, like this:

<customBinding>
  <
binding name="simple">
    <
security authenticationMode="IssuedTokenOverTransport"
             
messageSecurityVersion="WSSecurity11
                                      WSTrust13
                                      WSSecureConversation13
                                      WSSecurityPolicy12
                                      BasicSecurityProfile10
">
      <
issuedTokenParameters keyType="BearerKey" />
    </
security>
    <
binaryMessageEncoding />
    <
httpsTransport />
  </
binding>
</
customBinding>

The rest works as normal. You have to enable WIF in the service and you get your IClaimsPrincipal.

Some remarks:

  • Again this service needs a client access policy for Silverlight cross domain calls.
  • Keep in mind that these are bearer tokens. When you have a scenario that requires proof of possession, this will not work
  • The SOAP response from the service will also contain a security header. Since the client is not configured for security this header may be unexpected. Silverlight does not seem to care, but other web service stacks might. In WCF you can work around that problem by adding the ValidateMustUnderstand behavior to the client stack.

The complete code (STS extensions, Silverlight client and back-end service) is included in the next drop of the StarterSTS (version 0.95). I will upload that soon.

HTH


IdentityModel | WCF
Wednesday, October 28, 2009 8:04:00 AM UTC  #   
 Monday, October 26, 2009

Thinktecture.IdentityModel

Over the last years I have worked with several incarnations of what is now called the Windows Identity Foundation (WIF). Throughout that time I continuously built a little helper library that made common tasks easier to accomplish. Now that WIF is near to its release, I put that library (now called Thinktecture.IdentityModel) on Codeplex.

The library includes:

  • Extension methods for
    • IClaimsIdentity, IClaimsPrincipal, IPrincipal
    • XmlElement, XElement, XmlReader
    • RSA, GenericXmlSecurityToken
  • Extensions to ClaimsAuthorizationManager (inspecting messages, custom principals)
  • Logging extensions for SecurityTokenService
  • Simple STS (e.g. for REST)
  • Helpers for WS-Federation message handling (e.g. as a replacement for the STS WebControl)
  • Sample security tokens and security token handlers
    • simple access token with expiration
    • compressed security token
  • API and configuration section for easy certificate loading
  • Diagnostics helpers
  • ASP.NET WebControl for invoking an identity selector (e.g. CardSpace)

I have also added some samples and a rudimentary API documentation. You can download the whole package identitymodel.codeplex.com.

Feel free to contact me via the forum when you have questions or found a bug.



Monday, October 26, 2009 5:01:47 PM UTC  #   
 Saturday, October 17, 2009

Guide to WCF Extensibility

WCF extensibility is not trivial – this looks like it could become a very valuable source…


WCF
Saturday, October 17, 2009 8:51:42 AM UTC  #   
 Thursday, October 08, 2009

StarterSTS, WIF, Identity on Channel9

Dariusz interviewed me for Channel9. You can find the recording here.

Have fun ;)


IdentityModel
Thursday, October 08, 2009 11:15:46 AM UTC  #   
 Monday, October 05, 2009

Claims based Identity & Access Control Guide – Early drafts available

Eugenio just announced that the codeplex site is up now!

Have a look at the draft documents – feedback is always welcome!!


IdentityModel
Monday, October 05, 2009 5:47:39 AM UTC  #   
 Sunday, September 13, 2009

Restful Token Service Endpoints and Silverlight Clients

It turns out that there is no way in Silverlight to send credentials using the standard HTTP Authorize header (see here). WTF?!.

You have to use a custom HTTP header to transmit credentials in this case, e.g. X-Authorize (nice?). I have adjusted my service code to accept both headers and will update the StarterSTS bits on Codeplex.


IdentityModel
Sunday, September 13, 2009 8:11:35 AM UTC  #   
 Friday, September 11, 2009

StarterSTS Version 0.93

I just uploaded a minor update.

  • refactored ScopeOptions to PolicyOptions and added a PolicyScope class
  • CertificateProvider class abstracts physical loading of relying party encryption certificates
  • /users/restIssue.svc is a Restful token issuance endpoint – you can use a simple GET to retrieve a token (see here)

btw – this is the client code you can use to talk to the REST issuance endpoint:

public static string GetToken(
  string username, string password, string uri, string realm)
{
    using (var client = new WebClient())
    {
        var encoding = Encoding.GetEncoding("iso-8859-1");
        string encodedCreds = Convert.ToBase64String(
          encoding.GetBytes(String.Format("{0}:{1}", username, password)));
        string authHeader = string.Format("Basic {0}", encodedCreds);
        realm = HttpUtility.UrlEncode(realm);

        client.Headers.Add(HttpRequestHeader.Authorization, authHeader);

        return client.DownloadString(
          string.Format("{0}/?realm={1}", uri, realm));
    }
}


IdentityModel
Friday, September 11, 2009 5:43:51 PM UTC  #   

Adding a REST Endpoint to a WIF Token Service

Sometimes it is useful to have a really simple way to acquire a token from a token service – without having to fiddle around with WS-Federation or WS-Trust. Issuing a simple GET request against a token issuance endpoint seems to fulfill that requirement.

So I decided to a add a simple HTTP endpoint to my STS using the WCF web programming model:

[ServiceContract]
public interface IRestfulTokenServiceContract
{
    [OperationContract]
    [WebGet(UriTemplate = "/?realm={realm}")]
    XElement Issue(string realm);
}

You could provide more parameters here (like token type, lifetime etc.) but i decided to keep it simple.

For the implementation you have to decide which authentication types you want to support. Since I needed username/password authentication I used Cibrax’ excellent basic authentication extension. If you need to support client certificates, you would get the certificate details from WCF’s AuthorizationContext.

To route the GET request to the existing token issuance logic, you can create the STS using the static CreateSecurityTokenService method on the SecurityTokenServiceConfiguration class. Then you have to construct a RST and IClaimsPrincipal to describe the token request and pass that into the Issue method. Afterwards you serialize the security token back as a HTTP response and you are done.

I will incorporate that into the next drop of the StarterSTS – but for now here is the code:

public class RestfulTokenService : IRestfulTokenServiceContract
{
    public XElement Issue(string realm)
    {
        EndpointAddress epRealm;
        try
        {
            epRealm = new EndpointAddress(realm);
        }
        catch
        {
            WebOperationContext.Current.OutgoingResponse.StatusCode =
              HttpStatusCode
.BadRequest;
            return null;
        }
       
        RequestSecurityToken rst = new RequestSecurityToken
        {
            AppliesTo = epRealm,
            KeyType = KeyTypeConstants.Bearer
        };

        var sts =
          new StarterTokenServiceConfiguration().CreateSecurityTokenService();
        var rstr = sts.Issue(CreatePrincipal(), rst);

        StringBuilder sb = new StringBuilder();
        var writer = XmlWriter.Create(sb);

        var col =
SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();
        col.WriteSecurityToken(writer,
          rstr.RequestedSecurityToken.SecurityToken);
        writer.Flush();

        WebOperationContext.Current.OutgoingResponse.ContentType =
          "text/xml"
;
        return XElement.Parse(sb.ToString());
    }

    private IClaimsPrincipal CreatePrincipal()
    {
        if (Thread.CurrentPrincipal == null ||
            Thread.CurrentPrincipal.Identity == null ||
            string.IsNullOrEmpty(Thread.CurrentPrincipal.Identity.Name))
        {
            throw new InvalidRequestException("unknown client");
        }

        var identity = new ClaimsIdentity(
            new Claim(WSIdentityConstants.ClaimTypes.Name,
                      Thread
.CurrentPrincipal.Identity.Name));

        return new ClaimsPrincipal(identity);
    }


IdentityModel
Friday, September 11, 2009 9:51:13 AM UTC  #   
 Tuesday, September 01, 2009

StarterSTS Version 0.92

I have an update to the StarterSTS up on codeplex. There is also a new screencast that details the changes from the last version.

Have fun!


IdentityModel
Tuesday, September 01, 2009 10:32:50 AM UTC  #   
 Friday, August 28, 2009

.NET Usergroup Frankfurt – WIF, ADFS 2, CardSpace 2

Am 15. September sind Christian und Ich in Frankfurt und plaudern mal nen Abend lang über unsere Erfahrungen mit Identity und Claims in verteilten Anwendungen.

Wir freuen uns schon und das sollte ein netter Abend werden.

Es sind noch Plätze frei – Anmeldung ist hier erforderlich. Vielleicht sieht man sich ja dort.


Conferences | IdentityModel
Friday, August 28, 2009 6:48:03 PM UTC  #   
 Monday, August 24, 2009

Patterns & Practices - Claims based Authentication & Authorization Guide

Summer break is over – and exciting times lie ahead.

Over the course of the next months I will be working with Eugenio, Keith, Vittorio, Matias and David. The end result will (hopefully) be a very interesting, useful and pragmatic guide to all things claims.

Eugenio already posted some details on the guide and we will be releasing interim version so you can give us feedback.

Watch this space!


IdentityModel
Monday, August 24, 2009 6:11:21 AM UTC  #   
 Thursday, July 30, 2009
 Wednesday, July 22, 2009

Claims Authorization in WIF Beta 2 – ASP.NET and WCF Integration

In the previous post I illustrated how the basic claims authorization infrastructure in WIF (formerly Geneva) works. In this post I want to focus more on how claims authorization behaves when integrated in WCF and ASP.NET.

ASP.NET
In addition to using the claims authorization manager manually like I showed you in the last post, you can also opt-in to per-request claims authorization (think of it as a replacement for the “classic” URL authorization module in ASP.NET / IIS). For this purpose you’ll find an HTTP module called ClaimsAuthorizationModule in the Microsoft.IdentityModel.Web namespace.

This module simply subscribes to the AuthorizeRequest processing stage and calls the configured claims authorization manager for every request. The AuthorizationContext that gets passed in the manager consists of the current IClaimsPrincipal, the request URL and the HTTP method.

If you want to do tricks like custom IClaimsPrincipal implementations, you’d either exchange the principal before you hit the claims authorization manager (in PostAuthenticateRequest) or after it (in PostAuthorizeRequest).

WCF
As usual things are a little more complex in WCF. Authorization (amongst other things) is driven by a ServiceAuthorizationManager in WCF. When you call ConfigureServiceHost, WIF puts a special version of that class, the IdentityModelServiceAuthorizationManager, in place. This class in turn calls out to the configured ClaimsAuthorizationManager. In that case the WS-Addressing To and the Action header are passed in for every request.

HTH


WCF | ASP.NET | IdentityModel
Wednesday, July 22, 2009 5:24:30 AM UTC  #   
 Friday, July 10, 2009

Claims Authorization in Geneva Beta 2 - Introduction

I guess you already heard the term “claims based authorization” several times by now. But how exactly does the authorization work?

The typical pattern is that you iterate through the claims associated with the user and search for a special claim and maybe also a special value of that claim. Based on that you can grant/deny access or modify behavior or UI elements.

This typically leads to code like this:

if (principal.ClaimExists("http://someclaim", "somevalue")) {}

or

principal.DemandClaim(WSAuthorizationConstants.Action, "AddCustomer");

This has the downside, that claim types and values are embedded in your application code and this may become hard to maintain in certain situations. That’s the reason why the Geneva framework Beta 2 introduced a built-in infrastructure for authorization that operates at a higher level of abstraction.

In Geneva authorization information is abstracted as a resource that the subject tries to access and the action the subject wants to perform on that resource. The container for this information is called the AuthorizationContext.

Operation and action are collections of claims. This allows to express from simple to more complicated authorization statements. A simple resource/action pair could be e.g. Directory/Browse. A more complicated statement could be e.g. “Purge printer queue of laser printer in building 61”.

That’s how you could construct the corresponding AuthorizationContext:

var simpleContext = new AuthorizationContext(principal, "Directory", "Browse");

and

var advContext = new AuthorizationContext(principal,
    new Collection<Claim>
    {
        new Claim("http://claims/device", "Printer"),
        new Claim("http://claims/building", "61")
    },
    new Collection<Claim>
    {
        new Claim(WSAuthorizationConstants.Action, "PurgeQueue")
    });

The second piece of plumbing introduced by Geneva is the ClaimsAuthorizationManager. You derive from this class and implement the CheckAccess method. This method accepts an AuthorizationContext and returns true/false. In this method you have to do whatever mapping is necessary to resolve the resource/action pair to claims of the subject.

Use this sample authorization manager to inspect the data that gets passed in:

class SimpleAuthorizationManager : ClaimsAuthorizationManager
{
    public override bool CheckAccess(AuthorizationContext context)
    {
        Console.WriteLine("SimpleAuthorizationManager:");

        Console.WriteLine("\nSubject: {0}\n", context.Subject.Identity.Name);

        Console.WriteLine("Actions:");
        foreach (var action in context.Action)
        {
            Console.WriteLine(" {0}", action.ClaimType);
            Console.WriteLine(" {0}\n", action.Value);
        }

        Console.WriteLine("Resources:");
        foreach (var resource in context.Resource)
        {
            Console.WriteLine(" {0}", resource.ClaimType);
            Console.WriteLine(" {0}\n", resource.Value);
        }

        return true;
    }
}

While you could manually new up that class and directly call CheckAccess method – you can also use configuration to create the authorization manager. This has some interesting features.

First you need to configure the authorization manager in config:

<microsoft.identityModel>
  <
service>
    <
claimsAuthorizationManager
type="LeastPrivilege.PolicyAuthorizationManager, ClaimsAuthorization" />
  </
service>
</
microsoft.identityModel>

And then use the following code to create and use the authorization manager:

var config = new ServiceConfiguration();
var authz = config.ClaimsAuthorizationManager;

var simpleContext = new AuthorizationContext(
  principal, "Directory", "Browse");
var allowed = authz.CheckAccess(simpleContext);

You can also use the ClaimsPrincipalPermission/Attribute classes which simplify the call and automate the creation from configuration:

new ClaimsPrincipalPermission("Directory", "Browse").Demand();

or

[ClaimsPrincipalPermission(SecurityAction.Demand,
  Resource = "Directory", Operation = "Browse")]
private static void BrowseDirectory()
{ }

As with the normal PrincipalPermission – these classes throw a SecurityException and assume that you have populated Thread.CurrentPrincipal.

The configuration for the claims authorization manager has an interesting extensibility point. You can attach arbitrary XML to the configuration element. This allows to create policy statements directly in config or provide enough information for the authorization manager to load the policy from somewhere else. Whenever such an attached XML fragment exists, the configuration loader calls a special constructor of ClaimsAuthorizationManager and passes over the fragment as an XmlNodeList.

public class PolicyAuthorizationManager : ClaimsAuthorizationManager
{
   
// this ctor gets called when there is a child element in app.config
    public PolicyAuthorizationManager( object objXmlElement )
    {
        XmlNodeList nodes = objXmlElement as XmlNodeList;
        Process(nodes);
    }
}

The same mechanism is also used for SecurityTokenHandlers btw.

The Geneva SDK includes a sample that shows how to use this extensibility point to parse authorization policy (in the Extensibility folder). With this sample you could write something like this for the above authorization statements:

<claimsAuthorizationManager type="type">

  <policy resource="Directory"
          action="Browse">
    <
claim claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
          
claimValue="Users" />
  </
policy>
 
  <
policy resource="Printer_61"
         
action="PurgeQueue">
    <or>
      <claim claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
           claimValue="Enterprise Administrators" />
   
      <and>
        <claim claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
               claimValue="Administrators" />
        <claim claimType=http://claims/building
               claimValue="61" />
      </and>
    </or>
  </policy>
</claimsAuthorizationManager>

Everything you’ve seen here can be used in arbitrary application types. In the next post I show how this is integrated with WCF and ASP.NET.



Friday, July 10, 2009 2:29:17 PM UTC  #   

Defeating SSL

Not a really new paper – but definitely recommended reading.

Some lessons learned:

  • Moxie is not really attacking SSL – but uses HTTP to bypass HTTPS.
  • Switch to SSL as early as possible – but that might be too late already.
  • Users never type https:// (nor http://) – they start with plain text and hope the application is doing the right thing.
  • Fortunately (web) services are not affected. There is no human doing the http vs https decision. WCF e.g. also doesn’t like to be downgraded to plain text whenever credentials are involved. That’s a good thing in the face of such attacks.
  • Endpoint Identities (an addition to WS-Addressing) are a good thing.

I see interesting times for passive profile SSO scenarios like WS-Federation. This doesn’t mean that these technologies open new holes – it is just that the (username/password) credentials we send around are much more powerful because they can be used in multiple applications.

This also means – if you are building a passive STS – you should not solely rely on SSL to secure your tokens. Encrypt them!


IdentityModel | ASP.NET | WCF
Friday, July 10, 2009 10:09:50 AM UTC  #   
 Friday, July 03, 2009

A closer look at Sandboxing in (ASP.NET) V4

In the last two posts I described how ASP.NET uses the homogenous AppDomain model to implement partially trusted apps.

In ASP.NET you use the combination of a trust level (aka grant set) and a list of full trust assemblies to setup the homogenous AppDomain. This maps directly to the AppDomain.Create() call that allows the corresponding parameters to be passed in.

Another option is to determine the trust level of application assemblies using a policy resolver. The resolver gets called when an assembly gets loaded into the AppDomain and you can dynamically specify if the assembly should run in full trust or the AppDomain grant set.

The second option is implemented using the new features around AppDomain managers in .NET 4.0 (read more here, here, here). These new features basically boil down to two new ways to specify an AppDomainManager for the default or newly created AppDomains. You can now either use configuration (in the runtime section) or specify the AppDomainManager type on the AppDomainSetup object when manually creating AppDomains.

This is exactly what ASP.NET is doing. The AppDomainManager implemented in System.Web.Hosting.ApplicationManager+AspNetAppDomainManager is used for ASP.NET created AppDomains. This manager in turn uses a custom HostSecurityManager (implemented in System.Web.Hosting.ApplicationManager+AspNetHostSecurityManager). This host security manager in in turn expresses his interest to resolve policy when assemblies get loaded (using the Flags property).

In the ResolvePolicy method, the host security manager calls out to the policy resolver (if specified). The return is then parsed and turned into either full trust/appdomain trust/nothing permission sets. Nice.

This mechanism is not special to ASP.NET – and can be used in arbitrary applications. Useful for writing hosts with more advanced requirements.

(thanks to shawnfa/stefsch)


FX Security | ASP.NET
Friday, July 03, 2009 9:37:41 AM UTC  #   
 Thursday, July 02, 2009

Identity Metasystem Interoperability Version 1.0

The IMI spec is now approved. Grats!

Read more here and get the spec here.


IdentityModel
Thursday, July 02, 2009 7:25:29 AM UTC  #   
 Wednesday, July 01, 2009

Partial Trust ASP.NET in 4.0 (Advanced Scenarios)

In the last post I showed you how to use the new CLR security model to do sandboxing in ASP.NET.

One new hook into this system is a custom host security policy resolver. A policy resolver is a class that derives from System.Web.Hosting.HostSecurityPolicyResolver. The idea behind this extensibility point is, that a resolver can decide at runtime (as opposed to the static fullTrustAssemblies configuration element) in which “permission bucket” the assembly should get loaded – AppDomain grant set, full trust or nothing.

A resolver has a single method called ResolvePolicy. ASP.NET hands in the evidence of every application assembly that gets loaded into the resolver, and it is the implementer’s job to decide the “trust level”.

ResolvePolicy returns a HostSecurityPolicyResults enum which can have one of these values: DefaultPolicy, FullTrust, AppDomainTrust or Nothing.

You register the resolver using the following config element:

<trust level="Medium"
       permissionSetName="ASP.Net"
       hostSecurityPolicyResolverType="Policy.PolicyResolver, …" />

A resolver must be in the GAC – otherwise you may receive a strange exception saying “assembly still being loaded”…

HTH


FX Security | ASP.NET
Wednesday, July 01, 2009 6:40:07 AM UTC  #   
 Tuesday, June 30, 2009

Partial Trust ASP.NET in 4.0

In .NET v4 there are substantial changes to the CLR security model. Read about all the details here. With Beta 1 in hand I gave the new model a try in the probably most popular host for partial trust – ASP.NET.

You start with setting the trust level in web.config. This works exactly the same as in pre-V4. Also the same web_xytrust.config files from the framework configuration directory are used. Since policy levels and code groups are not in effect any longer in V4, ASP.NET by default uses the named permission set called ASP.Net as the grant set for the AppDomain.
You can also specify a different set via the new permissionSetName attribute.

<trust level="Medium" permissionSetName="ASP.Net" />

So far everything behaves like in CLR2. Now a typical thing to do would be to factor out the “dangerous” code into separate assemblies and grant these assemblies full trust to do their work. In CLR2 you either GACed such an assembly or modified the security policy to grant whatever permissions were needed.

Since there is no security policy anymore in V4 and ASP.NET has moved to the homogenous AppDomain model – things work differently (and easier) now. In a homogenous AppDomain there are permission-wise two types of assemblies – ones constrained by the AppDomain grant set and full trust assemblies. With the new fullTrustAssemblies configuration element, you can specify which assemblies should be loaded in full trust, e.g.:

<fullTrustAssemblies>
  <add assemblyName="HelperLib"
       version="1.0.0.0"
       publicKey="0024…cb0" />
</fullTrustAssemblies>

To make HelperLib callable from partial trust, you have to add the standard [AllowPartiallyTrustedCallers] attribute to the assembly. With the new transparency model in V4, APTCA means that the library provides services to partially trusted code and can contain critical and safe critical code. All un-annotated code in an APTCA assembly becomes security transparent by default.

This is a huge improvement over the old model. Since partially trusted code is always transparent, it can only call transparent or safe critical code. The typical pattern is that you provide safe critical “gateways” in your library where you do all the security checks, input validation and asserts (if necessary). From there you then call into the critical code (e.g. a library function).

The following is a simple example of a library that provides read access to certain directories to partially trusted ASP.NET applications:

[assembly: AllowPartiallyTrustedCallers]

namespace HelperLib
{
    public class Helper
    {
        [SecuritySafeCritical]
        public string ReadFile(string filename)
        {
            var perm = new FileIOPermission(
                FileIOPermissionAccess.Read, GetAllowedContentDirs());
            perm.Assert();

            return File.ReadAllText(filename);
        }
    }
}

HTH


ASP.NET | FX Security
Tuesday, June 30, 2009 12:02:08 PM UTC  #   
 Wednesday, June 17, 2009

Updated Starter STS

I just uploaded a minor update to the Starter STS sample to codeplex. This release adds more options for realm checking (see the allowKnownRealmsOnly config switch) as well as Information Card issuance.

As always – feedback is welcome!

http://startersts.codeplex.com


IdentityModel | ASP.NET | WCF
Wednesday, June 17, 2009 7:21:52 AM UTC  #   
 Friday, June 05, 2009

.NET Access Control Service Talk from Troopers09

I did a talk about the ACS in May. It was interesting to present that topic to a non-Developer, non-Microsoft minded audience.

Here’s the outcome:
http://www.viddler.com/explore/TROOPERS/videos/1/

_


IdentityModel
Friday, June 05, 2009 3:45:53 AM UTC  #   
 Thursday, June 04, 2009

Writing Custom Attribute Stores for Geneva Server (B2)

This document appeard on the connect site. Interesting.

_


IdentityModel
Thursday, June 04, 2009 6:31:37 AM UTC  #   
 Wednesday, June 03, 2009

Worker Process Accounts in IIS 7.5

Windows 7 and Windows Server 2008 R2 ship with IIS 7.5. While migrating the StarterSTS, I made an interesting observation. I remember vaguely I read about that somewhere – but basically I got this error message:

Cannot open database "aspnetdb" requested by the login. The login failed.Login failed for user 'IIS APPPOOL\DefaultAppPool'.

That’s an interesting account.

A closer look reveals, that in IIS manager you now have five accounts to choose from when setting up an App Pool: System, Network Service, Local Service, Custom… and ApplicationPoolIdentity. The default value is ApplicationPoolIdentity.

With this new setting, a new primary SID is injected into the worker process – all Windows security checks are done against this new SID. Converting that NT Account to an SID reveals an S-1-5-82 – which was new to me.

So in the light of the recent problems with system account sharing (here and here), this is a good change and makes it even easier to isolate worker processes.

HTH
IIS
Wednesday, June 03, 2009 6:59:03 PM UTC  #   

 Thursday, May 28, 2009

Geneva Framework Quick Tip: How to access Configuration

Remember that Geneva framework is a framework – all the nice integration into WCF and ASP.NET is built on top of a public API. This also means that you can use Geneva framework for integration in arbitrary hosts and environments.

One thing you most often need is access to the Geneva framework configuration (microsoft.identityModel section) from code – and again this is very easy:

ServiceConfiguration config = new
  ServiceConfiguration(ServiceConfiguration.DefaultServiceName);

HTH


IdentityModel
Thursday, May 28, 2009 5:21:31 AM UTC  #   

Geneva Framework Quick Tip: Hosting a Security Token Service

The idea of the security token service infrastructure in Geneva is, that it is completely host agnostic. The STS itself expects a RequestSecurityToken and returns a RequestSecurityTokenResponse. It is the job of the host to translate some protocol back and forth to this technology independent representation.

The key to STS hosting (and that’s btw what the WCF WSTrustServiceContract class or the FederatedPassiveSignin web control does) is to create a token service from configuration. And this couldn’t be easier ;)

var config = new TokenServiceConfiguration();
var sts = config.CreateSecurityTokenService();

var rstr = sts.Issue(principal, rst);

 

HTH


IdentityModel
Thursday, May 28, 2009 4:50:57 AM UTC  #   
 Wednesday, May 27, 2009

Starter STS Screencasts

All two screencasts about the starter STS sample are online now:


IdentityModel
Wednesday, May 27, 2009 1:54:12 PM UTC  #   
 Tuesday, May 26, 2009

Thinktecture Security Token Service Starter Kit

I am happy to announce the “Thinktecture STS Starter Kit” sample. The STS starter kit is a compact, easy to use identity provider that is completely based on the ASP.NET provider infrastructure. It is built using the Geneva framework Beta 2 bits and is a self contained web site with passive and active endpoints (Christian has some screenshots).

The motivation behind writing this sample is twofold. First, writing a custom STS from scratch is not terribly hard – but it is also not a trivial task. In addition the full featured Geneva Server product may not fit your requirements (e.g. because your users are not stored in Active Directory). So a lot of people I spoke to mentioned that it would be nice to have a simple STS that uses membership, roles and profile and that is easy to setup and get going.

The other reason is that starter STS is not terribly complex and could be used as a learning tool on how to write custom token services. You could e.g. replace the provider plumbing with your own libraries while you go.

Some features:

  • active and passive security token service
  • supports WS-Federation, WS-Trust 1.3 (message and mixed) and SAML 1.1/2.0 tokens
  • based on the standard membership, roles and profile provider infrastructure
  • membership provider is used to authenticate users and to provide a name and email claim
  • role provider is used for authorization in the web front-end and to provider role claims
  • profile provider is used to allow users to supply profile information which gets turned into claims
  • easy administration of the provider features using the IIS7 manager
  • easy configuration – you don’t have to deal with Geneva or WCF settings directly
  • control over security policy (SSL, encryption, SOAP security)
  • dynamic web UI to allow users to maintain their profile data
  • automatic generation of a WS-Federation metadata document to allow RPs to federate using e.g. FedUtil

To make it even easier for you to setup and start using the STS, I have recorded a screencast that walks you through the installation and setup process. In the following posts I will focus more on on some of the feature areas and explain how they are used and implemented. Have fun!

Download STS Starter Kit Sample.
Download Setup&Overview Screencast


IdentityModel
Tuesday, May 26, 2009 5:54:25 AM UTC  #   
 Sunday, May 24, 2009

Use Geneva Session Management for your own needs

Geneva Framework is a Framework is a Framework.

One part of that framework is the SessionAuthenticationModule for ASP.NET. In all the typical samples this is used to convert an incoming SAML token to a cookie to establish an authentication session.

A closer look reveals, that the purpose of this module is actually serializing SessionSecurityTokens into cookies. A SessionSecurityToken in turn is a container for an IClaimsPrincipal and an additional SecurityToken (the so called bootstrap token).

This means that the SessionAuthenticationModule is a general module and API to serialize claims principals and security tokens into cookies. In addition there is an extensible architecture around how these cookies are layed out and protected. You can utilize this infrastructure whenever you need to serialize and round-trip an IClaimsPrincipal.

Where can this be useful? Let’s do this little walkthrough…

First use the Visual Studio Geneva templates to create a simple “Claims-aware ASP.Net WebSite”. This sample uses the ClaimsPrincipalHttpModule to create an IClaimsPrincipal from the standard forms authentication principal.

In the next step add a ClaimsAuthenticationManager to the web site and register it, e.g.:

public class Transformer : ClaimsAuthenticationManager
{
    public override IClaimsPrincipal Authenticate(string endpointUri, IClaimsPrincipal incomingPrincipal)
    {
        // expensive operation
        incomingPrincipal.Identities[0].Claims.Add(new
          Claim("http://claims/expensive", "expensive value"));

        return incomingPrincipal;

    }
}

The custom claims you are adding in the authentication manager might come from some remote data store and you probably want to avoid such a round-trip on every request. To optimize this, you could come up with some server-local caching strategy – or use the SessionAuthenticationModule to serialize the IClaimsPrincipal after transformation to a cookie. The module will then reconstruct the IClaimsPrincipal on subsequest requests and set it as the current principal for the ASP.NET application.

First add the session authentication module to the modules section in web.config – then add this code to the authentication manager:

private void SetSessionCookie(IClaimsPrincipal incomingPrincipal)
{
  SessionSecurityToken token = new SessionSecurityToken(incomingPrincipal);
  FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(token);
}

Call this method before you return the transformed principal back to Geneva.

Note: When your app is not running over SSL – you need to set the requireSsl setting for the cookie handler in web.config to false.


IdentityModel | ASP.NET
Sunday, May 24, 2009 2:04:32 PM UTC  #   
 Friday, May 22, 2009

Thinktecture WS-Federation Metadata Generator

Mr. Metadata strikes back! This time with a generator/wizard for WS-Federation Metadata language. This makes it very easy to create documents that can be consumed by Geneva Server or FedUtil.

More info here.


ASP.NET | WCF | IdentityModel
Friday, May 22, 2009 11:43:30 AM UTC  #   
 Thursday, May 21, 2009

.NET 4.0 Security

Now that Beta 1 has shipped I am finally allowed to talk about the new/changed security features in 4.0 – but there is no one who can explain these things more elaborate and insightful than Shawn. I just saw that he is about to start a series of posts on the new feature areas. So watch his space closely!

(ah – and btw – leave a comment on his blog that he should write a book about security in .NET 4.0 – maybe we can convince him ;)


FX Security
Thursday, May 21, 2009 4:35:31 AM UTC  #   
 Monday, May 18, 2009

More Geneva Beta 2 Changes

Just came across this document. Interesting read.


IdentityModel
Monday, May 18, 2009 1:45:21 PM UTC  #   

Geneva Beta 2 Update: ClaimsPrincipalHttpModule

I am currently in the process of updating my Geneva code to Beta 2. There are some pretty substantial changes/additions in the new Beta – so I thought I’ll detail some of them while moving along. Today: ClaimsPrincipalHttpModule.

For a basic understanding what the module does, I recommend reading my initial post here.

Starting with Beta 2, ClaimsPrincipalHttpModule supports converting X509 client certificates to an IClaimsPrincipal. This is done by using the ctor of IClaimsIdentity that takes an X509Certificate2 which results in an authenticated identity with an authentication type set to “SSL/PCT”.

Now as always, certificate based authentication is a little different to e.g. username/password. In the strict sense a user is authenticated when you know “who he is”. For usernames/passwords authentication this means as soon as you have successfully validated the password against your data store (or put differently – as soon as the user provides a proof for his identity). Proofing identity in the certificate case basically means that the certificate is trusted and the client “knows” the corresponding private key. That’s why the ClaimsPrincipalHttpModule sets IsAuthenticated=true when the client certificate is valid.

Now Windows/IIS supports a number of certificate issuers and a user can potentially present a client cert to IIS which is “valid” but the client may still not be a valid/registered user in your system. This results (depending on your design) in different semantics for “IsAuthenticated” checks like Request.IsAuthenticated or <deny users=”?” />.

A better way would be to replace blanket authentication checks with checks for specific claims (like a “User” role or some permission).

HTH


IdentityModel | ASP.NET
Monday, May 18, 2009 6:23:27 AM UTC  #   
 Friday, May 15, 2009

Establishing Trust with the .NET Access Control Service (Geneva Beta 2)

In Geneva you use a IssuerNameRegistry to establish trust with token issuers. The job of the registry is to parse the issuer details and return a well-known string identifying that issuer. If the registry cannot determine that well known string, the issuer is considered non-trusted and request processing is stopped.

Typically it is enough to inspect the X509 certificate that was used to issue the SAML token, but with the Access Control Service the situation is a little different. The ACS uses a multi-tenant model and signs all outgoing tokens with the same certificate. This means it is not sufficient to check the signature only to determine that the token was issued by a specific instance of the ACS.

In addition you also have to check the value of the SAML issuer URI which contains the logical issuer name which in turn contains the ACS solution name. Prior to Geneva Beta 2 you had to use two different extensibility points to do both checks. I wrote about that here.

Starting with Beta 2, the issuer name registry now has the capability to parse both the physical and logical issuer. Great!

Find a sample implementation below:

class AccessControlServiceIssuerNameRegistry : IssuerNameRegistry
{
    string _solutionName = "leastprivilege";
    string _acsThumbprint = "6de1689a739d548a5690dbc3894b953ef6123d93";
    string _samlIssuer;

    public AccessControlServiceIssuerNameRegistry()
    {
         _samlIssuer = String.Format("http://{0}.accesscontrol.windows.net/",
           _solutionName);
    }

    public override string GetIssuerName(SecurityToken securityToken)
    {
        // should never get called
        throw new NotImplementedException();
    }

    public override string GetIssuerName(SecurityToken securityToken, string requestedIssuerName)
    {
        var issuerToken = securityToken as X509SecurityToken;
        if (issuerToken == null)
        {
            throw new ArgumentException("securityToken");
        }

        if (string.IsNullOrEmpty(requestedIssuerName))
        {
            throw new ArgumentNullException("requestedIssuerName");
        }

        if (!string.Equals(_acsThumbprint, issuerToken.Certificate.Thumbprint, StringComparison.OrdinalIgnoreCase))
        {
            throw new SecurityTokenException(
              "Token not issued by the Access Control Service");
        }

        if (!string.Equals(_samlIssuer, requestedIssuerName, StringComparison.OrdinalIgnoreCase))
        {
            throw new SecurityTokenException(
              "Token not issued by the requested instance of the Access Control Service");
        }

        return _samlIssuer;
    }
}



Friday, May 15, 2009 5:59:42 AM UTC  #   
 Monday, May 11, 2009

Die Information Card Foundation DACH-Initiative

Mehr Infos hier

 

 


IdentityModel | Misc
Monday, May 11, 2009 2:21:01 PM UTC  #   
 Thursday, April 16, 2009

Sod This!

I usually don’t listen to podcasts. But I must admit that Sod This! is quite entertaining. Oliver along with his buddy Gary do a nice mixture of geek-ish talk, interviews and just plain nonsense. Very recommended!


Misc
Thursday, April 16, 2009 8:10:05 PM UTC  #   
 Wednesday, April 15, 2009

Fixing Token Kidnapping

I while ago I wrote about the “Token Kidnapping” vulnerability in Windows. By looking at the slides and POC it becomes clear that there is no easy fix for that.

According to Microsoft, the problem is fixed now – and indeed – it seemed to be a huge effort:

“Addressing this issue required one of the most epic engineering efforts we have ever expended for a Microsoft security update. This security update changed parts of the Windows kernel; the COM, DCOM, and LSASS subsystems; the WMI and MSDTC built-in services; and the service control manager (SCM).”

The details are described here. Thanks for the information, MSRC!


Misc
Wednesday, April 15, 2009 8:13:37 AM UTC  #   
 Tuesday, April 07, 2009

Krise? Nein! „Service-Orientierung heute und morgen“: 5 Tage volle Power und praktisches Wissen

Sind Sie auch müde, ständig von „Krise“ und „Einschränkungen“ zu lesen? Sind Sie nicht jemand, der sich immer weiter entwickeln möchte und fit für die heutigen Problemstellungen aber auch vorbereitet für zukünftige Herausforderungen sein möchte? Wir haben da was für Sie…


Gemeinsam mit Referenten und Experten thinktecture präsentiert DevelopMentor fünf Tage voller Power, geballtem Wissen und praktischer Umsetzung mit dem „Service-Orientierung heute und morgen“-Kurs.


Dominick Baier und Christian Weyer zeigen Ihnen in gewohnt praxisorientierter Art und Weise sowohl Grundlagen und Konzepte als auch deren konkrete und pragmatische Umsetzung, alles basierend auf jahrelanger Projekterfahrung.
Erleben Sie wie Sie Service-Orientierung heute und morgen - gemischt mit dem zukunftsweisenden Themenkomplex Cloud Computing - auf Basis der Windows- und .NET –Plattform lokal und in der Cloud realisieren können. In Hands-on-Labs können Sie selbst die Ärmel hochkrempeln und gleich das Gelernte in Form von Code in Tatsachen umsetzen.


Nach diesen fünf Tagen werden Sie basierend auf diesen Themenbereichen die ersten Schritte in der Welt von Service-Orientierung alleine gehen können und vor allem vorbereitet sein für kommende Projektaufgaben:

  • Service-Orientierung
  • Cloud & Cloud Computing
  • Identitäts-Management & Claims-basierte Identität
  • Windows Communication Foundation (WCF)
  • Windows Workflow Foundation (WF)
  • Azure Services Plattform (mit Windows Azure und .NET Services)

Die folgende Auflistung gibt Ihnen einen detaillierteren Überblick über die behandelten Themen:

Tag 1

  • Service-Orientierung
  • WCF-Architektur
  • Design-by-Contract

Tag 2

  • WCF Instances, Concurrency & Session Management
  • WCF Security
  • WCF Hosting

Tag 3

  • WF Workflow Services
  • WCF REST
  • Azure-Services-Architektur

Tag 4

  • Windows Azure Development & Deployment
  • Windows Azure Storage
  • Identitäts-Management

Tag 5

  • .NET Services Access Control Service
  • .NET Services Service Bus
  • NET Services Workflow Service

Und hier noch die notwendigen Informationen für Ihre Planung:

Wann? 6.-10. Juli 2009
Wo? Häckers Kurhotel, Bad Ems
Wieviel? 3200,- € (inkl. Übernachtungen, Frühstück, Mittagessen und Abendessen)

Durchführender Veranstalter ist DevelopMentor.

 

Für Fragen, Wünsche oder Buchungsanfragen kontaktieren Sie bitte thinktecture oder DevelopMentor.

Vielen Dank.
ASP.NET | WCF | Work in Progress | IdentityModel | Conferences
Tuesday, April 07, 2009 12:02:31 PM UTC  #   

 Friday, April 03, 2009

PPID Information and Generation Examples

This article provides useful information on generating interoperable PPIDs.


IdentityModel
Friday, April 03, 2009 6:52:54 AM UTC  #   
 Thursday, April 02, 2009

Custom Principals in WCF with Geneva

WCF has an extensibility point to set your own IPrincipal implementation on Thread.CurrentPrincipal (I wrote about that here). Geneva uses this mechanism to set its IClaimsPrincipal (wrote about that here).

Since the standard “slot” for custom principals is already used by Geneva, it was unclear to me how to set your own IPrincipal after Geneva has done its work. With a little help from the Geneva team (thanks Jan) – I found a way that works.

You can replace the principal in a service authorization manager via the Properties collection on the authorization context. Voodoo.

class AuthorizationManager : IdentityModelServiceAuthorizationManager
{
    public override bool CheckAccess(OperationContext operationContext, ref Message message)
    {
        base.CheckAccess(operationContext, ref message);

        // action header to get to the request operation
        string action = operationContext.IncomingMessageHeaders.Action;

        // properties collection holds the principal that goes on Thread.CurrentPrincipal
        var properties = operationContext
                        .ServiceSecurityContext
                        .AuthorizationContext
                        .Properties;

        // retrieve current principal
        IClaimsPrincipal principal = properties["Principal"] as IClaimsPrincipal;
       
        // create custom principal
        var customPrincipal = new CustomClaimsPrincipal(principal, "some value");
       
        // set the custom principal
        properties["Principal"] = customPrincipal;
           
        return Authorize(action, customPrincipal);
    }

    private bool Authorize(string action, CustomClaimsPrincipal principal)
    {
        // do whatever authZ logic you have
        return true;
    }
}

public class CustomClaimsPrincipal : ClaimsPrincipal
{
    public CustomClaimsPrincipal(IClaimsPrincipal principal, string customValue)
      : base(principal)
    {
        CustomPropery = customValue;
    }

    public string CustomPropery { get; set; }
}

Afterwards register this class in the ServiceAuthorizationBehavior.

Be aware that this gets called on every request – so don’t put expensive operations in the custom principal creation code.


IdentityModel | WCF
Thursday, April 02, 2009 9:01:34 AM UTC  #   
 Sunday, March 29, 2009

Client Generated SAML Tokens to Interact with the Access Control Service

I recently wrote about generating SAML tokens at the client. Justin showed a similar approach at Mix to interact with the Access Control Service.


IdentityModel | WCF | ASP.NET
Sunday, March 29, 2009 5:34:35 AM UTC  #   
 Tuesday, March 17, 2009

Get Skilled or get 0wned

Nice claim for a conference ;)

I am happy to join my former colleagues from ERNW for their yearly Troopers conference in Munich.

Two days full of top notch security talks – should be big fun. I’ll add my 2c about the .NET Access Control Service (Microsoft’s R-STS in the cloud) to the mix.

http://www.troopers09.org


Conferences
Tuesday, March 17, 2009 8:01:56 AM UTC  #   
 Thursday, March 12, 2009

Geneva integration into ASP.NET

Geneva is integrated in ASP.NET/IIS using the standard IHttpModule extensibility mechanism. Geneva ships with three HTTP modules:

  • ClaimsPrincipalHttpModule (already wrote about it here).
  • WSFederationAuthenticationModule (implements WS-Federation authentication)
  • SessionAuthenticationModule (implements session authentication)

ClaimsPrincipalHttpModule is special – but the other two are built upon a framework for handling token based authentication in ASP.NET. To integrate into this framework, one has to derive from a base class called FederatedAuthenticationModuleBase. This implements the IHttpModule interface, subscribes to the AuthenticateRequest and EndRequest pipeline events and provides some helper methods. This base class drives the core logic of how a typical redirection and token based authentication works. For the protocol specific details, the derived class has to implement a bunch of abstract methods. This is how WS-Federation is implemented – other protocols could be realized in a similar fashion.

The core logic is as follows:

AuthenticateRequest

  • check if federated authentication is enabled
  • check if current request is a sign in request (abstract CanReadSignInRequest)
  • extract security token from request (abstract GetSecurityToken)
    • raise SecurityTokenReceived event
  • create IClaimsPrincipal from security token
    • raise SecurityTokenValidated event
  • set principal
  • create session security token
  • set session security token using the configured cookie handler
    • raise SessionSecurityTokenCreated event
  • raise SignedIn event
  • check for a return URL (abstract GetReturnUrlFromResponse)
    • do the redirect

EndRequest

  • check if federated authentication is enabled
  • if a 401 response is found, redirect to identity provider (abstract RedirectToIdentityProvider)

Now let’s have a close look what the two derived module do.

WSFederationAuthenticationModule
As stated earlier, this module deals with WS-Federation redirects and token parsing.

  • CanReadSigninRequest
    checks for the WS-Federation messages (wsignin1.0 / wsignoutcleanup1.0)
  • GetSecurityToken
    extracts the token from the STS response and uses the security token handler infrastructure to create a SecurityToken
  • GetReturnUrlFromResponse
    parses the WS-Fed context field for a return URL-
  • RedirectToIdentityProvider
    creates a SignInRequest message and redirects to the configured identity provider.

 

SessionAuthenticationModule
After the module implementing the authentication protocol has done its job, the base class creates a session token. This session token contains the original token issued from the STS (the bootstrap token) as well as a serialized version of the IClaimsPrincipal (after transformation via the ClaimsAuthenticationManager). This session token gets persisted by a cookie handler (typically into a HTTP cookie). The session authentication module uses this cookie to re-create the IClaimsPrincipal on each request.

Since the session token characteristics are a bit specific, the module builds upon the base framework and helper methods, but short-circuits the logic by overriding AuthenticateCore directly. This is what happens:

  • check if cookie is present (using the configured cookie handler)
  • recreate the SessionSecurityToken from the cookie (using the session security token handler)
  • raise SessionSecurityTokenReceived event
  • based on the outcome of the event either renew the cookie and/or set the principal
  • raise SignedIn event

HTH


ASP.NET | IdentityModel
Thursday, March 12, 2009 9:21:38 PM UTC  #   

Geneva integration into WCF

Having done quite a bit of WCF customization myself, it is fun to see how Geneva framework wires itself up into the WCF runtime.

The high-level goals are as follows:

  • route the token provisioning, serialization and authentication through the Geneva pipeline
  • make an IClaimsPrincipal available on the service side
  • allow setting issued tokens directly on a ChannelFactory

On the service side this is achieved by passing in a ServiceHost instance into FederatedServiceCredentials.ConfigureHost(). What does exactly happen inside that call?

  • replace the standard WCF ServiceCredential with a FederatedServiceCredential
    • the service credential drives the creation of a SecurityTokenManager (in this case the FederatedSecurityTokenManager)
    • this in turn creates the token provider, serializer and authenticator. In Geneva all three functionalities are inside a SecurityTokenHandler.
    • Geneva’s token manager dispatches the incoming requests to the corresponding methods of the token handler depending on the incoming token type
  • set the service certificate
    • either by copying the standard service certificate specified in the ServiceCredential.
    • or by replacing the existing one with the certificate specified in the <microsoft.IdentityModel /> configuration section
  • create token resolvers for
    • the service certificate
    • issuer certificates (if the WCF knownIssuers configuration element is set)
  • set a ClaimsAuthenticationManager (either a pass-through one, or the one specified in code/config)
  • set the PrincipalPermissionMode to Custom. This is necessary to populate Thread.CurrentPrincipal with an IClaimsPrincipal.
  • set the service authorization manager.
    • service authorization managers drive the creation of authorization policies.
    • an authorization policy in turn can parse the WCF internal claims and set Thread.CurrentPrincipal. Persisting the bootstrap token also happens here.
    • to make this all work, Geneva has its own service authorization manager (IdentityModelServiceAuthorizationManager) and its own authorization policy (Microsoft.IdentityModel.Tokens.AuthorizationPolicy).

 

On the client side things are much simpler. The main purpose of the Geneva client side plumbing is to allow more direct interaction with tokens. The standard WCF issued token client credential assumes you want to implicitly acquire a token from a WS-Trust token service.

Token provisioning is driven by so called SecurityTokenParameters. Whereas the WCF built-in IssuedSecurityTokenParameters only allow specifying the details of the token issuer, the Geneva FederatedClientCredentialsParameters instead allows setting a pre-acquired token directly.

So when you call FederatedClientCredentials.ConfigureChannelFactory<T> all that is happening is, that the standard WCF ClientCredentials get replaced by the FederatedClientCredentials class. This creates a FederatedClientCredentialsSecurityTokenManager which in turn instantiates the token serializer (via the security token handlers) and a token provider that is aware of FederatedClientCredentialsParameters.

To actually set the token on a channel, you call one of the extension methods for ChannelFactory<T>. They can be found in Microsoft.IdentityModel.Protocols.WSTrust.ChannelFactoryOperations. These extension methods take the token you pass in, create the token parameters and add them to the token parameters collection of the channel.

HTH


WCF | IdentityModel
Thursday, March 12, 2009 9:56:01 AM UTC  #   
 Tuesday, March 10, 2009

Using SAML as a Client Credential Type in WCF (with Geneva)

Disclaimer
For the motivation for this article please read this here first. I am not advocating the use of client generated SAML tokens in general, and I also know that there is not much point in the client generating claims for a service. This whole article is about replacing the UserName token with a SAML token in situations where you need extensibility points that a UserName tokens cannot give you.

As I said in my previous post, SAML is an extensible and flexible token type - but not very accessible in plain WCF. Geneva abstracts the creation and consumption of tokens in so called token handlers. All you need is a description of the token that you want to generate and then you feed this description into the appropriate token handler. I wrote an article about the token generation pipeline in Geneva here.

Even better, Geneva has some client side plumbing for WCF that lets you use the generated token for service calls in a quite straightforward fashion.

So the simple scenario is this: the client credential consists of three pieces: username, password and a customer ID (think e.g. of multi-tenant apps). The service receiving this credential could be a normal WCF service or a STS that issues tokens based on the client credential. For future extensibility a general version of this would be a credential with a user name and an unlimited number of properties (e.g. password, customer ID etc.). In a SAML token this would map to the name identifier and a number of attributes.

Client
Using Geneva you can generate a SAML token like this:

public static class ClientToken
{
  private const string _claimsUri = http://www.leastprivilege.com/claims/;

  public static SamlSecurityToken Create(string subjectName, Dictionary<string, string> properties)
  {
      ClaimsIdentity id = new ClaimsIdentity(
          from item in properties
          select new Claim(_claimsUri + item.Key, item.Value));
      id.Claims.Add(new Claim(WSIdentityConstants.ClaimTypes.NameIdentifier, subjectName));

      var description = new SecurityTokenDescriptor
      {
          Subject = id,
          TokenIssuerName = "http://self"
      };

      var handler = new Saml11SecurityTokenHandler(new SamlSecurityTokenRequirement());
      return (SamlSecurityToken)handler.CreateToken(description);
  }
}

After creating the token you can use the Geneva extension methods for ChannelFactory<T> to set the token as a client credential:

static void Main(string[] args)
{
  var props = new Dictionary<string, string>
  {
      { "password", "secret" },
      { "customerId", "42" }
  };

  var token = ClientToken.Create("dominick", props);
  var factory = new ChannelFactory<IServiceClientChannel>("*");
       
  FederatedClientCredentials.ConfigureChannelFactory<IServiceClientChannel>(factory);
  var proxy = factory.CreateChannelWithIssuedToken<IServiceClientChannel>(token);

  proxy.Operation("foo");
  proxy.Close();
}

Service
On the service side you need a corresponding token handler that “understands” the semantics of the SAML token. Geneva has a built-in handler for SAML tokens but it does not know how to authenticate the client based on the values of certain SAML attributes. Furthermore you need to make a decision which of the incoming attributes should become part of the claims identity in the service. Maybe you don’t want sensitive information like the password to flow to the service operations (maybe you want exactly that). Other customizations to the standard behavior would be to ignore audience URIs as well as signatures (since our client tokens won’t have them).

By deriving from the built-in token handler you can drive this logic while letting the base class do all the heavy lifting of token serialization and parsing:

public abstract class ClientSaml11SecurityTokenHandlerBase : Saml11SecurityTokenHandler
{
  // disable audience URI checking
  public ClientSaml11SecurityTokenHandlerBase()
      : base(new SamlSecurityTokenRequirement { AudienceUriMode = AudienceUriMode.Never })
  { }

  // extensibility point for authentication and claims filtering
  protected abstract bool ValidateUser(
      string subjectName, Dictionary<string, string> properties, ref List<string> claimsList);

  // override signature handling
  public override SecurityToken ReadToken(XmlReader reader)
  {
    Saml11Assertion assertion = this.ReadAssertion(reader);
    return new SamlSecurityToken(assertion);
  }

  public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
  {
    // call base class for token validation and serialization
    var ids = base.ValidateToken(token);
    var id = ids[0];

    // retrieve client name
    string subjectName = id.Claims.Where(
        claim => claim.ClaimType == WSIdentityConstants.ClaimTypes.NameIdentifier).First().Value;
        
    // copy attributes to dictionary
    var properties = new Dictionary<string, string>();
    id.Claims.ToList().ForEach(
        claim => properties.Add(claim.ClaimType, claim.Value));

    // call authentication and filtering logic
    var claimsToKeep = new List<string>();
    if (ValidateUser(subjectName, properties, ref claimsToKeep))
    {
      ClaimsIdentity identity = new ClaimsIdentity("ClientSAML");

      // add client name
      identity.Claims.Add(new Claim(
        WSIdentityConstants.ClaimTypes.Name, subjectName, ClaimValueTypes.String, "LOCAL"));


      // copy "allowed" attributes
      claimsToKeep.ForEach(claimType =>
        {
          string value = id.Claims.Where(claim => claim.ClaimType == claimType).FirstOrDefault().Value;
          if (!string.IsNullOrEmpty(value))
          {
            identity.Claims.Add(new Claim(claimType, value, ClaimValueTypes.String, "LOCAL"));
          }
        });

        return new ClaimsIdentityCollection(identity);
      }
        else
        {
            throw new SecurityTokenValidationException();
        }
    }
}

The authentication logic and filtering could be implemented like this:

class ClientSaml11SecurityTokenHandler : ClientSaml11SecurityTokenHandlerBase
{
    protected override bool ValidateUser(
      string subjectName, Dictionary<string, string> properties, ref List<string> claimsList)
    {
        string password = properties[_passwordClaimType];

        // sample password check – don’t just copy&paste this code ;)
        if (subjectName != password)
        {
            return false;
        }

        claimsList.Add(_customerIdClaimType);
        return true;
    }
}

After wiring up the new token handler in the WCF service you get access to the claims in the operation via IClaimsPrincipal as usual.

Configuration
The last step deals with setting up the security parameters on the binding. Since the client SAML token is much like a UserName token on steroids, we choose similar security configurations (and make the same security guarantees). You can either use message security where the client token gets encrypted with the service certificate – or mixed mode security where the transport is secured using SSL.

For mixed mode security you can use the IssuedTokenOverTransport authentication mode. The custom binding looks like this:

<customBinding>
  <
binding name="BearerTokenOverTransport">
    <
security authenticationMode="IssuedTokenOverTransport">
      <
issuedTokenParameters
        
tokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"
         
keyType="BearerKey" />
    </
security>
    <
textMessageEncoding />
    <
httpsTransport />
  </
binding>
</
customBinding>

For message security, there is no built-in binding element helper – you have to construct it via code:

public static SecurityBindingElement CreateClientTokenForCertificateBindingElement()
{
  // protection token
  var element = new SymmetricSecurityBindingElement(
      new X509SecurityTokenParameters(
          X509KeyIdentifierClauseType.Thumbprint, 
          SecurityTokenInclusionMode.Never));

  // client token
  var parameters = new IssuedSecurityTokenParameters(
      Saml11SecurityTokenHandler.OasisWssSamlTokenProfile11,
      new EndpointAddress(http://self),
      new BasicHttpBinding());
  parameters.KeyType = SecurityKeyType.BearerKey;
  parameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;

  element.EndpointSupportingTokenParameters.SignedEncrypted.Add(parameters);
  element.MessageSecurityVersion =
    MessageSecurityVersion.WSSecurity11WSTrust13
                           WSSecureConversation13
                           WSSecurityPolicy12BasicSecurityProfile10;

  return element;
}

 

You can then use this helper to construct a custom binding (see the download for the complete code).

That’s it. HTH

ClientSamlCredential.zip (450.94 KB)

 


IdentityModel | WCF
Tuesday, March 10, 2009 6:24:52 AM UTC  #   
 Monday, March 09, 2009

Custom WCF Credential Types

Every once in a while the question comes up how to extend WCF with custom credential types. It turns out that most of the time people don’t really want to invent custom tokens or credential types, but rather want to extend username/password style of credentials (e.g. username/password/customer ID). Unfortunately the UserName token does not support this type of extensibility but there are several options to accomplish this:

  • If your extensibility requirements are very simple you could try to encode all the information into the username and password fields of a UserName credential. You’d need some extra plumbing on the service side (UserNamePasswordValidator, custom IPrincipal) to decode the information again and provide normalized user information.
  • You could use SOAP headers to transmit the additional information. This has the potential to pollute your business logic with security plumbing and needs some wrapping. There are also some gotchas around adding headers on the fly, as well as protecting them.
  • You could write a full fledged custom credential that supports the extensibility you need. Unfortunately this is not the best documented area of WCF and you are mostly on your own. The WCF credential infrastructure is extremely flexible – but I wouldn’t call it an extensibility point – but rather a replacement point. You end up replacing a number of classes on the service and client side to make this happen (see here for an overview). I did that for a username/password/namevalue credential and it wasn’t a pleasant experience.
  • You could use a standard token type in WCF that already supports all the extensibility needs you might have – e.g. SAML. The problem here is that SAML and issued tokens are not very accessible through plain WCF – but Geneva makes it much easier to use them - even without a security token service. That’s the option I am going to look at in the next post.

WCF | IdentityModel
Monday, March 09, 2009 9:30:20 AM UTC  #   
 Friday, February 27, 2009

Setting Key Identifiers in Geneva

Keys used in tokens or RSTRs need to be identified somehow – common ways to do this is to use a thumbprint, a serial number or the subject key identifier.

A “Geneva” based token service will use the combination of issuer name and certificate serial number by default. This is usually fine, but you may need to change that because of interop scenarios. Metro based web services e.g. prefer the subject key identifier method.

Took me some time to figure it out – so maybe this info is useful to someone.

There are two key identifiers you may want to modify – the signing and the encrypting key. These are represented in “Geneva” using the SigningCredentials and EncryptingCredentials classes respectively. The signing credentials are supplied in the SecurityTokenServiceConfiguration whereas the encrypting credentials are specified in the GetScope method. On these classes you can set the key identifier method using the SecurityKeyIdentifier property or the constructor. You can use the following code to create a subject key identifier clause for X509 certificates:

var ski = new SecurityKeyIdentifier(
            new SecurityKeyIdentifierClause[]
            {
                new X509SecurityToken(cert).CreateKeyIdentifierClause<X509SubjectKeyIdentifierClause>()
            });

To see what other key identifier types are available, have a look at the inheritance hierarchy of the base class System.IdentityModel.Tokens.SecurityKeyIdentifierClause.

HTH


IdentityModel
Friday, February 27, 2009 9:33:49 AM UTC  #   
 Tuesday, February 10, 2009

Host Headers, SSL and WCF Metadata

One of my web servers here has a pretty common setup – a Windows machine name and a (different) DNS name (in this case dynamic DNS – but doesn’t matter). IIS has a single web site with bindings for HTTP and HTTPS. The common name of the SSL certificate matches the public DNS name. Everything looks good.

The server also hosts some WCF services and I noticed that the imports and endpoint addresses in the WSDL point to the machine name and not to the DNS name. No big deal – simply set the host header for the site via the IIS GUI and I am done. That’s what I thought at least.

And sure enough, after the configuration change my WSDL was correct and used the name configured in the host header.

Some weeks later I added some more WCF endpoints to the machine, this time I was using SSL – including an SSL WSDL/MEX endpoint. After some weird error messages I re-inspected the WSDL and everything looked fine - until I hit the WSDL document in the browser using SSL. Again imports and endpoint addresses were pointing to the machine name. What’s going on here?

After some googling I found articles about something I totally forgot about: SSL host headers. Since IIS 6 you can also set host headers for SSL site bindings. Since this option is not available via the GUI I kind of “missed” it. These two articles show the necessary steps for IIS6 and IIS7.

My applicationHost.config now looks like this for my site:

<bindings>
  <
binding protocol="http"
          
bindingInformation="*:80:www.mypublicname.com" />
  <
binding protocol="https"
          
bindingInformation="*:443:www.mypublicname.com" />
</
bindings>

HTH

(Rich: marked as answer)


WCF | IdentityModel
Tuesday, February 10, 2009 9:34:56 AM UTC  #   
 Wednesday, February 04, 2009

UAC flawed in Win7?

I really, really hope this is a beta only issue…

http://www.istartedsomething.com/20090204/second-windows-7-uac-flaw-malware-self-elevate/


Misc
Wednesday, February 04, 2009 7:53:17 PM UTC  #   
 Tuesday, January 20, 2009

SQL Data Services Query Injection

The “query language” of SQL Data Services is basically a LINQ statement as a string, e.g.:

from e in entities where e["username"] == "{0}" && e["password"] == "{1}" select e

Do you see a problem here?

Of course string concatenation combined with "no-schema” flex entities allows all kinds of injections. Marcus and I did some tests, e.g. try entering the following username for the above statement:

foo" || "" == "

This will select all users. I am sure there are other tricks, too.

So again – be aware that you have to validate all of your input! Some things you can do here include:

  1. run a regular expression over your inputs to make sure it only contains legal characters
  2. escape character like quotation marks and back slashes
  3. use e.g. the Single() LINQ operator on the returned entity list when you know that only one entity should be returned (otherwise something must be wrong).

HTH


Misc | Work in Progress
Tuesday, January 20, 2009 11:34:31 AM UTC  #   
 Monday, January 19, 2009

Get help running a partial SSL website in ASP.NET

A while ago I wrote this article about some of the things to watch out for when securing parts of an application with SSL. Keith used the attached code as part of his work and extended it. Even better he made his extensions available for download – I recommend to have a look. Thanks for sharing, Keith!

Read his post here.


ASP.NET
Monday, January 19, 2009 6:55:56 AM UTC  #   
 Saturday, January 10, 2009

Welcome Richard Blewett

I am thrilled to announce that Rich has joined thinktecture this week. That’s great news.

I’ve been working with Rich since 2004 (in fact – he was part of that scary initiation ritual at DevelopMentor called “Test Teach”). He’s a great guy and knows hell of a lot about .NET and distributed systems (and I am not going into some of his other skills which usually end in a terrible headache next day – and I am not talking about World of Warcraft ;). Welcome Rich!


Misc
Saturday, January 10, 2009 7:33:41 PM UTC  #   
 Wednesday, January 07, 2009

Live ID and Information Cards

I while ago I wrote that there is an experimental version of the Live ID login page that makes use of Information Cards linked to your Live ID account. Unfortunately this login form was only used for very specific services (hotmail only at that time IIRC).

I am happy to see that more and more sites these days use the InfoCard enabled sign in page – and more importantly - sites I actually use (e.g. MSDN, Live Mesh, Connect…). Way to go!


IdentityModel | Misc
Wednesday, January 07, 2009 5:30:19 AM UTC  #   
 Sunday, December 28, 2008

Federating with Live ID (using the Access Control Service)

There are already a number of ways today how you can federate with the Live ID service (e.g. using the Live ID SDK, OpenID or WS-Federation). Another option would be to use the Access Control Service. I can see a bunch of reasons why this may be compelling:

  • Live ID is pre-configured in the ACS. You don’t need any extra configuration steps to register your site with Live ID. It just works.
  • You can use the ACS rules engine to transform the Live ID claims to your application claims.
  • A Live ID is a low barrier entry for customers and partners to the ACS. In case they can’t federate “properly” (e.g. using Geneva or the Services Connector).

Generally, this is a good example of how the ACS can simplify security management and configuration in your application endpoints. You can simply add another authentication method to your application without needing to change anything substantial. All the heavy lifting like crypto, trust and claims configuration is done in the ACS.

This walkthrough uses the PDC bits of the ACS and Geneva framework to access Live ID logins in an ASP.NET app. This is all beta software and details are subject to change!

Step 1: Setting up ASP.NET to use the ACS
First you have to enable Geneva in ASP.NET. This involves adding the WS-Federation authentication module as well as the session authentication module. You also have to setup the service certificate and allowed audience URI. Nothing special here.

Very similar to the WCF scenario I described here, you also have to check the token and SAML issuer. For the issuer check you use the regular issuer name registry as described in my post. For the SAML issuer check you can use an extensibility point in the FAM – simply add this code to global.asax:

void WSFederationAuthenticationModule_SecurityTokenValidated(
  object sender, SecurityTokenValidatedEventArgs e)
{
    e.ClaimsPrincipal.DemandClaim(
      Microsoft.IdentityModel.Claims.ClaimTypes.SamlIssuerName,
      "http://accesscontrol.windows.net/solutionName");
}

These two customizations establish a trust relationship with your ACS. You can now start receiving tokens.

Step 2: Registering the application with the ACS
Again nothing special here. You have to create a scope for the application in your ACS as well as configure the the encrypting certificate to match the certificate you configured in step 1.

The interesting part is the rule definition. When you add a new rule, you can now select the Live ID as an input claim and map it to whatever output claim you want. Examples would be to map it to a group (which in turn can map to permissions) or to tunnel the ID to the relying party (either as-is or as a different claim). The following screenshot shows a rule that transforms the Live ID to a standard name claim:

Step 3: Triggering Live ID login
The last step is to trigger the Live ID handshake in your app. The ACS’ endpoint for federation with Live ID is

https://accesscontrol.windows.net/passivests/{solutionName}/LiveFederation.aspx

In the query string for this endpoint you have to provide the scope and the identity provider name (plus an optional reply-to address), like this:

wa=wsignin1.0&wtrealm={scope}&wreply={replyTo}&whr={identityProvider}

Unfortunately Geneva framework currently does not support the whr parameter directly, which means you have to construct the URL manually. Geneva’s SignInRequest class can help here. The following code does the redirect to the ACS and Live ID:

protected void _lnkLiveLogin_Click(object sender, EventArgs e)
{
    string homeRealm = "http://login.live.com";
    string scope = "http://myrp/default.aspx";
    string acs = "https://accesscontrol.windows.net/passivests/{solutionName}/LiveFederation.aspx";

    var request = new SignInRequestMessage(new Uri(acs), scope);
    request.Parameters.Add("whr", homeRealm);

    Response.Redirect(request.RequestUrl);
}

After all redirects have occurred you end up back in your application with a populated IClaimsPrincipal that contains the claims that you configured in your ACS scope. Adding new identity providers would be a matter of registering them with your ACS and changing the value of the home realm parameter.

 


ASP.NET | IdentityModel | WCF
Sunday, December 28, 2008 4:25:49 PM UTC  #   
 Friday, December 26, 2008

Display Tokens & Geneva

What are display tokens? In short: They allow an STS to pass some or all claims back to the client in a way that the client can read them. This differs from the “real” claims which are part of the security token and are encrypted for the relying party. A popular example of an application that consumes display claims is the CardSpace identity selector that allows you to preview the claims before they get send to the RP.

Look here in section 4.3.6 for the technical specification and here for a good discussion of use and abuse of display tokens.

In Geneva, display tokens are represented by the DisplayToken class (which is a container for DisplayClaims). The SecurityTokenService class has an overridable method called GetDisplayToken in which the DisplayToken gets constructed to be put into the RSTR (see also here). This method internally calls GetDisplayClaimsForSubject on the default ClaimsMapper that is configured on the SecurityTokenServiceConfiguration of your STS. This default claims mapper simply takes all claims found in the subject and emits them as display claims. For some standard claims the mapper already knows the display name and description – the others are emitted without further descriptions.

It seems that in the future you want to extend the ClaimsMapper class for your own display token work – for now the class does not seem to be ready for that. Another behavior of the current Geneva bits is, that display claims are enabled by default – that means if your user requests them (more on that later) all claims will be emitted in clear to the user. This may or may not be what you want. In future builds of Geneva, the display token feature will be opt-in.

But if you are building an STS with the current bits – you almost certainly want to take control over display token generation, because e.g.

  • maybe you emit claims that the user should not be able to see.
  • if you want to emit a display token and you use non-standard claims, you want to provide display names and descriptions.

 

Generating a display token
Currently the easiest way to do this is to override the above mentioned GetDisplayToken method in your STS, e.g.:

protected override DisplayToken GetDisplayToken(
  string requestedDisplayTokenLanguage, IClaimsIdentity subject)
{
    var displayClaims = new List<DisplayClaim>
    {
        new DisplayClaim(WSIdentityConstants.ClaimTypes.GivenName, "FirstName", "First Name",
            subject.GetClaimValue(WSIdentityConstants.ClaimTypes.GivenName)),
        new DisplayClaim(WSIdentityConstants.ClaimTypes.Surname, "LastName", "Last Name",
            subject.GetClaimValue(WSIdentityConstants.ClaimTypes.Surname)),
        new DisplayClaim(WSIdentityConstants.ClaimTypes.Name, "Name", "Name",
            subject.GetClaimValue(WSIdentityConstants.ClaimTypes.Email)),
    };


    return new DisplayToken(requestedDisplayTokenLanguage, displayClaims);
}

(of course – if you want to localize the claims – you should honor the requestDisplayTokenLanguage parameter)

 

Requesting and consuming a display token
The above GetDisplayToken method gets only called if a display token is requested. This is done by adding a <RequestDisplayToken /> element to the RST – either by adding this element to the additional request parameters collection on the binding or by explicitly setting the DisplayTokenLanguage property on the RequestSecurityToken class (e.g. when requesting a token using WSTrustClient).

The returned display token can be found in the RSTR on the RequestedDisplayToken property. The following code snippet shows both the request and the consumption (some details omitted):

WSTrustClient client = new WSTrustClient(
    GetStsBinding(),
    GetStsEndpoint(),
    TrustVersion.WSTrust13,
    GetStsCredentials());

RequestSecurityToken rst = new RequestSecurityToken();
rst.RequestType = WSTrust13Constants.RequestTypes.Issue;
rst.AppliesTo = new EndpointAddress(rp);
rst.TokenType = Saml11SecurityTokenHandler.OasisWssSamlTokenProfile11;
rst.DisplayTokenLanguage = "en";

RequestSecurityTokenResponse rstr;
client.Issue(rst, out rstr);

foreach (var displayClaim in rstr.RequestedDisplayToken.DisplayClaims)
{
    Console.WriteLine(string.Format("{0}: {1} ({2})",
        displayClaim.DisplayTag,
       
displayClaim.Description,
        displayClaim.DisplayValue));
}

 

HTH
ASP.NET | WCF | IdentityModel
Friday, December 26, 2008 10:44:36 AM UTC  #   
 Thursday, December 25, 2008

LeastPrivilege.IdentityModel2 Preview

I thought as a little X-Mas present – I just zip up the current version of my IdentityModel2 solution and make it available for download here. It is barely tested (besides my own use cases which were the reason why I wrote most of the code in the first place) so I thought I’d call it CTP1 and would appreciate your feedback ;)

What’s inside?

  • a bunch of extension methods (for IPrincipal, IClaimsPrincipal, IClaimsIdentity, RSACryptoServiceProvider…)
  • a custom configuration section for easy certificate loading
  • a simple claims viewer for console, WinForms and ASP.NET
  • helpers for federating with the Access Control Service

Merry Xmas!

 


ASP.NET | IdentityModel | WCF
Thursday, December 25, 2008 7:34:17 AM UTC  #   
 Tuesday, December 16, 2008

Final Release of InfoCardSelector on Codeplex

For a while I had some updates to the InfoCardSelector ASP.NET control sitting here – thanks to altair we made some minor modifications, nothing critical. I finally uploaded them to Codeplex.

However – this will be the last release of the control. It works as expected and will be soon superseded by the InfoCard control in Geneva.

Have fun!


ASP.NET | IdentityModel
Tuesday, December 16, 2008 7:14:11 AM UTC  #   
 Monday, December 15, 2008

ASP.NET Security Goodness

A bunch of (ASP.NET) security tools got released over the weekend – highly recommended!

Get more info from Mark and Barry.

CAT.NET V1 CTP

“CAT.NET is a snap-in to the Visual Studio IDE that helps you identify security flaws within a managed code (C#, Visual Basic .NET, J#) application you are developing. It does so by scanning the binary and/or assembly of the application, and tracing the data flow among its statements, methods, and assemblies. This includes indirect data types such as property assignments and instance tainting operations. The engine works by reading the target assembly and all reference assemblies used in the application -- module-by-module -- and then analyzing all of the methods contained within each. It finally displays the issues its finds in a list that you can use to jump directly to the places in your application's source code where those issues were found. The following rules are currently support by this version of the tool. - Cross Site Scripting - SQL Injection - Process Command Injection - File Canonicalization - Exception Information - LDAP Injection - XPATH Injection - Redirection to User Controlled Site.”

32 Bit / 64 Bit

 

AntiXSS 3.0 Beta

“The Microsoft Anti-Cross Site Scripting Library V3.0 (Anti-XSS V3.0) is an encoding library designed to help developers protect their ASP.NET web-based applications from XSS attacks. It differs from most encoding libraries in that it uses the white-listing technique -- sometimes referred to as the principle of inclusions -- to provide protection against XSS attacks. This approach works by first defining a valid or allowable set of characters, and encodes anything outside this set (invalid characters or potential attacks). The white-listing approach provides several advantages over other encoding schemes. New features in this version of the Microsoft Anti-Cross Site Scripting Library include: - An expanded white list that supports more languages - Performance improvements - Performance data sheets (in the online help) - Support for Shift_JIS encoding for mobile browsers - A sample application - Security Runtime Engine (SRE) HTTP module.”

download

 

AntiCSRF

“AntiCSRF makes it easier for ASP.NET developers to guard themselves against Cross Site Request Forgery. You'll no longer have to manually add and check protection tokens to protected yourself against CSRF attacks.”

Codeplex

 

Have fun!


ASP.NET | FX Security
Monday, December 15, 2008 9:53:52 AM UTC  #   
 Thursday, December 11, 2008

Federating with the .NET Access Control Service

In my previous post I showed how to migrate the .NET Access Control Service SDK “CardSpaceCalculator” sample to Geneva Framework. The way this sample is structured, it allows to authenticate with the InfoCard that is associated with your solution account to access the service via the ACS.

While this is nice for learning purposes – it limits you to this single account. In reality you want that your customers/partners federate with your ACS so you can give them access to your services. The ACS will then broker the trust and act as a rules-based claims generation engine.

It turns out that when you have the sample up and running, you are already very close to this scenario. How could this work in practice? This walkthrough basically documents the steps I did to integrate a custom STS written with the Geneva framework. This assumes you already have a working version of the SDK sample as well as a STS.

 

Step 1: Registering the partner’s STS at your Access Control Service
First you have to register the STS. This is done via the .NET Services portal. Go to your scope in advanced mode and click the Identity Issuers link. You need to specify three things:

  • A display name for the STS. This name is also used for defining rules later on
  • The STS URI
  • The STS token signing certificate

Step 2: Adding your Access Control Service to the partner’s STS known list of relying parties
The partner’s STS now has to be configured to issue tokens for the ACS. For this purpose the partner needs to know the value of the AppliesTo header field (the RP identitfier) and the public key of the ACS.

The AppliesTo header will be: “http://accesscontrol.windows.net/sts/<yoursolution>/issued_for_certificate”.

The encrypting certificate is not so obvious. It is basically the certificate that you can pull from https://accesscontrol.windows.net – but automatic browser redirects make that kinda hard (I forked mine from the custom IssuerNameRegistry I showed in my last post). You can also use this code here to download the cert.

Step 3: Updating client configuration
The next step is to update the client’s configuration to request a token from the STS before requesting the token from the ACS. This is very simple – when you use the SDK sample you will see a WCF custom binding with the name http://accesscontrol.windows.net/sts/<solutionname>/issued_for_certificate. Since this binding is configured for issued tokens but no STS is specified the CardSpace identity selector will pop up. When the partner STS issues cards, the user now only has to select the right card.

To configure a specific STS you have to add an <issuer> and <issuerMetadata> element to the binding that points to the partner’s STS WS-Trust endpoint (along with the right binding to authenticate with the STS). That’s it.

Step 4: Defining rules for the partner in the ACS
Now technically everything is set up. The last step would be to define rules in your ACS for the partner accounts. Let’s say the partner STS includes a “department” claim in the token. Now everybody in the department “Research” should have access to the “Add” operation of the calculator. The corresponding rule would look like this in the portal:

Another cool feature of the ACS rules engine is to copy input to output claims. This allows to tunnel claims from the partner’s STS to your service. You accomplish this by setting the “copy input value” option in the rules dialog.

I’d also recommend checking out Justin’s drill down talk from PDC to learn about the forward chaining capabilities of the rules engine.

HTH


ASP.NET | IdentityModel | WCF
Thursday, December 11, 2008 7:46:34 PM UTC  #   

Downloading the Certificate from an SSL Site

Sometimes this is very useful– you point the below code to a server and get the configured SSL certificate in return. After that you could import the cert into the local store or save it as a file (via the RawData property).

public static X509Certificate2 DownloadSslCertificate(string machinename, int port)
{
    using (TcpClient client = new TcpClient())
    {
        client.Connect(machinename, port);

        SslStream ssl = new SslStream(client.GetStream());
        ssl.AuthenticateAsClient(machinename);

       
        return new X509Certificate2(ssl.RemoteCertificate);
    }
}

HTH


Misc | IdentityModel
Thursday, December 11, 2008 7:30:47 PM UTC  #   

Using the .NET Access Control Service with Geneva

If you haven’t checked out the .NET Access Control Service yet – I can highly recommend it!

Justin did two talks about it at PDC:

In the 2nd talk Justin showed how to use and process claims coming from the ACS rules engine in your own services. You can find this code in the “CardSpace Calculator” sample in the ACS SDK.

The sample uses the “old” WCF plumbing to process tokens and create claims based on that. I wanted to find out what has to be done to migrate the sample to use Geneva.

First let’s have a look at what you want to accomplish with such a scenario:

  • your clients live in a different trust domain as your service
  • to federate these two domains, you do the following
    • register your client’s identity provider (Live ID, Geneva Server/Framework, other WS-Trust 1.3 compat STS) at the ACS
    • your client obtains a token from the ACS (by sending their identity token)
    • this token is used to authenticate with your service
    • your service accepts tokens from the ACS and uses their claims for identity related work

For your service this means the following:

  • accept tokens that are signed by the ACS
  • make sure the issuer of that token is your personal instance of the ACS (http://accesscontrol.windows.net/yoursolution)

In Geneva terms this boils down to the following pieces of plumbing:

  • issuer name registry that knows about the ACS issuer certificate
  • security token handler that check the SAML issuer name

Issuer Registry
There are two ways to accomplish this. Either you use the standard ConfigurationBasedIssuerNameRegistry and add the ACS issuer thumbprint to it:

<microsoft.identityModel>
  <
issuerNameRegistry type="…ConfigurationBasedIssuerNameRegistry">
    <
trustedIssuers>
      <
add name=http://accesscontrol.windows.net
          
thumbprint="416E6FA5D982B096931FBF42C4A3DCD608856C95" />
    </
trustedIssuers>
  </
issuerNameRegistry>
</
microsoft.identityModel>

Or you write a custom registry that has the ACS issuer baked in:

class AccessControlServiceIssuerRegistry : IssuerNameRegistry
{
  public override string GetIssuerName(SecurityToken securityToken)
  {
      X509SecurityToken token = securityToken as X509SecurityToken;
      if (token == null)
      {
        throw new SecurityTokenException("Token is not a X509 Security Token");
      }

      var cert = token.Certificate;
      if (cert.Thumbprint.Equals("416E6FA5D982B096931FBF42C4A3DCD608856C95", StringComparison.OrdinalIgnoreCase))
      {
        return "http://accesscontrol.windows.net";
      }

      throw new SecurityTokenException("Token not issued by access control service");
  }
}

Security Token Handler
Once you trust the issuer, you also have to make sure that the token got issued by your personal instance of the ACS. This is done by checking the SAML issuer name information in the token. This is the job of a custom security token handler – you can simply derive from the existing Saml11SecurityTokenHandler and inject this logic in the ValidateToken method.

class AccessControlServiceSaml11SecurityTokenHandler : Saml11SecurityTokenHandler
{
    string _solution;

    public AccessControlServiceSaml11SecurityTokenHandler(string solution)
      : base()
    {
        _solution = solution;
    }

    public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
    {
        var identities = base.ValidateToken(token);

        identities[0].DemandClaim(
            ClaimTypes.SamlIssuerName,
            "http://accesscontrol.windows.net/" + _solution);

        return identities;
    }
}

Bringing the pieces together
You can now wire up the two custom components using the FederatedServiceCredentials class like this:

ServiceHost host = new ServiceHost(typeof(CalculatorService));

var handlers = new SecurityTokenHandlerCollection();
handlers.Add(new AccessControlServiceSaml11SecurityTokenHandler("leastprivilege"));

FederatedServiceCredentials.ConfigureServiceHost(
    host,
    handlers,
    new AccessControlServiceIssuerRegistry(),
    TimeSpan.FromMinutes(5));

FederatedServiceCredentials.ConfigureServiceHost(host);
host.Open();

 

Another option would be to use the configuration file – but in this case we somehow have to transfer the solution name to the security token handler. Geneva security token handlers have a standard configuration extensibility hook that we can use to accomplish this (not very obvious at the beginning – but makes sense ;).

Let’s say our configuration should look like this:

<microsoft.identityModel>
  <
issuerNameRegistry type="LeastPrivilege.AccessControlServiceIssuerRegistry, Service" />

  <
securityTokenHandlers>
    <
clear />
    <
add type="LeastPrivilege.AccessControlServiceSaml11SecurityTokenHandler, Service">
      <
accessControlServiceTokenRequirement solutionName="leastprivilege" />
    </
add>
  </
securityTokenHandlers>
</
microsoft.identityModel>

 

To make the token handler aware of this sub config element, you have to add a new constructor to the token handler like this:

public AccessControlServiceSaml11SecurityTokenHandler(XmlElement customConfigElement)
    : base()
{
    if (customConfigElement.LocalName != "accessControlServiceTokenRequirement")
    {
        throw new InvalidOperationException("accessControlServiceTokenRequirement expected");
    }

    var solutionAttr = customConfigElement.Attributes["solutionName"];
    if (solutionAttr == null)
    {
        throw new InvalidOperationException("solution name expected");
    }

    _solution = solutionAttr.Value;
}

(if you also need support for the samlSecurityTokenRequirement element, you can manually call LoadSamlTokenAuthenticatorRequirement on the SecurityTokenHandlerElement class).

Here you can find the complete code – to get it working I’d suggest you first get the original SDK sample up and running. After that you have to make the necessary adjustments in my code (solution name, certificates and URIs).

HTH

 


ASP.NET | IdentityModel | WCF
Thursday, December 11, 2008 9:20:45 AM UTC  #   
 Sunday, December 07, 2008

LeastPrivilege.IdentityModel v2

Looking at the download numbers, my add-on library for System.IdentityModel was quite popular. Some days ago I started looking the code to see what could be still useful in the face of Geneva.

The good news is, that a lot of my helper classes are not necessary anymore thanks to the easier claims model in Geneva. Still I think that most of the time you have to wrap the raw IClaimsPrincipal with more domain specific functionality. Since my current project makes heavy use of Geneva I began compiling a set of classes that made my life easier while working with the Geneva framework.

Like in the first release, I added a bunch of extensions methods that make finding and demanding claims easier. This is mostly syntactic sugar because the new model is very LINQ friendly and you can easily write the queries yourself – but it makes the code easier to read IMO. At the heart of all functionality is this extension method:

public static IEnumerable<Claim> FindClaims(
  this IClaimsIdentity identity, Predicate<Claim> predicate)
{
    return from claim in identity.Claims
           where predicate(claim)
           select claim;
}

This allows layering all kinds of higher level functionality on top of both IClaimsIdentity and IClaimsPrincipal, e.g:

  • FindClaims(commonly used parameters)
    Returns a (possibly empty) list of claims.
  • DemandClaim(commonly user parameters)
    Throws a SecurityException if a specified claim is not found
  • GetClaimValue / TryGetClaimValue
    Returns the value of a specified claim

..and on top of that it is very easy to add business problem centric functionality.

This allows me to write code like this:

var principal = Thread.CurrentPrincipal.AsClaimsPrincipal();

principal.DemandClaim(
    WSAuthorizationConstants.Action,
    "Logs.Clear",
    http://accesscontrol.windows.net);

 

I will release the code once I have done more testing.


ASP.NET | IdentityModel | WCF
Sunday, December 07, 2008 4:49:10 PM UTC  #   
 Friday, December 05, 2008

T-Mobile Web’n’Walk & Vista 64

I just spent two very unpleasant days trying to get the T-Mobile ExpressCard IV to work with Vista 64. But for some reasons the T-Mobile drivers for the Huawei E870 are screwed under 64 bit.

Today I got a tip that I should try to install the latest version of Vodafone Mobile Connect which also includes drivers for the same hardware. And bingo this works. You can isolate the drivers from the Vodafone program files and uninstall Mobile Connect afterwards. awesome…

So you have to install a Vodafone software package to get T-Mobile hardware to run. Is that weird?

HTH


Misc
Friday, December 05, 2008 9:28:54 AM UTC  #   
 Thursday, November 27, 2008

UserName Supporting Token & WCF revisited (this time with Geneva)

A while back I wrote about UserName supporting tokens in WCF and how they can be handy to create light-weight “delegation” scenarios for middle-tiers. I wanted to give the same scenario a try with a Geneva enabled relying party.

First of all – there are no basic configuration changes necessary (specifically the SecurityBindingElement – refer to my original post for details). All you have to do is to configure the Geneva “runtime” and wire it in your service host. This involves:

  • Specifying an issuer registry for the client’s certificate.
  • Add a UserNameSecurityTokenHandler that can cope with empty passwords (this also gives you the chance to add some custom claims for the user name token).

Refer to this post for details about issuer registries, and this post for UserName security token handlers.

All you then have to do is, to take all these pieces and configure the service host to use Geneva:

ServiceHost host = new ServiceHost(typeof(Service));

// add the supporting token to the binding
host.Description.Endpoints[0].Binding =

    AddUserNameSupportingTokenToBinding(host.Description.Endpoints[0].Binding);

// create security token handlers
var handlers = new SecurityTokenHandlerCollection(
    SecurityTokenHandlerCollection.DefaultHandlers);

// add handler for supporting token (empty password)
handlers.AddOrReplace(new SupportingUserNameSecurityTokenHandler());

// add the issuer name registry (simple for demo purposes)
var registry = new SimpleIssuerNameRegistry();

// configure host to use Geneva plumbing
FederatedServiceCredentials.ConfigureServiceHost(
    host,
    handlers,
    registry,
    new TimeSpan(0, 5, 0));

host.Open();

On incoming requests, Geneva will now create an IClaimsPrincipal that contains two IClaimsIdentity instances. One for the direct caller (certificate) and one for the supporting token (user name). You can now use the standard means to query both identities and their claims. Nice.

SupportingUserNameToken1.zip (39.91 KB)

 


IdentityModel | WCF
Thursday, November 27, 2008 6:47:40 AM UTC  #   
 Saturday, November 22, 2008

(SAML) Token Creation in a Geneva STS

By default, Geneva STS developers are quite shielded from the SAML creation process – you simply derive from SecurityTokenService and implement GetScope and GetOutputClaimsIdentity, and the rest gets done by the framework. But if you need more control over the generated tokens, it’s worthwhile to have a closer look.

Internally the SecurityTokenService class drives a “token information gathering” pipeline which results in the construction of a SecurityTokenDescriptor (a token neutral description) of the token to be issued. After that the descriptor is passed on to a SecurityTokenHandler that creates the security token. In the last step, the generated token is wrapped in an RSTR and sent back.

In the current bits, the STS pipeline looks like this:

  • GetScope
    Must be implemented. Determines scope specific information like signing and encrypting credentials – usually based on the AppliesTo header.
  • CreateSecurityDescriptor
    Creates a default descriptor based on the scope from step 1. This is one option to modify the descriptor manually.
  • GetSecurityTokenHandler
    C
    reates the security token handler that is later used for creating the token. The handler is determined based on the TokenType property of the RST.
  • GetIssuerName
    Returns the issuer for the token. By default the issuer from the SecurityTokenServiceConfiguration is used.
  • GetTokenLifetime
    Returns the life time of the token. By default the default life time from SecurityTokenServiceConfiguration is used (which is 10 hours).
  • GetProofToken
    Creates a ProofTokenDescriptor that describes the proof token (asymmetric, symmetric or none). By default the information from the RST and the scope are used here.
  • GetOutputClaimsIdentity
    Must be implemented. Returns the identity that describes the subject.
  • SecurityTokenHandler.CreateToken
    The token handler creates the token and returns it to the token service (more details later)
  • GetDisplayToken
    Returns the claims that should be client visible (e.g. for an identity selector)
  • GetResponse
    Creates the RSTR. This is a popular hook for looking at the generated response before sending it back.

You can override any of these methods to modify the shape of the output token. This pipeline is always the same regardless of the token type. Token specific processing is done in the security token handler.

Security token handlers also have a pipeline that drives token creation. Since they are token specific, you have more control here over the output token details. For the purpose of this post, I will describe the SAML 1.1 token creation. The details differ for other token types.

  • CreateStatements
    Creates the SAML subject, attribute and authentication statements. This method calls out to:
    • CreateSamlSubject
      Looks for a name identifier claim and uses this to create the SAML subject. Additionally if this claim has properties that describe the name format and qualifier these values will be added to the subject. The last step is to set the proof key identifier and subject confirmation method (holder of key / bearer)
    • CreateAttributeStatement
      Creates the attribute statement based on the claims from the token service.
    • CreateAuthenticationStatementFromAuthenticationInformation
      Creates the authentication statement based on the authentication information in the token descriptor. This method only gets called if such information is present – so be sure to populate the AuthenticationInformation collection on the descriptor at some earlier point.
  • CreateConditions
    Sets the token lifetime and audience URIs restrictions.
  • CreateAdvice
    Creates the SAML advice. By default no advice is created.
  • CreateAssertion
    Creates the SAML assertion based on the statements, the conditions and the advice.
  • GetSigningCredentials
    Returns the credential used to sign the token.
  • GetEncryptingCredentials
    Returns the credential used to encrypt the token. If this method returns null, the token will not be encrypted.

Again you can override any of these methods.

OK – that was a lot of information. Where would you now plug in when you want to modify token creation? You basically have two options. Either you override the methods in SecurityTokenService to shape the token descriptor that gets passed to the handler. Of, if you need more control, you derive from one of the token handlers (e.g. Saml11SecurityTokenHandler) and override some of the methods that create the token details.

If you choose to write a custom handler, you can wire up the handler to the token service by overriding the SecurityTokenService.GetSecurityTokenHandler method.

HTH


ASP.NET | WCF | IdentityModel
Saturday, November 22, 2008 3:13:18 PM UTC  #   
 Monday, November 17, 2008

Geneva HTTP Modules: ClaimsPrincipalHttpModule

Geneva ships with three HTTP modules to use with ASP.NET: ClaimsPrincipalHttpModule, SessionAuthenticationModule and WSFederationAuthenticationModule. What are they for – and when to chose which?

In this post I will focus on the simplest one of the three: ClaimsPrincipalHttpModule – in following post we will have a close look at the remaining two.

The claims principal module is your easiest entry into the claims-based world. It simply takes whatever identity is on HttpContext.User and turns that into an IClaimsPrincipal. No STS or issued tokens required. There are three main decisions made:

  • If client is using Windows authentication, create a WindowsClaimsPrincipal. This principal allows downcasting to WindowsPrincipal and WindowsIdentity (to access things like impersonation and other Windows security specific features). Furthermore it contains the Windows token details as claims (primary SID, group SIDs, SAM account name…).
  • If the client is a FormsAuth client, a claims principal holding the user name, authentication method and instant is created.
  • If RoleManager is enabled, Roles.GetRolesForUser() is called to retrieve the user’s role. These roles are transformed into claims of the “http://schemas.microsoft.com/ws/2008/06/identity/claims/role” type. Lovely.

In all cases this means, that traditional IsInRole based security (imperative or via UrlAuthorizationModule) as well IIdentity.Name continues to work while you get the benefits of claims.

The next step would be to wire up a ClaimsAuthenticationManager to add your own custom claims to the principal. This gives you a smooth migration path and co-existence between roles and claims. Nice.

One thing that’s missing IMO is the conversion of client certificates to claims. I’ll file that as a feature request.

Sample: ClaimsHttpModule.zip (8.5 KB)

(btw – this all reminds me so much of my ClaimsManagerModule I have posted in March’08 ;))

 


ASP.NET | IdentityModel
Monday, November 17, 2008 11:07:10 AM UTC  #   
 Friday, November 14, 2008

ClaimsAuthenticationManager in Geneva

One of the things that Zermatt was lacking was a uniform way to look at incoming claims (either from an STS or from auto-converted authentication information).

In Geneva we now have a piece of plumbing called the ClaimsAuthenticationManager which gets called on the first request when a token comes into your application. This gives you a chance to reject or add claims as well as create a completely different claims principal (aka claims transformation). These new claims go into the session token and subsequent requests will bypass that logic.

A simple claims authentication manager could look like this:

class ClaimsTransformer : ClaimsAuthenticationManager
{
    public override IClaimsPrincipal Authenticate(
      string endpointUri, IClaimsPrincipal incomingPrincipal)
    {
        return GetClaims(incomingPrincipal.Identity.Name,
                         incomingPrincipal.Identity.AuthenticationType);
    }

    private IClaimsPrincipal GetClaims(string name, string authenticationType)
    {
        ClaimsIdentity id = new ClaimsIdentity(new List<Claim>
        {
            new Claim(WSIdentityConstants.ClaimTypes.Name,
                name,
                ClaimValueTypes.String,
                "LeastPrivilege"),
            new Claim("http://leastprivilege/claims/customClaim",
                "customValue",
                ClaimValueTypes.String,
                "LeastPrivilege")
        }, authenticationType);

        return new ClaimsPrincipal(id);
    }
}

You register the claims auth manager e.g. in config:

<microsoft.identityModel>
  <
claimsAuthenticationManager type="LeastPrivilege.ClaimsTransformer, AutoClaims" />
</
microsoft.identityModel>

HTH


ASP.NET | IdentityModel | WCF
Friday, November 14, 2008 7:51:53 AM UTC  #   
 Thursday, November 13, 2008

Username/Password Validation with Geneva

In my previous post I mentioned that Geneva takes over parts of the WCF security system - I used the example of certificate validation. This is also true for username/password authentication.

In the case you have an existing service with a UserNamePasswordValidator - as soon as you opt-into Geneva, the validator will stop to work. This is because Geneva takes over parts of the WCF processing pipeline and injects its own token parsing and validation system.

In Geneva, so-called SecurityTokenHandlers read and validate incoming tokens. As part of the validation process, claims based on that token are created and put into the IClaimsPrincipal, which will abe vailable from your operations. There are two handlers that register for UserName tokens: WindowsUserNameSecurityTokenHandler and MembershipUserNameSecurityTokenHandler (I guess it is clear which account stores they use).

By default the Windows handler is registered and unless you have a used a username/password pair that incidentally matches a Windows account on your system, username authentication will fail.

You now have two options: using the membership handler (if you have an existing membership provider) or write your own handler, which is pretty straightforward. The following handler code makes sure that username and password are identical - nothing you should do in your production systems - but you get the idea ;)

class SimpleUserNameSecurityTokenHandler : UserNameSecurityTokenHandler
{
    public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
    {
        UserNameSecurityToken unToken = token as UserNameSecurityToken;
        if (unToken == null)
        {
            throw new ArgumentException("token");
        }

        // replace with proper password validation!
        if (unToken.UserName != unToken.Password)
        {
            throw new SecurityTokenValidationException();
        }

        ClaimsIdentity id = new ClaimsIdentity(new List<Claim>
            {
                new Claim(WSIdentityConstants.ClaimTypes.Name, unToken.UserName)
            }, "UserName");

        return new ClaimsIdentityCollection(id);
    }

    public override bool CanValidateToken
    {
        get
        {
            return true;
        }
    }
}

You have to setup the handler in config - this is currently a little cumbersome but will hopefully get easier in the future. You first have to remove the windows handler - or clear the handler collection and add your own handler to it:

<microsoft.identityModel>
  <
securityTokenHandlers>
    <
clear />
    <
add type="LeastPrivilege.SimpleUserNameSecurityTokenHandler, AutoClaims" />
  </
securityTokenHandlers>
</
microsoft.identityModel>

 

There is also a thread on MSDN where Pedro shows how to do that programmatically.

HTH


IdentityModel | WCF
Thursday, November 13, 2008 6:43:34 PM UTC  #   
 Wednesday, November 12, 2008

Code Contracts in .NET 4

A really interesting feature in .NET 4 will be Code Contracts. They allow defining pre- and post-conditions in code along with some other more advanced options.

See the PDC video here - and  more here.


FX Security
Wednesday, November 12, 2008 7:02:03 AM UTC  #   
 Friday, October 31, 2008

Geneva is the new WCF Security

Geneva has evolved to not only a an extension to WCF/ASP.NET for STS/token related things - it also changes how base WCF security works - to the better IMO. Let me give you an example:

Trusted certificate issuers
When doing client certificate based authentication you always had three choices for validating those certs: PeerTrust, ChainTrust and Custom. I wrote about these options in detail (here). Typically you ended up writing some custom validation because both Peer- and ChainTrust is often  not what you want (and there are also some differences when it comes to message vs transport based security - see here, here and here).

Once you opt-in to the Geneva model - you will realize that client certificates start to break. This is because Geneva has a built-in way to restrict allowed CAs to a specified list, and by default this list is enforced - and empty. The background here is, that Geneva has this concept of an "issuer registry" - basically a mechanism how to map issuers (usually certificate issuers) to a name - the name is then placed on the Issuer property of claims. There are two built-in registry classes: the SimpleIssuerNameRegistry (which simply uses the CA's subject name and has no restrictions) and the ConfigurationBasedIssuerNameRegistry (which enforces the list I mentioned above).

To specify a list of allowed issuers, you have to put something like this in config:

<microsoft.identityModel>
  <
issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, …">
    <
trustedIssuers>
      <
add name="LeastPrivilege CA"
          
thumbprint="…" />
    </
trustedIssuers>
  </
issuerNameRegistry>
</
microsoft.identityModel>

This has the effect that only certificates issued by a CA in the trustedIssuers list will be allowed "in". If you don't want that restriction - or already have other validation code down the line - you can use the simple name registry. Another option is of course to write your own registry class.

Another big simplification with Geneva comes to custom token/credential types (ever tried adding a new credential type of WCF? Even really simple things require you to write 10+ classes and a good understanding how they relate to each other). With Geneva's concept of SecurityTokenHandlers this gets much easier.

So in summary - Geneva replaces parts of the WCF security system, simplifies it and makes it easier to extend - even if you are not using a security token service. I like that.


IdentityModel | WCF
Friday, October 31, 2008 6:35:55 AM UTC  #   
 Monday, October 27, 2008

Geneva is the new Zermatt (and much more)

Starting with the PDC release, Microsoft's identity framework is now code-named "Geneva Framework". Based on that framework, there is also a product called "Geneva Server" that brings the ADFS 1.x type of functionality (and more) to the web services/WS-Trust/CardSpace world. Furthermore there is also a release called "Geneva CardSpace" which seems to be CardSpace v.Next.

You can download all the new bits here.

I already had the chance to test-drive some of the new bits and made some interesting observations - stay tuned ;)


ASP.NET | CardSpace | IdentityModel | WCF
Monday, October 27, 2008 9:45:34 PM UTC  #   
 Thursday, October 16, 2008

Token Kidnapping (revisited)

It's been a while since I linked to Cesar Cerrudo's slide deck about token kidnapping. Now there is also a POC available (with samples how to use it from SQL Server and IIS).

There is also some movement at MS now...(here, here)

Quoting from the recommendations page of the original slide deck:

  • Windows XP and 2003
    • On IIS 6 don't run ASP .NET in full trust and if classic ASP is enabled don't allow users to execute binaries
  • On Windows Vista and 2008
    • On IIS 7 don't run ASP .NET in full trust or don't run web sites under NetworkServer or LocalService accounts
    • Don't run services under NetworkService or LocalService accounts
      • Use regular user accounts to run services

Work in Progress
Thursday, October 16, 2008 5:10:04 AM UTC  #   
 Wednesday, October 15, 2008

Getting rid of the .svc Extension in IIS

Jon posted a module that does this.

I recently tried to use the URL rewriting module for IIS 7 to achieve the same - this rule worked for me:

<system.webServer>
  <
rewrite>
    <
rules>
      <
rule name="Remove .svc">
        <
match url="^([0-9a-zA-Z\-]+)/([0-9a-zA-Z\-\.\/\(\)]*)" />
        <
action type="Rewrite"
               
url="{R:1}.svc/{R:2}" />
      </
rule>
    </
rules>
  </
rewrite>
</
system.webServer>

 

HTH


IIS | WCF
Wednesday, October 15, 2008 7:30:44 PM UTC  #   
 Thursday, October 09, 2008

CardSpace is…

I often get the Question: “What is CardSpace?

While there is a whole philosophical side to CardSpace (or similar products) – the technical and pragmatic answer is:

“CardSpace is a graphical client for security token services built into Windows”

(or as Keith recently said: “home realm discovery the nice way")

Related questions are:

What is a card?

“A card is a graphical representation of the configuration details how to talk to that security token service (address, required claims, credentials and more…)”

Then what’s the difference between personal and managed cards?

“Personal cards use a local (aka personal) STS. Managed cards a third-party/remote STS”

That’s it.


CardSpace | IdentityModel
Thursday, October 09, 2008 10:21:57 PM UTC  #   
 Saturday, September 20, 2008

MSDN Article about WCF Service Authorization

Christian and I have written an article about the authorization infrastructure in WCF. It covers roles- and claims-based authorization and how to customize both. Enjoy.

http://msdn.microsoft.com/en-us/magazine/cc948343.aspx
(back online now - sorry for the confusion)


IdentityModel | WCF
Saturday, September 20, 2008 9:59:05 AM UTC  #   
 Sunday, September 14, 2008

Certificate-backed InfoCards and Service Credential Negotiation

When trying to implement certificate backed managed InfoCards you might run into this slightly misleading error message:

"There was a failure making a WS-Trust exchange with an external application. Could not retrieve token from identity provider.

Inner Exception: SOAP security negotiation failed. See inner exception for more details.
Inner Exception: The certificate 'CN=xy' must have a private key. The process must have access rights for the private key."

The real cause for this error is a bug in Windows CardSpace. You can workaround that by disabling service credential negotiation on your STS binding by setting negotiateServiceCredential to false.

Thanks to the Zermatt forum people for pointing me into the right direction!


IdentityModel
Sunday, September 14, 2008 12:16:45 PM UTC  #   
 Wednesday, September 10, 2008

ASP.NET Controls and Output Encoding

The last two days I did an ASP.NET security training for a customer. One discussion was how ASP.NET control handle (or don't) output encoding - especially how inconsistent their behavior is.

Five minutes ago I found this post by Alex - and he links to this table. Wow.


ASP.NET
Wednesday, September 10, 2008 5:28:27 AM UTC  #   
 Wednesday, September 03, 2008

Zermatt: Source Code for FormsAuth STS

I got several requests to publish the full source of the FormsAuth STS I described here. Find it here. The setup is just like the passive STS/RP samples in the SDK.

HTH

 


IdentityModel
Wednesday, September 03, 2008 10:55:48 PM UTC  #   
 Sunday, August 17, 2008

P2P and WCF: Some Troubleshooting Resources

These are helpful resource when troubleshooting P2P:

Checking cloud status:
netsh p2p pnrp cloud show list

Checking Teredo status:
netsh int teredo show state

Enabling ping over P2P

P2P Traceroute

PNRP Debugging Guide

PNRP and WICN on Server 2008


WCF
Sunday, August 17, 2008 5:47:17 AM UTC  #   
 Friday, August 15, 2008

Zermatt: Using Forms Authentication in a Passive STS

Since all Zermatt samples use Windows authentication to auth against an STS - the question how to use forms authentication instead popped up several times. It is easy to do that.

Basically a passive STS endpoint is an ASP.NET handler - could be a plain IHttpHandler, an .ashx or a page. All samples simply hook the Page_PreRender event to render the redirect logic. But you could also show a UI before doing that. This means you can put e.g. a login control on your issuing page and manually verify username/password credentials before issuing the token.

My sample issuing page looks like this:

<html xmlns="http://www.w3.org/1999/xhtml">
<
head runat="server">
    <title>Forms Authentication Sign In</title>
</
head>
<
body>
    <form id="form1" runat="server">
    <div>
        <asp:Login runat="server" ID="_login" OnAuthenticate="_login_Authenticate" />
    </div>
    </form>
</
body>
</
html>

In the Authenticate event you verify credentials somehow, and if successful, create a ClaimsIdentity and  issue the token. In my sample I additionally issue a forms auth ticket for the STS domain so that returning users don't have to re-authenticate using the form.

Another approach to make the federation token apply to more than one RP is to modify the cookie domain (if the RPs are in the same domain).

protected void _login_Authenticate(object sender, AuthenticateEventArgs e)
{
    if (ValidateUser(_login.UserName, _login.Password))
    {
        FormsAuthentication.SetAuthCookie(_login.UserName, false);

        ClaimsIdentity identity = new ClaimsIdentity(
            new Claim(System.IdentityModel.Claims.ClaimTypes.Name, _login.UserName),
            "UserName");
        ClaimsPrincipal principal = new ClaimsPrincipal(
            new ClaimsIdentityCollection(identity));

        ProcessFederationMessage(principal);
    }
}

HTH


IdentityModel
Friday, August 15, 2008 6:58:18 AM UTC  #   
 Thursday, August 14, 2008

How to build a Development/Test/Demo CA

I often need X509 certificates - but I never really became friendly with makecert. So I ended up running Windows Cerificate Services which proved to be an easy to use, robust solution. You can have one at home or carry it around in a VM. Perfect.

There are some gotchas you can run into and I refined my configuration over the years. I just had to rebuild my Test CA (on Hyper-V) so I thought I'll document the important steps (for self-reference and whoever might be interested)

 

Basic Installation

  1. Install Windows Server (2003 or 2008) - either phyiscally or virtually.
  2. Install Certificate Services.
  3. Select Stand-alone CA.
  4. Choose a reasonable lifetime for the CA cert (like 10 years)
  5. Backup the CA cert. You need this when rebuilding the machine or having several installations act like the same CA.

 

Certificate Lifetimes
By default certificates issued with the CA have a lifetime of one year. They usually expire on the very day where you have to do an important demo. You can configure the lifetime in the registry. See here for details.

 

Revocation Lists
Another common reason why you run into problems with certificates are revocation lists. The location of the revocation list(s) is embedded in certificates in the CDP (CRL Distribution Point) extension. Now by default there is an entry pointing to the CA's Netbios name. Accessing that network location works while you are in your home network and the CA is up and running. If this network location cannot be accessed, many applications and frameworks will fail certificate validation (the default WCF binding security settings e.g.).

Simply removing the complete CDP extension would be one workaround - but some apps don't like that at all. So I wouldn't recommend doing that. A better solution is to create a revocation list once, and store that at a publicly available location. You can also set the lifetime of that revocation list to some high value (like 5 years), so Windows will cache the list. This way you have access to your CRL while on the road and due to the high lifetime value, this will even work when having no network access at all.

To change the CDP settings, open the Certificate Services MMC snap in. Right click on your CA and then select properties. On the extensions tab you can see the list of CRL locations. The first entry specifies the CA local location where CRLs are published. The last three locations get embedded in the certificate. You can delete them and add you publicly available location. Make sure you check the "Include in the CDP extensions of issued certificates" box for your new location.

Next you have to publish a CRL. First you have to set the CRL lifetime. This is configured in the properties of the 'Revoked Certificates' folder in the snap in. Set it to e.g. five years. Next you publish via right-Click -> All Tasks -> Publish. You can find the CRL at the previously configured local location.

The last step is to copy the CRL to your public location and that's it.

Now you can browse to the CA's web interface (http://server/certsrv) and request certificates. After requesting a certificate you have to go to the CA's MMC console and issue the cert (in 'Pending Requests'). Then you can download the certificate by returning to the web interface.

HTH


Work in Progress
Thursday, August 14, 2008 2:05:12 PM UTC  #   

Most important bug fix in 3.5 SP1

BradA says:

"We have brought managed executables in line with native code executables in how they behave when run off a network share.  Yea!"

VanceN says:

"Hurray, its finally fixed!  manage code 'just works' from network file share!"

Grats for fixing this bug!

 

(hint: some sarcasm is hidden in this post ;)


Misc
Thursday, August 14, 2008 9:06:21 AM UTC  #   
 Thursday, July 24, 2008

WCF Claims to "Zermatt" Claims Migration Story

Hey - that's a short post - there is none. thanks. bye...

OK hold on - some background info.

Microsoft introduced their new claims API with .NET 3.0 as part of the System.IdentityModel assembly (with super tight integration into WCF). Needless to say that I really like the claims approach - and I have written quite a lot about it here.

Also since that day we were all waiting for that super secret identity framework that was supposed to extend the claims API and which will finally give us easier support for security token services and Information Card related technologies. Now it is in beta and is called "Zermatt". Cool. Life is good.

After some experiments and proof of concepts - it turns out life is not so good.

To enable the "Zermatt" model in WCF you basically have to call the ConfigureServiceHost method on the ExtensibleServiceCredentials class (at least that's how it works with the current bits). As soon as you enable Zermatt the usual places where security happens in WCF don't work anymore - namely ServiceSecurityContext and AuthorizationContext. Interested readers of my blog know that these classes are the entry point into the claims based world in WCF. Also if you have made any investments already into the claims model, your code relies on these classes. If they are "gone", your code is broken.

All the claims functionality found in WCF is now replaced by the Zermatt model and there is no connection whatsoever between them. You'll also find that Zermatt has its own version of a Claim class (and other structural classes too). This basically means that if you have already invested in the WCF claims model but wanna move on to Zermatt, you have to throw away all your code and start from scratch. There is no migration or co-existence story between WCF claims and Zermatt claims.

OK - the next thing I tried is how existing WCF authorization policies work together with Zermatt. The results are quite mixed. First of all external policies only work with certain credential types - and Right.Idenity claims are not supported at all.

Fortunately, there is a forum for Zermatt so I can ask some MSFT people about their take on that. Here's what I got back (I'd love to provide links to the forum posts - but unfortunately this forum is sooo cool and ajaxy that one of the most important features of the web - called URLs - don't work):

"Hi Dominick,
Deeper investigation on my part into what I suspected was a bug turned
out to be by design. The scenario you are attempting (upgrading a
legacy app that depends on the WCF claims model) is not supported in
Zermatt.

Once you opt into Zermatt's claims model, the WCF claims API does not
work anymore. The reason for this behavior is the new claims model in
Zermatt is not backwards compatible with the WCF claims API and it is
not feasible to support both the old and new models at the same time
for WCF applications.

As you have called out earlier in a separate discussion, you have to
choose between staying with the WCF API and not use Zermatt, or move
your application to Zermatt. If you do choose to migrate, any code
that depends on the WCF claims API will need to be rewritten."

Have you also spotted the word "legacy" wrt to WCF??? They must be kidding me!

Here's my answer:

"I don't understand the problem - why can't you take existing authZ
policies and transform them into a ClaimsIdentity - this would be an
easy solution for the migration problem.

Frankly - this sucks.

What do I tell my customers? Sorry for leading you into the
System.IdentityModel direction? Your code will not move forward?

You have a brand new communication framework with a brand new claims
based authZ model - now you are releasing a brand new identity
framework that just disables the technologies used before???? This is
not right.

I don't ask for a full compatibility story between S.IM and Zermat -
but i don't want to throw away all my code (or my customers code)."

Am I asking for too much? Is this a non-issue? I filed a bug for that here. If this is also important for you - feel free to vote.

 

Disclaimer: Don't get me wrong. I don't want to bash Microsoft or the Zermatt team, nor the people on the forum which are really helpful. I just think this is a wrong design decision. And I read somewhere that Microsoft is looking for feedback. So here it is.


IdentityModel
Thursday, July 24, 2008 10:06:31 AM UTC  #