Wednesday, May 26, 2010

Updated StarterSTS Documentation & Identity Delegation Screencast

I recorded a short screencast describing the identity delegation feature in StarterSTS 1.1. You can watch it here.

I also uploaded an updated version of the documentation here.


IdentityModel
Wednesday, May 26, 2010 7:42:59 AM UTC  #   
 Monday, May 24, 2010

StarterSTS 1.1 CTP – ActAs Support

Due to popular demand, I added identity delegation (aka ActAs) support to StarterSTS.

To give this feature a try, first download the new bits and add a enableActAs = true to startersts.config. You then have to configure which user account is allowed to delegate, as well as the target realm to delegate to. This is done in usermappings.config, e.g.:

<userMappings xmlns="http://www.thinktecture.com/configuration/usermappings">
    <user name="middletier">
      <mappings>
        <mapping type="ActAs"
                 value="https://server/service.svc" />
      </mappings>
    </user>
  </users>
</userMappings>

Please use the forum for any feedback. thanks!


IdentityModel
Monday, May 24, 2010 12:05:19 PM UTC  #   
 Friday, May 14, 2010

A more elegant way of embedding a SOAP security header in Silverlight 4

The current situation with Silverlight is, that there is no support for the WCF federation binding. This means that all security token related interactions have to be done manually.

Requesting the token from an STS is not really the bad part, sending it along with outgoing SOAP messages is what’s a little annoying. So far you had to wrap all calls on the channel in an OperationContextScope wrapping an IContextChannel. This “programming model” was a little disruptive (in addition to all the async stuff that you are forced to do).

It seems that starting with SL4 there is more support for traditional WCF extensibility points – especially IEndpointBehavior, IClientMessageInspector. I never read somewhere that these are new features in SL4 – but I am pretty sure they did not exist in SL3.

With the above mentioned interfaces at my disposal, I thought I have another go at embedding a security header – and yeah – I managed to make the code much prettier (and much less bizarre). Here’s the code for the behavior/inspector:

public class IssuedTokenHeaderInspector : IClientMessageInspector
{
    RequestSecurityTokenResponse _rstr;
 
    public IssuedTokenHeaderInspector(RequestSecurityTokenResponse rstr)
    {
        _rstr = rstr;
    }
 
    public void AfterReceiveReply(ref Message reply, object correlationState)
    { }
 
    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        request.Headers.Add(new IssuedTokenHeader(_rstr));
        
        return null;
    }
}
 

public class IssuedTokenHeaderBehavior : IEndpointBehavior
{
    RequestSecurityTokenResponse _rstr;
 
    public IssuedTokenHeaderBehavior(RequestSecurityTokenResponse rstr)
    {
        if (rstr == null)
        {
            throw new ArgumentNullException();
        }
 
        _rstr = rstr;
    }
 
    public void ApplyClientBehavior(
      ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(new IssuedTokenHeaderInspector(_rstr));
    }
 
    // rest omitted
}

This allows to set up a proxy with an issued token header and you don’t have to worry anymore with embedding the header manually with every call:

var client = GetWSTrustClient();
 
var rst = new RequestSecurityToken(WSTrust13Constants.KeyTypes.Symmetric)
{
    AppliesTo = new EndpointAddress("https://rp/")
};
 
client.IssueCompleted += (s, args) =>
{
    _proxy = new StarterServiceContractClient();
    _proxy.Endpoint.Behaviors.Add(new IssuedTokenHeaderBehavior(args.Result));
 
};
 
client.IssueAsync(rst);

Since SL4 also support the IExtension<T> interface, you can also combine this with Nicholas Allen’s AutoHeaderExtension.


IdentityModel
Friday, May 14, 2010 5:01:54 AM UTC  #   
 Sunday, May 09, 2010

Thinktecture.IdentityModel: WRAP and SWT Support

The latest drop of Thinktecture.IdentityModel contains some helpers for the Web Resource Authorization Protocol (WRAP) and Simple Web Tokens (SWT).

