How to Use Windows CardSpace with Internet Explorer 7.0
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 |
---|---|
|
Instructs the browser to display the Identity Selector object. |
|
Controls the token type that the Identity Selector emits; in this case, a SAML 1.0 token. |
|
The Identity Provider’s URL that provides the identity. In this case, a hard-wired URI that invokes the built-in, self-issuing provider. |
|
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.
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.
Click Create a new Personal card and the screen for creating self-issued cards is shown.
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.
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.
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 |
---|---|---|
|
60 |
Optional. The maximum number of seconds the client and the server can be out of skew. |
|
<none> |
Optional. The thumbprint of the certificate to use to decrypt the tokens. The token class looks up the certificate automatically. |
|
My |
Optional. The Store name of the SSL certificate. Typically “My”. |
|
LocalMachine |
Optional. The Store location of the SSL certificate. Typically “LocalMachine”. |
|
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.
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.
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.
© 2007 Microsoft Corporation. All rights reserved.