Welcome to MSDN Blogs Sign in | Join | Help

How did you get started in software development?

[I suggest my usual readers to skip this post altogether, you won't find anything useful here :-)]

Romeo tagged me with this "How did you get started in software development?" quest. I was already feeling guilty, because given how swamped I am I knew I was not going to have time to reply to the tag: OTOH right now my main PC is unusable, since I am repaving a new HD on it, hence while the network install goes I can write this up.

How old were you when you started programming? A quale età hai cominciato a programmare?

I was 12. One Christmas parents & siblings joined forces and got me a Commodore16: it was just *fantastic*.

How did you get started in programming? Come hai cominciato a programmare?

With the reference manual of the basic 3.5.

What was your first language? Qual’è stato il tuo primo linguaggio di programmazione?

Basic, the one that came with the Commodore16.

What was the first real program you wrote? Qual’è stato il primo programma vero che hai scritto?

Hard to define "real" here. I would say that the first program I have wrote for a purpose different than pure enjoyment was a control routine for a Siemens PLC. It was for a shop class, we had those PLC working in AWL-step5. Not very structured, but hey... certainly software!

What languages have you used since you started programming? Quali linguaggi hai usato da quando hai cominciato a programmare?

Ah, hard to remember them all. Already mentioned Basic and AWL-Step5. At the University it was mainly Pascal, C and C++; SML was used only for a class, but it had huge impact on my development (and the class was really hard); matlab, if you'd consider it a language; DHTML, or javascript+HTML, as we were used to call it; and Lingo, Macromedia Director's language. Later I worked mainly in C and C++, though I had moments in which i needed Fortran (can you believe that the *column* where you write is important? How vestigial is that???), Java and a bit of prolog. Before joining Microsoft, back in 2001, I almost never targeted Windows: once I got in I promptly got a certification in VB, but i left it immediatly for C#; and of course I had my share of T-SQL, XML, XSLT, XPATH. The above are the languiages I've actually USED; the ones I've just toyed with are way too many to be mentioned here. Eiffel, Caml, objective C... blah blah

What was your first professional programming gig? Quando è stato il tuo primo vero lavoro da programmatore?

I am in doubt between 2 jobs, can;t remeber which one came first. One was the website for a catalog of electronic components, I did both the design and the sheer hml; the other one was a full multimedia CD in Director, for a local military cartography office. Pretty cool :-)

If you knew then what you know now, would you have started programming? Con il senno di poi, rifaresti lo stesso il programmatore? Ricominceresti a programmare?

I would. When it was time to choose which master degree class I wanted to take, I just completed a course on Shiatsu massaging techniques: and I *really* loved it (can't really give too many details here ;-)), hence i was tempted to pick up phisical therapy. And, I have to admit, had I been a rich kid I would have picked up philosophy. But I was not rich, I started working at 15 for helping to pay my studies, and I wanted the most bang for the buck: at the time computer science was hot, and the Genova university was Italy's best (together with Pisa) for the subject. But what started as a calculated choice quickly became a burning passion, and I am really really glad I went that way: I still think it is the best for realizing one's own potential, computer science (and IT) give you countless opportunities of stretching many of your talents.

If there is one thing you learned along the way that you would tell new developers, what would it be?  Se ci fosse una cosa che hai imparato nella tua carriera e che vorresti dire ai giovani programmatori, cosa diresti?

Keep pushing hard. There are times in which you are surrounded by great people, and the quality bar is high; and sometimes you move from those environments to others in which much less is expected from you. Don't allow that to soften you: keep asking the best from yourself, because soon you'll move again in some demanding ecology, and you will wish you used better the extra time. "Make every cut your best cut". 

What’s the most fun you’ve ever had … programming? Qual’è la cosa più divertente che hai programmato?

Hard to say. Since I've learned how to code, circa 92,  it is integral part of my expressivity repertoire: I've done many, many silly things with code since then ;-) this one is perhaps the only one that is safe to point out in public

Now, let’s tag someone else… Adesso è l’ora di taggare qualcun’altro…

Well, I think I'll tag my good friends & colleagues in the neighboring office: David & Ryan. Come on guys, I'm curious :-)

Posted by vibro | 1 Comments
Filed under: ,

2 new great reviews for our book, and status after 1/2 year of availability

It's since April that I don't write about the book (at the time we released the entire Chapter 2 on MSDN). Last week I received notice that 2 new reviews were published: one is from the Denver Visual Studio User Group, the other is on Paul Van Brenk's blog. Both reviews are extremely nice, for which we are very grateful; I especially like the fact that in both cases the reviewers perceived our intention to deal with the problem from an holistic point of view, regardless of our affiliation with a technology or another. Thank you guys! (update: I've just stumbled in another review I didn't know about, on (in)secure magazine issue 17. Niiiiice). In fact, in the last months various illustrious figures mentioned our book as well: David Chappell, Drummond Reed and Francis Shanahan wrote extremely nice reviews I never mentioned here until now, while I did mention the first entries from Kim and Mike. Add that to the podcast on Perspectives, the interview on channel9 with Carlo & Caleb, the podcast on SearchWinDevelopment, the bonus chapter on codeproject, the extremely nice reviews on the Amazon US page... and again, mentions from Neil HutsonAlexander Strauss, Feliciano Intini, Mario Fontana, ... I am sure I am forgetting something (for which I apologize). And now that I begun to hang out at Identity conferences, I can't tell you how pleasant it is to have complete strangers zeroing on you and telling you all sorts of nice things :-) I guess I am easily recognizable after all!

In summary: in the 6/7 months that the book has been available, we received an incredible amount of love about it. Thank you all!!! As always, if you have feedback feel free to get in touch via this feed

