Security Briefs

Step-by-Step Guide to InfoCard

Keith Brown

Code download available at:SecurityBriefs05.exe(125 KB)

Contents

InfoCard Interactions and Protocols
Considerations for Relying Parties
The Notepad Service
InfoCard-Enabling the Notepad Service
Exploring InfoCard Without WCF
Winding Down

In my April 2006 column I began a discussion of InfoCard, the upcoming identity metasystem, which is being prepared for release in the Windows Vista™ timeframe. If you haven’t read that column, you should definitely start there because I’m going to assume you’re familiar with the basics I covered. This time around, I’ll go deeper into how the identity metasystem works, and write a service that relies on InfoCard for authentication.

A number of you sent me questions after reading the April column, so I’d like to clarify some things before drilling deeper. Technically, InfoCard is only one part of the identity metasystem: it’s the identity selector—the front-end GUI that’s displayed to the user. I tend to use the term InfoCard to refer to the metasystem as a whole simply because it’s a heck of a lot easier to say, and I think it sounds more concrete.

The identity selector being implemented by Microsoft will first surface in the Windows Vista operating system. If you saw any PDC 2005 talks, you most likely saw the identity selector in action. But InfoCard will be available on earlier versions of Windows® as well, including Windows XP. And Microsoft has made it clear that it wants to work with other operating system vendors to provide tips on designing secure identity selectors for their platforms as well. If InfoCard is to be successful, it needs to be very widely deployed, and not just on Microsoft® operating systems.

Some of you also asked for clarification about Security Assertion Markup Language (SAML), which is a standard that specifies the shape of a credential (or token, in WS-* terminology), as well as a protocol for passing these credentials around. InfoCard can use many types of tokens, including SAML tokens; self-issued cards happen to use SAML 1.1 tokens, for example. While SAML tokens are fairly common in InfoCard, WS-Trust is the protocol that is used to obtain and exchange tokens. The SAML protocol is not used by InfoCard.

What about folks using the Java language to build Web services? Back in August 2005, Ping Identity, a major player in the SAML space, released a Java toolkit for writing server-side applications that interact with InfoCard. It was released as a work in progress, but when it is finished, according to the toolkit documentation, it should be possible to build Web services (on top of Axis) and servlet-based Web applications that can request and handle all kinds of InfoCards from InfoCard-enabled clients.

And finally, InfoCard is not the "Son of Passport" that some in the media seem to fear. Passport is a single identity system and, as such, naturally fits into the metasystem as one of many technologies available to InfoCard users. But unlike the old days when Passport was being positioned as the only identity system you’d ever need on the Internet, today Microsoft is proposing a metasystem that allows the user to choose the identity technologies that make sense for her. Passport works well for accessing Microsoft properties like MSN®, but as an InfoCard user, that’s the only context in which I’ll be using Passport. My friends will tell you that I was never a big fan of Passport, but I am really excited about InfoCard, and you should be too!

InfoCard Interactions and Protocols

In the April column I talked about three InfoCard players—the subject, relying party, and identity provider. Most Web developers who need to add support for InfoCard to their Web services and applications will be acting as a relying party, so I’ll focus on that role here.

Figure 1 is an interaction diagram from "A Guide to Integrating with InfoCard," which you can get from the Microsoft download center. It illustrates how a user can authenticate with a service using InfoCard. In the diagram, you can see the identity provider (the relying party), which is a Web service, and the subject, which is the user. The client app the user is running is also shown for clarity.

Figure 1 InfoCard Interaction

Figure 1** InfoCard Interaction **

The first thing to notice is that in order to use InfoCard the user must first enroll with an identity provider. That’s the out-of-band step shown by a dashed line in the figure. It could be as simple as creating a self-issued card on her own machine using the InfoCard GUI, in which case the identity provider is right on the user’s machine. Alternatively, the user might obtain an InfoCard from a standalone identity provider. A newly issued InfoCard is an XML document that can be transmitted to the user via e-mail, Web download, and so forth. There is no required protocol for how the identity provider authenticates the user or issues the InfoCard.

Once the user has one or more cards, the required protocols move into action. When the user runs an InfoCard-enabled application that makes a request of an InfoCard-enabled Web service, the first step is for the app to determine what type of identity and channel security the service requires. This is shown as the first round-trip to the service (Steps 2 and 3 in Figure 1). The protocol used here is WS-MetadataExchange, often referred to as WS-MEX, or just MEX.