WRAP
The WrapClient class is a helper to request SWT tokens via WRAP. It supports issuer/key, SWT and SAML input credentials, e.g.:

var client = new WrapClient(wrapEp);
var swt = client.Issue(issuerName, issuerKey, scope);

All Issue overrides return a SimpleWebToken type, which brings me to the next helper class.

SWT
The SimpleWebToken class wraps a SWT token. It combines a number of features:

  • conversion between string format and CLR type representation
  • creation of SWT tokens
  • validation of SWT token
  • projection of SWT token as IClaimsIdentity
  • helpers to embed SWT token in headers and query strings

The following sample code generates a SWT token using the helper class:

private static string CreateSwtToken()
{
    var signingKey = "wA…";
    var audience = "http://websample";
    var issuer = "http://self";
 
    var token = new SimpleWebToken(
      issuer, audience, Convert.FromBase64String(signingKey));

   
token.AddClaim(ClaimTypes.Name, "dominick");
    token.AddClaim(ClaimTypes.Role, "Users");
    token.AddClaim(ClaimTypes.Role, "Administrators");
    token.AddClaim("simple", "test");
 
    return token.ToString();
}


IdentityModel
Sunday, May 09, 2010 8:27:46 PM UTC  #   
 Saturday, May 08, 2010

Thinktecture.IdentityModel: Comparing Strings without leaking Timinig Information

Paul Hill commented on a recent post where I was comparing HMACSHA256 signatures. In a nutshell his complaint was that I am leaking timing information while doing so – or in other words, my code returned faster with wrong (or partially wrong) signatures than with the correct signature. This can be potentially used for timing attacks like this one.

I think he got a point here, especially in the era of cloud computing where you can potentially run attack code on the same physical machine as your target to do high resolution timing analysis (see here for an example).

It turns out that it is not that easy to write a time-constant string comparer due to all sort of (unexpected) clever optimization mechanisms in the CLR. With the help and feedback of Paul and Shawn I came up with this:

  • Structure the code in a way that the CLR will not try to optimize it
  • In addition turn off optimization (just in case a future version will come up with new optimization methods)
  • Add a random sleep when the comparison fails (using Shawn’s and Stephen’s nice Random wrapper for RNGCryptoServiceProvider).

You can find the full code in the Thinktecture.IdentityModel download.

[MethodImpl(MethodImplOptions.NoOptimization)]
public static bool IsEqual(string s1, string s2)
{
    if (s1 == null && s2 == null)
    {
        return true;
    }
 
    if (s1 == null || s2 == null)
    {
        return false;
    }
 
    if (s1.Length != s2.Length)
    {
        return false;
    }
 
    var s1chars = s1.ToCharArray();
    var s2chars = s2.ToCharArray();
 
    int hits = 0;
    for (int i = 0; i < s1.Length; i++)
    {
        if (s1chars[i].Equals(s2chars[i]))
        {
            hits += 2;
        }
        else
        {
            hits += 1;
        }
    }
 
    bool same = (hits == s1.Length * 2);
 
    if (!same)
    {
        var rnd = new CryptoRandom();
        Thread.Sleep(rnd.Next(0, 10));
    }
 
    return same;
}


IdentityModel
Saturday, May 08, 2010 7:51:07 PM UTC  #   
 Wednesday, May 05, 2010

ADFS 2.0 RTW

Finally – the identity story is complete (for now).

Download ADFS 2.0.


Misc
Wednesday, May 05, 2010 5:40:56 PM UTC  #   

Thinktecture.IdentityModel: WIF Support for WCF REST Services and OData

The latest drop of Thinktecture.IdentityModel includes plumbing and support for WIF, claims and tokens for WCF REST services and Data Services (aka OData).

Cibrax has an alternative implementation that uses the WCF Rest Starter Kit. His recent post reminded me that I should finally “document” that part of our library.