Issuing smartcard backed managed cards... using Zermatt

We are back! I hope you had fun with the STS tutorial I posted yesterday night; here we move a step further and examine how to equip our STS with managed card issuance logic & UI.

As anticipated, this is going to be MUCH faster. If you recall, in the last post I asked you not to delete the Default.aspx page that the new web site template created for you: we are going to put our card issuance UI there. At thsi point the visual studio project should look as follows:

image

The only new element I added is the information card image information-card.png, which will be used as the background of the information cards we'll issue. Of course nothing prevents you to get all fancy and allowing the user to upload an image for personalization purposes, but here we want to be quick & dirty (well, at least quick ;-)). The little image is below, for your viewing pleasure.

image

Time to add some UI. Let's open Default.aspx inn the designer and let's drag some controls.

image

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
        Managed Card Generator<br />
        <br />
        Card name:
        <asp:TextBox ID="txtCardname" runat="server" Width="426px">SmartInformationCard</asp:TextBox>
        <br />
        Smartcard certificate thumbprint         <asp:TextBox ID="txtCertthumb" runat="server" Width="301px">xx xx xx</asp:TextBox>
        <br />
        <br />
        <asp:Button ID="btnGenerate" runat="server" onclick="btnGenerate_Click" 
            Text="Generate" />
    
    </div>
    </form>
</body>
</html>

Now: remember that we want to generate a managed card backed by a smartcard. This means that our issued card will need to contain a reference to the certificate of the smartcard that is supposed to be used along with our managed card; in turn, this means that we need to know certain info about that certificate at card creation time. In a realistic scenario it would be reasonable to assume that the identity provider already knows about the certificate: if you think of an electronic ID, chances are that the identity provider is also the entity that emitted and maintains the smartcard & certificates in the first place. In our little example, however, we do not assume prior knowledge hence we require the user to paste in the thumbprint of the certificate at issuance time. Later in the post I will show you how it's done.

Let's move to the real meat of the issuance logic. The method below is fired by the Generate button, and takes care of generating the card bits and sending them down through the http response. Take a look at the code, we'll comment below.

using System;
using Microsoft.IdentityModel.Services.CardService;
using System.Security.Cryptography.X509Certificates;
using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.Protocols.WSIdentity;
using Microsoft.IdentityModel.Services.SecurityTokenService;
using System.IdentityModel.Tokens;
using System.Runtime.Remoting.Metadata.W3cXsd2001;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void btnGenerate_Click(object sender, EventArgs e)
    {        
        X509Certificate2 signingCertificate = CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, "CN=localhost");

        string issuer = "http://localhost/STS/Service.svc";
        string stsAddress = "http://xxxxx.redmond.corp.microsoft.com/STS/Service.svc";
        string mexEndpoint = "https://localhost/STS/Service.svc/Mex";

        InformationCardReference icr = new InformationCardReference("urn:uuid:278725f0-de1b-4126-bf32-04dd396b8490", 1);
        InformationCard card = new InformationCard(signingCertificate, issuer, icr, DateTime.Now);

        card.Language = "en";
        card.CardImage = new CardImage(Context.Request.PhysicalApplicationPath + @"\information-card.png");
        card.CardName = txtCardname.Text;
        card.RequireStrongRecipientIdentity = true;

        card.SupportedTokenTypeList.Add("http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1");
        
        card.SupportedClaimTypeList.Add(new DisplayClaim(WSIdentityConstants.ClaimTypes.Name,"Name","Your first name"));
        card.SupportedClaimTypeList.Add(new DisplayClaim(WSIdentityConstants.ClaimTypes.DateOfBirth,"Birth date","Your date of birth"));
        card.SupportedClaimTypeList.Add(new DisplayClaim("http://www.maseghepensu.it/hairlenght", "Hair Lenght", "Your hair lenght"));

        card.TokenServiceList.Add(
            new TokenService(
                new TokenServiceEndpoint(
                    stsAddress, signingCertificate, mexEndpoint, UserCredentialType.X509V3Credential
                ),
                new X509CertificateCredential(
            new X509ThumbprintKeyIdentifierClause(SoapHexBinary.Parse(txtCertthumb.Text).Value)

                )
            ));

        InformationCardSerializer serializer = new InformationCardSerializer();
        Response.ClearContent();
        Response.AddHeader("Content-Disposition", "attachment; filename=InformationCard.crd");
        Response.ContentType = WSIdentityConstants.InformationCardMimeType;
        serializer.WriteCard(Response.OutputStream, card);
        Response.End();
    }
}

I hope it does not look like a lot of code to you; if it does, I suggest going to take a second look at our old card writer example and I am sure you'll get the full feeling of the giant leap we made with Zermatt :-)

The code is pretty straightforward; in fact, it is a simplification of what the ActiveSTSWithManagedCard sample does (i,.e.: here I hardcode the URIs while the example derives them from the app context). Instead of commenting line by line, which would bore the both of us, below I provide you with a (pretty big) picture which shows how some of the key code lines influence the output in the resulting crd file. Follow the link for the full size version.

image

Note that in real settings you would probably want to keep track of the cards that you issue, especially in relation to users & versions; here the cardid is fixed, hence you will always overwrite cards issued earlier, but in general you want to maintain control over what what issued to whom; besides the stabdard verisoning considerations, this is crucial for handling revocation policies.

All right! Let's give the project a spin and let's see if we manage to get a card.

Navigate to https://localhost/STD/Default.aspx.

image

What should we fill in the "smartcard certificate thumbprint"? Easy. open an mmc console, add the certificates snapin, and pick the certificate you want to associate with the card. Here i use my smartcard, but any certificate for which you have the private key (an dwith the suitable intended usage) will do. Paste it in the textbox, and nevermind about blanks; the parser will take care of everything.