The application now invokes the identity selector (Step 4), passing in the policy retrieved from the service. The identity selector pops up a secure GUI showing the user a collection of cards that would work for the given policy (Step 5). This is primarily governed by the type of token and the type of claims required by the service.

If the user has never used this service before, InfoCard will display the service’s and issuer’s certificate logos, giving the user a chance to visually verify that he’s talking to the right Web service so he doesn’t give away identity details to an imposter.

Once the user selects a card to send (Step 6), the identity selector initiates a behind-the-scenes conversation with the identity provider that issued the card. First there’s a MEX exchange (Steps 7 and 8), where the provider’s security policy is discovered so that the exchange can be properly secured. This also tells InfoCard how the user is supposed to prove his identity to the identity provider. For example, if the provider requires a password, the identity selector will prompt the user for his password. Now a WS-Trust request is sent to the identity provider (Step 9). This request includes the user’s proof, such as the password as in the example. It also includes the ID of the card, which allows the provider to figure out which account is being accessed. Also included is a list of requested claims—the identity details that the Web service wants.

Assuming the identity provider can validate the user’s password that was sent, it will now construct a security token for the user to send to the service. This token will contain all the claims the service requested. If the service requested the user’s street address, that address will be included in the token. Remember that the original list of cards shown to the user included only those that support the claims being requested. Note that a password is just one of several ways an identity provider can authenticate the user. Other techniques include using a certificate, Kerberos credentials, or a self-issued InfoCard.

WS-Trust is the core protocol around which InfoCard is built. It is basically a credential exchange (or more technically, a security token exchange) protocol, and is implemented by what is called a security token service (STS). The most common type of STS is an identity provider like the one shown in Figure 1. In Steps 9 and 10, the user’s password is being exchanged for a signed set of claims from the identity provider’s STS.

Now the identity provider signs and encrypts the token and sends it back to the InfoCard identity selector (Step 10) along with some key material that can be used by the client application to prove that it obtained a legitimate token from the identity provider. This key material is known as proof of possession.

When the identity selector receives the token and proof of possession, it decrypts the token and shows the user one final GUI. This allows the user to see exactly what identity data is going to be sent to the service. If the service requested the user’s street address, the actual street address will be displayed to the user. Figure 1 doesn’t show this particular interaction, but it’s an important one for the user. Once the user gives his final blessing by pressing Send, the identity selector returns to the application (finally!) giving it the token and proof of possession it needs to authenticate with the target service. As you can see, there’s a lot going on under the hood when you select an InfoCard. Fortunately, if you’re a client or service developer, you don’t have to worry about building any of this infrastructure.

At this point the application makes its request to the target service using WS-Security to send the token along with a signature formed via the proof-of-possession key material (Step 11). The user has now been authenticated and the service has the claims it requested and can use those claims to make authorization decisions and carry out the user’s requests.

It’s possible and even likely that WS-SecureConversation might be used at this point to set up an efficient secure channel for an ongoing conversation between the application and the service, but that’s beyond the scope of the InfoCard specification.

Considerations for Relying Parties

As a relying party, the first thing you’re going to need is a certificate to identify your organization. This is the beacon type identity that I discussed in my previous column. A large percentage of secure Web services today already use certificates to enable secure sockets layer (SSL), so this shouldn’t be a significant barrier to adoption of the technology.

What is a bit new is that this certificate needs a name that represents your organization, not your URL (as in an SSL certificate). It also should include logo images for both the issuer and subject, following the guidelines in RFC 3709. Each image isn’t physically embedded in the certificate; rather, it’s linked to avoid making certificates even bigger than they already are. The logotype extension includes a URL that points to an image on the Web. It also includes a cryptographic hash of that image. The hash is embedded in the certificate to allow the program displaying the logo to ensure that the image hasn’t been modified since the certificate was issued.

Another major consideration is the type of identity information (claims) you’ll request of your users. InfoCard has already defined several claim types that will cover the needs of most applications, but this list can be extended by third-party identity providers that serve other types of claims. The current list is shown in Figure 2. To form the full Uniform Resource Identifier (URI) for each claim, append its suffix to schemas.microsoft.com/ws/2005/05/identity/claims. You’ll see these URIs in policies exposed by InfoCard-enabled services. This is the way you specify the identity expectations your service places on its users.

Figure 2 Claim Types Defined by InfoCard Profile

