Friday, August 28, 2009

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

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

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

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


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

Patterns & Practices - Claims based Authentication & Authorization Guide

Summer break is over – and exciting times lie ahead.

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

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

Watch this space!


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

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

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

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

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

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

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

HTH


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

Claims Authorization in Geneva Beta 2 - Introduction

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

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

This typically leads to code like this:

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

or

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

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

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

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

That’s how you could construct the corresponding AuthorizationContext:

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

and

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

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

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

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

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

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

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

        return true;
    }
}

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

First you need to configure the authorization manager in config:

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

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

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

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

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

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

or

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

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

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

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

The same mechanism is also used for SecurityTokenHandlers btw.

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

<claimsAuthorizationManager type="type">

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

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



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

Defeating SSL

Not a really new paper – but definitely recommended reading.

Some lessons learned:

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

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

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


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

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

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

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

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

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

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

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

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

(thanks to shawnfa/stefsch)


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

Identity Metasystem Interoperability Version 1.0

The IMI spec is now approved. Grats!

Read more here and get the spec here.


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

Partial Trust ASP.NET in 4.0 (Advanced Scenarios)

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

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

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

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

You register the resolver using the following config element:

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

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

HTH


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

Partial Trust ASP.NET in 4.0

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

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

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

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

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

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

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

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

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

[assembly: AllowPartiallyTrustedCallers]

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

            return File.ReadAllText(filename);
        }
    }
}

HTH


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

Updated Starter STS

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

As always – feedback is welcome!

http://startersts.codeplex.com


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

.NET Access Control Service Talk from Troopers09

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

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

_


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

Writing Custom Attribute Stores for Geneva Server (B2)

This document appeard on the connect site. Interesting.

_


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

Worker Process Accounts in IIS 7.5

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

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

That’s an interesting account.

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

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

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

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

 Thursday, May 28, 2009

Geneva Framework Quick Tip: How to access Configuration

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

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

ServiceConfiguration config = new
  ServiceConfiguration(ServiceConfiguration.DefaultServiceName);

HTH


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

Geneva Framework Quick Tip: Hosting a Security Token Service

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

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

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

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

 

HTH


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

Starter STS Screencasts

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


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

Thinktecture Security Token Service Starter Kit

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

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

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

Some features:

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

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

Download STS Starter Kit Sample.
Download Setup&Overview Screencast


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

Use Geneva Session Management for your own needs

Geneva Framework is a Framework is a Framework.

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

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

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

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

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

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

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

        return incomingPrincipal;

    }
}

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

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

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

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

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


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

Thinktecture WS-Federation Metadata Generator

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

More info here.


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

.NET 4.0 Security

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

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


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

More Geneva Beta 2 Changes

Just came across this document. Interesting read.


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

Geneva Beta 2 Update: ClaimsPrincipalHttpModule

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

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

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

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

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

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

HTH


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

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

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

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

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

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

Find a sample implementation below:

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

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

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

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

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

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

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

        return _samlIssuer;
    }
}



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

Die Information Card Foundation DACH-Initiative

Mehr Infos hier

 

 


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

Sod This!

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


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

Fixing Token Kidnapping

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

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

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

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


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

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

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


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


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


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

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

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

Tag 1

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

Tag 2

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

Tag 3

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

Tag 4

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

Tag 5

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

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

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

Durchführender Veranstalter ist DevelopMentor.

 

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

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

 Friday, April 03, 2009

PPID Information and Generation Examples

This article provides useful information on generating interoperable PPIDs.


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

Custom Principals in WCF with Geneva

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

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

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

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

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

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

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

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

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

    public string CustomPropery { get; set; }
}

Afterwards register this class in the ServiceAuthorizationBehavior.

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


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

Client Generated SAML Tokens to Interact with the Access Control Service

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


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

Get Skilled or get 0wned

Nice claim for a conference ;)

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

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

http://www.troopers09.org


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