Features include:

  • generic plumbing for all WebServiceHost derived WCF services
  • support for SAML and SWT tokens
  • support for ClaimsAuthenticationManager and ClaimsAuthorizationManager
  • based solely on native WCF extensibility points (and WIF)

This post walks you through the setup of an OData / WCF DataServices endpoint with token authentication and claims support. This sample is also included in the codeplex download along a similar sample for plain WCF REST services.

Setting up the Data Service
To prove the point I have created a simple WCF Data Service that renders the claims of the current client as an OData set.

public class ClaimsData
{
    public IQueryable<ViewClaim> Claims
    {
        get { return GetClaims().AsQueryable(); }
    }
 
    private List<ViewClaim> GetClaims()
    {
        var claims = new List<ViewClaim>();
        var identity = Thread.CurrentPrincipal.Identity as IClaimsIdentity;
 
        int id = 0;
        identity.Claims.ToList().ForEach(claim =>
            {
                claims.Add(new ViewClaim
                {
                   Id = ++id,
                   ClaimType = claim.ClaimType,
                   Value = claim.Value,
                   Issuer = claim.Issuer
                });
            });
 
        return claims;
    }
}

…and hooked that up with a read only data service:

public class ClaimsDataService : DataService<ClaimsData>
{
    public static void InitializeService(IDataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
    }
}

Enabling WIF
Before you enable WIF, you should generate your client proxies. Afterwards the service will only accept requests with an access token – and svcutil does not support that.

All the WIF magic is done in a special service authorization manager called the FederatedWebServiceAuthorizationManager. This code checks incoming calls to see if the Authorization HTTP header (or X-Authorization for environments where you are not allowed to set the authorization header) contains a token. This header must either start with SAML access_token= or WRAP access_token= (for SAML or SWT tokens respectively).

For SAML validation, the plumbing uses the normal WIF configuration. For SWT you can either pass in a SimpleWebTokenRequirement or the SwtIssuer, SwtAudience and SwtSigningKey app settings are checked.If the token can be successfully validated, ClaimsAuthenticationManager and ClaimsAuthorizationManager are invoked and the IClaimsPrincipal gets established.

The service authorization manager gets wired up by the FederatedWebServiceHostFactory:

public class FederatedWebServiceHostFactory : WebServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(
      Type serviceType, Uri[] baseAddresses)
    {
        var host = base.CreateServiceHost(serviceType, baseAddresses);
 
        host.Authorization.ServiceAuthorizationManager =
          new FederatedWebServiceAuthorizationManager();
        host.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
 
        return host;
    }
}

The last step is to set up the .svc file to use the service host factory (see the sample download).

Calling the Service
To call the service you need to somehow get a token. This is up to you. You can either use WSTrustChannelFactory (for the full CLR), WSTrustClient (Silverlight) or some other way to obtain a token. The sample also includes code to generate SWT tokens for testing – but the whole WRAP/SWT support will be subject of a separate post.

I created some extensions methods for the most common web clients (WebClient, HttpWebRequest, DataServiceContext) that allow easy setting of the token, e.g.:

public static void SetAccessToken(this DataServiceContext context,
  string token, string type, string headerName)
{
    context.SendingRequest += (s, e) =>
    {
        e.RequestHeaders[headerName] = GetHeader(token, type);
    };
}

Making a query against the Data Service could look like this:

static void CallService(string token, string type)
{
    var data = new ClaimsData(new Uri("https://server/odata.svc/"));
    data.SetAccessToken(token, type);
 
    data.Claims.ToList().ForEach(c =>
        Console.WriteLine("{0}\n {1}\n ({2})\n", c.ClaimType, c.Value, c.Issuer));
}

HTH


IdentityModel
Wednesday, May 05, 2010 2:54:51 PM UTC  #   

Thinktecture.IdentityModel: Claims Debugger Visualizer

In the latest drop of Thinktecture.IdentityModel you can find a debugger visualizer for IClaimsIdentity and IClaimsPrincipal.

Have fun ;)

PS. Thanks to Mr. UI.