Claim URI Suffix
First name givenname
Last name surname
E-mail address emailaddress
Street address streetaddress
Locality name or city locality
State or province stateorprovince
Postal code postalcode
Country country
Primary/home telephone number homephone
Secondary/work telephone number otherphone
Mobile telephone number mobilephone
Date of birth dateofbirth
Gender gender
Private personal identifier privatepersonalidentifier

Many Web services don’t need any personally identifiable information at all, and you shouldn’t ask for anything you don’t absolutely need. With InfoCard, a great way to start is by simply identifying the user with a Private Personal Identifier (PPID). This is communicated as a base64-encoded byte array. In my own tests this value has been 32 bytes long, but its definition doesn’t include a length, so don’t rely on this. As an example, a self-issued InfoCard will generate a unique PPID for each target service based on the card’s unique ID, the service’s public key, and a random salt value. The PPID alone is not considered personally identifiable information, so it’s a great way to associate your own data with a user while preserving her anonymity. I’ll show an example shortly.

The Notepad Service

Microsoft support for InfoCard rests entirely within Windows Communication Foundation today. It is surprisingly easy to add InfoCard support to a Web service, making that service into a relying party. It’s really just about selecting the appropriate binding, and you can do it all with a configuration file if you want.

Figure 3 shows a Windows Communication Foundation Web service with a contract called INotepad. This allows a user to leave herself a note by sending the SetNote message, and lets her retrieve that note later via the GetNote message.

Figure 3 Notepad Service

The Contract

[ServiceContract] public interface INotepad { [OperationContract] string GetNote(); [OperationContract] void SetNote(string data); }

The Service Code

public class Notepad : INotepad { static object _lock = new object(); static string note = ""; public string GetNote() { lock (_lock) return note; } public void SetNote(string newNote) { lock (_lock) note = newNote; } } class Program { static void Main(string[] args) { try { ServiceHost sh = new ServiceHost(typeof(Notepad), new Uri("http://localhost:8080/notepadService")); sh.Open(); Console.WriteLine( "Listening. Press <enter> to quit the service."); Console.ReadLine(); sh.Close(); } catch (Exception x) { Console.WriteLine(x); } } }

The Configuration File

<configuration> <system.serviceModel> <services> <service type="InfoCardSample.Notepad"> <endpoint address="http://localhost:4123/notepadService" contract="InfoCardSample.INotepad" binding="wsHttpBinding" bindingConfiguration="myBinding"/> </service> </services> <bindings> <wsHttpBinding> <binding name="myBinding"/> </wsHttpBinding> </bindings> </system.serviceModel> </configuration>

Figure 4 shows the corresponding Windows Communication Foundation client code. Because the client dynamically discovers the service’s binding requirements via WS-MEX, there’s no need for a client-side configuration file in this app. If you build and run this code, you’ll quickly see a flaw in the design. It works fine as a scratchpad for a single user, but as soon as two or more users invoke the service, they begin stepping on each other’s notes. By adding InfoCard support, I’ll ensure that each user gets a personal storage area for notes that no other user can see. I’ll do this without requiring user registration or any personal information.

Figure 4 Client Code