Geneva integration into ASP.NET

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

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

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

The core logic is as follows:

AuthenticateRequest

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

EndRequest

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

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

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

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

 

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

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

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

HTH


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

Geneva integration into WCF

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

The high-level goals are as follows:

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

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

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

 

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

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

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

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

HTH


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

The authentication logic and filtering could be implemented like this:

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

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

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

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

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

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

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

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

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

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

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

  return element;
}

 

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

That’s it. HTH

ClientSamlCredential.zip (450.94 KB)

 


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

Custom WCF Credential Types

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

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

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

Setting Key Identifiers in Geneva

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

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

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

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

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

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

HTH


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

Host Headers, SSL and WCF Metadata

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

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

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

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

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

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

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

HTH

(Rich: marked as answer)


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

UAC flawed in Win7?

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

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


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

SQL Data Services Query Injection

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

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

Do you see a problem here?

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

foo" || "" == "

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

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

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

HTH


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

Get help running a partial SSL website in ASP.NET

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

Read his post here.


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

Welcome Richard Blewett

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

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


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

Live ID and Information Cards

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

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


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

Federating with Live ID (using the Access Control Service)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Response.Redirect(request.RequestUrl);
}

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

 


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

Display Tokens & Geneva

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

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

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

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

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

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

 

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

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


    return new DisplayToken(requestedDisplayTokenLanguage, displayClaims);
}

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

 

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

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

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

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

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

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

 

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

LeastPrivilege.IdentityModel2 Preview

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

What’s inside?

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

Merry Xmas!

 


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

Final Release of InfoCardSelector on Codeplex

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

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

Have fun!


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

ASP.NET Security Goodness

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

Get more info from Mark and Barry.

CAT.NET V1 CTP

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

32 Bit / 64 Bit

 

AntiXSS 3.0 Beta

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

download

 

AntiCSRF

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

Codeplex

 

Have fun!


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

Federating with the .NET Access Control Service

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

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

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

 

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

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

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

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

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

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

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

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

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

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

HTH


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

Downloading the Certificate from an SSL Site

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

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

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

       
        return new X509Certificate2(ssl.RemoteCertificate);
    }
}

HTH


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

Using the .NET Access Control Service with Geneva

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

Justin did two talks about it at PDC:

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

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

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

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

For your service this means the following:

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

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

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

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

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

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

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

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

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

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

class AccessControlServiceSaml11SecurityTokenHandler : Saml11SecurityTokenHandler
{
    string _solution;

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

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

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

        return identities;
    }
}

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

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

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

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

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

 

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

Let’s say our configuration should look like this:

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

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

 

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

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

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

    _solution = solutionAttr.Value;
}

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

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

HTH

 


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

LeastPrivilege.IdentityModel v2

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

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

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

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

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

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

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

This allows me to write code like this:

var principal = Thread.CurrentPrincipal.AsClaimsPrincipal();

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

 

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


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

T-Mobile Web’n’Walk & Vista 64

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

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

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

HTH


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

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

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

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

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

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

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

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

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

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

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

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

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

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

host.Open();

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

SupportingUserNameToken1.zip (39.91 KB)

 


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

(SAML) Token Creation in a Geneva STS

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

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

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

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

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

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

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

Again you can override any of these methods.

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

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

HTH


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

Geneva HTTP Modules: ClaimsPrincipalHttpModule

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

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

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

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

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

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

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

Sample: ClaimsHttpModule.zip (8.5 KB)

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

 


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

ClaimsAuthenticationManager in Geneva

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

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

A simple claims authentication manager could look like this:

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

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

        return new ClaimsPrincipal(id);
    }
}

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

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

HTH


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

Username/Password Validation with Geneva

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

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

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

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

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

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

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

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

        return new ClaimsIdentityCollection(id);
    }

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

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

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

 

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

HTH


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

Code Contracts in .NET 4

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

See the PDC video here - and  more here.


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

