Welcome to MSDN Blogs Sign in | Join | Help

Interview with Mark Russinovich on EDGE

Mark Russinovich had a nice chat with David; check it out here. I really appreciate the practice of annotating the video with the times at which certain topics are touched, that allows me to thumb through things like I'm used to do with text: HUGE time saver!

Ryan was to kind to suggest me to check out the view of the bookshelf on frame at 40.6s, shown below: if you look on the right, between "Windows with C/C++" and the old-style MSDN Universal container, you'll spot a certain well known title :-)

image

Posted by vibro | 1 Comments

Visual Studio web project template for Zermatt... and your CardSpace RP ASP.NET web site is up&running in just 37.1 seconds

You would not believe how often I have to set up identity enabled web sites: for verifying a theory, for proving a point with colleagues, for demos and events... really really often. Vast majority of cases those are barely proofs of concept, nothing elaborated, so I've been working for reducing the overhead that every project entails.

Needless to say, Zermatt has been a miracle balm for this: instead of cut&paste reuse, I finally have a tool with most of the capabilities I need few intellisense steps away. However my laziness knows no boundaries, so I came out with something that's even faster: a Visual Studio template for web sites, which sets up the few knobs that Zermatt needs directly at project creation time. Oh, don't expect anything fancy: this is basically the RP project I walked you through few posts ago. The only difference is that instead of adding references, creating pages, dragging controls and working with the web.config the template itself takes care of that. I am providing the template as attachment to this post: you can just drop the ZIP it in C:\Users\<your user>\Documents\Visual Studio 2008\Templates\ProjectTemplates\Visual Web Developer (or equivalent, if you use another disk/OS) and next time you'll create a new web site with Visual Studio you'll find it under "My Templates" as shown below.

image

Now. ALL possible disclaimers apply for this template, the web site produced is just an example and lacks A LOT of key capabilities that should instead be implemented in an RP; furthermore, it assumes that you'll run the web site on the local IIS and that your SSL binding is using the selfsigned cert that gets installed with Zermatt's samples.

That said: using templates r o c k s. If all you need is creating a PoC, you can have your base RP site up&running REAL fast. How fast? Well, I decided to verify beforehand how long it would take to go from nothing (visual studio not running, no virtual directories, nothing) to being signed in in a newly created CardSpace RP web site. I downloaded a stopwatch gadget, reduced the screen resolution, fired up Camtasia... and timed myself while creating the project & running it. The results are pretty staggering... 37.1 seconds at the first attempt! And I blabbered the entire time, didn't optimize mouse paths, didn't use a monstrously powerful machine... in other words, this is a record you can smash any time if you just try. If you are into exotic accents, or if you don't believe me, you can see the above in action in the 3-minutes video below. Fun!

Windows CardSpace helps Eduserve to fuel DreamSpark authentication

I am sure you are all more than familiar with DreamSpark, the amazing (YES, amazing. Bravo Milo!) offer through which Microsoft gives access to developer & designer tools at no charge. That requires, naturally, to be able to prove that you are indeed a student.

Eduserv is a not-for-profit UK-based organization that focuses on IT solutions for the education sector: their identity management solutions are used by over 4 millions of students from universities in UK & other countries. And here comes the interesting bit: Eduserv wrote an identity management component for DreamSpark integrated with their OpenAthens SP, and based on WCF & CardSpace :-) you can read about this on a recently published case study (word document here).

With all the identity talent that runs abundant in the Microsoft offices in UK (Paul MacKinnon & Planky, congrats!) it is not really a surprise to see that they are ahead of the curve, but it is most definitely a pleasure :-) congratulations to all the people involved!

New Issue of the Architecture Journal: Article on "Claims and Identity, On-Premise and Cloud Solutions"

image

The latest issue of the Architecture Journal is available for download here (I am breaking the news even before the rest of the pages are updated from issue 15 to issue 16: see how much I care about you?;-)).

What makes this especially interesting is that issue 16 is entirely dedicated to identity! I have to admit that I've yet to read most of the articles, but I've definitely went through 2 of them:

Writing for the Architecture Journal is a big honor, as you can see from the list of high profile former contributors, and I am very grateful to Diego for having my article in this issue. Thanks man! And thanks also to Gianpaolo, with whom I had many deep discussions that helped me to keep the abstraction tangents to what i hope is an acceptable level :-)

As usual, if you have feedback feel free to send it my way