image

If you hit Generate, you'll get to the dialog below: click "Install & Exit", and we are done.

image

We didn't get any error message, which is comforting; but as good skeptics we want to verify that everything worked as expected. if you fire up cardspace form the control panel, you'll see that the card is now part of our collection and that it contains the expected claims.

image

Great! That concludes part II of the tutorial. In the next post we'll finally put all this to good use, by writing a suitable relying party.

Setting up a quick & dirty STS which supports smartcard backed managed cards... using Zermatt

Just back from vacation. The tan barely started to fade, and here I am already playing with the new shiny toy :-). Did you experiment with Zermatt by now? As Kim mentions the samples (and the documentation) are an excellent way to start, and I am sure that blog posts & tutorials will soon start mushrooming here and there in the blogosphere: here I begin my humble contribution with my first technical post about Zermatt.

I had *absolutely* no hesitations when deciding which scenario I should tackle first: an active STS which handles requests backed by smartcards. I received asks about from many segments (especially about eID management from governments and high authentication levels for finance) and pretty much from everywhere in the world (especially Europe and Asia): I am really delighted to finally have a chance to give you something about that scenario that you can compile in visual studio, as opposed to the usual whiteboard sketches :-)

Before we dive into the code, let me disclaim the disclaimable:

  • as usual, the code you see in this blog is just an example and is by no mean production ready code. My purpose here is to introduce you to new ideas, so I favor readability and clarity over completeness
  • If you consider the definition of best practices as "A technique or methodology that, through experience and research, has proven to reliably lead to a desired result", I think I can safely say that there are no established best practices yet. Sure, there are some fixed points (use applyto, always check issuers & revocations, encrypt & sign as appropriate, sanitize everything including incoming claims...) and I am happy to share my experience here, but I think that the "experience and research" of you guys using the product in your business scenarios is what will drive the emergence of best practices. That's why it's so crucial that we get your feedback, and why you should not take what I write here as the golden standard and maintain a healthy skeptical attitude :)

Ooook, let's get to work. We should start by better defining the problem: we want to develop a Security Token Service (STS) that can be invoked via WS-Trust (hence active); furthermore, we want our STS to process request for security token messages (RSTs) that have been secured by using a smartcard. Later we will also want to talk about managed cards, but let's forget about that for the time being.

 

Active STS project structure in Zermatt

What is an active STS in Zermatt? You guessed right: it is simply a WCF service. Zermatt leverages the factory based extensibility model of WCF for hiding much of the protocol heavy lifting, and expects you to weave your custom logic by overriding specific methods in some derivation of a couple of base classes. Sounds complicated? On the contrary. Consider the diagram below:

image

Those four files are the basis for the typical Zermatt active STS project. Let's start from the right and move to the left:

Service.svc and web.config

We mentioned that an STS is a common WCF service: hence, we can describe it via a .svc file and associated web.config. The content of the .svc file will look like the following:

<%@ServiceHost  
    language="c#"
    Factory="Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceHostFactory" 
    Service="MySTSConfig" %>

The Factory element uses WSTrustServiceHostFactory, which is the factory offered by Zermatt for hosting STSes in IIS. The factory generates a service called Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract, whose parameters can be influenced by creating the proper Service entry in the web.config: below there is a snippet of the first few lines of such config settings.

<system.serviceModel>
    <services>
      <service name="Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract"
         behaviorConfiguration="MySTSBehavior">
        <endpoint address=""
                  binding="customBinding"
                  bindingConfiguration="X509Binding"
                  contract="Microsoft.IdentityModel.Protocols.WSTrust.IWSTrustFeb2005SyncContract"/>
        <endpoint address="https://localhost/STS/Service.svc/Mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
      </service>
.....

The Service element of the .svc file points to a custom class, that in the diagram I called STSConfig.

STSConfig.cs

The STS programming model requires you to derive a class from SecurityTokenServiceConfiguration: here we call the resulting subclass STSConfig. The purpose of this class is to gather in a single entity information that must be fed to the factory for instantiate the STS service, namely:

  • intended address
  • signing certificate
  • custom issuance logic

The last element is provided by referencing in STSConfig another custom class, here called MySTS.

MySTS.cs

The custom issuance logic is injected in the system by deriving from (surprise surprise) the class SecurityTokenService, and by overriding two methods: GetScope and GetOutputSubjects. We will see those in details later, however the former performs some validation and prepares some crypto necessary for the issuance while the latter contains the actual claim values retrieval logic.

 

As you can see, this is not complicated at all. Let's go ahead and apply the above for developing our smartcard based STS.

Writing the STS

Let's start by firing up Visual Studio and creating a new web site; I suggest putting it in the local IIS and checking the "Use Secure Socket Layer" checkbox. In this example I called the IIS app "STS".

image

VS will create a Default.aspx page for you: ignore it for now, but don't delete it: it will come in handy in the next post.

We have seen in the former section what are the files that are needed for defining an STS. Let's create those files in reverse order: we will start from MySTS.cs.

Add a reference to System.ServiceUtil and Microsoft.IdentityModel; add the App_Code ASP.NET folder to the web site, and add to it a copy of CertificateUtil.cs (you can find it in the C:\<Program Files>\Microsoft Code Name Zermatt\Samples\Basic\ActiveSTSWithManagedCard sample); then, create the file MySTS.cs.

MySTS.cs

The using blocks, class declaration & constructor look like the following:

using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;

using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.Configuration;
using Microsoft.IdentityModel.Services;
using Microsoft.IdentityModel.Services.SecurityTokenService;
using Microsoft.IdentityModel.Protocols.WSIdentity;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
using System.Linq;