Geneva is the new WCF Security

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

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

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

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

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

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

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

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


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

Geneva is the new Zermatt (and much more)

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

You can download all the new bits here.

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


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

Token Kidnapping (revisited)

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

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

Quoting from the recommendations page of the original slide deck:

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

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

Getting rid of the .svc Extension in IIS

Jon posted a module that does this.

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

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

 

HTH


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

CardSpace is…

I often get the Question: “What is CardSpace?

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

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

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

Related questions are:

What is a card?

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

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

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

That’s it.


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

MSDN Article about WCF Service Authorization

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

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


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

Certificate-backed InfoCards and Service Credential Negotiation

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

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

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

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

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


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

ASP.NET Controls and Output Encoding

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

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


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

Zermatt: Source Code for FormsAuth STS

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

HTH

 


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

P2P and WCF: Some Troubleshooting Resources

These are helpful resource when troubleshooting P2P:

Checking cloud status:
netsh p2p pnrp cloud show list

Checking Teredo status:
netsh int teredo show state

Enabling ping over P2P

P2P Traceroute

PNRP Debugging Guide

PNRP and WICN on Server 2008


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

Zermatt: Using Forms Authentication in a Passive STS

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

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

My sample issuing page looks like this:

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

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

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

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

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

        ProcessFederationMessage(principal);
    }
}

HTH


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

How to build a Development/Test/Demo CA

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

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

 

Basic Installation

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

 

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

 

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

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

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

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

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

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

HTH


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

Most important bug fix in 3.5 SP1

BradA says:

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

VanceN says:

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

Grats for fixing this bug!

 

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


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

WCF Claims to "Zermatt" Claims Migration Story

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

OK hold on - some background info.

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

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

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

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

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

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

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

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

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

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

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

Here's my answer:

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

Frankly - this sucks.

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

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

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

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

 

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


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

Try "Zermatt" and give Feedback

The last week I spent some time exploring parts of the "Zermatt" framework - some things are really cool - some I have mixed feelings about.

The team is still in a quite early stage where design decisions and directions are (re-) considered. Since "Zermatt" is the main Microsoft identity framework we have to live (and work) with for the next years, take you chance to shape it!

I have already started some discussions, so feel free to contribute.


IdentityModel
Friday, July 18, 2008 7:35:37 AM UTC  #   
 Friday, July 11, 2008

CLR Security Site on Codeplex

The CLR security team has a site now on Codeplex - Shawn has all the details here.

Good stuff!


For Your Favourites | FX Security
Friday, July 11, 2008 6:15:18 AM UTC  #   
 Wednesday, July 09, 2008

Skiing in "Zermatt"

Today, Microsoft finally announced the first public version of their .NET identity framework code named "Zermatt". The most important things you get from this framework are:

  • APIs for the token/claims related heavy crypto lifting
  • Supporting classes for claims aware applications (including an IIdentity/IPrincipal implementation to give you a common programming model and smooth migration path)
  • ASP.NET plumbing for accepting tokens in web applications
  • ASP.NET controls for adding Information Card support to web applications
  • OM for creating Information Cards
  • Framework and base classes to write security token services (for active and passive scenarios)

If you have already started looking into claims based security, this framework extends the concepts found in System.IdentityModel and makes it much easier to exploit the full power of token/claims based security systems. See here for the official announcement.

You can download the bits and a good whitepaper (written by Keith) here:

https://connect.microsoft.com/site/sitehome.aspx?SiteID=642

Stay tuned ;)


IdentityModel
Wednesday, July 09, 2008 10:38:23 PM UTC  #   
 Wednesday, July 02, 2008

Using IdentityModel: Useful Extension Methods for Serializing Claim Sets

As a follow up to my last post - the following extension methods make it easy to manually serialize claim sets:

public static XElement Serialize(
  this ClaimSet set, IEnumerable<Type> knownTypes)
{
    DataContractSerializer dcs = new DataContractSerializer(
        set.GetType(),
        knownTypes,
        int.MaxValue,
        false,
        true,
        null);
   
    MemoryStream ms = new MemoryStream();
    dcs.WriteObject(ms, set);
    ms.Seek(0, SeekOrigin.Begin);
   
    return XElement.Load(new XmlTextReader(ms));
}

 

public static XElement Serialize(
  this IEnumerable<ClaimSet> claimSets, string rootName,
  string rootNamespace, IEnumerable<Type> knownTypes)
{
    XNamespace ns = XNamespace.Get(rootNamespace);

    return new XElement(ns + rootName,
                    from cs in claimSets
                    select cs.Serialize(knownTypes));
}


IdentityModel
Wednesday, July 02, 2008 9:13:54 PM UTC  #   

Re:MVP

Quoting Brian:

"Microsoft has decided I didn't cause too much trouble over the last 12 months so I get to continue being a {0} MVP. Thanks!", "Developer Security"


Misc
Wednesday, July 02, 2008 8:53:58 PM UTC  #   

Using IdentityModel: Serializing Claim Sets

Both Claim and ClaimSet are decorated with DataContract/DataMember attributes. This means they are made for serialization. And this makes sense - maybe you want to forward a claim set (server to server) or send a claim set from server to client (UI authorization).

But you will most likely run into problems when trying to serialize a claim set using the DataContractSerializer.

Known Types
DCS needs to 'know' all types that are involved in the serialization process. This involves every type in the inheritance chain down to ClaimSet (e.g. DefaultClaimSet or my DeferredLoadClaimSet) as well as all possible resource types. You either supply the known types via attributes/config (KnownType and ServiceKnownType).

Or you supply the types when newing up the DCS manually:

DataContractSerializer dcs = new DataContractSerializer(
    typeof(ClaimSet),
    new List<Type> { typeof(DefaultClaimSet), typeof(UIClaimResource) });

 

Circular References
Typical claim sets will have circular references - e.g. when the last issuer in the chain points to himself. DCS is not made for cyclic reference - but rather object trees (at least with the default settings). When you are trying to serialize objects with cyclic references you will get the following exception : "type contains cycles and cannot be serialized if reference tracking is disabled.". In WCF traces you will see something like "message not logged because its size exceeds configured quota".

When newing up a DCS you can opt for "preserving object references". This will create ID/IDREF pairs in the serialized XML and allows for type references and thus cycles. (Aaron has an explanation of how that works).

DataContractSerializer dcs = new DataContractSerializer(
    typeof(ClaimSet),
    new List<Type> { typeof(DefaultClaimSet), typeof(UIClaimResource) },
    int.MaxValue,
    true,
    true,  // preserveObjectReferences
    null);

 

This is fine when you can control the DCS parameters. But you can't easily do that in WCF. Sowmy has a sample on how to enable reference preserving in WCF. This will solve the problem!

[OperationContract]
[ReferencePreservingDataContractFormat]
ClaimSet GetClaims();

 

3.5 SP1 to the Rescue!?
Starting with 3.5 SP1 you can enable reference preserving on a DataContract like this:

[DataContract(Namespace = "...", IsReference = true)]
public abstract class DeferredLoadClaimSet : ClaimSet

 

But there are two problems with this approach:

  • You actually need access to the DataContract to change the attribute. In the claims case - you would need to change the framework's DefaultClaimSet or your own ClaimSet-derived class.
  • Every DataContract in the inheritance chain needs the IsReference attribute - otherwise you will get the following error: "Derived types must have the same value for IsReference as the base type". Since all custom claim sets ultimately derive from ClaimSet - but this DataContract has no IsReference set, we are back to square one.

 