Setting up a basic CardSpace RP ASP.NET website... using Zermatt

With few weeks of delay I finally forced in my schedule the conclusion of my little getting started series "... using Zermatt" (links to former episodes: setting up an STS for smartcard-backed managed cards & issuing smartcard-backed managed cards).

The first posts I wrote about Zermatt were all about producing identity info: today we'll take a look at consuming those info, something that will be done a lot more (there are only few mints, but an ocean of ways to spend the money they produce) and, fortunately, is also a dramatically simpler programming task.

Before we go any further: Please. Read. Keith's. White paper. This series of posts is a quick & dirty guide, designed to get you started and to be easily found via search engines when you need a quick lookup: Keith's article is exhaustive & well polished, hence (together with the product documentation) should be your main reference. I am Vittorio Bertocci and I approve of this message (if you don't live in the US, nevermind :-)).

Aaaaalllrighty, back to business. Thanks to the 2 former posts, we have an active STS and its associated managed card. Now we want to write a website which uses that STS for acquiring some info about our users in form of claims. Here the highest order bit is not the security paraphernalia we need to be familiar with when we work at the STS level: when designing an RP, the application biz requirements should be king. Taking that in mind, let's wear our web site dev hat and work backward from the app features to the steps we need for weaving identity capabilities in it with Zermatt. Where appropriate we'll switch to the identirati hat and will comment on the deeper meaning of what we are doing, but I'll try to keep that to a minimum.

Let's say that we are creating the pages of a local tournament of some sport, and we accept subscription applications online. We won't do anything fancy, I just want to show how to receive identity info and apply some logic to it without requiring any true knowledge of the details of the underlying auth technology used. The first step we need to do is creating an ASP.NET website in visual studio (let's call it simply "RP"), and add components & logic to our Default.aspx page.

Let's say that our personalization logic includes welcoming the user by using his/her name and stating in which category he/she will compete. The page layout will contain some text and labels:

image

The logic in the code behind is really really trivial:

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DateTime birthdate;
        string theName;
        int hairlenght;
        
        //...

        lblName.Text = theName;

        if(birthdate>(new DateTime(1998,1,1)))
            lblTournament.Text = "sorry, you're too young to compete";
        if(birthdate<(new DateTime(1980,1,1)))
            lblTournament.Text = "you'll run as Senior";
        else
            lblTournament.Text = "you'll run as Junior";
        if (hairlenght > 5)
        {
            lblWarning.Text = "by the way, you should probably CUT YOUR HAIR!!!";
        }
    }
}

No notion of identity so far. I have three variables, storing the info I need (name, birthdate, ahem.. hair length), some magic for initializing the  (represented by the //...) and the logic for driving the page appearance according to those values. Namely, we instantiate the name in the welcome line and we give details of the tournament category based on the age. I added a silly line about hair length, since when I was young and still more or less fit my various sensei often politely pointed out that my long hair were a disadvantage (they were right).

That's the use we want to do of the identity info (and ultimately the true reason for which we are writing the RP; the identity part is commodity). How do we get those values into our variables? Well, not surprisingly we expect those values to be dispatched to us in form of claims. Zermatt has a nice mechanism that will deliver those claims directly in the current IPrincipal & IIdentity. Yes you read well, it's the classic .NET IPrincipal & IIdentity I am talking about: Zermatt provides derived IClaimsPrincipal & IClaimsIDentity, which are extended with claims capabilities (and other goodies: here I am keeping the info to the base essential, check out Keith's paper & docs for more). Let's add a reference to the Zermatt assembly (Microsoft.IdentityModel), and let's fill in the necessary code to assign suitable claim values to our variables:

// Zermatt "usings"
using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.Protocols.WSIdentity;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DateTime birthdate;
        string theName;
        int hairlenght;
        
        //get ClaimsIdentity
        ClaimsIdentity identity = User.Identity as ClaimsIdentity;

        //get claim values
        theName = (from c in identity.Claims
                            where c.ClaimType == WSIdentityConstants.ClaimTypes.Name
                             select c.Value).Single();
        birthdate = DateTime.Parse((from c in identity.Claims
                                             where c.ClaimType == WSIdentityConstants.ClaimTypes.DateOfBirth
                                             select c.Value).Single());
        hairlenght = int.Parse((from c in identity.Claims
                                    where c.ClaimType == "http://www.maseghepensu.it/hairlenght"
                                    select c.Value).Single());

        lblName.Text = theName;

        if(birthdate>(new DateTime(1998,1,1)))
            lblTournament.Text = "sorry, you're too young to compete";
        if(birthdate<(new DateTime(1980,1,1)))
            lblTournament.Text = "you'll run as Senior";
        else
            lblTournament.Text = "you'll run as Junior";
        if (hairlenght > 5)
        {
            lblWarning.Text = "by the way, you should probably CUT YOUR HAIR!!!";
        }
    }
}