public class MySTS : SecurityTokenService
{
    public MySTS(SecurityTokenServiceConfiguration config)
        : base(config)
    {
    }

Nothing transcendental here. We use a bunch of namespaces, we derive from SecurityTokenService and we just call the base constructor. Then we finally start doing something interesting: remember the overrides I mentioned before? The first one we will implement is GetScope. GetScope takes care of verifying that we are happy with the RP for which the subject is requesting a token. Let's take a look at the code:

    /// <summary>
    /// verifies that the intended RP is one for which we are willing to issue a token;
    /// retrieves the corresponding certificate so that the resulting token can be encrypted accordingly
    /// </summary>
    protected override Scope GetScope(IClaimsPrincipal principal, RequestSecurityToken request)
    {
        //base
        Scope scope = base.GetScope(principal, request);
        //checks if we are happy with the intended RP
        ValidateAppliesTo(request.AppliesTo);
        //retrieves the corresponding cert and embeds it in the scope
        string RPhostname = request.AppliesTo.Uri.Host;
        scope.EncryptingCredentials = new X509EncryptingCredentials(CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, "CN=" + RPhostname));

        return scope;
    }
 

The input parameters are the principal of the requestor (the subject) and the request itself, already nicely deserialized an a handy class (the heroic pioneers of the do-it-yourself STS era can tell you how much code that takes if you have to do it by hand).

Here we mainly want to do 2 things:

  1. we want to make sure that the requested token is scoped for an RP that we like. That means that we need to verify that we have a non empty ApplyTo in the request, and that its content matches one entry in our list of approved RPs. The call to ValidateAppliesTo takes care of it
  2. We want to make sure that the token we will issue will be encrypted for the intended RP: that means retrieving the certificate associated to the RP and assigning it to the EncryptingCredentials element of our current scope. The code that performs this is pretty self explanatory, if a bit crude: we assume to have in our LocalMachine cert store certificates following the convention "CN=RPhostname"

An example of ValidatesApplyTo can be easily obtained from the above mentioned example ActiveSTSWithManagedCard.

Before we move on, let me make a couple of comments:

  • The fact that we mandate the presence of ApplyTo is a good practice, but it is by no mean an universal rule. A non-auditing STS would not need (or even want) an ApplyTo.
  • The cert that goes in EncryptingCredentials here comes from the local cert store; however it is also possible to take the cert that is sent in the request, and use that instead of requiring the corresponding certificate to be present in the local store from a prior time. The tradeoff is, naturally, agility vs. security.
  • Some would advocate that GetScope should contain also the subject authentication logic (that is, if that logic didn't run even before reaching the MySTS class). That makes a lot of sense, and would also justify the presence of the principal parameter; GetScope is the first override that is invoked in the request processing pipeline, hence if the user didn't present valid credentials the sooner we fail the less resources we waste. On the other hand it seems that GetScope is about "validating" the RP, hence putting user auth logic there may be perceived as a side effect. For the clarity vs. completeness tenet introduced above, here I keep GetScope focused on RP related tasks and perform subject authentication elsewhere; however I invite you to ponder the considerations in this bullet point, and make decisions accordingly in your own projects.

The next method is GetOutputSubject: as mentioned, its purpose is to actually fetch the claim values requested. Here there's the code:

 

/// <summary>
/// authenticates the user requesting the token
/// retrieves the values of the requested claims
/// </summary>
public override ClaimsIdentityCollection GetOutputSubjects(Scope scope, IClaimsPrincipal principal, 
    RequestSecurityToken request)
{        
    //verifies that the incoming RST has been secured by one smartcard among the ones we recognize
    AuthenticateCredentials((IClaimsIdentity)principal.Identity);

    //goes through the list of requested claims and retrieves the corresponding values from the stores
    List<Claim> claims = new List<Claim>();
    foreach (RequestClaim requestClaim in request.Claims)
    {
        claims.Add(new Claim(requestClaim.ClaimType, RetrieveClaimValue(principal, requestClaim.ClaimType)));            
    }
    ClaimsIdentityCollection collection = new ClaimsIdentityCollection();
    collection.Add(new ClaimsIdentity(claims));

    return collection;
}

The parameters are the same ones of GetScope, plus the Scope itself.

The first thing we do is authenticating the incoming subject, by examining the incoming principal (for details on the principal-claims structures, see Keith's whitepaper). Here there's the code of AuthenticateCredentials:

  /// <summary>
  ///  verifies that the incoming RST was secured by the certificate associated to the managed card we generated;
  ///  normally this check would be performed against a database, here it's all hardcoded
  /// </summary>
  void AuthenticateCredentials(IClaimsIdentity cert)
  {
      string thumbstring = (from c in cert.Claims
                            where c.ClaimType == WSIdentityConstants.ClaimTypes.Thumbprint
                            select c.Value).Single();
      string savedthumb = System.Convert.ToBase64String(SoapHexBinary.Parse("xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx").Value); 
      if (thumbstring != savedthumb)
      {
          throw new FailedAuthenticationException("The certificate credentials you presented are not recognized.");
      }
  }

This is the first time that we have any technology specific code. Here I assume that the incoming IClaimsIdentity has been created from an X509 certificate; hence I use a Linq expression for retrieving the base64 encoding of the incoming certificate thumbprint (do you have feedback about the logic we use for accessing claims?). The savedthumb assignment line is a terrible hack and a sublime trick at the same time. Here I am basically establishing what is the certificate that I am willing to accept: the way in which I obtain it is 1) going to the certificate MMC, selecting the certificate of the smartcard I am willing to accept and copying the thumbprint string from the cert properties dialog (the "xx xx .." censored string above) and 2) using this arcane SoapHexBinary.Parse method (from the esoteric System.Runtime.Remoting.Metadata.W3cXsd2001 namespace) which chews a hex string and gives back bytes[].