Conclusion
Keep these things in mind when serializing claim sets:

  • supply all involved types as known types
  • Set preserveObjectReferences to true on the DCS. The new attribute on DataContract in 3.5 SP1 is nice - but does not help with claim sets. Use the [ReferencePreservingDataContractFormat] attribute instead (find the code here).
  • Reference preserving adds ID/IDREF attributes to the resulting XML. These attributes come from a Microsoft namespace. This may be a problem for interop scenarios. If you need full control over the XML, either use the DCS extensibility points for manual serialization, or don't use the DCS at all (and use one of the alternative message generation mechanisms). Another option would be to use a more standardized serialization format for claims like a SAML token.
  • WindowsClaimSet and X509CertificateClaimSet are not marked with [DataContract] at all - they are not intended for serialization.

HTH


IdentityModel
Wednesday, July 02, 2008 8:00:28 AM UTC  #   
 Sunday, June 15, 2008

PowerShell Profile

Putting these three things (and a little bit of this) together - you can build a very nice profile script for PowerShell ;)


Work in Progress
Sunday, June 15, 2008 2:44:38 PM UTC  #   
 Thursday, June 12, 2008

Advanced Extensions to IIS 7 Configuration

Great article about IIS 7 configuration extensibility:

http://learn.iis.net/page.aspx/241/configuration-extensibility/

Especially infos about the COM backed extensions are hard to find elsewhere...


IIS
Thursday, June 12, 2008 10:55:59 PM UTC  #   
 Saturday, June 07, 2008

Software Architect 2008

Thanks to everyone who attended my IdentityModel talk at Software Architect.

You can have all the code I showed you during my talk - just send me a private message or leave a comment. Most of the demos are online anyways - have a look at my IdentityModel micro-site.

Questions and feedback are more than welcome. Happy identity-ing.


Conferences | IdentityModel
Saturday, June 07, 2008 4:44:43 AM UTC  #   
 Thursday, June 05, 2008

Writing IIS 7 Manager Extensions

Good walkthrough here:

http://learn.iis.net/page.aspx/441/understanding-ui-extension-authoring/


IIS
Thursday, June 05, 2008 9:16:30 AM UTC  #   
 Wednesday, May 28, 2008

SQL Server Security Best Practices

Bob wrote me an email as a response to this post. He also directed me to this whitepaper he wrote about SQL Server Security. Interesting read!


For Your Favourites
Wednesday, May 28, 2008 8:39:37 AM UTC  #   
 Monday, May 26, 2008

OpenID Phishing Demo

Funny and educational:

http://idtheft.fun.de/


For Your Favourites | IdentityModel
Monday, May 26, 2008 8:02:32 PM UTC  #   

System Accounts and SQL Server 2005

I recently ran into a strange situation - I was expecting an "access denied" but it didn't happen (yes - security guys are strange people ;). Here's the long story:

I was writing some test code for LINQ to SQL (see here) in ASP.NET. Since this was on a freshly installed box I was expecting an access denied since I hadn't created a SQL login for Network Service yet. But it worked - I could successfully query (and update) data in all databases. Shock.

After some investigation I found the reason for this behavior. Since I was using SQL Express, the SQL instance was running as Network Service (the default). Furthermore setup creates a Windows group for SQL Server service accounts (e.g. MACHINE\SQLServer2005MSSQLUser$...) and puts Network Service in there. It turns out that this Windows group is mapped to a SQL login with a server role of sysadmin...

This means (on my machine) that all SQL clients running as Network Service (or can get an impersonation token for that account) have sysadmin privileges in the SQL Server installation. Or more generally - when a client can use the same Windows account as SQL Server itself - it will get sysadmin privileges

I thought I might point this out, since running SQL Server and ASP.NET as Network Service seems to be a pretty common configuration.

The moral of the story: Always create dedicated service accounts for SQL Server (or every service you install).

btw - the full blown SQL Server installation specifically asks you for the account to use (but also gives Network Service as a choice).


Work in Progress
Monday, May 26, 2008 11:26:37 AM UTC  #   
 Friday, May 23, 2008