We added a couple of new using directives (beside the default page usings, not shown) for Zermatt namespace, and we added our magic code for

  1. Getting an instance of our special claims-friendly IIdentity implementation
  2. Querying it for retrieving the claim values we need. Here we use Linq, one of the methods that the Zermatt documentation suggests; the other one is a foreach. Personally I like to keep the access logic plumbing hidden, for clarity of code: this can be achieved by simply customizing the principal in the token processing pipeline (see below), perhaps by adding an indexer on the claims type; but that's a matter of tastes.

Is our code ready to run? Not yet. We wrote the code processing the identity info as they come out of our input pipeline: now we need to set up the pipeline itself.

Zermatt introduces an HttpModule, the FederationAuthenticationModule (FAM for friends & close relatives); this is where most of the metamorphosis from token to identity happens. We won't go into details in this post: let's say that FAM loads the necessary logic for deserializing, validating & transforming token info before feeding it to the application logic in form of IClaimsPrincipal. The web site can work with form authentication, and the FAM can be configured to work accordingly. Practically any aspect of the processing pipeline can be customized, however here we'll stick with the defaults as much as possible. The FAM needs to be set up by adding few strategic lines in the website web.config: let's go through those.

<configuration>
    <configSections>
    <!-- Registers the microsoft.IdentityModel configuration section -->
    <section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=0.4.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    <!---->
...
    </configSections>

The first place we modify is the configSections element, where we add the reference to Zermatt's microsoft.identityModel config.

<system.web>
     ...
    <authentication mode="Forms"/>
    <!-- Denies "?", so unauthenticated users are always redirected to the login page. -->
    <authorization>
      <deny users="?"/>
    </authorization>
    
       ...
    <!-- Registers the FederatedAuthenticationModule in classic ASP.NET applications -->
    <httpModules>
      <add name="FederatedAuthentication" type="Microsoft.IdentityModel.Web.FederatedAuthenticationModule, Microsoft.IdentityModel, Version=0.4.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
     ...
   </httpModules>
</system.web>

The system.web element is next. We set up Forms authentication (not strictly necessary for Zermatt), then we add the FAM in the httpModules.

<microsoft.identityModel>
   <serviceCertificate>
     <certificateReference findValue="CN=localhost" storeLocation="LocalMachine" storeName="My"/>
   </serviceCertificate>
   <tokenHandlers>
     <remove type="Microsoft.IdentityModel.Tokens.Saml11.Saml11TokenHandler, Microsoft.IdentityModel, Version=0.4.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
     <add type="Microsoft.IdentityModel.Tokens.Saml11.Saml11TokenHandler, Microsoft.IdentityModel, Version=0.4.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
       <samlSecurityTokenRequirement>
         <allowedAudienceUris>
           <add value="https://localhost/RP/Default.aspx"/>
           <add value="https://localhost/RP/Login.aspx"/>
           <add value="https://localhost/RP/login.aspx"/>
         </allowedAudienceUris>
       </samlSecurityTokenRequirement>
     </add>
   </tokenHandlers>
   <federatedAuthentication enabled="true">
   </federatedAuthentication>
 </microsoft.identityModel>

What we have done before merely inserts the FAM in the ASP.NET pipeline: the section microsoft.identityModel is what actually influences the FAM behavior. The first subelement tells to the FAM which cert shoukd be used for decrypting tokens: typically it will be the same cert that the web site uses for https (if the https binding is active). In this case we are using the selfsigned cert that comes with the Zermatt samples. The last subelement, federatedAuthentication, is used for turning the FAM on and off without having to comment or delete the conf lines.

