How to Use Windows CardSpace with Internet Explorer 7.0

Download sample

CardSpace provides users with the ability to manage their digital identities, and with Internet Explorer 7.0, Web sites can request a digital identity from the user. The following exercises demonstrate the steps to accept identities using CardSpace and Internet Explorer 7.0. There are four exercises in this walkthrough:

  • Hello, World!

  • Activate the Identity Selector on demand

  • Accessing the claims in the security token

  • Uniquely identifying the user

To work through the exercises, Web site configuration is necessary. The configuration is done using the installation batch file provided in the sample folder:

Setup.bat

For more information about installation of the Web site, and some troubleshooting tips, see Installing CardSpace Sample Certificates.

Hello World! Sample

The Hello World sample demonstrates the HTML code required to use the Identity Selector. This sample uses the following files:

sample1.htm

login1.aspx

The Identity Selector is displayed by using either an <object> element or a binary behavior object. The easiest way is to include the <object> element in the body of a <form> element, which activates the Identity Selector when the form is submitted. The following is the Sample1.htm file:

<!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>
  <title>Sample 1</title>
</head>
<body>
    <form id="form1" method="post" action="login1.aspx">
      <button type="submit">Click here to sign in with your Information Card</button>
      <object type="application/x-informationcard" name="xmlToken">
        <param name="tokenType" value="urn:oasis:names:tc:SAML:1.0:assertion" />
        <param name="issuer" 
               value="https://schemas.xmlsoap.org/ws/2005/05/identity/issuer/self" />
        <param name="requiredClaims" 
             value="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname
                    https://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname
                    https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
                    https://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier" />
      </object>
    </form>
</body>
</html>

The results of the <object> element are posted directly into the login1.aspx page, where the processing occurs. The Identity Selector displays when the submit button is pressed.

The important elements of the object element are in the following table.

Element Description

type="application/x-informationcard"

Instructs the browser to display the Identity Selector object.

param name="tokenType"

Controls the token type that the Identity Selector emits; in this case, a SAML 1.0 token.

param name="issuer"

The Identity Provider’s URL that provides the identity. In this case, a hard-wired URI that invokes the built-in, self-issuing provider.

param name="requiredClaims"

The Relying Party requests the User to provide a token from the Identity Provider (or the User) with certain claims. The examples here are part of the pre-defined set for self-issued (personal) cards.

When the button is pressed, the CardSpace Identity Selector is shown. This allows the user to select a CardSpace Identity to submit.

Choosing a Windows CardSpce card

Click Yes, choose to send a card. If there are no cards in the system, the Identity Selector presents the opportunity to create or import a card.

Using Windows CardSpace with Internet Explorer 7.0

Click Create a new Personal card and the screen for creating self-issued cards is shown.

Editing a Windows CardSpace card

Fill in the required fields, choose a picture, give the card a name, and click Save. Once a Personal card has been created that satisfies the claims listed, send the card.

Sending a Windows CardSpace card to a site