IdentityModel
Wednesday, May 05, 2010 12:47:42 PM UTC  #   
 Tuesday, April 27, 2010

Sod This! – reloaded

Oliver and Gary fortunately decided to continue with their “Sod This” podcast show. That’s good – because I always found this very entertaining.

The “comeback” show is about security and identity – awesome ;)



Tuesday, April 27, 2010 10:53:55 AM UTC  #   
 Wednesday, April 14, 2010

Using an Active Endpoint to sign into a Web Application

This question comes up from time to time, so I thought I’ll document it here.

The scenario is, that you don’t want to do a passive redirect in a web app – but directly talk to an active STS endpoint to authenticate and request a token. The reasons for that could be that you need a local sign-in page in the web app – or that the token service is not publicly reachable.

The following code can be used on a login page:

protected void _btnLogin_Click(object sender, EventArgs e)
{
    // authenticate with WS-Trust endpoint
    var factory = new WSTrustChannelFactory(
        new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
        new EndpointAddress("https://sts/endpoint"));

   
factory.Credentials.UserName.UserName = _txtUserName.Text;
    factory.Credentials.UserName.Password = _txtPassword.Text;
 
    var channel = factory.CreateChannel();
 
    var rst = new RequestSecurityToken
    {
        RequestType = RequestTypes.Issue,
        AppliesTo = new EndpointAddress("https://rp/"),
        KeyType = KeyTypes.Bearer
    };
 
    var genericToken = channel.Issue(rst) as GenericXmlSecurityToken;
 
    // parse token
    var handlers = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;
    var token = handlers.ReadToken(new XmlTextReader(
       new StringReader(genericToken.TokenXml.OuterXml)));
    var identity = handlers.ValidateToken(token).First();

   
// create session token
    var sessionToken = new SessionSecurityToken(
       ClaimsPrincipal.CreateFromIdentity(identity));
    FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
 
    Response.Redirect("~/users/default.aspx");
}


IdentityModel
Wednesday, April 14, 2010 12:51:50 PM UTC  #   
 Tuesday, April 06, 2010

Taken by Storm

Any more dodgy puns?

I am happy to announce that my good friend Oliver Sturm has joined thinktecture.

Oliver is a brilliant computer geek in general and a language wonk in particular – good company to hang out in bars – and just generally a nice guy. Looking forward working with you!


Misc
Tuesday, April 06, 2010 10:18:00 AM UTC  #   
 Sunday, April 04, 2010

Thinktecture StarterSTS 1.0 RTW

Wow – I can’t tell you how happy and relieved I am to write this post ;)

I started to work with what’s now called WIF approximately two years ago – and built various security token services for customers, demos and internal use. The idea behind StarterSTS was to have a non-trivial security token service sample that demonstrates the typical tasks of an STS (where it turns out that issuing tokens is by far the smallest part) and at the same time is real world enough to be directly used in specialized situations like development STSes.

I checked-in the first public version of StarterSTS at 25th May 2009 and had 1861 download so far. Today I am announcing StarterSTS 1.0 which is feature complete (and hopefully reasonably bug-free) and finally includes documentation as well as nine new screencasts on the various feature areas.

I want to thank all beta-testers and early adopters that gave feedback along the way! Now that 1.0 is done we can think about ways to extend the STS in the future.

Codeplex Site
http://startersts.codeplex.com (main)
http://startersts.codeplex.com/releases/view/43054#DownloadId=115213 (direct)
http://startersts.codeplex.com/thread/list.aspx (forum)

Documentation
http://identity.thinktecture.com/stsce/docs/

Screencasts
Initial setup & configuration
Federating your first web application
Federating with web services
Single-Sign-On & Confirmation screen
Using the REST endpoint
Using the OpenId bridge
Tracing
Using client certificates
Using Information Cards


IdentityModel
Sunday, April 04, 2010 6:33:42 AM UTC  #   
 Tuesday, March 30, 2010

Using Silverlight to Access WIF secured WCF Services (Part 3)