If the 2 thumbprints correspond, this means that the request was secured by using the smartcard I chose hence the user is authenticated. Obviously a real system would have a database of accepted smartcards/soft certificates.

Back to GetOutputSubjects: the central foreach goes through the claims requested in the RST and retrieves the corresponding value. Note that here I don't handle optional claims for the sake of clarity, you can refer to the ActiveSTSWithManagedCard sample if you are curious about it. The retrieving legwork is performed by the helper function RetrieveClaimValue: the code is below.

/// <summary>
/// retrieves the value of a claim associated to a certain principal
/// </summary>
private string RetrieveClaimValue(IClaimsPrincipal principal, string claimType)
{
    //here I would normally use something of the principal for looking up attributes values in one (or more) stores
    //here i ignore it and return hardcoded values
    switch (claimType)
    {
        case WSIdentityConstants.ClaimTypes.DateOfBirth: return "01/30/70";
        case WSIdentityConstants.ClaimTypes.Name: return "Gion";
        case "http://www.maseghepensu.it/hairlenght": return "50";
        default: throw new InvalidRequestException(claimType + " is not a claim issued by this STS.");
    }
}

A real attribute retrieval function would use the principal for querying an attribute store (or more than one) and return the value of the requested claim for that specific user. Here we don't do that, in fact we just have 3 hardcoded values that correspond to 3 claim types. Those claim types are the ones that our STS will support; the first 2 are the common DateOfBirth and Name, the third one is the classic custom claim that I use in every sts sample:  HairLenght. Any request asking for a claim that does not belong to this set of three would get an InvalidRequestException.

That's all: all our custom logic is there, the rest is just infrastructure.

MySTConfig.cs

Create the file MySTSConfig.cs, and paste in it the following:

using System.Security.Cryptography.X509Certificates;
using Microsoft.IdentityModel.Configuration;
using Microsoft.IdentityModel.Services.SecurityTokenService;

/// <summary>
/// Summary description for SecurityTokenServiceConfiguration
/// </summary>
public class MySTSConfig : SecurityTokenServiceConfiguration
{
    public const string issuerAddress = "http://localhost/STS/Service.svc";

    public MySTSConfig()
        : base(issuerAddress, new X509SigningCredentials(CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, "CN=localhost")))
    {
        SecurityTokenService = typeof(MySTS);
    }
}

This is exactly as we described in the STS project structure section: our custom config class assigns a name to the issuer, establishes which certificate will be used for signing the issued tokens and embeds our custom logic by assigning the MySTS type to the SecurityTokenService that will be instantiated by the factory.

Service.svc

Create the Service.svc file and paste in it the lines we already saw:

<%@ServiceHost  
    language="c#"
    Factory="Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceHostFactory" 
    Service="MySTSConfig" %>

web.config

The last piece we need for completing our STS is the service configuration. The web site already has a web.config file: we just need to add a serviceModel section to it, so that we can associate to the Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract service a binding suitable for invoking the service by using a smartcard (or soft cert) as credentials. Below there is the excerpt of the serviceModel section:

<system.serviceModel>
    <services>
      <service name="Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract"
         behaviorConfiguration="MySTSBehavior">
        <endpoint address=""
                  binding="customBinding"
                  bindingConfiguration="X509Binding"
                  contract="Microsoft.IdentityModel.Protocols.WSTrust.IWSTrustFeb2005SyncContract"/>
        <endpoint address="https://localhost/STS/Service.svc/Mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <bindings>
      <customBinding>
        <binding name="X509Binding">
          <security authenticationMode="MutualCertificate" />
          <httpTransport />
        </binding>
      </customBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MySTSBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceCredentials>
            <serviceCertificate findValue="localhost"
                     storeLocation="LocalMachine"
                     storeName="My"
                     x509FindType="FindBySubjectName" />

            <issuedTokenAuthentication allowUntrustedRsaIssuers="true" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Looks familiar? It should. It is pretty much the same config we were using with the simpleSTS.

Next steps

We are done! The steps above were enough for setting up a fully functional, albeit simple, active STS which authenticates request for security tokens secured via smartcard/soft certificates. Now we need to test it: in the next couple of posts we will

  1. Add UI and logic for issuing cards associated to this STS and backed by smartcards
  2. Create an RP that will require tokens from our STS

As you can imagine, both tasks are going to be much easier that the already semi-trivial tutorial described in this post. At the end of the series I'll probably post as attachment the complete solution.

Well, that was FUN! Would you have ever imagined that one day we would say that about writing an STS? ;-) hehehe

John Fontana on Zermatt

I am sure you already saw Kim's post about John Fontana's interview with Stuart, appeared on Network World. I like how John communicates the importance of this release, and how it positions it in the context of the broader picture. Recommended reading :)

Also, the blogosphere is buzzing: if you toy with your favorite feeds or search engines, you'll find many sources chiming in or even already playing with Zermatt... that's the spirit! See you next week ;-)

Posted by vibro | 1 Comments
Filed under: ,

Announcing the Beta release of “Zermatt” Developer Identity Framework

Ahh, I’ve been looking forward for this post for a looong time.

We just made available for download the bits of the Beta of “Zermatt” Developer Identity Framework. “Zermatt” is the codename of a .NET framework that helps developers build claims-aware applications to address challenging application security requirements using a simplified application access model.