The encrypted card data is sent to the following Login1.aspx page (which is shown below in C#).

<%@ Page Language="C#"  Debug="true" ValidateRequest="false"%>

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

<script runat="server">

    protected void Page_Load(object sender, EventArgs e) {
        Label1.Text = Request.Params["xmlToken"];
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        The value of the token is:<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label></div>
    </form>
</body>
</html>

The encrypted card data is sent to the login1.aspx page in VB.net.

<%@ Page Language="VB"  Debug="true" ValidateRequest="false"%>

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

<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
   Label1.Text = Request.Params("xmlToken");
End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        The value of the token is:<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label></div>
    </form>
</body>
</html>

The login1.aspx page displays the encrypted token back to the screen.

Using Windows CardSpace with Internet Explorer 7.0

Activating the Identity Selector on demand

This sample demonstrates a method to display the Identity Selector with more flexibility. The sample uses the following files:

Sample2.htm

Login2.aspx

Developers may want more flexibility around the timing and handling of the invocation of the Identity Selector. To display the Identity Selector at a time more suited to a particular application, the <object> element is scripted to return the encrypted token on request. This is shown in the following Sample2.htm file.

<!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>
  <title>Sample 2</title>
  <object type="application/x-informationcard" name="_xmlToken">
    <param name="tokenType" value="urn:oasis:names:tc:SAML:1.0:assertion" />
    <param name="requiredClaims" 
        value="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname
        https://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname
        https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
        https://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier" />
  </object>
  <script language="javascript">
    function GoGetIt(){
      var xmltkn=document.getElementById("_xmltoken");
      var thetextarea = document.getElementById("xmltoken");
      thetextarea.value = xmltkn.value ;
    }
  </script>
</head>
<body>
  <form id="form1" method="post" action="login2.aspx">
    <button name="go" id="go" onclick="javascript:GoGetIt();">Click here to get the token.</button>
    <button type="submit">Click here to send the card to the server</button>
    <textarea cols=100 rows=20 id="xmltoken" name="xmlToken" ></textarea>
  </form>
</body>
</html>

The <object> element is placed in the header of the HTML document, and the Identity Selector is invoked when the value property is accessed. The script in this example places the token XML into a <textarea> element that allows the developer to view the contents before the <form> is submitted.

Note

The token text in the text area does not exactly match the token text in the login2.aspx page because the browser is suppressing the display of the XML tags.

Getting access to the claims

This sample demonstrates how to use the TokenProcessor.cs to access the claims in a card sent to a Web site. The sample uses the following files:

Sample3.htm

Login3.aspx

app_code\TokenProcessor.cs

Web.config

To process the claims out of the encrypted data, developers that use ASP.NET 2.0 or later versions can use the TokenProcessor.cs sample code presented in this exercise. The Token class handles all of the decryption and verification of the token, using the Windows Communication Foundation (WCF) classes. The Token class is used in the target page of the post, in this case the login3.aspx page in C#:

<%@ Page Language="C#"  Debug="true" ValidateRequest="false" %>
<%@ Import Namespace="System.IdentityModel.Claims" %>
<%@ Import Namespace="Microsoft.IdentityModel.TokenProcessor" %>

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

<script runat="server">

    protected void ShowError(string text) {
        fields.Visible = false;
        errors.Visible = true;
        errtext.Text = text;
    }
    protected void Page_Load(object sender, EventArgs e)
        string xmlToken;
        xmlToken = Request.Params["xmlToken"];
        if (xmlToken == null || xmlToken.Equals("")){
            ShowError("Token presented was null");
        }
        else {
            Token token= new Token(xmlToken);
            givenname.Text = token.Claims[ClaimTypes.GivenName];
            surname.Text = token.Claims[ClaimTypes.Surname];
            email.Text = token.Claims[ClaimTypes.Email];
        }
        
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Login Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div runat="server" id="fields">
        Given Name:<asp:Label ID="givenname" runat="server" Text=""></asp:Label><br/>
        Surname:<asp:Label ID="surname" runat="server" Text=""></asp:Label><br/>
        Email Address:<asp:Label ID="email" runat="server" Text=""></asp:Label><br/>
    </div>
    <div runat="server" id="errors" visible="false">
        Error:<asp:Label ID="errtext" runat="server" Text=""></asp:Label><br/>
    </div>
        
    </form>
</body>
</html>

And in Visual Basic .NET:

<%@ Page Language="VB"  Debug="true" ValidateRequest="false" %>
<%@ Import Namespace="System.IdentityModel.Claims" %>
<%@ Import Namespace="Microsoft.IdentityModel.TokenProcessor" %>

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

<script runat="server">

Protected  Sub ShowError(ByVal text As String) 
   fields.Visible = False 
   errors.Visible = True 
   errtext.Text = text 
End Sub

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
   Dim xmlToken As String
   xmlToken = Request.Params("xmlToken")
   If xmlToken = Nothing Or xmlToken.Equals("") Then
      ShowError("Token presented was null")
   Else
      Dim token As New Token(xmlToken)
      givenname.Text = token.Claims(ClaimTypes.GivenName)
      surname.Text = token.Claims(ClaimTypes.Surname)
      email.Text = token.Claims(ClaimTypes.Email)
   End If
End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Login Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div runat="server" id="fields">
        Given Name:<asp:Label ID="givenname" runat="server" Text=""></asp:Label><br/>
        Surname:<asp:Label ID="surname" runat="server" Text=""></asp:Label><br/>
        Email Address:<asp:Label ID="email" runat="server" Text=""></asp:Label><br/>
    </div>
    <div runat="server" id="errors" visible="false">
        Error:<asp:Label ID="errtext" runat="server" Text=""></asp:Label><br/>
    </div>
        
    </form>
</body>
</html>

To get the values of the claims out of the token, use the Claims property. This takes the URI of the claim as a parameter, and returns the value as a string. The URIs for self-issued cards are listed later in this document, but to save time, they are predefined in the SelfIssued class.

There is configuration data that goes along with the Token class. In the Web.config file, the configuration items can be found:

<configuration>
  <appSettings>
    <add key="MaximumClockSkew" value="60"/>
    <add key="CertifcateThumbprint" value="01234567890ABCDEFEDCBA01234567890ABCDEFEDCBA"/>
    <add key="StoreName" value="My"/>
    <add key="StoreLocation" value="LocalMachine"/>
    <add key="IdentityClaimType" 
         value="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier"/>
  </appSettings>
<configuration>
Element Value Description

MaximumClockSkew

60

Optional. The maximum number of seconds the client and the server can be out of skew.

CertificateThumbprint

<none>

Optional. The thumbprint of the certificate to use to decrypt the tokens. The token class looks up the certificate automatically.

StoreName

My

Optional. The Store name of the SSL certificate. Typically “My”.

StoreLocation

LocalMachine

Optional. The Store location of the SSL certificate. Typically “LocalMachine”.

IdentityClaimType

PPID

Optional. The URI for the claim type used as the claim that uniquely identifies the user.

When the token is posted to the login page, and decrypted we can now see the claim values.

Using Windows CardSpace with Internet Explorer 7.0

Uniquely identifying the user

This sample demonstrates how to use the Token class to uniquely identify a user. This sample uses the following files:

Sample4.htm

Login4.aspx

app_code\TokenProcessor.cs

web.config

Given that anyone can create a card with the same values for the claim, it is necessary to be able to uniquely identify a particular card, other than the self-issued claim values. This is done by calculating the UniqueID of the card. This UniqueID is the hash of the Issuer’s Public Key and any claim unique to that issuer. Because the keys for the conversation between the client and the server are randomly generated on the first communication, the public key is unique to card—if you use the same self-issued card at multiple sites, a new key pair is generated with every new association. For the unique claim, the Private Personal Identifier (PPID) of the card is unique to that issuer. The UniqueID property calculates the hashed value for the developer. Adding the code to the login4.aspx page in C#:

<%@ Page Language="C#"  Debug="true" ValidateRequest="false" %>
<%@ Import Namespace="System.IdentityModel.Claims" %>
<%@ Import Namespace="Microsoft.IdentityModel.TokenProcessor" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
    protected void ShowError(string text) {
        fields.Visible = false;
        errors.Visible = true;
        errtext.Text = text;
    }
    protected void Page_Load(object sender, EventArgs e) {
        string xmlToken;
        xmlToken = Request.Params["xmlToken"];
        if (xmlToken == null || xmlToken.Equals(""))
            ShowError("Token presented was null");
        else
        {
                Token token = new Token (xmlToken);
                givenname.Text = token.Claims[SelfIssued.GivenName];
                surname.Text = token.Claims[SelfIssued.Surname];
                email.Text = token.Claims[SelfIssued.EmailAddress];
                uid.Text = token.UniqueID;
        }
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Login Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div runat="server" id="fields">
        Given Name:<asp:Label ID="givenname" runat="server" Text=""></asp:Label><br/>
        Surname:<asp:Label ID="surname" runat="server" Text=""></asp:Label><br/>
        Email Address:<asp:Label ID="email" runat="server" Text=""></asp:Label><br/>
        Unique ID:<asp:Label ID="uid" runat="server" Text=""></asp:Label><br/>
    </div>
    <div runat="server" id="errors" visible="false">
        Error:<asp:Label ID="errtext" runat="server" Text=""></asp:Label><br/>
    </div>
        
    </form>
</body>
</html>

And in Visual Basic .NET:

<%@ Page Language="VB"  Debug="true" ValidateRequest="false" %>
<%@ Import Namespace="System.IdentityModel.Claims" %>
<%@ Import Namespace="Microsoft.IdentityModel.TokenProcessor" %>

<script runat="server">
Protected  Sub ShowError(ByVal text As String) 
   fields.Visible = False 
   errors.Visible = True 
   errtext.Text = text 
End Sub

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
   Dim xmlToken As String
   xmlToken = Request.Params("xmlToken")
   If xmlToken = Nothing Or xmlToken.Equals("") Then
      ShowError("Token presented was null")
   Else
      Dim token As New Token(xmlToken)
      givenname.Text = token.Claims(ClaimTypes.GivenName)
      surname.Text = token.Claims(ClaimTypes.Surname)
      email.Text = token.Claims(ClaimTypes.Email)
      uid.Text = token.UniqueID
   End If
End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Login Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div runat="server" id="fields">
        Given Name:<asp:Label ID="givenname" runat="server" Text=""></asp:Label><br/>
        Surname:<asp:Label ID="surname" runat="server" Text=""></asp:Label><br/>
        Email Address:<asp:Label ID="email" runat="server" Text=""></asp:Label><br/>
        Unique ID:<asp:Label ID="uid" runat="server" Text=""></asp:Label><br/>
    </div>
    <div runat="server" id="errors" visible="false">
        Error:<asp:Label ID="errtext" runat="server" Text=""></asp:Label><br/>
    </div>
        
    </form>
</body>
</html>

The result is a 20-character, base64-encoded, hash value that can be used in a database to uniquely identify a visitor.

Using Windows CardSpace with Internet Explorer 7.0

To change the claim used for uniqueness, add the following key to the Web.config, and change the value to a different claim URI.

<add key="IdentityClaimType" value="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier"/>

About the actual token

For more information about the format and consumption of the encrypted XML token, consult the following resources:

https://go.microsoft.com/fwlink/?LinkId=95951

Claims in Self Issued Cards

  • Given Name = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname";

  • Email Address = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";

  • Surname = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname";

  • Street Address = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress";

  • Locality = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/locality";

  • State/Province = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince";

  • Postal Code = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode";

  • Country = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/country";

  • Home Phone = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/homephone";

  • Other Phone = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone";

  • Mobile Phone = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone";

  • Date of Birth = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth";

  • Gender = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender";

  • PPID = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier";

  • Web site = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/website";

Glossary

  • Identity Provider - The agency (company, Web site, organization, yourself) that is asserting claims about a Subject (person).

  • Identity Selector - The Identity Selector is the dialog that presents the user’s different digital identities and allows the selection of a relevant one for submission to the Relying Party.

  • Relying Party - The agency (Web site, server, or other party) that relies on the claims presented by the subject.

  • Subject - The entity (the user) that has claims made about their identity. The Subject is always in control in the release of their digital identity information to the Relying Party.

Footer image

© 2007 Microsoft Corporation. All rights reserved.