In this last part of the series (see here and here) I want to show you how to use the WIF/SL integration ClaimsIdentitySessionManager to request tokens and talk to WIF secured services.

The ClaimsIdentityManager registers as an ApplicationService in SL. Once registered, it can encapsulate the process of requesting a token for a relying party, caching that token as well as setting the SOAP security header for outgoing service requests.

Registration
ClaimsIdentitySessionManager gets registered in app.xaml. Here you can specify the endpoint address of the WS-Trust token services as well as the credential type. In this sample I am using the ADFS2 Windows/Transport endpoint from my last post.

<Application.ApplicationLifetimeObjects>
    <id:ClaimsIdentitySessionManager>
        <id:ClaimsIdentitySessionManager.IdentityProvider>
            <id:WSTrustSecurityTokenService
                   Endpoint="https://server/services/trust/13/windowstransport" 
                   CredentialType="DefaultCredential" />
        </id:ClaimsIdentitySessionManager.IdentityProvider>
    </id:ClaimsIdentitySessionManager>
</Application.ApplicationLifetimeObjects>

Calling the Service
All the service interaction is abstracted by the ClaimsIdentitySessionManager. The call to InvokeAsync does a few things:

  • checks if a token has already been obtained for the service endpoint
    • if not, requests the token and caches it
    • if a password is required, invokes a callback to the UI
  • sets the SOAP security header using the requested token

private void CallService()
{
    var factory = new ChannelFactory<StarterServiceContract>("symmetric");
    var proxy = factory.CreateChannel();
    var channel = proxy as IClientChannel;

    ClaimsIdentitySessionManager.Current.InvokeAsync(() =>
        {
            proxy.BeginGetClaims(result => ShowClaims(proxy, result), null);
        }, channel);
}


IdentityModel
Tuesday, March 30, 2010 8:18:07 AM UTC  #   
 Sunday, March 28, 2010

Requesting Tokens from ADFS2 using Silverlight and Windows Authentication

With SL4’s support for NTLM and the WIF integration bits, you can now easily request tokens from ADFS2 (or any other token service that supports Windows authentication) in single-sign-on style. Here’s the quick walk-through…

Enable the right endpoint in ADFS2
You need a WS-Trust endpoint for version 1.3 that supports transport security and Windows authentication. This endpoint needs to be enabled in the ADFS2 MMC (/trust/13/windowstransport).

Configure WSTrustClient and request the Token
Next you have to configure WSTrustClient to use this endpoint, using the Windows binding and Windows credential type:

var client = new WSTrustClient(
    new WSTrustBindingWindows(),
    new EndpointAddress("https://server/adfs/services/trust/13/windowstransport"),
    new WindowsCredentials());

From there on you can include the token to auth against other services.


IdentityModel
Sunday, March 28, 2010 3:37:27 PM UTC  #   
 Sunday, March 21, 2010

Using Silverlight to Access WIF secured WCF Services (Part 2)

This was one of my most popular blog post in the recent time (please read it first to get the necessary background information). I thought I give this another shot with the new SL/WIF integration.

There are other ways to accomplish the below things, e.g. using the SL application service or passive identity providers. I am focusing here purely on the SL initiated active STS/RP communication scenario and the raw APIs.

Requesting Tokens from within Silverlight
In my old post I had to use a custom REST endpoint in StarterSTS to request a bearer token. With the new WSTrustChannel, it is now possible to talk to a standard WS-Trust 1.3 endpoint (like the one in StarterSTS or ADFS2).

var client = new WSTrustClient(
    new WSTrustBindingUsernameMixed(),
    new EndpointAddress("https://.../issue.svc/mixed/username"),
    new UsernameCredentials("username", "password"));

You then have to construct an RST. Basically you specify the key type (bearer or symmetric) and appliesTo value.

var rst = new RequestSecurityToken(WSTrust13Constants.KeyTypes.Symmetric)
{
    AppliesTo = new EndpointAddress("https://roadie/StarterRP/")
};