Avoid unhandled Exceptions in WCF Error Handlers

The IErrorHandler interface in WCF allows to write some central error handling code that gets invoked whenever an unhandled exception bubbles up from your service. There are two methods to implement:

  • ProvideFault - called on the request thread to turn the exception into a fault message
  • HandleError - called on a separate thread for error logging and the like

While WCF tries its best to shield the service host from all kinds of error conditions, there are some situations where unhandled exceptions can hurt your hosting process. One of them is the HandleError method on IErrorHandler.

HandleError is called on a background thread to allow doing (kind of) lenghty operations without impacting the request where the error originally occurred. If you have an unhandled exception in HandleError the normal CLR rules for excpetions in background threads apply - which means shutting down the process. Be careful here.


WCF
Friday, May 23, 2008 8:26:30 AM UTC  #   
 Sunday, May 18, 2008
 Thursday, May 15, 2008

Two important Security changes in .NET 3.5 SP1

Shawn details the two big security changes in .NET 3.5 SP1 on his blog:

We have discussed both changes internally - and I have mixed feelings about them. I guess the most important thing to be aware of is, that they are not opt-in changes. By installing SP1 - the behavior will change automatically - if you like it or not.


FX Security
Thursday, May 15, 2008 6:53:45 AM UTC  #   
 Wednesday, May 14, 2008

Improved IisRegMgmt

Thanks to CarlosAg from the IIS team, I was able to improve my tool for registering IIS 7 management modules.

IisRegMgmt01.zip


IIS
Wednesday, May 14, 2008 6:34:10 AM UTC  #   

P2P and WCF: The PeerName Tool

To play around with peer name registration and resolution, I wrote a little tool that makes this easy (yes - I know all this functionality is also available via netsh - but I wanted something more specialized).

Registering

Resolving

PeerName.zip (27.31 KB)

 


WCF
Wednesday, May 14, 2008 6:03:31 AM UTC  #   
 Monday, May 12, 2008

Using IdentityModel: Tracing

While reading through some of the code of System.IdentityModel, I noticed that there is some diagnostics tracing going on. Just add a trace listener for the source 'System.IdentityModel' to your config file.

HTH


IdentityModel | WCF
Monday, May 12, 2008 5:28:09 PM UTC  #   
 Friday, May 02, 2008

P2P and WCF: Some Resources

If you want to know more about P2P and its related protocols and components, here's a list of online resource I found useful while researching:

Have fun!


For Your Favourites | WCF
Friday, May 02, 2008 4:09:01 AM UTC  #   
 Thursday, May 01, 2008

P2P and WCF: Exposing a Service

The last post explained how to find a PNRP registered service. What else do you have to do for e.g. exposing a WCF service over the P2P infrastructure?

Code-wise nothing. If the WCF service listens on all NICs (the default), a client can do a resolution via the peer DNS name and connect to it. Easy.

Well - hold on - does that mean that arbitrary clients can now traverse my NAT and connect to my intranet machine? Kind of - yes...

For the service to be accessible you also have to adjust firewall rules:

  • the port the service is listening on must be openend (this will allow normal TCP/IP traffic to the endpoint)
  • to allow Teredo traffic to the service, additionally the "allow edge traversal" option must be checked. This option is only available via the advanced firewall (available via Administrative Tools or MMC). See screenshot:

So to recap - these are the prereqs for a globally reachable service:

  • P2P (PNRP and Teredo) must work properly
  • the service must be registered
  • the client (or peer) must know the peer name
  • the endpoint port must be opened in the firewall
  • Teredo traffic must be allowed for this port

But one thing is very true, you now allow (internet) inbound traffic to an intranet hosted service, which has some implications:

  • there is probably no security around that intranet machine (like a DMZ).
  • intranet machines are typically not hardened for exposing internet services.
  • this means that if the service has some security problem (e.g. directory traversal etc), there are no safe-nets that will stop an attacker e.g. accessing other machines or system resources.
  • your administrators may not like this!