using System; using System.ServiceModel; using System.ServiceModel.Design; using Microsoft.InfoCards; using InfoCardSample; class Client { static void Main(string[] args) { try { if (1 != args.Length) { Console.WriteLine("Usage: client \"string to send\""); return; } string url = "http://localhost:8080/notepadService/mex"; ChannelFactory<INotepad> factory = findService(url); INotepad chn = factory.CreateChannel(); displayNote(chn.GetNote(), "Old"); chn.SetNote(args[0]); string newNote = chn.GetNote(); displayNote(chn.GetNote(), "New"); // Clean up factory.Close(); // close the client’s channel } catch (Exception x) { Console.WriteLine(x); } } static ChannelFactory<INotepad> findService(string addr) { MetadataResolver mexProxy = new MetadataResolver( new EndpointAddress(addr)); foreach (ServiceEndpoint serviceEndpoint in mexProxy.RetrieveEndpoints()) { if (serviceEndpoint.Contract.Name.Equals( typeof(INotepad).Name)) { return new ChannelFactory<INotepad>( serviceEndpoint.Binding, serviceEndpoint.Address); } } throw new Exception( string.Format("Couldn’t find INotepad at address {0}", addr)); } private static void displayNote(string note, string desc) { Console.WriteLine("{0} note: {1}", desc, null == note ? "<<NULL>>" : note); } }

The majority of typing you’ll do will be in the service configuration file. You’ll need to tell Windows Communication Foundation where to find its certificate. You’ll also need to advertise what sort of security token you want from your clients and what claims you expect to see in that token. For this application, I allow my clients to remain anonymous, choosing to rely on a PPID claim. I let clients use the self-issued identity provider, which issues SAML tokens.

It may seem odd to authenticate clients that will remain anonymous, but it’s really no different than the way a typical bulletin board works today. When you create an account, you supply a user name and password. The user name is pretty meaningless; keith3425 doesn’t give the board a clue as to how to get in touch with me. But the password allows the site to ensure that it’s the same person logging in each time.

InfoCard makes this type of service very easy for users. There’s zero registration required; because PPIDs are unique for each site, the user can simply create a single card that she uses at all anonymous sites like this. She doesn’t have to go into that familiar loop of attempting user names until she finds one that hasn’t been used already. You can think of her user name as being replaced by a PPID, which is generated automatically by InfoCard. She also doesn’t have to generate and manage yet another password. A strong key will be generated dynamically to use with the service.

The biggest drawback to using self-issued tokens is that they can be a hassle if the user works on multiple machines. Eventually, a third-party identity provider will be able to centralize the user’s identity so that it can be used from any machine. In the future there may even be portable STS hardware devices that you can carry around and plug into your computer’s USB port. This would make self-issued cards more portable and secure.

InfoCard-Enabling the Notepad Service

Enough talk; let’s do it. The first step in InfoCard-enabling the service is to obtain and install a certificate. I’m going to use the one that came with the InfoCard Resource Kit that shipped back in September 2005. The logos in it are configured to point to GIF files in a virtual directory at localhost/ServiceModelSamples. I’ll supply a batch file to get the certificates and logos set up for you if you’re following along with the code sample.

Figure 5 shows the updated service configuration file. Note that the references to the Fabrikam certificate are required because it’s used to authenticate the service to the client application, allowing the client app and service to negotiate security for their communication channel. Also, it’s used to authenticate the service to the identity provider.

Figure 5 Updated Service Configuration File

<configuration> <system.serviceModel> <services> <service type="InfoCardSample.Notepad" behaviorConfiguration="MyServiceBehavior"> <endpoint address="http://localhost:4123/notepadService" contract="InfoCardSample.INotepad" binding="wsHttpBinding" bindingConfiguration="simpleInfoCardBinding"> <identity> <certificateReference findValue="Fabrikam" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" /> </identity> </endpoint> </service> </services> <bindings> <wsHttpBinding> <binding name="simpleInfoCardBinding"> <security mode="Message"> <message clientCredentialType="InfoCard"/> </security> </binding> </wsHttpBinding> </bindings> <behaviors> <behavior name="MyServiceBehavior" returnUnknownExceptionsAsFaults="true" > <serviceCredentials> <serviceCertificate findValue="Fabrikam" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" /> </serviceCredentials> </behavior> </behaviors> </system.serviceModel> </configuration>

Also note the binding’s security mode. I’m now specifying message-level security, which indicates the need for the WS-Security suite of protocols. The clientCredentialType is specified as InfoCard, which is really just shorthand for a self-issued SAML token that has no personally identifiable information in it, only a PPID. If you want to specify other claims, use the wsFederationBinding instead of wsHttpBinding; this allows you to specify the exact claim types you’re looking for.

Figure 6 shows the updated service code, with only the guts of the Notepad class that changed. You’ll see here that I’m now using a dictionary instead of a single string to store notes. The dictionary is keyed off the base64-encoded PPID. There’s really no reason to bother decoding the PPID into a byte array if a unique string is good enough to identify the user, so my dictionary uses a string PPID as its key.

Figure 6 Updated Service Code

const string CLAIMTYPE_PPID = "http://schemas.microsoft.com/ws/" + "2005/05/identity/claims:PrivatePersonalIdentifier"; static Dictionary<string, string> ppidToNotes = new Dictionary<string, string>(); string getCallerPPID() { AuthorizationContext ctx = OperationContext.Current.ServiceSecurityContext.AuthorizationContext; foreach (ClaimSet cs in ctx.ClaimSets) { foreach (Claim c in cs) { if (CLAIMTYPE_PPID == c.ClaimType) { return (string)c.Resource; } } } throw new Exception("Expected a PPID claim"); } public string GetNote() { string base64EncodedPPID = getCallerPPID(); lock (ppidToNotes) { if (ppidToNotes.ContainsKey(base64EncodedPPID)) return ppidToNotes[base64EncodedPPID]; else return null; // new users start with null note } } public void SetNote(string data) { lock (ppidToNotes) { string base64EncodedPPID = getCallerPPID(); ppidToNotes[base64EncodedPPID] = data; } }

Besides the synchronization code, the major new addition is the getCallerPPID function, which shows you how to use the new claims-based authorization feature in Windows Communication Foundation to discover the claims that were sent in the token. This code simply searches for a PPID claim. If there are other claims you requested, such as a user name or e-mail address, you can look for those as well using the URI for the claim types you are interested in.

The client code that looks up the service via WS-MEX also changed a bit. The MEX code doesn’t change, but once the channel factory is created, a behavior is dynamically added that tells the client-side Windows Communication Foundation plumbing to use InfoCard credentials with the service, as well as what certificate to expect for the service. This extra piece of code is here:

ChannelFactory<INotepad> factory = new ChannelFactory<INotepad>( serviceEndpoint.Binding, serviceEndpoint.Address); // indicate that we’re going to use InfoCard InfoCardClientCredentials creds = new InfoCardClientCredentials(); X509CertificateIdentity cid = (X509CertificateIdentity) serviceEndpoint.Address.Identity; creds.ServiceCertificate.Certificate = cid.Certificates[0]; factory.Description.Behaviors.Add((IChannelBehavior)creds); return factory;

If you build and run the new service, you’ll notice that on the very first call to the Web service, the identity selector pops up! Once you select a card and submit it, you’ll see the second GUI that shows the actual information that’s going to be sent; click the Information tab to see the personal information that will be sent. In this case, you will see an empty list since none of your personal information is requested. The PPID isn’t really personal information; it’s just an anonymous identifier that doesn’t mean anything to the user anyway, so it’s not shown here. After pressing the Send button, the rest of the client code runs, making a couple more calls to the Web service. You shouldn’t be prompted again while the client application is running though since the Windows Communication Foundation proxy is caching your credentials and doesn’t need to bug you anymore.

It’s pretty amazing to realize what you’re getting for about 10 lines of configuration code and maybe 20 lines of C#. You now have a login system that works over the Web with state-of-the-art authentication protocols. Windows Communication Foundation handles the heavy crypto required for authenticating the user’s credentials. There’s no worry about weak passwords, because you’re not relying on them! The user can create a single InfoCard that works at your site and at other sites; each site no longer needs to ask for a user name and password.

Exploring InfoCard Without WCF

You can play with InfoCard without using Windows Communication Foundation. Earlier I explained how the client application must invoke the InfoCard identity selector, handing it the server’s policy so the selector can display appropriate cards to the user. Well, if you’re using Windows Communication Foundation, the client-side plumbing handles this for you transparently. You don’t have to call InfoCard yourself, but you can if you want to.

If you look in the %WINDIR%\system32 directory, you’ll find a file called infocardapi.dll. A quick dump of its exports shows a function called GetToken. There’s also the managed assembly, Microsoft.Infocards.dll, which has a class called InfoCardClient with a static GetToken function that wraps the unmanaged version. You can build an array of policy elements and call this method directly if you want to pop up the identity selector and let the user choose a card. When the function returns, you’ll have the dereferenced InfoCard in your hands in the form of a security token, which is a great idea if you want to learn more about how the identity selector works.

If you want to simply pop the identity selector so the user can manage his cards, you can do this via the ManageInfoCard method. And if you want to import an InfoCard, you can do so by calling ImportInfoCard. There are no APIs for enumerating or otherwise programmatically manipulating InfoCards; you need to remember that this is something that the user must manage, since it’s his own personal information.

Oh, and one final note. If you’re wondering where the InfoCard identity selector itself lives, you can find it in a service called Microsoft Digital Identity Service. The code behind this service lives in a file called, appropriately enough, infocard.exe.

Winding Down

In this issue, I drilled deeper into InfoCard and showed the code for a relying party and a client. If it’s not already apparent, I’m really excited about the possibilities that InfoCard and the underlying identity metasystem present. Kim Cameron (the chief identity architect at Microsoft I told you about last time) has often said that if we can succeed in building an identity metasystem that respects the laws of identity, we will reach what he calls the "identity big bang," a new era of software which is identity-aware. I’m hopeful that InfoCard will help lead us there.

Send your questions and comments for Keith to  briefs@microsoft.com.

Keith Brown is a cofounder of Pluralsight, a premier Microsoft .NET training provider. Keith is the author of Pluralsight’s Applied .NET Security course, as well as several books, including The .NET Developer’s Guide to Windows Security, which is available both in print and on the Web.