The call to WSTrustClient.Issue returns an RSTR – which in turn contains the requested token and further key material. The identity kit also contains a token cache called TokenCache. You could use this class if you want to to store that token for further use.

client.IssueCompleted += (s, args) =>
{
    _cache.AddTokenToCache("myRP", args.Result);
};
 
client.IssueAsync(rst);

Using a Token to authenticate with a WCF Relying Party
Since Silverlight does not support issued token credentials, we must handcraft the SOAP security header. The identity kit includes the IssuedTokenHeader class for this purpose. The nice thing is, that this class supports symmetric proof keys as well as bearer tokens. But you still have to set this header manually on every call.

The identity kit includes its own wrapper to abstract away the header generation. I am using my own little helper here to make this process less disruptive.

public static class IssuedTokenHeaderExtensions
{
    public static void SendWithIssuedToken(this IContextChannel channel,
      RequestSecurityTokenResponse
rstr, Action action)
    {
        using (new OperationContextScope(channel))
        {
            OperationContext.Current.OutgoingMessageHeaders.Add(
              new IssuedTokenHeader(rstr));

           
action();
        }
    }
}

This allows calling a WCF service like this:

private void CallService()
{
    var factory = new ChannelFactory<StarterServiceContract>("myRP");
    var proxy = factory.CreateChannel();
    var channel = proxy as IContextChannel;
 
    channel.SendWithIssuedToken(_cache.GetTokenFromCache("myRP"), () =>
        {
            proxy.BeginGetClaims(result => ShowClaims(proxy, result), null);
        });
}

The trick here again is, that the client stack is configured for no security at all, whereas the WCF service uses a federation binding (with SecureConversation turned off).

I think this is pretty cool and solves some of the problems I had in the past. If Silverlight would only support client certificate credentials….


IdentityModel
Sunday, March 21, 2010 8:52:58 PM UTC  #   

A first Look at Silverlight and WIF Integration

At MIX, Caleb did a talk about the new Silverlight/WIF integration classes that “ship” with the latest identity training kit. Since this is a topic that comes up really frequently – I had a first look.

The integration code consists of two projects (client & server side plumbing) and can be divided into several feature areas. I will post more information on the corresponding areas when I have written more code against them.

Same claims programming model as in WIF
The integration code includes (I)ClaimsPrincipal, (I)ClaimsIdentity, Claim, ClaimCollection as well as the standard claim types.

WS-Trust and WS-Security support
This is my favourite feature! The WSTrustClient class allows requesting tokens from WS-Trust 1.3 endpoints. It supports Username/Password and Windows credentials as well as bearer and symmetric token types. The IssuedTokenHeader class makes it easier to embed the requested token in calls to backend services. The TokenCache class allows caching RSTRs to be used with the issued token header.

Bringing claims to a Silverlight UI
Another feature area deals with bringing claims into the SL UI for personalization and authorization purposes. This needs some server side plumbing (the AuthenticationService) and seems to focus on passive scenarios. The current implementation simply mirrors the user claims that are visible in the app/service backend back to the UI.

Silverlight integration
This part of the integration code makes logons and claims access more SLish by providing an SL appplication service and thus data binding access to claims.

HTH


IdentityModel
Sunday, March 21, 2010 10:23:59 AM UTC  #   
 Tuesday, March 09, 2010

Thinktecture.DataObjectModel

Our very own Jörg Neumann had this cooking for quite a while. tt.DOM is a library that lets you add features like change tracking, undo, redo, views, transactions and n-tier support to arbitrary types (or lists of types). This makes typical data scenarios in 3-tier applications *much* easier to handle.

Expect more information and documentation soon (of course ;).

In the meanwhile feel free to play around with it and give us feedback via the codeplex forum!

http://dataobjectmodel.codeplex.com


Tools for Thinktecture
Tuesday, March 09, 2010 9:45:21 AM UTC  #   
 Sunday, March 07, 2010