Let me expand a bit on that. If you want to develop applications that take advantage of claims & identity Metasystem goodness in general, Zermatt makes your life easier by providing base classes, controls but especially capabilities & a programming model that take care of most of the plumbing for you. Regardless of the role (IP, RP, subject) or the style (Active, Passive, “Passive-Aggressive”), Zermatt shields you from the sheer handling of protocols & tokens and provides you with a great model for externalizing your access logic. For my loyal readers and in general to whoever worked with tokens and cardspace in general, who stormed me with mails since the TechEd EMEA demo and even earlier: this means that we can finally retire historical samples like the SimpleSTS and the TokenProcessor class. Zermatt is a fully supported developer framework that gives you those capabilities and MUCH more. How much more? Below there’s a partial list of the goodies you get:

· An HttpModule (the Federated Access Module, or FAM) that takes care of handling the token processing pipeline: fully extensible & web.config-urable, it exposes programmable events for every relevant step in the authentication lifecycle

· A new claim model, which unifies token & principal programming models achieving direct reuse of some classic access control techniques (IsInRole, PrincipalPermission) without requiring a rewrite

· Visual ASP.NET controls which take care of enhancing web pages with capabilities such as: information card signin and one-off information card requests, passive signin, session management and passive STS capabilities. All of those include comprehensive property management a and a rich events model

· Full control of session management: intended audience, pages whitelist, session duration, custom session tickets, etc

· A unified token handling model that works across ASP.NET and WCF applications alike

· Base classes for authoring STS, which handle automatically historically tedious tasks such as RST & RSTR parsing

· Native support for handling information cards: serialization, deserialization, issuance. Integration with the STS programming model for simplifying the development of cardspace-ready STSes

· Delegate authentication. Applications can now request new tokens on behalf of their callers, greatly simplifying three tier architectures and enabling a whole new class of scenarios

This is only a partial list. For a more in-depth coverage of Zermatt capabilities I invite you to read this excellent paper from Keith Brown, which introduces you to the basic concepts behind claim based identity management and describes Zermatt object model with samples and walkthroughs.

Needless to say, I’ll blog about this every single time I’ll have a moment. Once I’ll be back from vacation, we’ll also get a surprise guest on channel9 for hearing directly from the engineers who brought us Zermatt.

Finally, this is the tool that can help developers to experience directly the power of claim-aware applications. I invite you to download Zermatt and use it as much as you can: as you know this world is very new, and we’d really like feedback, feedback, feedback. Feedback on what works, what doesn’t, what you’d like to see, what you accomplished with it… we love every bit :-) the place for sending us your feedback & discussing Zermatt is the forum at this address.

Summary:

· Get Zermatt bits from here

· Discuss here & give feedback here

· Read Keith Brown paper about Zermatt here

Congratulations to the Zermatt team for a great beta of a new breed of products!

And now… back to the beach ;-) see you in a week!

New home for Windows CardSpace on microsoft.com

image

One year ago we had a brief wall-to-wall exchange with Keith about the need of having consumer (as non-developer) info about CardSpace. The Information Card Foundation is doing a great job at handling those info for the general concept of information card. Specifically for Windows CardSpace,  I am happy to announce that we now have a consumer friendly home for Windows CardSpace! I am especially fond of the two videos (home & work) from the UK crew; and big kudos to Eileen for the entire effort. Take it to a spin and let us know what you think!

 

Note to self: How come that I'm blogging more when I am in vacation than when I am working? Long flights & jetlag, I guess... ;-)

How often should you ask for a token?

On the Seattle-Paris flight. I've just posted the piece about validation-authentication-authorization, and i am a bit bothered by the fact that I was unable to delve into greater details for what concerns the authoriZation part. In particular, I'd like to address one of the misunderstandings which can derive from transporting verbatim the knowledge of Kerberos & "unattended" security in general to the world of user centered identity management. Some of you claimaniacs may find the stuff below pretty obvious: I do. But judging from some heated argument I had about this, it may turn out that it is not that obvious after all so it's worth to write it down.

How often should your application ask for a token? It may seem a silly question, and you may be tempted to reply with the answer that my wife gets when she asks to her auntie how often she should turn the roast: "as often as needed". Not the most actionable answer, I'm sure you'll concur :-). As in good tradition, let's take few steps back and look at the bigger picture.

When you sit at your workstation and log in your domain, if your local network uses kerberos you get your nice ticket granting ticket (TGT); from that moment on, every time you take a ride on your network carnival (access a share, a portal, a printer...) the network software takes care of using the TGT for getting a ticket for you, which is specialized for the resource you are accessing. Everything happens seamlessly, and the user is lulled in blissful ignorance of those frantic exchanges (that is, until you don't stumble on a resource that you can't access) thanks to the benevolent tyranny of the KDC on every account & resource in the domain.

Let's now consider a web site. The user signs in through an entry point, where he is authenticated; but a successful authentication does not mean that from now on it's a all-you-can-eat buffer, every single operation will still undergo authorization decisions before being performed. Maybe there's premium content that is reserved to users who pay more; maybe you're a reader role for a certain portal, which grant you readonly access but clicking on the "edit" links would result in access denied. In a traditional web site, those decisions would usually derive from the user information kept in the profile (the famous "answers" described in the Tao of authentication). By now we know that thanks to claims (&, by extension, tokens) the profile is no longer the only place we can turn to for answers, since we can obtain claims with just-in-time answers directly from trusted sources. However, that doesn't mean that the strategy described for kerberos would be the best way of leveraging tokens in this case. The key point is that here we deal with an heterogeneous system, where different authorities come into play and boundaries have to be crossed: in this scenario obtaining a token means that the user is called to make an explicit decision and perform steps such as reviewing the info requested and authenticating with the IP of choice. In the example made in the former post, we required the signin token to contain both a http://.../PPID and http://.../age; however, it is possible that only http://.../PPID was strictly needed for a successful signin. The age claim may come into play at some later moment in the session lifecycle, for example when the subject attempts to access the trailer of a PG-13 movie. Does that mean that we should have just asked for PPID at signin, and that we should ask for a new token now? If you are used to non-interactive systems, such as backend 2 backed communications, you'd probably reply "yes"; however I would urge you not to underestimate the "interaction costs". How likely is that during the session the user will attempt an access that entails an age verification? If the probability is high, one could say that the application needs the age info for working properly hence it makes sense to ask for it at signin time even if the actual authorization check will be performed at some later time. Besides minimizing costly cross boundary calls, this avoids to anesthetize the subject by asking too often its explicit consent and helps to understand what info the application works with; otherwise we risk training the user to click trough the process without paying attention.
This holds if we expect http://.../PPID and http://.../age from the same issuer, of course. If the former would come from a personal card and the latter from an IP, I would not advocate to force the user to pick all the tokens at signin time: besides leading to a confusing experience (I know others beg to differ here ;-) since we're both guessing...), it would not optimize roundtrips and it may even not be compatible with some business model (if the IPs charge you for the tokens they issue, asking for more claims form the same issuer would save money; asking for more tokens upfront may result in charges that are not justified if you end up not ever performing the operation that would have required the extra tokens).