Typical P2P scenarios don't necessarily involve publicly known peer names, so you maybe only have a limited exposure. But still - the traffic bypasses perimeter security and goes directly into the intranet. So be careful.

 


WCF
Thursday, May 01, 2008 9:26:52 AM UTC  #   

P2P and WCF: Finding a Service

After you have registered a service, the next step is to find it again. The System.Net.PeerToPeer API includes a PeerNameResolver class which does that.

You input the peer name and get back the registration details (IP addresses, port, comment and data):

static void Resolve(string name)
{
    PeerNameResolver resolver = new PeerNameResolver();
    PeerName peerName = new PeerName(name);

    Console.WriteLine("Resolving {0}...", peerName);
    Console.WriteLine();

    PeerNameRecordCollection results = resolver.Resolve(peerName);

    if (results.Count == 0)
    {
        Console.WriteLine("No records found.");
        return;
    }

    int count = 1;
    foreach (PeerNameRecord record in results)
    {
        Console.WriteLine("Record #{0}\n", count);
        Console.WriteLine("DNS Name: {0}", record.PeerName.PeerHostName);

        Console.WriteLine("Endpoints:");
        foreach (IPEndPoint endpoint in record.EndPointCollection)
        {
            Console.WriteLine("\t Endpoint:{0}", endpoint);
        }

        count++;
    }
}

The way you will resolve peer names more commonly is via the DNS format (the PeerHostName property in the above code). A peer name also has DNS name representation (e.g. foo.pnrp.net for an unsecured service named foo). Whenever you use this format (e.g. with ping or any other application that does DNS name resolution), Windows will use the P2P APIs internally to return the corresponding IP address). See here for the details.

This e.g. means that you could make a registration on a web server for port 80 and can use the browser to directly connect to the web server using the DNS format name.


WCF
Thursday, May 01, 2008 6:43:10 AM UTC  #   

P2P and WCF: Registering a Service

To make a service discoverable using the P2P infrastructure, you first have to do a so called peer name registration.

A peer name registration has the following properties:

  • a name (there are two different flavours: secured and unsecured - more on that later)
  • one or more IP addresses and scope
  • a port number
  • a comment (optional)
  • up to 4KB of binary data (optional)

Peer Name
The name of the service you want to register. Names have the following format: 'authorityId.Name'. Unsecured Names use a '0' as the authorityId and are easy to spoof/squat. When using a secured name, a key/pair is generated on the fly (the first time only) to sign the registration request. The public key hash becomes the authorityId in this case.

IP addresses and scope
That's the most fascinating (and complicated) part. The peer name registration can have local and/or a global scope. A global scope means that the service can be discovered and contacted - well - globally. How can that work, given the service is behind a NAT device? IPv6 is the answer.

Now you may ask yourself: "but my network/router hardware is not IPv6 enabled, can this still work?". Yes it does - making the transition between IPv4 and IPv6 is the job of so called transition or tunneling protocols. Teredo is the name of the protocol that is typically used here. Teredo has several jobs - one is to provide a globally unique IPv6 address, the other is to enable NAT traversal. I won't go into the Teredo details here, but this document describes how it works.

When you do a 'ipconfig' on the command line you may already see a bunch of IPv6 addresses. The one that is directly associated with your NIC is the local address. You may also see a "Tunnel Adapter" interface - that would be the global Teredo provided address.

You can check the status/health of the Teredo protocol by using this command: 'netsh int teredo show state'. This article helps you with troubleshooting if Teredo should not be enabled on your machine.

You can also have a look at the scope of your registration by checking the clouds to which your machine has access. This is done by doing a 'netsh p2p pnrp cloud show list'. You should see one or more LinkLocal_ clouds and a Global_ cloud.

Again this article has all the details on clouds and their background.