This week: Trooper Heidelberg

Looking forward to this week’s nice little security conference organized by my old friends at ERNW.

Federated Identity - Opportunities and Risks
The world is moving towards a federated identity model. Public facing websites like Google or Facebook utilize technologies like OpenID, OAuth and WRAP to provide single-sign-on capabilities. Enterprises and ISVs start deploying WS-Federation, WS-Trust and SAML to federate with customers, partners and even internally. The goals are always the same: provide a more meaningful representation of "identity" for authentication, authorization and personalization. This talks sheds light on all these technologies, how they work and how to secure them.


Conferences
Sunday, March 07, 2010 5:45:39 PM UTC  #   
 Friday, March 05, 2010

Guide to Claims-based Identity and Access Control

RTM finally ;)

Book here.
Code here.
More info here.

Enjoy!!!


IdentityModel
Friday, March 05, 2010 12:36:46 PM UTC  #   

WIF Workshop

Mein geschätzter Kollege Vittorio Bertocci führt einen 2-Tägigen Workshop zum Thema Windows Identity Foundation in München durch. Das ist bestimmt eine gute Gelegenheit sich mal abseits vom Projektalltag mit dem Thema genauer zu beschäftigen.

Wenn danach alle (un)Klarheiten beseitigt sind, und Sie weiterführenden Informationen oder Unterstützung zur Implementierung von Claims in der Praxis benötigen – einfach Email an mich (dominick.baier (_at_) thinktecture.com). Ich helfe gerne weiter. Viel Spaß!


IdentityModel
Friday, March 05, 2010 12:28:46 PM UTC  #   
 Monday, March 01, 2010

Zurück von der BASTA

So – zurück und (wichtiger) erholt von der BASTA. Muss sagen – es war mal wieder sehr nett – großes Lob an Veranstalter und Teilnehmer. Hat Spaß gemacht!

Am meisten war ich über das große Interesse an WIF überrascht. Ein voller Raum für nen Security Talk – und das direkt nach dem Essen ;)

Hier habe ich eine sehr gute Zusammenfassung des Talks gefunden – die Punkte, die mir am Herzen lagen, scheinen angekommen zu sein! Das freut mich!

Ich habe es schon während des Vortrags erwähnt – WIF ist sowohl ein neuer API als auch ein neues Paradigma. Dafür reichen 75min einfach nicht aus. Wer Fragen dazu hat, oder Unterstützung braucht – einfach Mail an mich.

Bis zum nächsten Mal!


Conferences
Monday, March 01, 2010 8:06:39 AM UTC  #   

Adding StarterSTS as a Claims Provider for ADFS2

The v1 beta of StarterSTS has an updated relying party configuration section. This allows to “plugin” the STS into ADFS2 or Sharepoint as a claims provider.

Here’s a quick walkthrough for ADFS2:

Register StarterSTS as claims provider in ADFS
This is really easy. Simply go to the ADFS2 configuration console and add a new claims provider. Then point the wizard to the StarterSTS WS-Federation metadata file (either by URL or using a file path). Afterwards you have to add some claim rules – to get started you could add a pass-through rule for the name claim.

You will also need to export the ADFS2 certificate that is used for token decryption.

Registering ADFS2 as a relying party in StarterSTS
The next step is to register ADFS2 in StarterSTS. This is done by modifying the relyingParty.config file (in the configuration sub folder). You need three things for that – the ADFS issuer URI, the physical address of the ADFS2 sign-in page and the ADFS2 token encryption certificate. The certificate could be either imported into the certificate store or you copy it to ~/App_Data/certificates.

The config entry looks similar to this:

<add realm="http://<adfsname>/adfs/services/trust"
     replyTo="https://<adfsname>/adfs/ls/">
  <certificate filename="tokendecryption.cer" />
</add>

HTH


IdentityModel
Monday, March 01, 2010 7:30:14 AM UTC  #   
 Friday, February 19, 2010

WCF, WIF and Load Balancing (and a bit of Azure)