Bottom line: when the owner of the resources relies on information from external authorities for deciding if a subject should be granted access, it is a good idea to (whenever appropriate) consolidate the acquisition of those info in order to minimize cognitive overhead for the user & crossboundary authentications (while maintaining full user control, of course).

Once I decide ask those "extra claims" at sign in time, verifying their presence in the incoming token becomes responsibility of the authentication phase; the reason for which I require those claims, the fact that they will be later used for authorization purposes, does not change what I have to do for authenticating the token.

Alright, that takes care of the easy case: but what should we do when we do have to ask for a new token besides the sign in token, like when we need further assurances from a different IP? That would be out of the scope of this post, which would be satisfied from the mere recognition that we do have situations in which we have to do it. Anyway, I don't think there can be hard & fast rules on how your app should metabolize the new claims; that would depend on the meaning that the operation has in the context of your application. If you are requesting assurance that the subject has enough money on his account for buying something, incorporating such a claim in the session may not be an especially intelligent idea: if you requested that info for authorizing a purchase, the amount in the account changed as a consequence of it and the claim "UserCanBuy$1000Item==true" may not hold anymore. If you are requesting to know if the user is not married, so that you can give write access to the personal ads, you can merge the new info with the claims you already received at signin time and be reasonably sure that the situation won't change for the duration of the session. In any case, regardless of the transience of the claims, IMHO every incoming token should be processed through the validation-authentication-authorization with the same separation of concerns we pinpointed for the signin token, without succumbing to the temptation of shortcuts "because it's just authorization".

Alrighty, more and more abstract... it must be the low pressure in the cabin :-) But please don't flip the "philosopher" bit on me just yet, all of the above have very concrete aspects that I'll eventually demonstrate in this feed

Validation, Authentication, Authorization: mangling tokens for your dark purposes

Flying back from S.Diego, after attending a great edition of Catalyst. I should probably write down my impressions before they fade, like it happened with the IIW, but there's in fact something (only mildly related) that bugged me for quite some time and I just want to flush it out of my system before going in vacation (somehow I feel that my old time Italian friends would not appreciate me blabbering about tokens, especially if I do it with my mouth full of focaccia al formaggio :-)).

Ok, the story is somewhat similar to the "credentials are not identities" and returning user woes discussed in the Tao of authentication: it's a matter of agreeing on the semantic of terms that in the pre-token era had a simpler meaning, but that today need a richer/more rigorous definition. In summary: in practice, what RPs and STSes are supposed to do with incoming tokens? 

