Authenticate Users with Microsoft Passport
Make User Logins Simple and Consistent
October 30, 2009
asp:feature
Languages: C# |VB
Technologies: Security| Authentication | Passport
AuthenticateUsers with Microsoft Passport
MakeUser Logins Simple and Consistent
By SteveTurley
Passportis the key technology used by .NET My Services to authenticate users on a Website. Adding Passport to your ASP.NET site is easy to do and gives the user aconsistent, convenient method of logging in without having to remember yetanother user name and password. ASP.NET wraps much of the older Passport SDK toprovide a single object and simple configuration.
Writingan ASP.NET site enabled with .NET Passport is relatively simple: You installthe .NET Passport SDK, register your site, install your .NET Passport site key,change your s ite's authentication mode to Passport, and deny access tounauthorized users. (These last two items occur in the site's web.config file.)That's it. Your site now requires all users to sign in with their .NET Passportaccount before they can see any content. Follow along, and this article willshow you how it's done.
The User's Experience
Imagineyou have a site, www.mysite.com, with a homepage named default.aspx. The site's virtual directory contains a web.configfile enables Passport authentication and blocks any access to the site untilthe user has signed into his or her .NET Passport account:
Forexample, a user named John browses to your site. Because he hasn't signed intohis .NET Passport account during this session, the first thing John sees is thescreen shown in FIGURE 1.
FIGURE 1: This is the default pageunauthorized users will see when trying to access the site without signing intotheir Passport account. However, you might wish to construct a more attractiveand user-friendly page.
Whenclicking on the SignIn button, which thosefamiliar with Passport refer to as a scarab, John sees the page shown in FIGURE2.
FIGURE 2: The Passport server provides the .NET Passport sign-in page. Passportvalidates the user's name and password and it returns a ticket to the client.
Now Johnenters his .NET Passport credentials. If he doesn't have a .NET Passportaccount, he can get one here. He also can access pages on the Microsoft .NETPassport site to learn more about .NET Passport. Once he enters hiscredentials, which consist of his e-mail address and password, John clicks onthe SignIn button. Voil .He finally sees the page he originally requested, www.mysite.com/default.aspx.After he signs in, John can browse the site at his leisure. Moreover, he canbrowse to any .NET Passport site, even sites in completely separate domains,without signing in again. After he finishes, he signs out by clicking on the.NET Passport scarab again or simply closing his browser.
A .NETPassport site needs a few more things before it is considered a valid site thatyou can make public. The SDK help file offers a complete checklist. Look forthe topic Reviewingthe Checklist. Oneimportant requirement is that every site using .NET Passport displays thesign-in and sign-out scarab on every page. You'll see how to do this later, butfor now, consider what's happening during John's visit to your site: Johnrequests www.mysite.com/default.aspx. ASP.NETnotices that unauthorized users are denied by virtue of entries in theweb.config file:
ASP.NETnotices the site uses Passport authentication and unauthenticated users are tobe sent to the internal page for authentication:
ASP.NETautomatically redirects the user to the built-in, internal authentication page.This is the first page John sees-the one that denies him access. This pagedoesn't authenticate John, but instead, it simply has a link (the scarab) toanother page. Next, John clicks on the Passport sign-in scarab, which sends himto the .NET Passport sign-in page provided by the Microsoft .NET Passportservers. John signs in.
NowPassport authenticates John by comparing his sign-in information (e-mailaddress and password) with the information in its database. If John presentsvalid credentials, the Passport server sets some cookies on his browser and(finally) sends him to the page he originally wanted. This time, ASP.NET seesthat John is authenticated (his browser has the Passport cookies) and lets himview the page. Once John's browser has the Passport cookies, he can visit any.NET Passport site without signing in again. For tighter security, sites cancontrol automatic sign-in if they want by requiring, for example, that the usersigns in within a certain time limit, and a site could also force John to signin again even though he has valid credentials. In addition, John is able todelete the cookies at any time by signing out explicitly or by closing hisbrowser.
Noticethat during John's visit, the entire Web site is protected. Regardless of thepage John requests, ASP.NET would stop him and require him to sign in. But,once signed in, he has free access to the entire site. Sometimes this isexactly what you want, but sometimes it isn't. Here are two easy ways to pickand choose which pages you want to protect: You could put all the protectedpages in a separate directory and set the authentication and authorizationrequirements in it while leaving your main directory open to everyone; or youcould use tags in your web.config to requireauthentication for specific pages only. But this gets cumbersome if you havemany pages to protect.
OnlyASP.NET (e.g.., aspx, asmx, ascx, and so on) pages are protected by web.configsettings. HTML and ASP pages are not affected and are accessible to anyone.
Passport Identity
Everyclient that accesses your Web site has an Identity object associatedwith it. The Identity is available to your ASP.NET code as Context.User.Identity.Simple unauthenticated pages have a GenericIdentity, which provides afew properties such as Name, AuthenticationType, and IsAuthenticated.When Passport authentication is used, the page has a PassportIdentity,which is significantly more powerful. Among the most important differences isthat the Name property is a unique, 16-digit, hexadecimal string thatidentifies the user. FIGURE 3 shows some of the interesting members of the PassportIdentityclass (see the .NET Framework documentation for compete details).
Property or Method | Data Type | Comment |
---|---|---|
AuthenticationType | String property | "Passport" |
Error | Property | Passport error code |
GetFromNetworkServer | Boolean property | True when the client has just returned from signing in; otherwise False |
HexPUID | String property (2.x SDK only) | The unique Passport User Identity (PUID) for this user |
IsAuthenticated | Boolean property | True if the user is signed in |
Name | String property | Same as HexPUID |
TicketAge | Int property | Number of seconds since the user signed in |
GetCurrentConfig | String method (2.x SDK only) | Returns configuration information from the registry |
GetIsAuthenticated | Boolean method | Similar to IsAuthenticated property but allows testing for timeout |
GetProfileObject | Method | Returns information from the user's profile |
LogoTag2 | Method | Displays the scarab |
LoginUser | Method | Redirects user to sign-in server |
FIGURE3: This is apartial list of properties and methods the PassportIdentity objectprovides.
By usinga page's PassportIdentity object, you can make your pages more usefuland powerful. You must use a minimum set of its features to meet the Passportrequirements before you can publish your site. For example, Passport requiresyou to display the sign-out scarab on every protected page. The LogoTag2method does this for you.
Tactical Authentication
The Website described at the beginning of this article uses hard authentication, soit's all or nothing. By using subdirectories or tags,you can control access to individual pages. But you might want even finercontrol of the protected areas. For example, imagine your site is accessible toeveryone but offers additional or personalized content to authenticated users.MSN.com is a perfect example of this. Anyone can view it, but users who sign inhave additional, personalized content and layout. Passport makes this level ofcontrol easy: Remove the sectionfrom your web.config file, then use the PassportIdentity.IsAuthenticatedflag to control the portions of the page you want to customize. Use the .NETPUID to identify the user and look up details for personalizing the page.
In abasic example, the web.config file looks like this:
Noticethat no one is denied access; anyone can view any page. It's up to each page todetermine whether users are authenticated.
FIGURE 4shows a simple page that displays the user's PUID and some special content ifthey sign in.
...
protected voidPage_Load(){ if (!Page.IsPostBack) { try { if ( !(Context.User.Identity isPassportIdentity) ) { authLabel.Text = "Error:Passport not installed."; return; } // Expire the page to avoid thebrowser's cache Response.Cache.SetCacheability( HttpCacheability.NoCache); bool bSSL = Request.IsSecureConnection; StringBuilder sb = new StringBuilder(); sb.AppendFormat("{0}{1}{2}", (bSSL ? "https://" :"http://"), Request.ServerVariables["SERVER_NAME"], Request.ServerVariables["SCRIPT_NAME"]); String sThisPage = sb.ToString(); // -1 or null means use default valuesfrom registry int TimeWindow = -1; int ForceLogin = -1; string coBrandArgs = null; int lang_id = -1; int bSecure = (bSSL ? 1 : 0); string NameSpace = null; int KPP = -1; int SecureLevel = 0; // 0=None, 10=SSL, 100=SSL+PIN PassportIdentity id = (PassportIdentity)Context.User.Identity; // Remove cookies passed on query string // after a user logs in. if (id.GetFromNetworkServer) { Response.Redirect(sThisPage); } // display the sign-in scarab scarab.Text =id.LogoTag2(Server.UrlEncode(sThisPage), TimeWindow, ForceLogin,coBrandArgs,lang_id, bSecure, NameSpace, KPP, SecureLevel); if (id.IsAuthenticated) { protectedContent.Visible = true; authLabel.Text = "You'reauthenticated on site " + id.GetCurrentConfig("SiteID") + "."; if (id.HasProfile("core")) { authLabel2.Text = "YourPUID is " + id.Name + "."; } } } catch (Exception e) { authLabel.Text = "ERROR:Unhandled exception - " + e.Message; } } }
...
FIGURE4: This excerptfrom a simple Passport-enabled page uses the PassportIdentity's LogoTag2method to display the scarab and the IsAuthenticated property to controlthe page's content.
The IsAuthenticatedproperty is used to control the content and visibility of the content on thepage. If the user is authenticated, the text of authLabel and authLabel2is modified. The page also uses a panel server control to contain a block ofmaterial that is invisible to unauthenticated users.
The PUIDis guaranteed to be unique for each user. The sample page in FIGURE 4 doesn'tdo much with it, but it's easy to see how you could use the PUID to provide anindex into a database to obtain the user's preferences or other information youcould use to further customize the page.
In the2.x version of the Passport SDK, the PUID string is available as boththe PassportIdentity.Name and PassportIdentity.HexPUIDproperties. In version 1.4, it is available from the user's profile as MemberIDHighand MemberIDLow. To construct the full PUID, you need to combine them:
string PUID =String.Format("{0:X8}{1:X8}",
id.GetProfileObject("MemberIdHigh"),
id.GetProfileObject("MemberIdLow"));
The PUIDalso can fine-tune site access. Use it in the web.config file to allow or denyaccess to specific PUIDs:
Forexample, you might use this to make an administration page available only to arestricted set of users.
Put It All Together
Ifyou're going to display the scarab and check authentication on each page, youwill need to add code like that contained in FIGURE 4 to every page on yoursite. The obvious way to do this is to encapsulate it all in a user control andadd the control to every page. Now, the sample page becomes what you see inFIGURE 5.
<%@ RegisterTagPrefix="passport" TagName="scarab"
Src="Figure7_cs.ascx" %>
Protected SubPage_Load()
If (pp.IsAuthenticated)Then
protectedContent.Visible = True
authLabel.Text = "You areauthenticated on site " & _
pp.GetCurrentConfig("SiteID")& "."
authLabel2.Text = "Your PUID is" & pp.PUID & "."
End If
EndSub
SimplePassportControl Page
You are notauthenticated. Please sign in with your
.NET Passport.
visible="false"> This materialis only visible to authenticated users. FIGURE5: You cansimplify this page by encapsulating all the Passport code into a user control.Find the source code for the user control on the online version of thisarticle. When you register your site with Passport, you might havespecified a Logout URL. This is the URL the user is sent to after signing outfrom Passport. Be sure this page doesn't require hard authentication. If itdoes, the user will sign out, only to be forced to sign in again to see thelogout page - not a friendly design. You also will want to ensure that yourco-branding material, privacy policy, terms of use, and customer-support pagesare freely accessible. Signing Out When auser signs out of .NET Passport by clicking on the scarab in its sign-out mode,it is your site's responsibility to delete any cookies it created. The .NETPassport servers keep track of the sites the user visits and automaticallyrequest an expire-cookie page (also called the Logoutgif page) from each sitewhen the user clicks on the sign-out scarab. You must provide this page on yoursite, and you provide its URL to .NET Passport when you register the site.ASP.NET provides a convenient method that makes writing your expire-cookie pagevery easy: Simply call the PassportIdentity.SignOut method. It takes oneargument, which is the path to a gif of a green check mark. The check mark isdisplayed when the browser deletes the cookies successfully and signs out ofyour site. Recentprivacy rules from the Platform for Privacy Protection (P3P) are designed,among other things, to protect browsers from third-party cookies - cookiescreated by something other than the site the browser is visiting. Passport'scookies fall into this category and will not be deleted by browsers such asInternet Explorer 6.0 that honor P3P. In order for your site to work withInternet Explorer 6.0 and other P3P-aware browsers, each page on your site thatperforms a Set-Cookie operation must provide P3P headers. Unless your sitecreates its own cookies, the only time you need to worry about this is in theexpire-cookie page. You must add a P3P mini-header to the page so it will beallowed to delete the cookies. Here is a complete expire-cookie page in VB.NET: <% Response.Cache.SetCacheability(HttpCacheability.NoCache) Response.AppendHeader("P3P", _ "CP=""DSPNOI""") System.Web.Security.PassportIdentity.SignOut( _ "signoutcheckmark.gif") %> This isonly an example and it might not represent the security policy of your site. CP="NOI DSP" is the minimum policy required todelete the .NET Passport cookies, but that might misrepresent your site'sactual policy if used on a public site. See http://msdn.microsoft.com/library/default.asp?url=/workshop/security/privacy/overview/createprivacypolicy.aspfor more details on P3P headers. Don't use CP="TST" as described in some versions of the Passportdocumentation - it won't work. ASP.NET 1.0 uses the Passport Cookie Path to determine howto delete the cookies. If this path is blank, the cookies might not be deletedproperly. Use the Passport Administration Utility to ensure the Cookie Path isset to some non-empty value. Set it to "/" if it's currently empty. Here aresome final things to consider when developing authentication procedures withPassport: When developingASP.NET pages, it's common to browse your pages from the server using thedomain name localhost. If you're developing your site within Visual Studio.NET, this domain is used automatically. Unfortunately, if you do this with aPassport page, the GetFromNetworkServer redirect won't work. You shouldspecify the true domain name or machine name of the server. Recent releases of the .NET Passport SDK supported afeature called Inline Sign-In. It allowed you to create your own sign-in pageinstead of having the user redirected to the Passport login servers. Thisfeature turned out to be a security risk, and Passport dumped it. If you useit, you should remove it and revert to the standard sign-in procedure. .NETPassport 1.4 and 2.1 will not work for authenticating Web Services. A futurerelease will address this need. In addition, .NET Passport works best ifSession State is not running: Prohibit your server and browsers to cache thepage, and don't save the PassportIdentity object in an object of applicationor session scope; instead, get a new instance on each page. The .NETFramework and .NET Passport are built into the Windows .NET Server products, soto enable .NET Passport for your ASP.NET Web site, all you need to do isspecify in the web.config file. In addition, Windows XP and Internet Explorer 6.0 are.NET Passport-aware. Windows XP and later systems recognize .NET Passportauthentication and handle some of the process automatically. The first time youaccess a .NET Passport site from Windows XP, you'll notice the new .NETPassport pop-up (see FIGURE 6).
FIGURE 6: .NET Passport is integratedclosely with Windows XP. Signing into Passport on XP with Internet Explorer 6.0is handled locally and doesn't involve a redirect to the Passport servers. Theclient system now handles the authentication user interface instead ofredirecting you to the .NET Passport login servers. For this to work, theclient system must know which .NET Passport environment to authenticateagainst. Normally, this is the production environment. But when you'redeveloping a site that hasn't yet been released to the world, you're working inthe pre-production environment. If you browse to your site from a Windows XPclient, you'll see an error like the one in FIGURE 7.
FIGURE 7: You must configure your Windows XPand Internet Explorer 6.0 clients to authenticate against the same environmentyour server uses. You'll see this error if they're mismatched. You mustconfigure your XP and Internet Explorer 6.0 clients to authenticate against thesame environment your server uses. The SDK 2.1 help document has details. Lookfor the topic named .NET Passport SDK: SystemRequirements. Althoughyour client system is configured for the test environments, you won't be ableto browse live sites. This is such a pain that I do most of my testing with aWindows 2000 client. .NETPassport has much more functionality than I could cover in this single article.Take the time to dig into all .NET Passport has to offer. Download the SDK at http://www.passport.com and get the helpfile from the Microsoft Developer Network (http://msdn.microsoft.com/downloads/default.asp).Select SoftwareDevelopment Kits andthen MicrosoftPassport SDK from themenu. Explore, have fun, and create the next killer Web application. The files referenced in this article are available for download. Steve Turleyis a software development engineer on Microsoft's ASP.NET team. He has been apart of the .NET team from its beginning and has seen it go through at leastfive code name changes. Steve has more than 20 years of experience writing codefor microcomputers and still has his Northstar Horizon with the wooden case.Contact him at mailto:[email protected].
Read more about:
MicrosoftAbout the Author
You May Also Like