The tokenHandlers section contains most of the action. In this case we want to accept Saml1.1 tokens, and we are happy with the default token handler (we can write our own, for any kind of token). However if we want to configure it (and we want), we have to remove the default instance and re-add it with our values. Here the only noteworthy config we add is the allowedAudienceUris set; this is a value associated to an element in the SAML token format, AllowedAudienceURI. which is a mechanism for preventing improper re-use of tokens with destinations that are different from the intended receiver: but I promised I'll keep complexity to a minimum, so let's just say that if you don't list a page of your website here the FAM will prevent you to land there. Those Uris are case sensitive, as requested by the associated RFC: keeping that in mind saves you from having to chase unnerving errors. Note that I added a login.aspx page, since we configured the web site to use forms auth (usual right click on the project->add new item..->web form).

 
        The system.webServer section is required for running ASP.NET AJAX under Internet
        Information Services 7.0.  It is not necessary for previous version of IIS.
    -->
    <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
    <!-- Registers the FederatedAuthenticationModule in IIS7 "integrated mode" applications -->
    <modules>
      <add name="FederatedAuthentication" type="Microsoft.IdentityModel.Web.FederatedAuthenticationModule, Microsoft.IdentityModel, Version=0.4.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler"/>
..
    </modules>
  ..
    </system.webServer>
..
</configuration>

The last config piece we add is for our good friend IIS7, which has a special place for HttpModules.

Now the FAM is sitting steadily in front of our web site. Are we finally ready to rock? Nooope. If somebody sends us a token, we are ready to process it: but we are not doing anything for asking the user for a token, nor we are saying anything about which info we need (name, birth date, hair length), in which format or from where.

The login.aspx page is the ideal place to do that; and we can use cardspace for specifying our requirements above. As we know by now, Zermatt comes with some ASP.NET control that can help the developer to add identity capabilities to web pages: in this case we can use the InformationCard control, which gives us both an UI element for starting the identity selector prompt and a way to publish our policies & integrate with the FAM.

Let's go ahead and drag an InformationCard control instance on Login.aspx.

image

You'll note that the look of your control as just dragged is different from the one here: that's because I fiddled with the control properties for changing its appearance. Most properties have a self explanatory name:

image

For example, here I've set the DisplayRememberMe to false.

The most important properties are the ones that influence its behavior: SignInMode, for example, configures the control to create a FAM session with the token it requires or (if set to Single) it can ask for a one-off token without touching the session.

Other properties such as the ones describing the policy requirements (Issuer, IssuerPolicy, RequiredClaims...) can be easily set by using a wizard, which can be accessed by clicking on the right topmost area of the control on the page surface:

image

Remember when at the end of the last episode we obtained a managed card from MySTS? If you saved the file instead of installing it directly, we cal load it here for automatically acquiring issuer information and the set of claims we can obtain with that card (if you didn't, just visit the STS page and follow the generation procedure once more, then save. We had an hardcoded cardID, so the card generation operation should be idempotent if you give the same input).

image

If you hit Load Managed Cards, you'll get the dialog above; once you browse to the crd file of our custom STS, you'll have in all the info about the issuer and we'll be ready to choose the claims we require.

image

Here you can see that all the claims supported by our card are nicely listed. Well, not that nicely, since I've been sloppy and I didn't supply a display name for our custom claim hair length (the system uses the claim URI instead) but you get the point.

Do i need to do anything more? Not really, we are finally ready to test our entire system (web site, STS and generated card); but I want to point out a couple more things before giving it a spin.

The first one is that the InformationCard control, like every other Zermatt control, comes with a collection of events that you can implement for inserting your logic at various stages of the token processing: you can see a list of those below.

image

In this case I implement just SignInError, a practice that I recommend if you want to see details of what goes wrong. For this example  I don't do anything fancy:

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

    }
    protected void InformationCard1_SignInError(object sender, Microsoft.IdentityModel.Web.Controls.ErrorEventArgs e)
    {
        throw new Exception("error signing in, see if you can figure out why: " + e.Exception.Message, e.Exception);
    }
}

As you can see, the code behind is real easy here; everything is handled elsewhere, in the FAM. That's the best way from the architectural standpoint.

The second thing I wanted to point out has to do with the session. Now that our login creates a session, we may want to give to the user a way of explicitly signing out. This is certainly useful when you are developing, and you want to test your logic with different claim values in rapid succession hence you want to get rid of a former session and sign in again with a new claims set. Needless to say, this is brain-dead easy with Zermatt: just go to the Default.aspx page, and drag on it a SignInStatus control.

image

The SignInStatus control hooks up completely automatically to the FAM session. You don't even need to look at the properties, let alone writing code (but you could, if you want to).