The answer lies in asking ourselves why we asked for a token in the first place. Perhaps the RP wants to see if the subject is allowed to sign in and start a session; an STS wants to know if the subject is worthy of being issued with the token he is requesting; and again, the RP may want to verify the the user has the necessary rights for performing a certain action (one may argue that this is a generalization of the signin case; I sort of agree, but later I'll make things more complicated). Even if we'd live in a world fueled only by shared secrets, there would be different cases to handle. If the RP is a simple password-protected file, verifying that the subject knows the password would suffice; no user store to look up, no identity (hence the term blind credentials). Would you call that "authenticating the user"? I wouldn't, because in that case there's no user to speak of; or perhaps I would, since in fact all possible users are divided in 2 big categories: the ones who know THE password (singular), and the ones who don't. If you want, it's like with earthworms: there are many of them, but they're all identical down to the cellular level hence you could say that there is only one earthworm (I suspect I am getting confused with some other species, but you get the idea). And so much for my promise of being more concrete.

If the RP is something slightly more complicated, like pretty much any website that grants some degree of customization or resources that are associated to specific users (think mailbox), all of the sudden we have to handle a list of username-password couples; that entails FIRST to look up if the incoming username exists in the list, THEN if the provided password happen to match with the corresponding one the list (hey kids, don't store passwords in clear :-) this is just pour parler). As I argued in one Tao, the lookup & password check are TWO distinct actions and in this case they just happen to be conflated in a single movement given the nature of the credential mechanism (shared secret). I won't bore you with a detailed historical analysis of how things went that way; let's just say that overloading the username (mnemonic moniker often used for human interactions, such as chat nickname) with the function of index for the user database happened to be the path of least resistance, but it could have gone in a different way. For example, the fact that the username must be unique is a consequence of that conflation but should not be assumed as the only possible practice. Just imagine if in real life we would be forced to have unique names: I would *really* not be thrilled to be called Vittorio_12345, and neither would you. When institutions needed to associate a record with me, they just created an index for the purpose; codice fiscale, social security number, costco membership number... all stuff that can be used as part of the credential mechanism, and that should not circulate beyond that purpose (just think of the horrible mess of having a number of institutions all deciding to use the SSN as the key for locating your record; welcome to unintendedconsequencesland).

Now that we see that there's no spoon, we can move to consider serious tokens (the ones with decent crypto capabilities). Tokens have this interesting <claims list-credentials> dual nature, which makes them handy for rewriting a better physics of identity but also offers more opportunities for confusion. Let's consider a website RP that requires for signin a token as follows: SAML 1.1 format, issued by http://myissuer, containing the claims http://.../age and http://.../PPID (for the sake of argument, let's say that the RP accepts only users who signed up at a certain moment in the past: for signing in, you must be a returning user. This makes our scenario closer to the familiar case, but later we'll relax this assumption and venture in uncharted territory).

The incoming token is the material component of our credential verification mechanism: what do we need to do for ensuring that we should let the user in? Let's try a (incomplete) list:

  1. check that it is a valid (well formed) SAML 1.1 token
  2. check that the signature is still OK (nobody tampered with it)
  3. check that it contains the 2 claims we asked for (http://.../age and http://.../PPID)
  4. check that the issuer is http://myissuer
  5. lookup in the DB the value in the http://.../PPID claim

If all checks work OK, we can let the user in. As I mentioned, this is really incomplete (where is AudienceRestriction?) but it is enough to make a couple of observation. For example:

  • 1. and 2. are operations that we can perform regardless of the context (or better, even before getting to know that there is a context). It's a bit like asking a jeweler to estimate if the stone you have is a diamond: he can do that even if he doesn't know what you want to do with the diamond. In fact he really does not care if that's an appropriate gift for a 20 years anniversary, all you can expect from his estimate is "this is a fine stone, worth X" or "sorry, this is no diamond".
  • 3. and 4. are associated with a context, those are requirements we are imposing; nonetheless, they still seem to have to do with well-formedness. If 1 and 2 are the moral equivalent of verifying that an XML doc is valid XML, 3 and 4 are the moral equivalent of verifying that it matches a schema; still something we can expect the infrastructure to lend a hand, but the responsibility of providing the requirements is on us.
  • 5 is something that is really dependent on our infrastructure. Here we have chosen the PPID; we may have chosen the email as well. Furthermore: this operation can be independent from the token structure, or even from the fact that the value we lookup has been received in form of claim (provided that you keep claims separated from credentials).

How to tie the sequence above to the title of the post? I think we can have a lot of arguing here (trust me been there, done that :-), so I'll go straight to my take:

  • I would call 1 and 2 validation. Those are the steps that just verify that the caller is respecting the game rules of the specific credentials technology we are using. Is this a well formed, non tampered SAML? Is this X509 token a projection of a cert that was not revoked?
  • I would call 3, 4 and 5 authentication. Why? Because those are the info I need for determining if the subject belongs to the category I am interested into. In this case, the category I am talking about is users that are able to obtain from http://myissuer tokens containing http://...age and http://..PPID, and that used such a token in the past to sign up with me

I should be able to expect the validation to be performed entirely by the infrastructure. I should expect significant help from the infrastructure for the authentication operations, too, but i have to be prepared to do my part and at a minimum describe the category I am interested into.

Now: let's say that I want to relax the condition that imposes the subject to be a returning user; as long as you can present a token with the right features & from the right issuer, I'll do business with you even if I never saw you before. That models much more closely what happens in meatspace, I don't see bartenders searching for my name in a huge phonebook-like tome when I ask for a gintonic: who cares if I showed up before, or if I'll never go back there? Anyway, the above sequence still works beautifully: we just get rid of step 5. And finally this allows me to close the circle. When you use passwords, looking up the moniker-password couple in the database seems like a validation because of the nature of the credential mechanism: but if we'd extend that view to other token types, we'd lose the separation of concern that we achieved by having the validation as a context free operation and the authentication as something driven by our requirements. And doing that would be equivalent to build a geometry model of triangles that's biased toward the case of segments as degenerate triangles: we should have a theory that correctly predicts the behavior of triangles even in the degenerate case in which they are a segment, but IMHO it is a mistake to assume that every triangle is a segment and then struggle for predicting its behavior. OK, that was really abstract, but I hope you see what I mean; i understand the need of forcing username/password credentials in the tokens system, despite their lame single claim (username; which IMHO is not even a valid claim, since it is part of the cred mechanism and non-descriptive, but ignore this last parenthesis), but I am always worried when its special characteristic are generalized beyond their boundaries.

I started writing this on the flight from S.Diego to Seattle, and I am finishing it from the NW lounge in Seattle waiting for my flight to Paris (and the Genova: vacation!!!). In 20 mins I have to board, so I have to wrap up. I purposefully left out authorization, because it deserves a post (actually, many) by itself: anyway, let me add one small thing about it. Once could say that the value of the claim age is something that influences the ability of a subject to sign in and start a session, hence thta would belong to the authentication realm; OTOH you could also think that starting a session is an operation by itself, and as such it needs to be authorized. For that reason I would advocate that the validation-authentication sequence above is unchanged, and the check of values of claims would be performed at a later stage of the pipeline that takes care of authorization. That would allow you to reuse exactly the same pipeline even when you are asking for a token for authorization reasons, as opposed to starting a session (think home banking application, which asks for a certain token for starting a session and prompts for another token with higher assurance levels just for authorizing a certain operation beyond a given threshold). However for this last part I am more malleable and happy to discuss, that's a complicated space and there's still a lot to be figured out.

Alright, vacation time! I'll probably still write something on the plane, but in general I won't be too active in the next 2 weeks: be patient if your comments don't show up immediately or I won't respond to comments quickly. ;-)