Pablo wrote a post yesterday giving some background information on how session tokens are protected in WIF – here some additional info for WCF:

The ws* bindings in WCF establish a security session by default (via WS-SecureConversation). This has some implications, e.g.

  • You end up with a stateful service – or more important – with a stateful programming model. You have all the typical session “problems” like faulted sessions, timeout, retries etc…
  • By default SecureConversation only transmits a session identifier (like a ASP.NET session cookie) – the actual session is stored in-memory at the server. Not good for load balancing.

When you want to use WCF in a load balanced environment (e.g Azure) – you have to change the default behavior – you basically have two options:

  • Turn off SecureConversation all together. This has the advantage of being stateless (at least in that part of the communication). But this also means, that the bootstrap (SAML) token will get parsed on every request – this includes invoking the ClaimsAuthenticationManager. This might have performance implications – but depends on your scenario.
  • Force WCF into “cookie mode”. This means that the complete IClaimsPrincipal (after ClaimsAuthenticationManager has run) gets serialized and round-tripped in the SOAP header.

Turning off SecureConversation
Unfortunately WCF 3.5 does not directly allow that on the standard federation bindings. You would need to create a custom binding that uses an authentication mode of IssuedTokenOverTransport (for mixed mode) or IssuedTokenForCertificate (for message security).

In .NET 4 you can simply set establishSecurityContext to false on the standard ws-fed binding.

Cookie Mode
Forcing WCF into cookie mode requires a custom binding. The “trick” here is to set requireSecurityContextCancellation to false – which is just a fancy name for “serialize the context into the message”. Here’s the binding I am using (mixed mode security):

<customBinding>
  <binding name="federation_cookie">
    <security authenticationMode="SecureConversation"
              messageSecurityVersion="WSSecurity11
                                      WSTrust13
                                      WSSecureConversation13
                                      WSSecurityPolicy12
                                      BasicSecurityProfile10
"
              requireSecurityContextCancellation="false">
      <secureConversationBootstrap authenticationMode="IssuedTokenOverTransport"
                                   messageSecurityVersion="WSSecurity11
                                                           WSTrust13
                                                           WSSecureConversation13
                                                           WSSecurityPolicy12
                                                           BasicSecurityProfile10
">
        <issuedTokenParameters>
          <issuerMetadata address="https://…" />
        </issuedTokenParameters>
      </secureConversationBootstrap>
    </security>
   
    <textMessageEncoding />
    <httpsTransport />
  </binding>
</customBinding>

As Pablo points out in his post, the session cookie must be protected somehow. The standard WIF behavior is to the DPAPI user key. This key cannot be easily shared between nodes in a cluster (unless the nodes are all domain members and roaming profiles are activated). Another more explicit (and practical) option is to use an RSA key. Most typically you would feed your SSL certificate or the certificate used to decrypt incoming tokens into the following session token handler:

public class WebFarmSessionSecurityTokenHandler : SessionSecurityTokenHandler
{
    public WebFarmSessionSecurityTokenHandler(X509Certificate2 protectionCertificate)
        : base(CreateRsaTransforms(protectionCertificate))
    { }
 
    private static ReadOnlyCollection<CookieTransform> CreateRsaTransforms
      (X509Certificate2 protectionCertificate)
    {
        var transforms = new List<CookieTransform>()
                        {
                            new DeflateCookieTransform(),
                            new RsaEncryptionCookieTransform(protectionCertificate),
                            new RsaSignatureCookieTransform(protectionCertificate),
                        };
 
        return transforms.AsReadOnly();
    }
}

One way of wiring up the above handler would be a service host factory for the WIF enabled WCF service. If you want to put a little more work in it you can also make the handler configuration friendly (see here).

In general I’d recommend watching Hervey’s excellent talk from PDC09 about WIF in load balanced environments (e.g. Azure).

HTH


IdentityModel
Friday, February 19, 2010 7:36:26 AM UTC  #   
 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  #