So to wrap it up - by default a peer name registration will use all available NICs/IP addresses. If you have a global IPv6 address (which means that Teredo is working properly and you can 'see' the global cloud) this one is used also. This in turn means that the service can be used by every client that also has a global address.

The remaining properties are self explaining I think.

The following code snippet would register a secured peer name in all available clouds (you can find the APIs in the System.Net assembly (v3.5):

private void Register(string name, int port, string comment)
{
    PeerName peerName = new PeerName(name, PeerNameType.Secured);
    PeerNameRegistration reg = new PeerNameRegistration();
   
    reg.PeerName = peerName;
    reg.Port = port;
    reg.Cloud = Cloud.Available;
    reg.Comment = _cl.Comment;

    reg.Start();
}

The next posts will deal with peer name resolution and how to host a WCF service over this infrastructure.


WCF
Thursday, May 01, 2008 5:42:58 AM UTC  #   
 Wednesday, April 30, 2008

P2P, PNRP, Teredo...the Motivation

Since I started playing around with computers, communication of machines over a "wire" has been fascinating to me. This is probably why I ended up in the distributed applications space.

Typically clients talk to servers and servers to servers - but less common clients directly to clients. But applications like MSN Messenger or Skype show useful use cases of client to client communication. With Vista and Server 2008 (and XP SP2 + some components) peer to peer networking has become part of the operating system. There is also a peer channel in WCF that sits on top of these core components. Time to have a closer look.

So what features is the P2P infrastructure supposed to give you?

  • Global/local registration of services
  • Global/local connectivity between peers which includes the capability to traverse NAT devices
  • Global/local virtual broadcasting networks
  • Peer/Service Discovery
  • Invitation/activation of P2P enabled applications

All of these capabilities are as fascinating as they are scary. More importantly I really think that P2P communication patterns will be a "big" thing and will also change the way we have to think about network/perimeter security.

In the next posts I will write about some of my findings. Stay tuned.


WCF
Wednesday, April 30, 2008 6:18:56 AM UTC  #   
 Monday, April 28, 2008

Using IdentityModel: Converting ADFS Security Properties to Claims

This little helper might be useful when you are working with ADFS, but want to use the IdentityModel types in your app:

public static ClaimSet ToClaimSet(this SingleSignOnIdentity identity)
{
    List<Claim> claims = new List<Claim>();

    claims.Add(new Claim(identity.NameType, identity.Name, Rights.Identity));

    foreach (SecurityProperty property in identity.SecurityPropertyCollection)
    {
        string claimType = property.Uri;
        if (claimType.EndsWith("NameValue"))
        {
            claimType = property.Name;
        }

        claims.Add(new Claim(claimType, property.Value, Rights.PossessProperty));
    }

    return new DefaultClaimSet(ClaimSet.System, claims);
}


IdentityModel
Monday, April 28, 2008 5:39:21 AM UTC  #   
 Tuesday, April 22, 2008

Ein Session Abstract ganz genau nach meinem Geschmack

Gesehen auf der JAX2008 Webseite:

Security Last – Sicherheitsentscheidungen spät treffen
Sicherheitsanforderungen wie Logins und Berechtigung sind wichtig – aber müssen diese wirklich gleich am Anfang umgesetzt werden? Das nachträgliche Hinzufügen dieser Anforderungen mit reinem Java und OOP ist sehr schwierig, weshalb dies meistens mit „Ja“ beantwortet wird. Erfahren Sie hier, wie mithilfe von Tools wie Spring Security, AspectJ und CAS auch spät in Anwendungen integriert werden kann.

Ohne Worte...

 


Microsoft Deutschland Security Portal
Tuesday, April 22, 2008 11:49:20 AM UTC  #   
 Sunday, April 20, 2008

Token Kidnapping

Interesting...and shocking.

Read more here:
http://www.argeniss.com/research/TokenKidnapping.pdf


For Your Favourites
Sunday, April 20, 2008 7:15:28 AM UTC  #