OK, enough blabbering: David & co should come to pick me up for curry soon, it's time to close the circle and test if everything works as expected. Let's compile and fire up a browser, and navigate to https://localhost/RP/Default.aspx.

image

Our good old forms auth settings promptly redirect us to https://localhost/RP/login.aspx?ReturnUrl=%2fRP%2fDefault.aspx. Let's click on the information card icon:

image

Do you recognize the only card not grayed out? As expected, it is the one we issued in the former episode. Let's see (by clicking preview) what claims we are required to present:

image

Exactly the ones we were expecting. Right on! Let's click retrieve, we will be prompted to insert our smartcard and type our PIN:

image

image

And here we go! CardSpace shows us the values we required (from the display token), so that we can take an informed decision if we want to share it with the RP.

image

Let's go ahead (those are fake data anyway;-) incidentally the same that we hardcoded in the STS episode) an press send.

image

Oh marvel! The RP received the claims correctly: it welcomes me as Gion, informs me that we'll be in the senior category and gently reproaches me for my heavy metal mane. Observe the behavior of the SignInStatus control: it figured out that it is being instantiated in the context of an active session, hence it automatically adjust the text to "Sign out". Handy!

As promised, we managed to write a simple RP without the need to understand much about underlying authentication technology. Things can be further simplified, as I hope I'll manage to show in an upcoming post, but for now I'd say we can be pretty satisfied already :-)

That's it, this concludes this first three-parts tutorial about Zermatt: I hope it helped to give you an idea of how much easier things can be with this new baby!  I also hope that I'll manage to post more, this time about advanced scenarios, but reality is that I am heads down for PDC. I have a couple of very long flights that I could use for writing while disconnected, though. We'll see :-)

The New York Times on passwords, OpenID, Information Cards Foundation & Kim

I was dividing my attention between the Scrubs special on TV & Digg on my PC, when an article titled "Experts: Passwords May Not Be a Good Online Defense" caught my eye: well, couldn't agree more!:-)

It turns out that the article is from the NY Times, and it's short & sweet hence there's no need for me to summarize it here: Mr. Stross manages to capture the problem pretty effectively, also thanks to some nice quotes from Kim.

 

 

P.S.: I know, I know. I still owe you an RP post for completing the Zermatt intro series started with the STS and card issuance. Keep the faith, it's coming! ;-)

Zermatt & Cloud @ TechEd New Zealand/Australia

image

Well, it's almost one month since I wrote the last "useful" posts: you would not believe how incredibly busy I am on stuff I can't talk about just yet (but soon, very soon).

In this quick update I am excited to report that I am going to speak at TechEd New Zealand & TechEd Australia! As strange as it may sound, the 114 flights I've boarded since I moved to Corp (October 2005) never took me under the equatorial line; furthermore, it's since first grade that I'm told how cool it is that New Zealand is at the exact antipodes of Italy, has roughly a boot shape as well, etc... that's the farthest place from home I can travel to without leaving the planet :-)

I am going to deliver 2 sessions, both in NZ and in AU:

Identity & Cloud Services
(Architecture track, level 300)

The shift towards cloud computing is one of the major trends in today’s IT industry. As resources and assets are increasingly hosted off-premise, traditional strategies for access control and identity management are proving incapable of handling distributed scenarios and cross-boundary communication. This presentation briefly outlines how architectures relying on claims-based identity management, security tokens and open standards can address cloud computing scenarios with the same ease with which they can handle traditional ones. The identity capabilities of Biztalk Services will be featured as a concrete example of an application of the new paradigm.

“Zermatt” Developer Framework: Putting Authentication Code in its Place
(SOA & Business Process, level 300)

The current practice of embedding identity management logic in the application code has led to a generation of software that is brittle, hard to maintain and difficult to use in a service oriented architecture. Rethinking identity management in terms of claims and security tokens eliminates the problem at the root, by externalizing the authentication logic. The “Zermatt” Developer Framework provides developers with a set of classes, tools and controls for building claims-aware applications and Security Token Services (STS). In this session you will learn the essential patterns for authentication, claims-driven behavior, STS use and development, as well as advanced scenarios.

If you follow this blog, expect many of the concepts seen here to be featured as visual studio escapades, slideware and blabbering in a thick Italian accent.

Unfortunately I won't have any time at all to look around, but I do hope that I'll have a chance to breathe some of the atmosphere there and meet a lot of interesting people. Really, really , really looking forward!!! :-)

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 | 2 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