Programming Windows Identity
Programming Windows Identity
Programming Windows Identity
Windows Identity
®
Foundation
Vittorio Bertocci
PUBLISHED BY
Microsoft Press
A Division of Microsoft Corporation
One Microsoft Way
Redmond, Washington 98052-6399
Copyright © 2011 by Vittorio Bertocci
All rights reserved. No part of the contents of this book may be reproduced or transmitted in any form or by any means
without the written permission of the publisher.
Library of Congress Control Number: 2010933007
A CIP catalogue record for this book is available from the British Library.
Microsoft Press books are available through booksellers and distributors worldwide. For further information about
international editions, contact your local Microsoft Corporation office or contact Microsoft Press International directly
at fax (425) 936-7329. Visit our Web site at www.microsoft.com/mspress. Send comments to [email protected].
The example companies, organizations, products, domain names, e-mail addresses, logos, people, places, and events
depicted herein are fictitious. No association with any real company, organization, product, domain name, e-mail address,
logo, person, place, or event is intended or should be inferred.
This book expresses the author’s views and opinions. The information contained in this book is provided without any
express, statutory, or implied warranties. Neither the authors, Microsoft Corporation, nor its resellers, or distributors will
be held liable for any damages caused or alleged to be caused either directly or indirectly by this book.
v
Table of Contents
Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii
Microsoft is interested in hearing your feedback so we can continually improve our books and learning
resources for you. To participate in a brief online survey, please visit:
www.microsoft.com/learning/booksurvey/
vii
viii Table of Contents
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
Microsoft is interested in hearing your feedback so we can continually improve our books and learning
resources for you. To participate in a brief online survey, please visit:
www.microsoft.com/learning/booksurvey/
Foreword
A few years ago, I was sitting at a table playing a game of poker with a few colleagues from
Microsoft who had all been involved at various times in the development of Web Services
Enhancements for Microsoft .NET (WSE). Don Box, Mark Fussell, Kirill Gavrylyuk, and I played
the hands while showman extraordinaire Doug Purdy engaged us with lively banter and
more than a few questions about the product—all of this in front of the cameras at the
MSDN studios.
We had each selected a person from the field to play for; someone whom we each
thought had made a significant contribution to the success of WSE but hadn’t been a direct
member of the product team itself. If we won, then our nominee would get a prize, a token
of our appreciation for the work that he or she had done. My selection was a guy called
Vittorio Bertocci who was working for Microsoft in Italy at the time. I’d never met Vittorio,
nor even seen a photo of him, but he was a prolific poster on our internal discussion list,
clearly understood the key security concepts for the product including the WS-* protocols,
and had even crafted an extension to enable Reliable Messaging despite some of the crude
extensibility we had in place at the time. Vittorio was someone worth playing for but,
unfortunately, I didn’t win.
Time passed, the Windows Communication Foundation (WCF) superseded WSE, and I moved
to become the Architect for the Identity and Access team tasked with building a Security
Token Service for Windows Server. One day, out of the blue, I got an e-mail from Vittorio
to say that he’d moved to Redmond to take on a Platform Evangelist role and asking if we
could meet up. Of course I said yes, but what I couldn’t have anticipated was that mane of
jet-black hair....
Vittorio was deeply interested in the work that we were doing to enable a claims-based
programming model for .NET, on top of which we planned to build the second version of our
security token service. Over time, these ideas became the “Geneva” wave of products and
were finally birthed as the Windows Identity Foundation and Active Directory Federation
Services 2.0.
Throughout several years of product development, Vittorio became not only a remarkable
spokesperson for the products but a key source of feedback on our work, both from the
customers and partners that he met with and from his own direct efforts to use the product.
He was instrumental in encouraging me, and the product team, to take on the last-minute
task of making WIF run in Windows Azure just in time for PDC 2009 and the product release.
Watching Vittorio present a session on WIF is a pleasure—his depth of knowledge and his
creative presentation skills allow him to deliver the message on an increasingly important
topic despite the fact that it is too frequently tainted with the dryness of the “security” label.
xi
xii Foreword
Within the pages of this book, you’ll learn how to use the Windows Identity Foundation from
someone who is not only a great teacher but is also deeply familiar with the concepts be-
hind the technology itself and who has worked directly with the product team, and myself
personally, on a very close basis over the course of the last four to five years.
Vittorio takes you through the terminology and key concepts, and explains the integration
of WIF with ASP.NET, Windows Communication Foundation, and Windows Azure, culminat-
ing in a speculative look ahead at the scenarios that the product might tackle in a future
release. I encourage you, the reader, to think deeply about the concepts here and how you
will manage identity in the applications that you go on to build; it’s a topic that is becoming
increasingly important to both enterprises and the Web community.
Finally, I want to thank Vittorio for his enthusiasm, support, and tireless energy over the
years. I have but one final request of him: please get a haircut.
Hervey Wilson
Architect, AppFabric Access Control Service
Microsoft, Redmond
July 2010
Acknowledgments
You create the world of the dream. We bring the subject into that dream and fill it
with their subconscious.
—Cobb in “Inception”, Christopher Nolan, 2010
Some time ago, a friend asked me what the point was of writing a book when I already have
a well-read blog. There are many excellent answers to that question, from the extra reach
that a book has to the advantages of reading without having to constantly fight the op-
portunity costs of not following a link. My favorite answer, however, is that whereas a blog is
a one-man operation, a book is the result of the contribution of many people and its value
for the reader is proportionally higher. It might be my name on the cover, but the reality
is that I stand on the shoulders of many fine people, who I want to acknowledge here. I’ve
been working with identity for the last 8 years or so, interacting with an incredible amount of
people; hence, I am pretty sure I’ll forget somebody. I apologize in advance.
Peter Kron is a Principal Software Developer Engineer on the WIF team, and the official
technical editor of this book. Without his patience, thoroughness, and deep knowledge of
WIF, this would have been a much inferior book.
Hervey Wilson is the Architect of the Access Control service. He led the Web Services
Enhancements (WSE) team, and he happens to be the one who envisioned Windows Identity
Foundation. I’ve been working with Hervey since 2002, well before I moved to Redmond. At
the time, I was still using his WSE for securing solutions for Italian customers. If you believe
what Malcom Gladwell says in his book Outliers: The Story of Success (Little, Brown and Co.,
2008), that you need 10,000 hours of practice for becoming real good at something, nobody
contributed more than Hervey to my professional growth in the field of Identity. I am very
honored he agreed to write the foreword for this book. Thanks, man!
The crew at Microsoft Press has been outstanding, chopping into manageable chunks my
long “Itanglish” sentences without changing the meaning and working around my abysmal
delays and crazy schedule. (In the last year alone, I handed a boarding pass to smiling ladies
55 times.) Specifically, thanks go to Ben Ryan and Gerry O’Brien for having trust in me and
the book, to Devon Musgrave for bootstrapping the project, and to Rosemary Caperton
for running the project. Steve Sagman of Waypoint Press led a fantastic production team:
Roger LeBlanc as Copy Editor, Thomas Speeches as Proofreader, and Audrey Marr as
Illustrator. Special thanks to Audrey for working on really challenging illustrations: you can
pull out the needles from my doll now!
Stuart Kwan, Group Program Manager for WIF, and Conrad Bayer, GM for the Identity and
Access division, have been great partners and supported this project from the very start.
xiii
xiv Acknowledgments
I did most of the writing at night, on weekends, and during vacation time, but at times
the book did impact my day job. James Conard and Neil Hutson, Senior Directors in the
Developer and Platform Evangelism group and my direct management chain, have been very
patient and supportive of the effort.
Justine Smith and Brjann Brekkan, from the Business Group of the Identity and Access
Division, have been incredibly helpful on activities that ultimately had an impact on the
sample code discussed here.
Todd West, at the time with the WIF test team, is one of the most gifted Web services
developers I’ve ever met. Most of the guidance regarding WIF and Windows Azure in this
book and out there is the result of his work.
My good friend Caleb Baker, Program Manager on the WIF team, is a never-ending source
of insights and useful discussions. He is also the owner of the WIF and Silverlight integration.
The Silverlight code samples are all based on his work.
Together with Hervey, the original WSE team merged with WIF too. I had a chance to
tap their brains countless times. Thanks to Sidd Shenoy, Govind Ramanathan, Vick
Mukherjee, HongMei Ge, and Keith Ballinger.
The entire WIF team contributed to this book. Here I’ll call a few people out to give you
a feeling for the quality of their work. Daniel Wu was of great help on sessions; Brent
Schmaltz was key for helping me understand the inner workings of WIF and WCF; Vani Nori
and Vick devised the way of using WIF with MVC; Junaid Tisekar was key for starting the
work with WIF and OAuth 2.0; Shiung Yong was instrumental in figuring out some parts of
the WIF pipeline in the early days of WIF.
Many others in the identity product team contributed through the years: thanks to Jan
Alexander, Vijay Gajjala, Arun Nanda, Marc Goodner, Mike Jones, Craig Wittenberg,
Don Schmidt, Ruchi Bhargava, Sesha Mani, Matt Steele, and Sam Devasahayam.
My teammates in the Windows Azure platform evangelism team played a key role in
keeping me on my toes, and they’re simply awesome to hang out with. Thanks to Ryan
Dunn, David Aiken, Nigel Watling, and Zach Owen. Please delete all the pictures you
saved!
The guys at Southworks, the company that helped me with practically all the identity
samples and labs in the last two years, are fantastic to work with. Many thanks to Matias
Woloski, Pablo Damiani, Tim Osborn, Johnny Halife, and many others.
Conversations about identity with Gianpaolo Carraro and Eugenio Pace were extremely
valuable, especially the ones related to the P&P guide on claims-based identity led by
Eugenio.
Acknowledgments xv
Donovan Follette has been the ADFS evangelist for a long time, sharing with me the pains
and the joys of the claims-based identity renaissance at PDC08. Even if now he is all cozy
in his new Office role, I cannot forget his incredible contribution to bringing identity to the
community.
Of course, we would not be even discussing this if Kim Cameron had not driven the
conversation on the identity metasystem and claims-based identity with the entire industry.
Thank you, Kim!
My wife, Iwona Bialynicka-Birula, deserves special thanks. She accepted and supported
this crazy initiative no matter what, whether it meant skipping beach time while in Maui or
coping with insurance agents and contractors after our house got flooded. Without her,
not only would you not be holding this book in your hands, I don’t know what I would do….
Thank you, darling. I promise: no more books for some time!
Finally, I want to thank you: the readers of my blog, who followed faithfully my ramblings for
seven years without asking too often about the weird blog name; the participants of the WIF
workshops in Belgium, UK, Germany, Singapore, Melbourne, and Redmond, who put up so
nicely with my “sexy” accent; and the attendees of the many sessions I gave at events all over
the world in the last five years. Without your questions, your critiques, your comments, your
compliments, and your longing for understanding, I would have never found the motivation
to do this and the other things I do for evangelizing identity. This book is for you.
Introduction
It has been said that every problem in Computer Science can be solved by adding a level of
indirection.
You don’t have to go far to find examples of successful applications of that principle. Before
the introduction of the concept of driver, programs had to be rewritten every time one
changed something as simple as the monitor. Before the introduction of TCP/IP, programs
targeting a token ring network environment had to be rewritten if the network protocol
changed. Drivers and TCP/IP helped to free application developers from the need to worry
about unnecessary details, presenting them with a generic façade while leaving the nitty-
gritty details to the underlying infrastructure. In addition to making the developer profession
a happier one, the approach led to more robust and long-lived software for the benefit of
everybody.
For various historical reasons, authentication and identity management practices never really
followed the same route of monitors and network cards. Adding “authentication” to your
software today still largely means messing with the code of the application itself, writing
logic that takes care in detail of low level tasks such as verifying username and passwords
against an account store, juggling with X509 certificates or similar. When you are spared from
handling things at such low level, which usually means that you took a strong dependency on
your infrastructure and your application will be unmovable without substantial rewriting: just
like a program from the pre-drivers era.
As you will learn in the first chapters of this book, claims-based identity is changing all this.
Without going too much into details, claims are the means to add that extra level of
indirection that eluded the identity world so far. The introduction of open protocols enjoying
wide industry consensus & support, the converge toward the idea of a meta-system for
identity, the success of metadata formats which can automate many tedious and error-prone
tasks created the perfect storm that generated the practices collectively known as claims-
based identity. Claims are paving the way for identity and access management to be pushed
outside of applications and down in the infrastructure, freeing developers from the need
to handle it explicitly while enhancing solutions with welcome extra advantages (such as
cross-platform interoperability out of the box).
I have spent full four years working almost exclusively on claims-based architectures with
customers and product teams here in Redmond; the model is sound, and it invariably delivers
significant improvements against any other authentication system. However, until recently,
actually implementing systems according to the model was a painful experience, since it
required writing large amounts of custom code that would handle protocols, cryptography,
and similar low level aspects.
xvii
xviii Introduction
This all changed when, in October 2008, Microsoft announced the “Geneva” wave of
claims-aware beta products: among those there was Windows Identity Foundation, the
protagonist of the book you are holding, which was finally released in November 2009.
True to the claims-based identity promise, you can decide to use WIF to externalize all
identity and access control logic from your applications: Visual Studio will make it a breeze,
and you will not be required to know any detail about the underlying security protocols. If
you want to take finer control of the authentication and authorization process, however, WIF
offers you a powerful and flexible programming model that will give you complete access to
all aspects of the identity management pipeline.
This book will show you how to use Windows Identity Foundation for handling
authentication, authorization and identity-driven customization of your .NET applications.
Although the text will often be task-oriented, especially for the novice part of the book, the
ultimate goal will always be to help you understanding the claims based approach and the
pattern that is most appropriate for the problem at hand.
In Part II I shift gear pretty dramatically, assuming that you are an experienced .NET
developer who knows about ASP.NET pipeline, Forms authentication, X.509 certificates, LINQ
syntax and the like. I often try to add sidebars which introduce the topic if you know little
about it but you want to follow the text anyway, but reality is that without concrete, hands-
on knowledge of the .NET Framework (and specifically C#) Part II could be hard to navigate. I
also assume that you are motivated to invest energy on understanding the “why”s of identity
and security.
to be a WCF expert for appreciating the chapters about ASP.NET. Chapter 3 and Chapter 4
require you to be familiar with ASP.NET and its extensibility model. Chapter 5 is for experi-
enced WCF developers. Chapter 6 requires you to be familiar with Windows Azure and its
programming model. Chapter 7 sweeps on a number of different technologies, including
Silverlight and ASP.NET MVC Framework, and expects you to be at ease with terminology
and usage.
The bottom line is that in order to fully take advantage of the book you need to be an expert
.NET and Web developer. On the other hand, the book contains a lot of architectural patterns
and explanations which could easily be applied to products on other platforms: hence if you
are an architect that can stomach patterns explanations intertwined with code commentary,
chances are that you’ll find this book a good reference on how claims-based identity solves
various canonical problems in the identity and access space.
System Requirements
You’ll need the following software and hardware to build and run the code samples for
this book:
■ Microsoft® Windows 7; Windows Server 2003 Service Pack 2; Windows Server 2008 R2;
Windows Server 2008 Service Pack 2; Windows Vista
■ Windows Identity Foundation 1.0 runtime
■ Windows Identity Foundation SDK 4.0
■ Microsoft® Internet Information Services (IIS) 7.5, 7.0 or 6.0
■ Microsoft® .NET Framework 4.0
■ Visual Studio 2010
■ 1.6-GHz Pentium or compatible processor
■ 1 GB RAM for x86
■ 2 GB RAM for x64
■ An additional 512 MB RAM if running in a virtual machine
■ DirectX 9–capable video card that runs at 1024 × 768 or higher display resolution
■ 5400-RPM hard drive (with 3 GB of available hard disk space)
■ DVD-ROM drive
■ Microsoft mouse or compatible pointing device
■ Approximately 78 MB of available hard disk space to install the code samples
xx Introduction
Note that the WIF runtime and the WIF SDK 3.5 are compatible with Visual Studio 2008 and
the .NET Framework 3.5 SP2. The March 2010 version of the Identity Training Kit contains
most of the samples of the book in a form that is compatible with VS 2008 and the .NET
Framework 3.5, however please note that the code in the text refers to VS 2010 and there are
small differences here and there.
Code Samples
The code samples for this book are available for download here:
http://www.microsoftpressstore.com/title/9780735627185.
Click the download link and follow the instructions to save the code samples to your local
hard drive.
The code samples used in this book are mostly from the Identity Developer Training Kit, a
collection of hands-on labs, presentations, and instructional videos, which is meant to help
developers learn Microsoft’s identity technologies. It is a self-extracting .EXE. Every lab has its
own setup, which will take care of most prerequisites for you. Please follow the instructions
on the Welcome page.
Producing the Identity Developer Training Kit is one of the things I do during my day job.
Whereas in the book I highlight code snippets to help you understand the technology, in
the Identity Developer Training Kit documentation I give step-by-step instructions. Feel
free to combine the two approaches as you ramp up your knowledge of Windows Identity
Foundation.
The Identity Developer Training Kit is a living deliverable; every time there is a new ver-
sion of a product I update it accordingly. However, I want to make sure that the code
samples referenced in the book will not break. For that reason, I am including in the book
code sample archive the current version of the training kit, June 2010, which will always be
available, even if I keep updating the training kit in its original download location.
1. Go to
2. In the Search box, enter the book’s ISBN or title.
3. Select your book from the search results.
4. On your book’s catalog page, find the Errata & Updates tab
5. Click View/Submit Errata.
Introduction xxi
You’ll find additional information and services for your book on its catalog page. If you need
additional support, please e-mail Microsoft Press Book Support at [email protected].
Please note that product support for Microsoft software is not offered through the addresses
above.
http://www.microsoft.com/learning/booksurvey
The survey is short, and we read every one of your comments and ideas. Thanks in advance
for your input!
Stay in Touch
Let’s keep the conversation going! We’re on Twitter: http://twitter.com/MicrosoftPress.
Chapter 1
Claims-Based Identity
In this chapter:
What Is Claims-Based Identity? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
WIF Programming Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Microsoft Windows Identity Foundation (WIF) enables you to apply the principles of
claims-based identity when securing your Microsoft .NET application. Claims-based identity
is so important that I want to make sure you understand it well before I formally introduce
Windows Identity Foundation.
Claims-based identity is a natural way of dealing with identity and access control. However,
the old ways of doing this are well established, so before delving into the new approach, it’s
useful to describe and challenge the classic assumptions about authentication and authoriza-
tion. Once you have a clear understanding of some of the issues with traditional approaches,
I’ll introduce the basic principles of claims-based identity—I’ll say enough to enable you to
proficiently use Windows Identity Foundation for the most common scenarios. This chapter
contains some simplifications that will get you going without overloading you with infor-
mation. For a more thorough coverage of the subject, refer to Part II, “Windows Identity
Foundation for Identity Developers.”
Finally, we’ll take our initial look at how WIF implements the mechanisms of claims-based
identity and how you, the developer, can access the main elements exposed by its object
model.
After reading this chapter, you’ll be able to describe how claims-based identity works and
how to take advantage of it in solutions to common problems. Furthermore, you’ll be able to
define Windows Identity Foundation and recognize its main elements.
Note If you already know about claims, feel free to skip ahead to the “WIF Programming
Model” section. If you are in a big hurry, I offer you the following summary of this section before
you skip to the next section: Claims-based identity allows you to outsource identity and access
management to external entities.
3
4 Part I Windows Identity Foundation for Everybody
The problem of recognizing people and granting access rights to them is one of the oldest
in the history of computer science, and it has its roots in identity and access problems we all
experience every day as we go through our lives.
Although we can classify almost all the solutions to the problem in relatively few categories,
an incredible number of solutions tailored specifically to solve this or that problem exists.
From the innumerable ways of handling user names and passwords to the most exotic
hardware-based cryptography solutions, the panorama of identity and access meth-
ods creates a sequence of systems that are almost never compatible, each with different
advantages, disadvantages, tradeoffs, and so on.
From the developer perspective, this status quo is bad news: this diversity forces you to
continually relearn how to do the same thing with different APIs, exposes you to details
of the security mechanisms that you’d rather not be responsible for, and subjects you to
software that is brittle and difficult to maintain.
What you need is a way to secure your applications without having to work directly at the
security mechanism level: an abstraction layer, which would allow you to express your secu-
rity requirements (the “what”) without getting caught in the specifics of how to make that
happen (the “how”). If your specialty is designing user experiences for Microsoft ASP.NET, you
should be allowed to focus your effort on that aspect of the solution and not be forced to
become an expert in security (beyond the basic, secure-coding best practices, of course—all
developers need to know those).
If you need a good reference on secure coding best practices, I highly recommend Writing
Secure Code, Second Edition, by Michael Howard and David LeBlanc (Microsoft Press, 2002).
What we collectively call “claims-based identity” provides that layer of abstraction and helps
you avoid the shortcomings of traditional solutions. Claims-based identity makes it possible
to have technologies such as Windows Identity Foundation, which enables you to secure
systems without being required to understand the fine details of the security mechanisms
involved.
It’s beyond the scope of this book to give an exhaustive list of authentication systems and
their characteristics; fortunately, that won’t be necessary for making our point. In this section
I’ll briefly examine the built-in mechanisms offered by the .NET Framework and provide some
examples of how they might not always offer a complete solution.
In a .NET application the user in the current context is represented by an IIdentity, a simple
interface that provides basic information about the user and how the user was authenticated:
IIdentity lives inside IPrincipal, another interface that contains more information about
the user (such as whether he belongs to a certain security group) that can be used in
authorization decisions:
You can always reach the current IPrincipal in the code of your .NET application: in
ASP.NET, you will find it in HttpContext.Current.User, and in general, you’ll find it in
Thread.CurrentPrincipal.
IPrincipal and IIdentity, as they exist out of the box, do provide some good decoupling
from how the authentication actually happened. They do not force you to deal with the
details of how the system came to know how the information about the user was acquired.
If your users are allowed to perform a certain action only if they are administrators, you
can write Thread.CurrentPrincipal.IsInRole(“Administrators”) without having to change your
code according to the authentication method. The framework uses different extensions
of IPrincipal—WindowsPrincipal, GenericPrincipal, or your own custom class—to accom-
modate the specific mechanism, and you can always cast from IPrincipal to one of those
6 Part I Windows Identity Foundation for Everybody
classes if you need to access the extra functionalities they provide. However, in general, using
IPrincipal directly makes your code more resilient to changes.
Unfortunately, the preceding discussion is just a tiny part of what you need to know about
.NET security if you want to implement a real system.
Populating IPrincipal
Most of the information you need to know about the user is in IPrincipal, but how do you get
that information in there? The values in IPrincipal are the result of a successful authentication:
before being able to take advantage of the approach, you have to worry about making the
authentication step happen. That is where things might start getting confusing if you don’t
want to invest a lot in security know-how.
When I joined Microsoft in 2001, my background was mainly in scientific visualization and
with Silicon Graphics; I knew nothing about Microsoft technologies. One of the first projects
I worked on was a line-of-business application for a customer’s intranet. Today I can say I’ve
had my fair share of experience with .NET and authentication, but I can still recall the confu-
sion I experienced back then. Let’s take a look at some concrete examples of using IPrincipal.
Up until the release of Microsoft Visual Studio 2008, if you created a Web site from the
template, the default authentication mode was Windows. That means that the application
expects Internet Information Services (IIS) to take care of authenticating the user. However, if
you inspect the IPrincipal in such an application you will find it largely empty. This is because
the Web application has anonymous authentication enabled in IIS by default, so no attempt
to authenticate the user is made. This is the first breach in the abstraction: you have to leave
your development environment, go to the IIS console, disable anonymous authentication,
and explicitly enable Windows authentication. (You could do this directly by modifying the
web.config file of the application in Microsoft Visual Studio, but going through IIS is still the
most common approach in my experience.)
After you adjust the IIS authentication types, you’re good to go, at least as long as you
remain within the boundaries of the intranet. If you are developing on your domain-joined
laptop and you decide to burn some midnight oil at home working on your application,
don’t be surprised if your calls to IsInRole now fail. Without the network infrastructure readily
available, the names of the groups to which the user belongs cannot be resolved. As you can
imagine, the same thing happens if the application is moved to a hoster, to the cloud, or in
general away from your company’s network environment.
In fact, you’ll encounter precious few cases in which you enjoy the luxury of having
authentication taken care of by the infrastructure. If the users you want to authenticate live
outside of your directory, you are normally forced to take the matter into your own hands
and use authentication APIs. That usually means configuring your ASP.NET application to use
Chapter 1 Claims-Based Identity 7
Forms authentication, perhaps creating and populating a users and roles store according to
the schema imposed by sqlMembershipProvider, implementing your own MembershipProvider
if your scenario cannot fit what is available out of the box, and so on.
There’s more: not everything can be solved by providing a custom user store. Often, your
users are already provisioned in an existing store but that store is not under your direct
control. (Think about employees of business partners, suppliers, and customers.) Store dupli-
cation is sometimes an option, but it normally brings more problems than the ones it solves.
ASP.NET provides mechanisms for extending Forms authentication to those cases, but they
require you to learn even more security and, above all, they are not guaranteed to work with
other platforms.
If you’ve dealt with security issues in the past, you can certainly relate to what I’ve just
described. If you haven’t, don’t worry if you didn’t understand everything in the last couple
of paragraphs. You can still understand that you need to learn a lot to add authentication
capabilities to your application, despite ASP.NET providing you with helper classes, tooling,
and models. If you’re not interested in becoming a security expert, you would probably
rather spend your time and energy on something else.
Here’s one last note before moving on. When using Forms authentication, you do need
to write extra code for taking care of authentication, but in the end you can still use the
IPrincipal abstraction. (The user’s information is copied from a FormsIdentity object into a
GenericPrincipal.) This might induce you to think that all you need is better tooling to handle
authentication and that the abstraction is already the right one. You’re on the right track,
but this is not the case if you stick with the current idea of authentication. Imagine a case in
which you want authentication to happen using radically different credentials, such as a client
Secure Sockets Layer (SSL) certificate, but those credentials do not map to existing Windows
users. In the traditional case, you have to directly inspect the request for the incoming X.509
certificate and learn new concepts (subject, thumbprint, and so on) to perform the same task
you already know how to do with other APIs.
The problem here is not with how ASP.NET handles authentication: it is systemic, and you’d
have the same issues with any other general-purpose technology. By the way, if you consider
how to handle identity and access with Microsoft Windows Communication Foundation
(WCF), you have to learn yet another model, one that is largely incompatible with what we
have seen so far and with its own range of APIs and exceptions.
When you can rely on infrastructure, like in the Windows Authentication example, you do
fine: most details are handled by Windows, and all that’s left for you is deciding what to do
with the user information. When you can’t rely on the infrastructure, as in the generic case,
you can observe a consistent issue across all cases: you are burdened with the responsibil-
ity of driving the mechanics of authentication, and that often means dealing with complex
issues. As I’ve already stressed, the gamut of all authentication options is wide, diverse, and
8 Part I Windows Identity Foundation for Everybody
c onstantly evolving. Tooling can help you only so far, and it is doomed to be obsolete as
soon as a new authentication scheme emerges.
What should developers do? Are we doomed to operate in an infinite arms race between
authentication systems and the APIs supporting them?
Those days are fortunately long gone. Today’s software takes advantage of the available
hardware via device drivers. A device driver is a program that acts as an intermediary be-
tween a given device and the software that wants to use it. All drivers have one logical
layer, which exposes a generic representation of the device and the functionalities that are
common to the device class and reveals no details about the specific hardware of a given
device. The logical layer is the layer with which the higher level software interacts—for
example, “print this string.” The driver contains a physical layer too, which is tailored to the
specific hardware of a given device. The physical layer takes care of translating the high-
level commands from the logical layer to the hardware-specific instructions required by the
exact device model being used—for example, “put this byte array in that register,” “add the
following delimiter,” “push the following instructions in the stack,” and so forth.
If you want to print from your .NET application, you just call some method on PrintDocument,
which will eventually take advantage of the local drivers and make that happen for you. Who
cares about which printer model will actually be available at run time?
Doesn’t this scenario sound awfully familiar? Managing hardware directly from applications
is similar to the problem of dealing with authentication and authorization from applications’
code: there are too many (difficult!) details to handle, and results are too inflexible and vul-
nerable to changes. The hardware problem was solved by the introduction of device drivers;
there is reason to believe that a similar approach can solve the access management problem,
too.
so on. The chances of a level of indirection spontaneously emerging from that chaos are
practically zero.
With the inflationary growth of distributed systems and online businesses, in the last
few years the increasing need for interoperable protocols that could tear down the walls
between silos became clear. The big players in the IT industry got together and agreed
on a set of common protocols that would support interoperable communications across
different platforms. Some examples of those protocols are SOAP, WS-Security, WS-Trust,
WS-Federation, Security Assertion Markup Language (SAML), and in more recent times,
OpenID, OAuth, and other open protocols. Don’t worry if you don’t recognize some or
any of those names. What is important here is that the emergence of common protocols,
combined with the extra attention that the security aspects commanded in their redaction,
finally created the conditions for introducing the missing logical layer in identity and access
management. It is that extra layer that will make it possible to isolate applications and their
developers from the gory details of authentication and authorization mechanics. In this part,
I am not going to go into the details of what those protocols are or how they work; instead, I
will concentrate on the scenarios that they enable and how to take advantage of them.
Now that you’ve gained some perspective on why today’s approaches are less than ideal, it is
time to focus on how you can move beyond them.
We have been handling low-level details for so long that it may be hard to see the bigger
picture. A useful exercise is to step back and spend a moment analyzing how identity is
actually used for authorization in the real world, and see if what you learn can be of help in
designing your new identity layer. Let’s look at an easy example.
Imagine you are going to a movie theater to see a documentary film. Consider the following
facts:
1. The documentary contains scenes that are not suitable for a young and impression-
able audience; therefore, the clerk at the box office asks you for a picture ID so that he
can verify whether you are old enough to watch the film. You reach for your wallet and
extract your driver’s license, and in so doing you realize that it is expired.
2. Resigned to missing the first show, you walk to a nearby office of the Department of
Licensing (DOL). At the DOL, you hand over your old driver’s license and ask to get a
new one.
10 Part I Windows Identity Foundation for Everybody
3. The clerk takes a good look at you to see whether you look like the photo on record.
Perhaps he asks you to read a few letters from an eye test chart. When he’s satisfied
that you are who you claim to be, he hands you your new driver’s license.
4. You go back to the movie theater and present your new driver’s license to the clerk.
The clerk, now satisfied that you are old enough to watch the movie, issues you a ticket
for the next show.
Figure 1-1 shows a diagram of the transaction just described.
This is certainly not rocket science. We go through similar interactions all the time, from
when we board a plane to when we deal with our insurance companies. Yet, the story
contains precious clues about how we can add our missing identity layer.
Let’s consider things from the perspective of the box-office clerk. The clerk regulates access
to the movie, actually authorizing (or blocking) viewers from acquiring a ticket. The question
that the clerk needs to answer is, “Is this person older than X?” Here comes the interesting
part: the box-office clerk does not verify your age directly. How could he? Instead, he relies
on the verification that somebody else already did. In this case, the DOL certified your birth
date in its driver’s license document. The box-office clerk trusts the DOL to tell the truth
about your age. The DOL is a recognized government institution, and it has a solid business
need to know a person’s correct age because it is relevant to that person’s ability to drive.
The outcome of the interaction would be different if you presented the box-office clerk a
sticky note on which you scribbled your age. In such a transaction, you are not a trustworthy
source. (Unless the clerk knows you personally, he must assume bias on your part—that is,
you could lie in order to get into the movie theater.)
Chapter 1 Claims-Based Identity 11
Note that in this scenario you presented a driver’s license as proof of age, but from the clerk’s
point of view not much would have changed if you had used your passport or any other
document as long as the institution issuing it is known and trusted by the box office clerk.
One last thought before drawing our parallel to software: the box-office clerk does not know
which procedure the DOL clerk followed for issuing you a driver’s license, how the DOL
verified your identity, which things he verified, and how he verified them. He does not need
to know these things because once he decides he trusts the DOL to certify age correctly,
he’ll believe in whatever birth date appears on a valid driver’s license with the picture of
the bearer.
■ The box-office clerk does not verify the customer’s age directly, but relies on a trusted
party (the DOL) to do so and finds the result in a document (the driver’s license).
■ The box-office clerk is not tied to a particular document format or source. As long as
the issuer is trusted and the format is recognized, the clerk will accept the document.
■ The box-office clerk does not know or care about the details of how the customer has
been identified by the document issuer.
This sounds quite efficient. In fact, similar transactions have been successfully taking place for
the last few thousand years of civilization. It’s high time that we learn how to take advantage
of such transactions in our software solutions as well.
Let’s try to extract from the story a generic pattern describing a generic authentication and
authorization system. Pay close attention for the next few paragraphs. Once you understand
this pattern, it is yours forever. It will provide you with the key for dealing with most of the
scenarios you encounter in implementing identity-based transactions.
Entities Figure 1-2 shows the main entities that play a role in most identity-based
transactions.
12 Part I Windows Identity Foundation for Everybody
Identity Provider
Claim
Security
Token
Let’s say that our system includes a user, which in literature is often referred to as a subject,
and the application the user wants to access. In our earlier example, the subject was the
moviegoer; in the general case, a subject can be pretty much anything that needs to be
identified, from an actual user to the application identities of unattended processes.
The application can be a Web site, a Web service, or in general any software that has a
need to authenticate and authorize users. In identity jargon, it is called a relying party, often
abbreviated as RP. In our earlier example, the RP is the combination of the box-office clerk
and movie theater.
The system might include one or more identity providers (IPs). An IP is an entity that knows
about subjects. It knows how to authenticate them, like the DOL in the example knew how
to compare the customer’s face to its picture archives; it knows facts about the customer, like
the DOL knows about the birth date of every licensed driver in its region. An identity pro-
vider is an abstract role, but it requires concrete components: directories, user repositories,
and authentication systems are all examples of parts often used by an identity provider to
perform its function.
We assume that a subject has standard ways of authenticating with an IP and receiving
in return the necessary user information (like the birth date in the example) for a specific
identity transaction. We call that user information claims.
The magical word “claim” finally comes out. A claim is a statement about a subject made by
an entity. The statement can be literally anything that can be associated with a subject, from
attributes such as birth date to the fact that the subject belongs to a certain security group. A
claim is distinct from a simple attribute by the fact that a claim is always associated with the
entity that issued it. This is an important distinction: it provides you with a criterion for decid-
ing if you want to believe that the assertion applies to the subject. Recall the example of the
birth date printed on the driver’s license versus a birth date scribbled on a sticky note: the
clerk believes the former but not the latter because of the entities backing the assertion.
Chapter 1 Claims-Based Identity 13
Claims travel across the nodes of distributed systems in security tokens, which are XML or
binary fragments constructed according to some security standard. Tokens are digitally
signed, which means that they cannot be tampered with and that they can always be traced
back to the IP that issued them (which provides a nice mechanism for associating token
content with its issuer, as required by the definition of claims).
Flow Claims are the currency of identity systems: they are what describe the subject in
the current context, what the IP produces, and what the RP consumes. Here’s how the
transaction unfolds.
Well before your transaction starts, the RP publishes a document, often called a policy, in
which it advertises its security requirements: things such as which security protocols the RP
understands and similar information. This is analogous to the box office hanging up a sign
that says, “Be ready to show your driver’s license or your passport to the clerk.” The most
important part of the RP policy is the list of the identity providers it trusts. This is equivalent
to another sign at the box office specifying, “Drivers’ licenses from U.S. states only; passports
from Schengen Treaty countries only.”
Again, before the transaction starts, the IP publishes an analogous policy document that
advertises its own security requirements. This document provides instructions on how to
ask the IP to issue a security token. In literature, you will often find that IPs offer their token
issuance services via a special flavor of Web services, called STS (Security Token Service).
You’ll read more (MUCH more) about STS throughout the book.
Identity Provider
Policy
STS
2
Security
3 Token
5
4
1
Policy
Subject Relying Party
FIGURE 1-3 The flow of the canonical transaction in claims-based identity
1. The subject wants to access the RP application. It does that via an agent of some sort
(a browser, a rich client, and so on). The subject begins by reading the RP policy. In so
doing, it learns which identity providers the RP trusts, which kind of claims are required,
and which security protocols should be used.
2. The subject chooses one of the IPs that the RP trust and inspects its policy to find out
which security protocol is required. Then it sends a request to the IP to issue a token
that matches the RP requirements. This process is the equivalent of going to the DOL
and asking for a document containing a birth date. In so doing, the subject is required
to provide some credentials in order to be recognized by the IP. The details of the
protocol used are described in the IP policy.
3. The IP processes the request; if it finds the request to be satisfactory, it retrieves the
values of the requested claims, sending them back to the subject in the form of a
security token.
4. The subject receives the security token from the IP and sends it together with his first
request to the RP application.
5. The RP application examines the incoming token and verifies that it matches all the
requirements (coming from one trusted IP, in the expected format, not having been
tampered with, containing the right set of claims, and so on). If everything looks as
expected, the RP grants access to the subject.
This sequence of steps could describe a user buying something online and presenting to
the Web merchant a credit score from a financial institution; it could describe the user of a
Windows Presentation Foundation (WPF) application accessing a Web service on the local
intranet by presenting a group membership claim issued from the domain controller; it could
describe pretty much any identity transaction if you assign the subject, RP, and IP roles in the
right way.
The abstraction layer we were searching for The pattern we’ve been discussing describes a
generic identity transaction. Without going into detail about the actual protocols and tech-
nologies involved, we can say that it just makes assumptions about what capabilities those
technologies should have, such as the capability of exposing policies.
The model is profoundly different from what we have observed in classic approaches:
whereas a traditional application takes care of authentication more or less directly, here the
RP outsources it entirely to a third party, the identity provider. The details of how authenti-
cation happens are no longer a concern of the application developer; all you need to do is
configure your application to redirect users to the intended identity providers and be able
to process the security tokens they issue. Although you can use many different protocols
for obtaining and using a security token, the abstract idea of claims and security tokens is
Chapter 1 Claims-Based Identity 15
onspecific enough to allow you to create a generic programming model for representing
n
users and the outcome of authentication operations without exceptions.
Those changes in perspective finally eliminate the systemic flaw that prevented us from
eradicating from the application code the explicit handling of identity without relying on
demanding infrastructure. All that’s left to do is for platform and developer tools providers to
take advantage of the claims-based identity model in their products.
Note The model is extremely expressive. In fact, you can easily use it for representing
t raditional scenarios too. If the IP and the RP are the same entity, you are back to the case in
which the application itself takes care of handling authentication. The important difference in
the implementation is that both code and architecture will show that this is just a special case
of a more generic scenario. Therefore, the decoupling will be respected and changes will be
accommodated gracefully.
Windows Identity Foundation (WIF) is a set of classes and tools, an extension to the .NET
Framework, that enables you to use claims-based identity when developing ASP.NET or
WCF applications. It is seamlessly integrated with the core .NET Framework classes and in
Visual Studio so that you can keep using the tools and techniques you are familiar with for
developing your applications, while reaping the advantages of the new model when it comes
to identity.
In this section, I will introduce the basics of Windows Identity Foundation: how it exposes
claims-based identity principles to developers, some fundamental considerations about its
structure, and the essential programming surface every developer should be aware of.
16 Part I Windows Identity Foundation for Everybody
Figure 1-4 shows a simplified diagram of how WIF handles authentication in the
ASP.NET case.
Chapter 1 Claims-Based Identity 17
Identity Provider
STS
2 4
3 5
1 Claims
Browser
WIF
Subject Application
FIGURE 1-4 A simplified diagram of how Windows Identity Foundation takes care of handling authentication
for an ASP.NET application
The idea is extremely simple and closely mimics the canonical claims-based identity pattern:
1. WIF sits in front of your application in the ASP.NET pipeline. When an unauthenticated
user requests a page, it redirects the browser to the identity provider pages.
2. Here the IP authenticates the user in whatever way it chooses (perhaps by showing
a page with user name and password, using Kerberos, or in some other way). Then it
manufactures a token with the required claims and sends it back.
3. The browser posts the token it got from the IP to the application, where WIF again
intercepts the request.
4. If the token satisfies the requirements of the application (that is, it comes from the right
IP, contains the right claims, and so on), the user is considered authenticated. WIF then
drops a cookie, and a session is established.
5. The claims in the incoming token are made available to the application code, and the
control is passed to the application.
As long as the session cookie is valid, the subsequent requests won’t need to go through the
same flow because the user will be considered to be authenticated.
You are not supposed to know it yet, but the preceding flow unfolds according to the
WS-Federation protocol specification: most of the magic is done by two HTTP modules:
WSFederationAuthenticationModule (WSFAM) and SessionAuthenticationModule.
18 Part I Windows Identity Foundation for Everybody
The whole trick of using WIF in your application boils down to the following tasks:
1. Configure the application so that the WIF HTTP modules sit in the ASP.NET pipeline in
front of it.
2. Configure the WIF modules so that they refer to the intended IPs, use the right
protocols, protect the planned resources of the application, and in general enforce all
the desired application policies.
3. Access claim values from the application code whenever there is a need in the
application logic to make a decision driven by user identity attributes.
The good news is that in many cases steps 1 and 2 can be performed via Visual Studio
tooling. There is a handy wizard that walks you through the process of choosing an identity
provider, offers you various options, and informs you about the kind of claims you can get
about the user from the specific IP you are referring to. The wizard translates all the prefer-
ences you expressed via point and click in the web.config settings. The next time you press
F5, your application will already apply the new authentication strategy. Congratulations, your
application is now claims-aware.
The good news keep coming; performing step 3 is simple and perfectly in line with what
.NET developers are already accustomed to doing when handling user attributes.
WIF provides two extensions to IIdentity and IPrincipal, IClaimsIdentity and IClaimsPrincipal,
respectively—which are used to make the claims processed in the WIF pipeline available to
the application code. The instances live in the usual HttpContext.Current.User property in
ASP.NET applications. You can use them as is with the usual IIdentity and IPrincipal program-
ming model, or you can cast them to the correct interface and take advantage of the new
functionalities.
Let’s take a quick look at the members of the new interfaces. Note that the list for now is by
no means exhaustive and highlights only properties that will be useful in basic scenarios.
Chapter 1 Claims-Based Identity 19
// Properties
ClaimsIdentityCollection Identities { get; }
}
The only noteworthy news is the Identities collection, which is in fact a list of IClaimsIdentity.
Let’s take a look at the definition of IClaimsIdentity:
Here I stripped out most of the IClaimsIdentity members (because I’ll have a chance to
introduce them all as you proceed though the book), but I left in the most important one,
the list of claims associated with the current user. What does a Claim look like?
Once again, many members have been stripped out for the sake of clarity. The properties
shown are self-explanatory:
■ ClaimType Represents the type of the claim: birth date, role, and group membership
are all good examples. WIF comes with a number of constants representing names of
claim types in common use; however, you can easily define your own types if you need
to. The typical claim type is represented with a URI.
■ Value Specifies, as you can imagine, the value of the claim. It is always a string,
although it can represent a value of a different CLR type. (Birth date is a good example.)
20 Part I Windows Identity Foundation for Everybody
■ Issuer Indicates the name of the IP that issued the current claim.
■ Subject Points to the IClaimsIdentity to which the current Claim belongs, which is a
representation of the identity of the subject to which the claim refers to.
If you understand what a claim is, and if you have any type of identity card in your wallet, the
properties just described are intuitive and easy to use. Let’s look at one easy example.
Suppose that you are working on one application that has been configured with WIF to use
claims-based identity. Let’s say that authentication takes place at the very beginning of the
session, so that during the execution you can always assume the user is authenticated. At a
certain point in your code, you need to send an e-mail notification to your user. Therefore,
you need to retrieve her e-mail address. Here there’s how you do it with WIF:
The first line retrieves the current IClaimsIdentity from the current principal of the thread,
exactly as it would if you wanted to work with the classic .NET IIdentity—the only difference
is the downcast to IClaimsPrincipal.
The second line uses LINQ for retrieving the e-mail address from the current claim collection.
The query is very intuitive: you search for all the claims whose type corresponds to the well-
known Email claim type, and you return the value of the first occurrence you find. For the
e-mail case, it is reasonable to expect that there will be only one occurrence in the collection,
However, this is not true in the general case. Just think of how many group claims would be
generated for any given Windows user; thus, the standard way of retrieving a claims value
must take into account that there might be multiple claims of the same type in the current
IClaimsIdentity.
Nothing in the code shown indicates which protocol or credential types have been used for
authenticating the user. That means you are free to make any changes in the way in which
users authenticate, without having to change anything in your code. Relying on one IP for
handling user authentication and using open protocols delivers true separation of concerns;
therefore, making those changes is also very easy.
Relying on claims for getting information about the user mitigates the need for maintaining
attribute stores, where the data can become stale or be compromised. As you can observe,
the code shown in this section does not contain any call to a local database that could be
broken by routine changes or that could become a problem if the application is moved to an
external host that cannot access local resources. In the age of the cloud, the importance of
being able to move applications around cannot be overestimated.
Chapter 1 Claims-Based Identity 21
Finally, the two lines of code shown earlier will work with any kind of .NET program,
ASP.NET or WCF. The way in which WIF snaps to the two different hosting models and
pipelines is different. I will describe how it does this in detail in Part II; however, from the
perspective of the application developer, nothing changes. The tooling operates its magic
for configuring the application to externalize authentication. All you need to know is how to
mine the results with a consistent API without worrying about underlying protocols, hosting
model, or location.
It would appear that adding one extra layer of indirection worked. We finally found an API
that can secure your applications without forcing you to take care of the details.
Summary
Traditional approaches to adding identity and access management functionality to
applications all have the same issues: they require the developer to take matters into his own
hands, calling for specialized security knowledge, or they heavily rely on the features of the
underlying infrastructure. This situation has led to a proliferation of APIs and techniques,
forcing developers to continually re-learn how to perform the same task with different APIs.
The resulting software is brittle, difficult to maintain, and resistant to change. In this chapter,
I gave some concrete examples of how this systemic flaw in the approach to adding identity
and access management affects development, even development in .NET.
Claims-based identity is an approach that changes the way we think about authentication
and authorization, adding a logical representation of identity transactions and identifying
the roles that every entity plays. By adding that further level of indirection, claims-based
identity created the basis for the decoupling of the programming model and the details of
deploy-time systems. In the chapter, I described the basics of claims-based identity and you
learned how it can be used to model a wide variety of scenarios.
Windows Identity Foundation is one set of .NET classes and tools that helps developers to
secure applications by following the principles of claims-based identity. This chapter intro-
duced the essential programming surface exposed by WIF, and it demonstrated how WIF
does not suffer from the issues I mentioned for traditional approaches.
In the next chapter, I will show how to take advantage of WIF for performing authentication,
authorization and identity-driven customization in a variety of common Web scenarios.
Chapter 4
Advanced ASP.NET Programming
In this chapter:
More About Externalizing Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Single Sign-on, Single Sign-out, and Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Federation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
Claims Processing at the RP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Now that most technicalities are out of the way, we can focus on intended usage of the
product for addressing a wider range of scenarios.
This chapter resumes the architectural considerations that drove Part I of the book, “Windows
Identity Foundation for Everybody,” by tackling more complex situations. I’ll assume you
are now familiar with the flow described in Chapter 3, “WIF Processing Pipeline in ASP.NET.”
I’ll give you concrete indications about how to customize the default behavior of Windows
Identity Foundation (WIF) to obtain the desired effect for every given scenario.
Using claims-based identity in your application is, for the most part, the art of choosing
who to outsource authentication to and providing just the right amount of information for
influencing the process. This chapter will not exhaust all the possible ways you can customize
WIF—far from it. However, it will equip you with the principles you need to confidently
explore new scenarios on your own.
The first section, “More About Externalizing Authentication,” takes a deeper look at the
entities to which you can outsource authentication for your application. I’ll go beyond the
simplifications offered so far, introducing the idea of multiple provider types. A lot of the
discussion will be at the architectural level, helping you with the design choices in your
solutions. However, hardcore coders should not fear! The section also dives deep into the
Security Token Service (STS) project template that comes with the WIF SDK. Although in real
scenarios you’ll rarely need to create a custom STS, given that more often than not you’ll rely
on off-the-shelf products such as Active Directory Federation Services 2.0 (ADFS 2.0), you’ll
find it useful to see a concrete example of how the architectural considerations mentioned
are reflected in code.
The “Single Sign-on, Single Sign-out, and Sessions” section explores techniques that reduce
the need for users to explicitly enter their credentials when visiting affiliated Web sites and
95
96 Part II Windows Identity Foundation for Identity Developers
shows how to clean up multiple sessions at once. One specific case, sessions with sliding
validity, is the occasion for a deeper look at how WIF handles sessions.
The “Federation” section dissects the pattern that is most widely used for handling access
across multiple organizations. I’ll cover more in depth the use of STSes for processing claims,
and we’ll tackle the problem of deciding who should authenticate the user when there are
many identity providers (IPs) to choose from (something known as the home realm discovery
problem). The solutions to those problems can be easily generalized to any situation in which
the relying party (RP)—which was discussed in Chapter 3—needs to communicate options to
the IP. I’ll demonstrate that with another example: the explicit request for a certain
authentication level.
The “Claims Processing at the RP” section closes the chapter by describing how to use
Windows Identity Foundation for preprocessing the claims received from the identity
provider. I’ll briefly revisit the claims-based authorization flow—introduced in minimal terms
in Chapter 2, “Core ASP.NET programming.” Then I’ll show you how to filter and enrich the
IClaimsPrincipal before the application code gains access to it.
After you read this chapter, you’ll be able to make informed decisions about the identity
management architecture of your solutions. You’ll know what it takes to implement such
decisions in ASP.NET. You’ll have concrete experience using the WIF extensibility model for
solving a range of classic identity management scenarios. That experience will help you to
devise your own WIF-based solutions. Once again, I’ll give you practical code indications
about the ASP.NET case, but the general principles introduced here can be applied more
broadly, often to the WCF services case and even on non-Microsoft platforms.
So far, the role played by the entity within a transaction (the identity provider) has been
conflated with the instrument used to perform the function (the STS). The purpose of this
section is to help you better understand the separation between the two by providing
more details about the nature of the identity provider, introducing a new role known
as the federation provider, and studying how those high-level functions reflect on the
implementation of the associated STS.
Chapter 4 Advanced ASP.NET Programming 97
Identity Providers
Being an identity provider is a role, a job if you will. You know from Chapter 1, “Claims-Based
Identity,” that an IP “knows about subjects.” In fact, all the thinking behind the idea of IP is
just good service orientation applied to identity.
The standard example of a concrete identity provider is one built on top of a directory, just as
ADFS 2.0 is built on top of Active Directory. In this scenario, there’s an entity that is capable
of authenticating users and making assertions about them, and all you are doing is making
that capability reusable to a wider audience by slapping a standard façade (the STS) in front
of it. The use of standards when exposing the STS is simply a way of maximizing the audience
and increasing reusability. Here’s an example: Although a SharePoint instance on an intranet
can take advantage of Active Directory authentication capabilities directly via Kerberos,
that is not the case for a SharePoint instance living outside the corporate boundaries and
hosted by a different company. Exposing the authentication capabilities of Active Directory
via ADFS 2.0 makes it possible to reuse identities with the SharePoint instance in the second
scenario, removing the platform and location constraints. WIF is just machinery that enables
your application to take advantage of the same mechanism. It is worthwhile to point out that
SharePoint 2010 is, in fact, based on WIF.
Those characteristics of the IP role tell you quite a lot about what to expect regarding the
structure of the STS exposed by one IP.
Note In literature, you’ll often find that one STS used by one IP can be defined as an “IP-STS.”
In a short, you’ll see how this can sometimes be useful for disambiguating the function the STS
offers.
In the WS-Federation Sign-in flow, described in Chapter 3, you saw that the details of how
the STS authenticates the request for security tokens is a private matter between the STS and
the user. Now you know that such a system has to be something that allows the STS to look
up user information from some store—so that it can be extracted and packaged in the form
of claims. Notable examples are the ones in which the STS leverages the same authentication
methods of the resource it is wrapping. If the IP is a façade for Active Directory and the user
98 Part II Windows Identity Foundation for Identity Developers
is on the intranet, the STS might very well be hosted on one ASPX page that is configured in
Internet Information Services (IIS) to leverage Windows native authentication. If the source
is a membership database, the STS site will be protected via a membership provider, and so
on. The claim value’s retrieval logic in the STS will use whatever moniker the authentication
scheme offers for looking up claim values, but the authentication will often be performed by
the infrastructure hosting the STS rather than the STS code itself.
Nothing prevents one IP from exposing more than one STS endpoint to accommodate
multiple consumption models. For example, the same IP might be listening for Kerberos
authenticated requests from the intranet and X.509 secured calls on an endpoint available
on the Internet; the IP might expose further endpoints, both for browser-based requestors
via WS-Federation and SAMLP or for active requestors via WS-Trust; and so on. This process
offers another insight into how one IP is structured: authentication and claims issuance logic
should communicate but remain separate so that multiple STS endpoints scenarios are han-
dled with little or no duplication. As you’ll see later in the section, the WIF STS programming
model is consistent with that consideration.
An IP will actively manage the list of the RPs it is willing to issue a token for. This is not only
a matter of ensuring that claims are transmitted exclusively to intended recipients, but also a
practical necessity. Especially in the passive case, in which token requests are usually simple,
the IP decides what list of claims will be included in a token according to the RP the token is
being issued for. (“Passive case” is mainly another way to say that you use a browser. You’ll
know everything about it after reading Chapter 5, “WIF and WCF.”) Such a list is established
when the RP is provisioned in the IP’s allow list. Just like WIF enables one application to es-
tablish a trust relationship with an IP by consuming its metadata via the Federation Utility
Wizard, IP software such as ADFS 2.0 includes wizards that can consume the application
metadata and automatically provision the RP entry in its allow list.
Note In computer science as in other disciplines, an allow list is a list of entities that are
pproved to do something or to be recipients of some action. For example, if your company
a
network has an allow list of Web sites, that means you can browse only on those sites and no
other. Conversely, having a blacklist of Web sites means that you can browse everywhere but on
those. An IP normally maintains an allow list of RPs it is willing to issue a token for: any request
for a recipient not in the allow list is refused. The ADFS 2.0 UI describes that as Relying Party
Trust. I am not very fond of that use of “trust,” which in this context has a special meaning (be-
lieving that the claims issued by a given IP about a subject are true), but your mileage may vary.
The IP also keeps track of the certificate associated with the RP, both for ensuring that the
RP has a strong endpoint identity (exposed via HTTPS) and for encrypting the token with the
correct key if confidentiality is required.
Chapter 4 Advanced ASP.NET Programming 99
Nonauditing STS
There are situations, especially in the area of e-government, in which the user would
like to keep private the identity of the RP he is using. For example, a citizen might
want to use a token issued by a government IP proving his age, but at the same time
he would like to maintain his privacy about what kind of sites (for example, liquor
merchants) he is using the token for.
In the business world, the most common scenario requires the IP to have a preexisting
relationship with the RP before issuing tokens for it; therefore, off-the-shelf products
such as ADFS 2.0 normally mandate it.
Federation Providers
Let’s consider for a moment the matter of handling multiple identity providers. Imagine
being a developer for a financial institution. Let’s say you are writing a corporate banking
application, which allows companies to handle the salary payment process for their work-
force. This is clearly one case in which you need to trust multiple identity providers—namely,
all the companies who access your financial institution for managing payments.
From what you have seen so far, you know only one way of handling the situation: adding
multiple FederatedPassiveSignIn controls to your application entry page, each of them
pointing to a different identity provider. Although the approach works, it can hardly be
called a full externalization of identity management because provisioning and deprovisioning
identity providers forces you to change the application code. Things get worse when you
have one entire portfolio of applications to make available to a list of multiple identity
providers—having to reapply the trick mentioned previously for every application rapidly
100 Part II Windows Identity Foundation for Identity Developers
ecomes unsustainable as the number of apps and IPs goes up. This clearly indicates the
b
need to factor out IP relationship management from the application responsibilities.
Another common issue you might encounter has to do with the ability of your application to
understand claims as issued by one identity provider. Here is why:
■ Sometimes you might have simple format issues. For example, the users you are
interested in might come from another country and their IP might use claim URIs
containing locale-specific terms your application does not understand. (An English
application might need to know the name of the current user and expect it in an
http://claims/name format, while an Italian IP might send the desired information in the
http://claims/nome claim format.)
■ Sometimes the information will need some processing before being fed to your
application. For example, an IP might offer a birth date claim, but your application
might be forbidden from receiving personally identifiable information (PII). All you
require here is a simple Boolean value indicating if the user is below or above a certain
threshold age. Although the information is clearly available to the IP, it might not be
offered as a claim.
■ Finally, you might need to integrate the claims received from the IP with further
information that the IP does not know. For example, you might be an online book shop
accepting users from a partner IP. The IP can provide you with name and shipping
address claims, but it cannot provide you with the last 10 books the user bought from
your store. That is data that belongs to you, and you have the responsibility of making
it available in the form of claims if you want to offer to your developers a consistent
way of consuming identity information.
What is needed here is a means of doing some preprocessing—some kind of intermediary
that can massage the claims and make them more digestible for the application.
The standard solution to these issues is the introduction of a new role in identity transactions,
which goes by the name of Federation Provider (FP).
The reason that it’s known as the Federation Provider is that enabling federation is the
primary purpose that led to the emergence of this role. In a nutshell, here’s how that works.
Imagine company A is a manufacturer that has a number of line-of-business (LOB) applica-
tions for its own employees, including applications for supply management, inventory, and
other usual stuff. Company B is a retailer that sells the products manufactured by A. To im-
prove the efficiency of their collaboration, A and B decide to enter into a federation agree-
ment: certain B employees will have access to certain A applications. Instead of having every
A application add the B identity provider and having the B IP provision every application as a
recognized RP, A exposes a Federation Provider.
The B IP will provision the A FP just like any other RP, associating to the relationship the list of
claims that B decides to share with A about its users. All of the A applications that need to be
accessible will enter into a trust relationship with the A FP, outsourcing their authentication
management to its STS. Figure 4-1 shows the trust relationships and the sign-in flow.
IP FP
B A
IP-STS R-STS
Trust
B Trust
3 4
2
5 B A
6
APP
Browser
1
7
A
FIGURE 4-1 The authentication flow in a federation relationship between two organizations
In other words, running an STS is serious business: don’t let anybody convince you otherwise.
An endpoint that understands WS-Federation, WS-Trust, or SAMLP requests and can issue a
token accordingly technically fits the definition of “STS,” but protocol capabilities alone can’t
help with any of the requirements just mentioned.
This is why in the vast majority of real-world scenarios it is wise to rely on off-the-shelf STS
products, such as ADFS 2.0. Those products host STS endpoints and advanced management
features that simplify both small and large maintenance operations that running an IP or an
FP (or both) entails. Let’s take ADFS 2.0 as an example: ADFS 2.0 is a true Windows server
role—tried, stressed, and tested just like any other Windows server feature.
The Windows Identity Foundation SDK makes the generation of an STS deceivingly simple
by offering Microsoft Visual Studio templates for both ASP.NET Web sites and WCF services
projects that implement a bare-bones STS endpoint (for WS-Federation and WS-Trust, re-
spectively). The Generate New STS option in the Add STS Reference Wizard just instantiates
one of those templates in the current solution. Those test STSes are an incredibly useful tool
for testing applications, thanks to the near absence of infrastructure requirements (ADFS 2.0
requires a working Active Directory instance, SQL Server, Windows Server 2008 R2, and so
on) and instantaneous creation. As somebody who had to write STSes from scratch with WCF
in the past (a long and messy business), I am delighted by how easy it is to generate a test
STS with WIF. For the same reason, such test STSes are consistently used in WIF samples and
courseware. This book is no exception.
Why do I say “deceivingly simple”? Because of all the requirements I listed earlier. WIF can
certainly be used to build an enterprise-class STS—it has been used for building ADFS 2.0
itself. However, between the STS template offered by the WIF SDK and ADFS 2.0, there are
many, many man-years of design, enormous amounts of development and testing, tons of
assumptions and default choices, brutal fuzzing, relentless stressing, and so on. The fact that
the STS template gives you back a token does not mean it can be used as is in a real-life sys-
tem. People regularly underestimate the effort required for building a viable STS, an error of
judgment that can result in serious issues. That is why I always discourage the creation of cus-
tom STSes unless it’s absolutely necessary, and there’s not a lot of detailed guidance on that.
Now that I’ve got the disclaimer out of the way: this chapter will use a lot of custom STSes.
Taking a peek inside an STS is a powerful educational tool that can help you understand
scenarios end to end. Being able to put together test STSes can help you simulate complex
setups before committing resources to them. Finally, you’ll likely encounter situations in
which setting up a custom STS is the way to go—for example, if your user credentials are
not stored in Active Directory. The guidance here is absolutely not enough for handling the
task—that would involve teaching how to build secure, scalable, manageable, and perform-
ing services, which is well beyond the scope of this text—but it can be a starting point for
understanding the token issuance model offered by WIF.
104 Part II Windows Identity Foundation for Identity Developers
The rest of the section describes the STS template for ASP.NET offered by WIF SDK 4.0. As
you read through this section, I suggest you go back to the simple example you created in
Chapter 2 and put breakpoints on the parts of the STS project being discussed. Every time
something is not too clear, try a test run in the debugger to get a better sense of what’s
going on.
FIGURE 4-2 The templates installed by WIF SDK 4.0, with the template used for creating an ASP.NET STS
highlighted
The STS Web site is typically created on the local IIS. Although it is possible to use the plain
HTTP binding, in general the STS Web site will be created on an HTTPS endpoint.
Note Using HTTP in this case is normally a really bad idea. Even if you encrypt the tokens you
issue, and even if the RP can take steps for mitigating the risk of accepting stolen tokens, the
reality is that using plain HTTP on browser-based scenarios makes you vulnerable to man-in-
the-middle and other attacks. In Chapter 5, you’ll have a chance to dig deeper into the topic.
Chapter 4 Advanced ASP.NET Programming 105
Although you can get WIF to work on Web sites running on the ASP.NET Development
Server, there are limitations (for example, the built-in Web server does not support
HTTPS) and complications (for example, the dynamically assigned ports change the site
URIs and thus force changes in the configuration). Because of this, it’s just simpler to
use IIS.
Similar considerations led me to use Web site projects rather than Web application
ones. Web application development starts on the file system and requires extra steps
for hosting (and debugging) the application in IIS. Furthermore, at the time of this
writing, Fedutil.exe is not a big friend of the dynamic ports system featured by ASP.NET
Development Server. The Add STS Reference Wizard will not always work as expected
when launched on a Web application project.
That is the structure of a minimal Web site protected via Forms authentication, containing
the classic Login.aspx and Default.aspx pages. The web.config file is minimal, containing prac-
tically nothing specific to WIF apart from the reference to its assembly and a few values in
the <appSettings>. The Web site is configured to use Forms Authentication. As you saw in the
first example in Chapter 2, Login.aspx does not actually verify any credentials and represents
106 Part II Windows Identity Foundation for Identity Developers
just a pro-forma authentication page: the page will just create the authentication cookie and
start a session regardless of the credentials entered in the UI.
All this emphasizes what I mentioned earlier about the separation between the STS functions
and the authentication mechanism: here Forms authentication is the method of choice, but
it is independent from what WIF does for implementing the token-issuing functionality. The
authentication system could be easily substituted with Windows integrated authentication
or whatever else, as long as it takes care of authenticating the user before giving access to
Default.aspx.
Note An obvious observation is that the STS template generates an IP-STS, something that
uthenticates users and issues tokens describing them. It is not hard to transform it into an
a
R-STS: you can just run the Add STS Reference Wizard on the STS project itself, and that will be
enough for excluding the current Forms authentication settings and externalize authentication
to the second STS of your choosing. However, that would change only the way authentication is
handled, not the way claims are generated: an R-STS transforms incoming claims, but the default
template implementation does not do that. At the end of the section, I’ll discuss what you need
to change for modifying the claim issuance criteria as well.
The Default.aspx page represents the STS endpoint, and it takes care of instantiating and
executing the token-issuing logic in the context of an ASP.NET request. The page itself
does not contain much. What we are interested in is the Page_PreRender handler in
Default.aspx.cs:
try
{
if ( action == WSFederationConstants.Actions.SignIn )
{
// Process signin request.
SignInRequestMessage requestMessage =
(SignInRequestMessage)WSFederationMessage.CreateFromUri( Request.Url );
if ( User != null && User.Identity != null && User.Identity.IsAuthenticated )
{
Chapter 4 Advanced ASP.NET Programming 107
SecurityTokenService sts =
new CustomSecurityTokenService( CustomSecurityTokenServiceConfiguration.Current );
SignInResponseMessage responseMessage =
FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest
(requestMessage, User, sts );
FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse
(responseMessage, Response );
}
else
{
throw new UnauthorizedAccessException();
}
}
else if ( action == WSFederationConstants.Actions.SignOut )
{
// Ignore the rest for now
// ...
}
}
This code is the STS counterpart of the WS-Federation processing logic that WIF provides for
RPs, as studied in Chapter 3. Whereas the RP generates the request for a security token and
validates it, the STS listens to those requests and issues tokens according to the
WS-Federation protocol. Here’s a quick explanation of what the method does:
■ The handler inspects the request QueryString for the WS-Federation action parameter,
wa. Let’s focus on the case in which wa is present and has the value wsignin1.0, which
indicates a request for a token. (We’ll explore the sign-out case later in the chapter.)
■ The code creates a new SignInRequestMessage from the request—that is, a name-value
collection that surfaces the various WS-Federation parameters as properties.
■ Do you have a non-empty IPrincipal? Is the current user authenticated? If it isn’t, an
UnauthorizedAccessException is thrown and the user is redirected to the login page. If it
is, the following must take place:
❑ Get an instance of SecurityTokenService by retrieving an instance of a subclass,
CustomSecurityTokenService. This class contains the core STS logic, as you’ll see in
a moment.
❑ The new STS instance, along with the incoming SignInRequestMessage and
the user’s IPrincipal, is fed to FederatedPassiveSecurityTokenServiceOperations.
ProcessSignInRequest, where it will be used for issuing the token and producing a
suitable SignInResponseMessage.
❑ Finally, FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse
writes the SignInResponseMessage in the response stream, which will be
eventually forwarded to the RP and processed as you saw in Chapter 3.
108 Part II Windows Identity Foundation for Identity Developers
There are a lot of classes with long names, but in the end the code shown earlier just feeds
the authenticated user and the request to a custom SecurityTokenService class and sends back
the result. The STS project features an App_Code folder, which contains all the classes the STS
needs, including the CustomSecurityTokenService class; all you need to do is take a look at
what happens there.
Finally, we get to the very heart of the STS: the class in CustomSecurityToken.cs. The code
generated by the template has the purpose of doing the bare minimum for obtaining a
working STS; hence, I won’t analyze it too closely here, except for pointing out some notable
behavior. Rather, I’ll use it as a base for telling you about the more general model that you
have to follow when developing a custom STS in WIF. Note that the considerations about
SecurityTokenService apply both to ASP.NET and WCF STSes.
of SecurityTokenService methods, which are invoked following a precise syntax that leads the
form request validation to emit the token bits. Complete coverage of that sequence is be-
yond the scope of this book; however, here I’ll list the main methods you should know about:
If the AppliesTo value is valid, it is fed into the Scope object. It will be needed for
the AudienceRestriction element of the issued token, which in turn will be vali-
dated by WIF against the <audienceURI> config element on the RP.
❑ Should the issued token be encrypted? If yes, with which certificate? The STS
configuration should specify whether the token should be encrypted. If it should
110 Part II Windows Identity Foundation for Identity Developers
be, the same store that was used for establishing whether the RP was valid should
also carry information about which encryption certificate should be used. The
template uses a value from config.
❑ To which address should the token be returned? The template assumes that
wtrealm—that is, the AppliesTo value—is both the identifier of the RP and its
network-addressable URI. As a result, GetScope assigns the value of AppliesTo to
the ReplyToAddress property of the Scope object.
Important Although in many cases it is true that AppliesTo contains the network
ddressable endpoint of one RP, that does not always hold. Sometimes wtrealm will be a
a
logical identifier for the application rather than a network address, and the actual address
to which the token should be returned will be different. A way of handling this is by
sending the actual address in the request via the wreply parameter, and then assigning
it to Scope.ReplyToAddress (from RequestSecurityToken.ReplyTo). ReplyTo addresses
should always be thoroughly validated because supporting wreply opens your STS up
to redirect attacks.
return outputIdentity;
}
Note ADFS 2.0 uses that approach in every case. The list of claims to issue is always
established on the basis of the RP for which the token is being issued.
Chances are that the list of claims to use will be available in the same store you
used in GetScope for retrieving the RP URI and encryption certificate.
WS-Trust (and WS-Federation, via wreq or wreqptr parameters) supports request-
ing a specific list of claims for every request. Although that requires more work,
which probably includes checking on an RP-bound list if the required claims are
allowed for that given RP, there are many advantages to the approach. Apart
from minimal disclosure and privacy considerations, possibly a bit out of scope
here, one obvious advantage is that this can help keep the token size under con-
trol. A token representing a Windows identity can have many group claims. If for
a given transaction the group claim is not required, being able to exclude it can
dramatically shrink the resulting token.
If you want to support requests that specify the required claims, you’ll find that
list in the RequestSecurityToken.Claims collection.
❑ Given the current principal, which claim values should be assigned?
Together with the request authentication method, this is the question that
determines whether your STS is an IP-STS or an R-STS.
112 Part II Windows Identity Foundation for Identity Developers
One IP-STS uses some claims of the incoming IClaimsPrincipal for looking up the
caller in one or more attribute stores, from where the STS will retrieve the values
to assign to the established claim types. That’s the direct descendent of using
a user name for looking up attributes in a profile store; in fact, it can take place
in exactly the same way if you have a user name claim. Of course, you are not
limited to it—you can use any claim you like.
One R-STS processes the claims in the incoming IClaimsPrincipal in arbitrary ways,
storing the results in other claims in the outgoing IClaimsIdentity. Note that the
STS can also just copy some claims from the incoming token to the outgoing one
without modification, and it can even add new claims in the same way the IP-STS
does. I’ll show some examples of this later, during the federation and home-realm
discovery discussions.
ADFS 2.0 offers a management UI, where administrators can specify how to
source or transform claims. The mappings can be specified via a simple UI or via
a SQL-like language that is especially well suited for claims issuance. In your own
STS, you can embed the corresponding code directly in GetOutputClaimsIdentity,
or you can develop a mechanism for driving its behavior from outside.
Metadata
You know about metadata from Chapter 3. If you need to change something in the metadata
document of one RP, you can simply edit it. Perhaps that’s not the greatest fun you’ll have,
but it is feasible.
Doing the same for one STS is out of the question because an STS metadata document must
always be signed. The WIF SDK has one example showing how to use the WIF API for gener-
ating a metadata document programmatically. It’s not rocket science, just a lot of serializa-
tion. Generating the document has the advantage of keeping it automatically updated if you
play your cards well and read things from the config. It also has another advantage of grant-
ing you better control of complicated situations, such as cases in which on the same Web site
you expose both WS-Federation and WS-Trust endpoints.
Any dynamic content generation mechanism will do. My favorite is exposing a WCF service
and hiding the .svc extension with some IIS URL rewriting.
s essions are still open. Finally, I’ll share a few tricks you can use for tweaking the way in which
WIF handles sessions.
Single Sign-on
In Chapter 3, I illustrated the dance that WS-Federation prescribes for signing in a relying
party and how the WIF object model implements that. Let’s move the scenario a little further
by supposing that you want to model the case in which the user visits more than one RP
application.
If the RPs have absolutely nothing in common, there is not much to be said: every RP session
will have its own independent story. But what happens if, for example, two RPs trust the same
STS? Things get more interesting. Figure 4-4 briefly revisits the sign-in sequence, showing the
user signing in the first RP application, named A.
STS
2
3 4
1
5 A
STS A
3 5
FIGURE 4-4 The user signs in the RP named A, and in so doing it receives session cookies both from
the STS and A
such as Kerberos (which leverages the session that the user created from her workstation
at login time) or Forms authentication (which drops a session cookie, just like the WIF STS
template does). If that is the case, at the end of the sign-in sequence the user’s machine will
have two cookies: one representing the session with A, created by WIF, and one representing
the session with the STS. Starting from that situation, let’s now look at Figure 4-5 to see what
happens when the user signs in with B, another RP, that trusts the same STS.
STS
1
4
B
STS A
B
4 A
FIGURE 4-5 The user signs in to the RP named B, and the existing session with the STS allows the user to sign
in without being prompted for the STS credentials
The flow starts as usual, the user requests a page from B (step 1, as shown in Figure 4-5) and
gets redirected to the STS to obtain a token (step 2). However, this time the user is already
authenticated with the STS site because there is an active session represented by the STS
cookie. This means the request for the STS page—say, Default.aspx if you are in the WIF STS
template case—leads straight to execution of the SecurityTokenService issuing sequence
without showing to the user any UI for credential gathering. The token is issued silently
(step 3) and forwarded to B (step 4) according to the usual sequence. From the moment the
user clicks on the link to B and the browser displays the requested page from B, only some
flickering of the address bar in the browser will give away the fact that some authentication
took place under the hood. That’s pretty much what Single Sign-on (SSO) means: the user
went through the experience of signing in only once, and from that moment on the system is
able to gain access to further RPs without prompting the user for credentials again.
SSO is an all-time favorite for end users. Using a single set of credentials for different Web
sites without being reproached for it? Typing stuff only once? Count me in! This is also
something that greatly pleases system administrators, because reducing the number of
credentials to manage eases the administrative burden, lowers the probability that users will
reuse the same password in different Web sites, and so on.
Chapter 4 Advanced ASP.NET Programming 115
Note By now, you can certainly see the fundamental difference between authenticating with
an STS only once, and silently obtaining tokens for multiple Web sites after that single credential
gathering moment and reusing the same credentials across multiple Web sites (each handling
their own authentication). Whereas the first approach minimizes the chances of passwords being
stolen, the second maximizes it.
You’ll find that although most uninitiated people will not understand most of the stuff I
covered in this book, everybody will have a clear, intuitive understanding and appreciation
of SSO. Perhaps not surprisingly, SSO became the Holy Grail of the industry long before the
emergence of claims-based identity, and as of today a lot of people think that the ultimate
goal of identity management should be universal SSO.
The good news? As long as the STS creates a session in its authentication method, having
SSO across Web site RPs protected via WIF is something that works right out of the box.
There’s no arcane WS-Federation trick here, just good old cookies and a bit of trust
management.
Single Sign-out
In one of those rare instances in which building is easier than destroying, you are about to
discover that Single Sign-out is somewhat harder to implement than Single Sign-on.
Single Sign-out, or SSOut, takes place when the termination of one session with a specific RP
triggers the cleanup of state and other sessions across the same über session. In other words,
signing out from one Web site cascades through all the Web sites that were part of the SSO
club and signs out from them as well.
Note The basic idea of SSOut is readily understood and can be easily experienced even outside
federated scenarios: the sign-out option of Live ID, which (at the time of this writing) throws you
out at once from all the Web sites accepting Live ID you’ve been signing in to, is a good example
of that. However, in literature “Single Sign-out” is almost always used as a synonym of “federated
sign-out” and is expected to behave as specified by WS-Federation or SAMLP.
116 Part II Windows Identity Foundation for Identity Developers
The mechanics of SSOut are not very straightforward, especially because the outcome of the
entire process relies on all the entities involved receiving messages and complying. Both of
those things are hard to enforce without reliable messaging or transactions; hence, the entire
thing ends up being a “make your best effort” attempt. This state of affairs was well known
to the authors of the WS-Federation specification, who were not especially prescriptive in
describing the messages and mechanisms used for implementing SSOut. WIF does support
SSOut out of the box for RPs, but the STS template is not especially thorough in implement-
ing all its details. In this section, I’ll clue you in to the things you need to add for achieving
more complete support.
What keeps a user session alive, apart from the sheer Forms authentication machinery? First
of all, it’s the existence (and validity) of the session cookie generated at sign-on time. The
default name used by WIF for that cookie is FedAuth, with an additional FedAuth1…FedAuthn
if the size of the SessionSecurityToken requires multiple cookies. You can easily take care
of that yourself—it’s just a matter of calling FormsAuthentication.SignOut and deleting the
session cookie (by hand or via SessionAuthenticationModule.DeleteSessionTokenCookie).
Second, it’s the session with the STS. If you delete the session with the RP but the user still
has a valid session with the STS, she will still have access to the RP. The first unauthenticated
GET elicits the usual redirect to the STS, and a valid session means that the user will be issued
a new token without even being prompted for credentials.
The RP cannot directly change the STS session. In fact, it is not even supposed to know how
that session (if any) is implemented to begin with! Luckily, WS-Federation defines a way for
the RP to ask the STS to sign out the current principal. It will be up to the STS to decide what
specific steps that entails in the context of its own implementation.
The mechanism that WS-Federation uses for signing out is straightforward: you are supposed
to do a GET of the STS endpoint page with the parameter wa=wsignout1.0 and a wreply in-
dicating where you want the browser to be redirected after the sign out is done. Once again,
this is something you could do yourself; but why bother, when there is something that can
take care of both the RP session cleanup and sending the sign-out message to the STS? That
something is FederatedPassiveSignInStatus, an ASP.NET control that comes with WIF.
FederatedPassiveSignInStatus, as the name implies, can be used for easily displaying on your
Web site the current state of the session. Drag it on any page, and its appearance will change
according to whether you have a valid session in place. If you do, by default the control
appears as a hyperlink with the text “Sign Out.” Clicking that link results in the current RP
session being cleaned up. If the control property SignOutAction is set to FederatedSignOut,
Chapter 4 Advanced ASP.NET Programming 117
the control takes care of sending the wsignout1.0 message to the STS indicated in the
SessionSecurityToken. Handy, isn’t it? That’s my favorite way of implementing sign out with
WIF—it’s easy and painless.
All that is left to do is for the other RPs to get rid of their sessions. Note that the STS already
eliminated its own session with the user; hence, there is no risk of silent re-issuing after the
other RPs do their cleanup.
118 Part II Windows Identity Foundation for Identity Developers
Once again, WS-Federation provides a mechanism for that. I won’t go into the details
here—it suffices to say that one way of requesting a cleanup to one RP is simply by doing a
GET request on the RP and including in the query string the action wa=wsignoutcleanup1.0.
You could specify an address via wreply to return to after the cleanup is done, but things
can get problematic here. What if you have three RPs that need to clean up their sessions?
If you are relying on the browser to perform the necessary GETs, you’d have to chain the
requests. In addition to being complicated, this is a very brittle approach because some-
thing going wrong with one RP would jeopardize the chance of sending cleanup requests
to all the subsequent RPs in the list. The STS can avoid using the browser and send the GET
requests directly, but again, this is not very straightforward. For those reasons and others,
the presence of a wreply is optional in wsignoutcleanup1.0 messages; it is acceptable to re-
turn something from the RP that somehow indicates the outcome of the operation. There’s
more: the cleanup operation is required to be idempotent—that is, you should be able to call
the same operation multiple times without affecting the outcome or raising errors. This al-
lows you to retry the operation if you think something went wrong, without worrying about
creating error situations.
Now for some good news: RPs secured via WIF handle wsignoutcleanup1.0 messages out of
the box. The WSFAM looks out for those messages in its AuthenticateRequest handler. If the
incoming message has a wsignoutcleanup1.0 action, WSFAM promptly deletes the session
cookie and drops the corresponding token from the cache.
What sets apart the cleanup from all other actions I’ve described so far is that it might not
end with a redirect. If the message contains a wreply, WSFAM dutifully returns a 302 message
to the indicated location; if it doesn’t, it will return an image or .gif of a green check mark.
Returning the bits of one image upon successful cleanup is part of a clever strategy for
working around the “chaining of sign-out redirects” problem described earlier. After the STS
successfully clears its own session, it can return a page containing an <img> element for
each RP whose session is up for cleanup. If the src value of the <img> elements is of the form
https://RPAddress/Default.aspx?wa=wsignoutcleanup1.0, just rendering the list of images in
the browser sends as many cleanup messages to the RPs in the list. Every successful cleanup
sends back the image of the green check box, which the STS page can use for confirming
that the sign-out actually took place for a given RP. Failure to render the image might be an
indication that something went wrong with the cleanup operations.
All of the preceding activity relies on the fact that the STS will keep track of the RPs for which
it issued a token in the context of one federated session. At sign-out time, the STS needs to
remember the address of all RPs in order to generate the correct cleanup URIs for the src of
the images collection in the sign-out page. The STS can use whatever state-preserving mech-
anism its owner sees fit. In my samples, I usually keep the list of RP URIs in a protected cookie
because it requires zero state-management code on the server.
Chapter 4 Advanced ASP.NET Programming 119
Did you get lost in all the back and forth required by the SSOut process? Let’s take a look
at one example. Figure 4-6 illustrates the Single Sign-out message flow across two Web
sites and a common STS, together with what happens to the client’s cookie collection as the
sequence progresses.
STSASPXAUTH
STSASPXAUTH
SsoSessions
SsoSessions
SsoSessions
FedAuth
FedAuth
STS
2
SsoSessions
f%2fWebSiteA%2fDefault.aspx
FedAuth
...
Set-Cookie: FedAuth=; expires=Fri, 18-Jun-2010
05:47:03 GMT; path=/SSOWebSiteA/
GET
/STS/?wa=wsignout1.0&wreply=https%3a%2f%
2fWebSiteA%2fDefault.aspx HTTP/1.1
3 ..
Cookie: .STSASPXAUTH … SsoSessions
HTTP/1.1 200 OK
…
WebSiteA WebSiteB STS Set-Cookie: .STSASPXAUTH=; expires=…; path=/; HttpOnly
Set-Cookie: SsoSessions=; expires=… path=/
<html>...<body>
<form method="POST" action=" /?wa=wsignout1.0&wreply=…">
You are now signed out of the following sites:
<div id="SignoutLinks">
4
FedAuth
<p><a href='https://WebSiteA/'>WebSiteA/</a>
<img src='https://WebSiteA/?wa=wsignoutcleanup1.0'/> </p>
<p><a href='https://WebSiteB/'>WebSiteB/</a>
<img src='https://WebSiteB/?wa=wsignoutcleanup1.0/></p>
</div></form>
</body>..</html>
5 HTTP/1.1 200 OK
Content-Type: image/gif
...
WebSiteA WebSiteB STS GIF89a
GET / WebSiteB/?wa=wsignoutcleanup1.0 HTTP/1.1
Cookie: FedAuth=…
6 HTTP/1.1 200 OK
Content-Type: image/gif
Set-Cookie: FedAuth=; expires=…;
path=/SSOWebSiteB/
...
GIF89a
Let’s examine every step. In the beginning, the user is signed in to WebSiteA and WebSiteB
via tokens obtained from STS, and his browser is currently on WebSiteA. His cookie collec-
tion contains a FedAuth session cookie for each RP and one Forms authentication cookie
(STSASPXAUTH) with STS. It also has an SsoSessions cookie with STS, which contains the list of
RPs for which the STS issued a token in the context of its STSASPXAUTH session. Here’s how
the process unfolds:
FederatedPassiveSecurityTokenServiceOperations.ProcessSignOutRequest(
requestMessage, User, /*requestMessage.Reply*/ null, Response );
// new
string[] signedInUrls = SingleSignOnManager.SignOut();
lblSignoutText.Visible = true;
foreach (string url in signedInUrls)
{
SignoutLinks.Controls.Add(
new LiteralControl(String.Format(
"<p><a href='{0}'>{0}</a> <img src='{0}?wa=wsignoutcleanup1.0'
title='Signout request: {0}?wa=wsignoutcleanup1.0'/></p>," url)));
}
}
The changes are straightforward. The call to ProcessSignOutRequest does not redirect
to wreply, because after it cleaned up its own session there’s still work to do that would
not be done if it redirected as in the default case. After cleaning its own session, the
STS prepares the UI for the sign-out by turning on the visibility of a sign-out message
(here, in a label). The call to SingleSignOutManager returns the list of all the RPs whose
session should be cleaned up. The foreach that appears below that uses that list for
generating and appending to the page as many images as needed, which will dispatch
the cleanup message once they are rendered.
122 Part II Windows Identity Foundation for Identity Developers
Sliding Sessions
By default, WIF creates SessionSecurityTokens whose validity is based on the validity of the
incoming token. You can overrule that behavior without writing any code, by adding to the
<microsoft.identityModel> element in the web.config file something like the following:
<securityTokenHandlers>
<add type="Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler,
Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35">
<sessionTokenRequirement lifetime="0:02" />
</add>
</securityTokenHandlers>
Note The lifetime property can restrict only the validity expressed by the token to begin with. In
the preceding code snippet, I set the lifetime to 2 minutes, but if the incoming security token was
valid for just 1 minute, the session token would have 1 minute of validity. If you want to increase
the validity beyond what the initial token specified, you need to do so in code (by subclassing
SessionSecurityTokenHandler or by handling SessionSecurityTokenReceived).
Now, let’s say that you want to implement a more sophisticated behavior. For example,
you want to keep the session alive indefinitely as long as the user is actively working with
the pages. However, you want to terminate the session if you do not detect user activity in
the past 2 minutes, regardless of the fact that the initial token would still be valid. This is a
common requirement for Web sites that reveal personally identifiable information (PII) or
give control to banking operations. Those are cases in which you want to ensure that the
user is actually in front of the machine and the pages are not abandoned to the mercy (or
mercenary instincts) of bystanders.
In Chapter 3, I hinted at this scenario, suggesting that it could be solved by subclassing the
SessionAuthenticationModule. That is the right strategy if you expect to reuse this function-
ality over and over again across multiple applications, given that it neatly packages it in a
class you can include in your code base. In fact, SharePoint 2010 offers sliding sessions and
implements those precisely in that way. If, instead, this is an improvement you need to apply
Chapter 4 Advanced ASP.NET Programming 123
only occasionally, or you own just one application, you can obtain the same effect simply by
handling the SessionSecurityTokenReceived event. Take a look at the following code:
<script runat=”server”>
void SessionAuthenticationModule_SessionSecurityTokenReceived
(object sender, SessionSecurityTokenReceivedEventArgs e)
{
DateTime now = DateTime.UtcNow;
DateTime validFrom = e.SessionToken.ValidFrom;
DateTime validTo = e.SessionToken.ValidTo;
double halfSpan = (validTo – validFrom).TotalMinutes / 2;
if ( validFrom.AddMinutes( halfSpan ) < now && now < validTo )
{
SessionAuthenticationModule sam = sender as SessionAuthenticationModule;
e.SessionToken = sam.CreateSessionSecurityToken(e.SessionToken.ClaimsPrincipal,
e.SessionToken.Context,
now, now.AddMinutes(2), e.SessionToken.IsPersistent);
e.ReissueCookie = true;
}
}
//...
As you certainly guessed, this is a fragment of the global.asax file of the RP application.
SessionSecurityTokenReceived gets called as soon as the session cookie is deserialized
(or resolved from the cache if you are in session mode). Here you verify whether you
are within the second half of the validity window of the session token. If you are, you
extend the validity to another 2 minutes, starting now. That change takes place on the
in-memory instance of the SessionSecurityToken. Setting ReissueToken to true instructs the
SessionAuthenticationModule to persist the new settings in the cookie after the execution
leaves SessionSecurityTokenReceived. Let’s say that the token is valid between 10:00 a.m. and
10:02 a.m. If the current time falls between 10:01 a.m. and 10:02 a.m.—say, 10:01:15—the
code sets the new validity boundaries to go from 10:01:15 to 10:03:15 and saves those in the
session cookie.
Note This is the same heuristic that FormsAuthentication uses for sliding expiration. Why renew
the session only during the second half of the validity interval? Well, writing the cookie is not for
free. This is just a heuristic for reducing the times at which the session gets refreshed, but you
can certainly choose to apply different strategies.
pages earlier, you’ll realize that if the STS session outlives the RP session the user will just
silently re-obtain the authentication token and renew the session without even realizing
anything happened.
This works well when all the requests in the context of a user session are aimed at the same
machine. But what happens when the RP is hosted on multiple machines—for example, in a
load-balanced environment? A session cookie might be created on one machine and sent to
a different machine at the next postback. Unless the two machines share the same machine
key and use it for encrypting the cookie instead of taking advantage of the DPAPI Encryption
key, a cookie originated from machine A will be unreadable from machine B.
There are various solutions to the situation. One obvious one is using sticky sessions—that is,
guaranteeing that a session beginning with machine A keeps referring to A for all subsequent
requests. I am not a big fan of that solution because it dampens the advantages of using a
load-balanced environment. Furthermore, you might not always have a say in the matter—
for example, if you are hosting your applications on a third-party infrastructure (such as
Windows Azure), your control of the environment will be limited.
Another solution is to synchronize the machine keys of every machine and use those for
encrypting cookies. I like this better than using sticky sessions, but there is an approach I like
even better. More often than not, your RP application will use Secure Sockets Layer (SSL),
which means you need to make the certificate and corresponding private key available on
every node. It makes perfect sense to use the same cryptographic material for securing the
cookie in a load-balancer-friendly way.
WIF makes the process of applying the aforementioned strategy in ASP.NET applications
trivial. The following code illustrates how it can be done:
e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
}
Instead of using the usual inline approach, this time I am showing you the code-behind
file global.asax.cs. OnServiceConfigurationCreated is—Surprise! Surprise!—a handler for
the ServiceConfigurationCreated event and fires just after WIF reads the configuration. If
you make changes here, you have the guarantee that they will already be applied from the
request coming in.
Note Contrary to what various samples out there would lead you to believe,
OnServiceConfigurationCreated is pretty much the only WIF event handler that should be
associated to its event in Application_Start. This has to do with the way (and the number of times)
ASP.NET invokes the handlers though the application lifetime.
Note Why do you sign the cookie? Wouldn’t it be enough to encrypt it? If you use the RP
c ertificate, encryption would not be enough. Remember, the RP certificate is a public key. If you
just encrypt it, a crafty client can just discard the session cookie, create a new one with super-
privileges in the claims, and encrypt it with the RP certificate. The RP would not be able to tell
the difference. Adding the signature successfully prevents this attack because it requires a private
key, which is not available to the client or anybody else but the RP itself.
Federation
At the beginning of the chapter, I introduced the Federation Provider and discussed some
of the advantages that the IP-FP-RP pattern offers. The temptation to expand the architec-
tural considerations about this important pattern is strong; however, here I want to keep
the focus on WIF and give you a concrete coding example. There are many good high-level
introductions to the topic you can refer to.
For a good introduction to the subject, refer to A Guide to Claims-Based Identity and Access
Control by Dominick Baier, Vittorio Bertocci, Keith Brown, Matias Woloski, and Eugenio Pace
(Microsoft Press, 2010).
WIF does not really care if the STS used by the RP is an IP-STS or an R-STS. Both types look
the same in their metadata description and, despite the differences in the sequence that
ultimately lead to that, they both issue a token as requested. It helps to see this in action in a
concrete example.
Note As usual, in a realistic scenario you can expect the R-STS to be provided by one ADFS 2.0
instance playing the FP role. Once again, for educational purposes, I’ll take advantage of custom
STSes here.
Do you recall the first example we explored in Chapter 2? It was a classic RP-IP scenario,
but it is very easy to transform it into a toy federation sample. Just right-click on the
BasicWebSite_STS project in Solution Explorer, select the Add STS Reference entry, and use
the wizard for creating yet another new STS project in the current solution.
Note The Add STS Reference Wizard adds an <httpModules> element in the <system.web>
s ection of BasicWebSite_STS config, which does not play well with the IIS integrated pipeline. You
might have to comment out that <httpModules> entry.
Nothing changed for the RP, BasicWebSite, which is still outsourcing authentication to
BasicWebSite_STS. BasicWebSite_STS was an IP-STS when we started, because it was an
unmodified instance of the WIF STS template. After the wizard configured it to outsource
authentication to BasicWebSite_STS_STS, however, BasicWebSite_STS became an R-STS;
therefore, its login.aspx page will not be used anymore. If you run the solution you’ll observe
the browser being redirected from BasicWebSite to BasicWebSite_STS, which will redirect
right away to BasicWebSite_STS_STS, which will finally show its own login.aspx page. After
you click Submit on the login form, the flow will go through the chain in the opposite order:
BasicWebSite_STS_STS will issue a token that will be used for signing in BasicWebSite_STS,
which in turn will issue a new token that will be used for signing in BasicWebSite. Figure 4-8
summarizes the sign-in flow.
128 Part II Windows Identity Foundation for Identity Developers
5A
BasicWebSite_STS_STS BasicWebSite_STS
Trust
Trust
3 4
2 5 6
BasicWebSite
Browser 1
7
FIGURE 4-8 The authentication flow linking BasicWebSite, BasicWebSite _STS, and BasicWebSite_STS_STS
Transforming Claims
The example in the preceding section modified the authentication flow to conform to the
federation pattern, but it didn’t really change the way in which BasicWebSite_STS processes
claims. With its hard-coded claims entries, the default WIF STS template behavior mimics that
of an IP-STS; whereas in its new FP role, BasicWebSite_STS is expected to process the incom-
ing claims (in this case, from BasicWebSite_STS_STS). If you want to change BasicWebSite_STS
into a proper R-STS, you need to modify the GetOutputClaimsIdentity method of the
CustomSecurityTokenService class.
As you already know, in GetOutputClaimsIdentity the incoming claims are available in the
IClaimsPrincipal principal parameter. You can pretty much do anything you want with the
incoming claims, but I find it useful to classify the possible actions into three (non-exhaustive)
categories: pass-through, modification, and injection of new claims. They are represented in
step 5a of Figure 4-8. Here is a simple example of a GetOutputClaimsIdentity implementation
that features all three methods:
// Pass-through
Claim nname = (from c in incomingIdentity.Claims
where c.ClaimType == ClaimTypes.Name
select c).Single();
Claim nnnm = new Claim(ClaimTypes.Name, nname.Value, ClaimValueTypes.String, nname.
OriginalIssuer);
outputIdentity.Claims.Add(nnnm);
// Modified
string rrole = (from c in incomingIdentity.Claims
where c.ClaimType == ClaimTypes.Role
select c.Value).Single();
outputIdentity.Claims.Add(new Claim(ClaimTypes.Role, "Transformed " + rrole));
// New
outputIdentity.Claims.Add(new Claim("http://maseghepensu.it/hairlength",
"a value", ClaimValueTypes.Double));
return outputIdentity;
}
130 Part II Windows Identity Foundation for Identity Developers
Before going into the details of how the various transformations work, it is finally time to take
a deeper look at that Claim class we’ve been using without giving it too much thought so far.
Here are the various properties of the class and some methods of interest:
One thing that immediately grabs your attention is that all properties of Claim are read-only:
after the class has been created, the values cannot be changed. The only exception is the
subject to which the Claim instance is referring to: SetSubject will change the value of the
Subject property to a new IClaimsIdentity.
You are already familiar with Value and ClaimType because I’ve been using those throughout
the entire book. ValueType is more interesting. It allows you to specify a type for the claim
value, which the claim consumer can use to deserialize the claim in a common language
runtime (CLR) type (or whatever type system your programming stack requires if you are
not in .NET) other than the default string. That is a key enabler for applying complex logic to
claims. Without knowing that DateOfBirth should be deserialized in a DateTime, you’ll find
it difficult to verify whether it is below or above a given threshold. Note that the ValueType
is just one indication: the Value returned by the claim is always a string regardless of the
ValueType. You’ll have to call the appropriate Parse method (or similar) yourself.
The Properties dictionary is used for carrying extra information about the claim itself
when the protocol requires it. For example, in SAML2 you might have properties such as
SamlAttributeDisplayName assigned to a claim.
Note The WIF token handlers will not serialize the properties. If you want them to travel, you’ll
have to take care of that yourself.
The Issuer property is a string representing the token issuer from which the claim has been
extracted. The string itself comes from the mapping that IssuerNameRegistry makes between
the certificate used for signing the token and the friendly name assigned to the associated
issuer. The OriginalIssuer property records the first issuer that produced this claim in the fed-
eration chain. I’ve included more details about this in the “Pass-Through Claims” section.
Chapter 4 Advanced ASP.NET Programming 131
// Nested Types
public static class Prip
{
// Fields
public const string ClaimTypeNamespace = "http://schemas.xmlsoap.org/claims";
public const string CommonName = "http://schemas.xmlsoap.org/claims/
CommonName";
public const string Email = "http://schemas.xmlsoap.org/claims/EmailAddress";
public const string Group = "http://schemas.xmlsoap.org/claims/Group";
public const string Upn = "http://schemas.xmlsoap.org/claims/UPN";
}
}
You can, of course, create your own claim types. However, I suggest that before doing
so you take a look at the Information Card Foundation Web site, which (among other
things) gathers all the known and emergent claim types from the community. The
direct address is http://informationcard.net/resources/claim-catalog.
WIF also offers various constants representing common types of claim values:
public static class ClaimValueTypes
{
// Fields
public const string Base64Binary = "http://www.w3.org/2001/XMLSchema#base64Binary";
public const string Boolean = "http://www.w3.org/2001/XMLSchema#boolean";
public const string Date = "http://www.w3.org/2001/XMLSchema#date";
public const string Datetime = "http://www.w3.org/2001/XMLSchema#dateTime";
public const string DaytimeDuration = "http://www.w3.org/TR/2002/WD-xquery-
operators-20020816#dayTimeDuration";
public const string Double = "http://www.w3.org/2001/XMLSchema#double";
public const string DsaKeyValue = "http://www.w3.org/2000/09/xmldsig#DSAKeyValue";
public const string HexBinary = "http://www.w3.org/2001/XMLSchema#hexBinary";
public const string Integer = "http://www.w3.org/2001/XMLSchema#integer";
134 Part II Windows Identity Foundation for Identity Developers
The types are represented according to W3C and OASIS type URIs, but the mapping to
CLR types is obvious most of the time.
Now that you understand a bit better how the Claim class works, let’s resume the discussion
about the claim transformations.
Pass-Through Claims
One of the most common transformations you’ll want to apply to your claims is…no
transformation at all. Sometimes the IP directly issues the claims the RP needs; hence, you
have to make sure that those claims are reissued as-is by the R-STS.
Although the claim type and value come straight from the incoming values, the fact that the
new claim is issued in a token signed by the R-STS makes the R-STS itself the asserting party
and shadows the original issuer. The R-STS might even be accepting tokens from multiple
issuers, which would complicate things further. There could be situations in which know-
ing the actual origin of the claim could change the way in which the information it carries is
processed; therefore, it is important to somehow let the RP know which IP issued the claim
in the first place. This is done by setting the OriginalIssuer property of the outgoing claim to
the OriginalIssuer carried by the claim you are re-issuing. Here are the relevant lines from the
GetOutputClaimsIdentity implementation shown earlier:
// Pass-through
Claim nname = (from c in incomingIdentity.Claims
where c.ClaimType == ClaimTypes.Name
select c).Single();
Claim nnnm = new Claim(ClaimTypes.Name, nname.Value, ClaimValueTypes.String, "," nname.
OriginalIssuer);
outputIdentity.Claims.Add(nnnm);
Chapter 4 Advanced ASP.NET Programming 135
In this example, the claim to be reissued is the Name claim. The code retrieves it from the
incoming principal, and then it just creates a new claim that copies everything from the origi-
nal except for the issuer. (Here the issuer parameter is left empty because it is going to be
overridden with the current R-STS, anyway.) That snippet is designed to surface to you the
use of OriginalIssuer, but in fact you can use a more compact form using Copy as shown here:
// Pass-through
Claim nname = (from c in incomingIdentity.Claims
where c.ClaimType == ClaimTypes.Name
select c).Single();
Claim nnnm = nname.Copy();
outputIdentity.Claims.Add(nnnm);
Modifying a claim means producing a new claim by processing or combining the value of
one or more incoming claims, according to arbitrary logic. An excellent example of that is
given by the ADFS 2.0 claims-transformation language, which allows administrators to specify
transformations without writing any explicit code. Of course, in GetOutputClaimsIdentity you
can literally write whatever logic you want.
Injecting new claims usually entails looking up new information about the incoming
subject—information that was not available to the IP but that the RP needs. A classic example
is the buyer’s profile: imagine that the user is one employee, the IP is the user’s employer,
and the RP is some kind of online shop. The R-STS might maintain information such as the
last 10 items the user bought, data that the employer does not keep track of and that should
be injected by the resource organization—for example, in the R-STS. The challenge here
can be choosing which incoming claims should be used for uniquely identifying the cur-
rent user and looking up his data in the R-STS profile store. Whereas the IP has one strong
incentive to have such a unique identifier—because that is usually needed in order to apply
the mechanics of the authentication method of choice—the R-STS does not have a similar
requirement per se. The claims chosen should be unique, at least in the context of the current
R-STS, and stable enough to be reusable across multiple transactions. The e-mail claim is a
good example, but of course it’s not a perfect one because e-mail addresses do change from
time to time—think of the situation where interns become full-time employees and similar
events.
take care of all the trust relationships. Extending the audience of the application without pay-
ing any complexity price is great; however, the sheer possibility of using more than one IP
does introduce a new problem: when an unauthenticated user shows up, which IP should she
ultimately authenticate with? In the trivial federation case examined so far, the one with one
FP and one IP, the answer is obvious: the redirect chain crawls all the way to the IP and back.
When you have more than one IP, however, how does the R-STS decide if the redirect should
go to IP A or IP B?
The problem of deciding which IP should authenticate the user is well known in literature,
and it goes under the name of Home Realm Discovery (HRD). The HRD problem has many
solutions, although as of today they are mostly ad hoc and what works in one given scenario
might not be suitable for another. For example, one classic solution (offered out of the box
by ADFS 2.0) asks the R-STS to show a Web page in which the user can pick his own realm
among the list of all trusted IPs. This is often a good solution, but there are situations in
which it is not advisable to reveal the list of all trusted IPs. Furthermore, sometimes asking
the user to make a choice is inconvenient or unacceptable, in which case the IP selection
should be done silently according to some criteria.
WS-Federation provides a parameter that can be useful in handling HRD: whr. It is meant to
carry the address (or the urn: identifier) of the home realm. An R-STS receiving a wsignin1.0
message that includes whr will consider whr content to be the IP-STS of the requestor and
will drive the sequence accordingly. (See Figure 4-9.)
IP-STS B
Trust
IP-STS A
Trust R-STS
/A
http:/
HR= Trust
W
3 4
6
2 5
APP
Browser
1
7
FIGURE 4-9 The Home Realm Discovery problem
Chapter 4 Advanced ASP.NET Programming 137
■ The requestor You can imagine a scenario in which the administrator of the
organization of IP A gives to all users a link to the RP that already contains the whr
parameter preselecting IP A. That is a handy technique, which eliminated the HRD
problem at its root. Unfortunately, this is not guaranteed to work: this system requires
the RP to understand (or at least preserve in the redirect to the R-STS) the whr param-
eter, but WS-Federation does not mandate this to the RP. In fact, RPs implemented via
WIF do not support this behavior out of the box (although it’s not especially hard to
add it).
■ The RP The RP itself could inject whr in the message to the R-STS. Imagine the case
in which the RP is one specific instance of a multitenant application. In that case, the
whr might be one of the parameters that personalize the instance for a given tenant.
WIF supports this specific setup on the RP, by allowing you to specify the attribute
homeRealm in the <federatedAuthentication/wsFederation> element of the WIF con-
figuration. The value of homeRealm will be sent via whr to the R-STS. However, the WIF
STS template project knows nothing about whr and will just ignore it. Once again, it is
not hard to add some handling logic.
The R-STS is the recipient of whr. If the execution reaches the FP without having added a whr,
it is up to the R-STS to make a decision on the basis of anything else that is available in the
specific situation and can help decide which IP should be chosen.
Let’s once again set up a hypothetical solution in Visual Studio so that you can gain hands-on
experience with the flow the scenario entails.
If you still have the solution we used for showing how federation works, right-click on
BasicWebSite_STS, and again use the Add STS Reference Wizard to outsource its authentica-
tion to a new STS. Visual Studio will call the new STS BasicWebSite_STS_STS1. The current
situation is described in Figure 4-10.
138 Part II Windows Identity Foundation for Identity Developers
Note With all those STSes looking alike, things might become hard to follow. A good trick for
always knowing what is going on is assigning different colors to the background of the login.aspx
pages of the various STS projects.
The easiest thing to accomplish in the scenario is enabling the RP BasicWebSite to express a
preference for one IP via whr. As mentioned earlier, this can be done easily via configuration:
<federatedAuthentication>
<wsFederation passiveRedirectEnabled=”true”
issuer=”https://localhost/BasicWebSite_STS/”
realm=”https://localhost/BasicWebSite/”
homeRealm=”https://localhost/BasicWebSite_STS_STS/”
requireHttps=”true” />
<cookieHandler requireSsl=”true” />
</federatedAuthentication>
Note As is usually the case for the parameters in <wsFederation>, you can do something to the
same effect by using the PassiveFederationSignInControl and its properties. From now on, I’ll omit
this note, assuming that in similar situations you’ll know that the control alternative is available.
The next step is making the WIF STS template understand whr. It is actually simple—it is
mainly a matter of intercepting the redirect to the IP and forcing it to go whenever the whr
Chapter 4 Advanced ASP.NET Programming 139
decides. Add to the BasicWebSite_STS project a global.asax file. Here you can handle the
WSFAM RedirectingToIdentityProvider event as follows:
<script runat=”server”>
void WSFederationAuthenticationModule_RedirectingToIdentityProvider
(object sender, RedirectingToIdentityProviderEventArgs e)
{
string a = HttpContext.Current.Request.QueryString[“whr”];
if (a != null)
{
e.SignInRequestMessage.BaseUri = new Uri(a);
}
}
The code could not be easier. It verifies whether there is a whr parameter in the query string,
and if it there is one, it assigns it to the BaseUri in the SignInRequestMessage, overwriting
whatever value the BasicWebSite_STS configuration had put in there. As soon as the handler
returns, the WSFAM will redirect the sign-in message to the whr—in this case,
BasicWebSite_STS_STS. And that is exactly as you wanted it.
Note The code here assumes that whr carries a network-addressable URI, but per the
WS-Federation specification this might not be the case. If the URI is an urn identifier,
BasicWebSite_STS should look up the actual address in some mapping store.
Having to specify the home realm in the RP configuration might be too static a behav-
ior for many occasions. Fortunately, the RedirectingToIdentityProvider event can be easily
handled on the RP as well, implementing any dynamic behavior. For example, you can think
of maintaining a table of IP ranges where requests might come from, and map them to the
corresponding IP addresses. For the sake of simplicity, here I’ll show you how to implement
the approach when it is the requestor that sends the whr up front in its first request to the RP.
If you add a global.asax file to BasicWebSite, almost exactly the same code as shown earlier
will give you the desired effect:
<script runat=”server”>
void WSFederationAuthenticationModule_RedirectingToIdentityProvider
(object sender, RedirectingToIdentityProviderEventArgs e)
{
string a = HttpContext.Current.Request.QueryString[“whr”];
if (a != null)
{
e.SignInRequestMessage.HomeRealm = a;
}
}
140 Part II Windows Identity Foundation for Identity Developers
The code here intercepts the execution right before sending back the redirect to the R-STS,
and if the original request contained whr it ensures that it will be propagated to the R-STS
as well. That means you can delete the homeRealm attribute in the BasicWebSite config,
because now you have the ability to express whr directly at request time.
Important Keep in mind that all the samples here aim to help you understand the problem,
but they do not constitute complete solutions. Handling HRD in practice is not just a matter
of complying with the protocol. Instead, it presents various challenges with manageability and
maintenance aspects that are beyond the scope of this book and are best addressed by using
packaged server-grade products such as ADFS 2.0.
One eminent example of this shows up every time the RP needs to communicate some kind
of preference about the authentication process the IP should use when issuing tokens to
users. It’s great that claims-based identity decouples the RP from the authentication respon-
sibilities, but there are situations in which the value of the operation imposes certain guar-
antees about the strength of the authentication. Imagine a banking Web site or a medical
records Web site that gives access to certain operations only if the user is authenticated with
a high-assurance method such as X.509 certificates or similar.
As you’ve grown to expect, WS-Federation has a parameter for that: wauth. It is supposed to
be attached to wsignin1.0 messages to communicate to the STS the authentication method
preference. Usually, the STS uses that for performing internal redirects to one endpoint that
is secured with the corresponding authentication technique, or something to that effect (for
example, wiring custom HttpHandlers or similar low-level tricks).
Important I won’t go into the details here of how an STS should handle wauth, mainly because
it would do so by leveraging the authentication infrastructures rather than WIF APIs. The main
thing to remember on the STS side is that a token will advertise the authentication method that
led to its own issuance by the presence of the claim of type ClaimTypes.Authentication.
Each RP has its own criteria for assigning a value to wauth. Sometimes it is a blanket property
for the entire Web site—in which case, it is expressed directly in <wsFederation> in the au-
thenticationType attribute. At other times, the user is given the chance of selecting (directly
or indirectly) from among multiple credential types. In yet another situation, there might be
logic that silently establishes whether the current authentication level is enough for accessing
the requested resource, or whether the system should step up to a higher level of assurance
Chapter 4 Advanced ASP.NET Programming 141
and re-authenticate the user accordingly. The last two cases call for a dynamic assignment of
wauth, which is when reusing what you learned about whr and RedirectingToIdentityProvider
comes in handy for wauth too.
Authentication Methods
WIF offers handy constants representing common authentication methods. Once
again, they are grouped in multiple collections: Microsoft.IdentityModel.Claims.
AuthenticationMethods and Microsoft.IdentityModel.Tokens.Saml11.Saml11Constants+
AuthenticationMethods (shown next). The SDK samples use the first one, whereas the
second one is used when communicating with ADFS (though in that case, it boils down
to Password, TlsClientString, and WindowsString). In fact, the values in the following
AuthenticationMethods are only used in the on-the-wire format specified by SAML. In
the general case you won’t need them.
public static class AuthenticationMethods
{
// Fields
public const string HardwareTokenString = "URI:urn:oasis:names:tc:SAML:1.0:am:
HardwareToken";
public const string KerberosString = "urn:ietf:rfc:1510";
public const string PasswordString = "urn:oasis:names:tc:SAML:1.0:am:password";
public const string PgpString = "urn:oasis:names:tc:SAML:1.0:am:PGP";
public const string SecureRemotePasswordString = "urn:ietf:rfc:2945";
public const string SignatureString = "urn:ietf:rfc:3075";
public const string SpkiString = "urn:oasis:names:tc:SAML:1.0:am:SPKI";
public const string TlsClientString = "urn:ietf:rfc:2246";
public const string UnspecifiedString = "urn:oasis:names:tc:SAML:1.0:am:
unspecified";
public const string WindowsString = "urn:federation:authentication:windows";
public const string X509String = "urn:oasis:names:tc:SAML:1.0:am:X509-PKI";
public const string XkmsString = "urn:oasis:names:tc:SAML:1.0:am:XKMS";
}
There is not a whole lot of coding required, especially considering that I already covered
ClaimsAuthorizationManager in detail in Chapter 2. This section attempts to give you an idea
of the intended usage of those extension points and inspire you to take advantage of them
in your scenarios.
142 Part II Windows Identity Foundation for Identity Developers
Authorization
Claims authorization is a fascinating subject that probably deserves an entire book of its own.
One thing that puts off the various Role-Based Access Control (RBAC) aficionados is that
there is so much freedom and so many ways of doing things. For example, take the coarse
form of authorization that can be implemented by simply refusing to issue a token. You
can set up rules at the IP that prevent from obtaining a token all the users that are already
known not to be authorized to access the application they are asking for. That is feasible for
all the situations in which the IP knows enough to make a decision—for example, in cases
like Customer Relationship Management (CRM) online, in which users need to be explicitly
invited before having access, even when there’s a federation in place.
Another obvious place for enforcing authorization is in the R-STS, which might deny tokens
on the basis of some cross-organizational considerations. For example, the R-STS used by one
independent software vendor (ISV) for managing access to its application portfolio might
keep track of how many concurrent users are currently holding active sessions and refuse to
issue a new token if that would exceed the number of licenses bought by the IP organization.
The enforcement point that is the closest to traditional authorization systems is the RP itself,
which is where ClaimsAuthorizationManager is positioned. There are intrinsic advantages to
enforcing authorization here. The resources are well known. For example, if the RP is a docu-
ment management system, the life cycle of documents themselves is under the control of
the RP, which can easily manage permissions as well; whereas others (such as the R-STS, or
worse still, the IP) would need to be synchronized. Another advantage is the availability of
the call itself, although that’s easier to see with Web services than with Web sites. If you want
to authorize the user to make a purchase according to a spending-limit claim, you need both
the claim value and the amount of the proposed purchase: one STS would only see the claim
value, as the body of a call plays no part in RST/RSTR exchanges.
For doing any of these things, WIF offers you a specific hook in the RP pipeline, which
you can leverage by providing your own claims-manipulation logic wrapped in a cus-
tom ClaimsAuthenticationManager class. ClaimsAuthenticationManager works a lot like
ClaimsAuthorizationManager: you provide your logic by overriding one method (here it’s
Authenticate), and you add your class in the pipeline by adding in the WIF config the element
<claimsAuthenticationManager type=”CustomClaimsAuthnMgr”/>.
In your implementation of Authenticate, you can do whatever you want with the principal,
including deleting claims, adding claims, or even using a custom IClaimsPrincipal
implementation. Here is a super-simple example of ClaimsAuthenticationManager:
In this case, the code simply adds an extra claim to the principal. Note that the issuer is
assigned to “LOCAL AUTHORITY.” You can use pretty much anything you want here, but you
should really avoid using an existing issuer identifier because it is equivalent to pretending to
be a legitimate issuer.
Summary
Wow, that was an intense chapter! I hope you had as much fun reading it as I had writing it.
This chapter took a much more concrete approach to WIF programming, leveraging the
programming model knowledge you acquired in Chapter 3 to tackle many important
problems and scenarios you might encounter when securing ASP.NET applications.
You learned about the distinction between identity providers and Federation Providers,
acquiring familiarity with the WIF STS template in the process.
You finally saw applied in practice the sign-in flow studied in Chapter 3, applying it to the
case of multiple Web sites and discovering how the underlying structure makes SSO possible.
You had a chance to learn how Single Sign-out works, and how to use WIF for implementing
144 Part II Windows Identity Foundation for Identity Developers
it in a few lines of code. We explored one case of exotic session management, in which the
validity is driven by user activity rather than fixed expiration times.
The classic federation case and home realm discovery are now very concrete scenarios for
you, and you know what it takes for dealing with them in various situations. In the process of
learning this, you also gained familiarity with WIF’s object model for claims.
Finally, you had a chance to tie up a few loose ends regarding the use of
ClaimsAuthenticationManager and ClaimsAuthorizationManager for processing claims once
they have already reached the RP.
If you develop for the ASP.NET platform, this chapter should have equipped you with all
the knowledge you need for tackling the most common problems and then some. For
anything not explicitly covered here, you should now be able to investigate and solve issues
on your own.
In the next chapter, I’ll turn to Web services and explore how WIF and WCF can work
together to create safer applications while delivering a killer development experience.
Index
Symbols A
<applicationService>, 86 access grants, 237
<audienceURI>, 85 ACS. See AppFabric Access Control Service
<authorization> element in the <system.web> ActAs
block, 36 STS support, 177
<behavior> element, 157 tokens, 176
<certificateValidation>, 89 ActAs approach, 173
<certificateValidator>, 89 Action collection, 42
<ClaimsAuthenticationManager>, 87 active clients, 56, 148
<ClaimsAuthorizationManager>, 87 holder-of-key confirmation method, 151
<cookieHandler>, 85, 88 message-based security, 150
<federatedAuthentication>, 85, 87 message-level security options, 150
<issuerNameRegistry>, 86 Active Directory Federation Services 2.0, 15, 32,
<issuerTokenResolver>, 89 57
<maximumClockSkew>, 88 active STS endpoints, 209
<microsoft.identityModel>, 82, 84, 155 active systems, 146
overview, 39 Actor property, 176
<service> elements, 84 Add STS Reference, 26
<microsoft.identityModel/Service> structure, 86 ADFS2. See Active Directory Federation Services 2
.NET applications Adobe Flash, 147
IIdentity, 5 anonymous authentication, 6
IPrincipal, 5 App_Code, 108
.NET Framework App_Code folder, 108
authentication mechanisms, 5 AppFabric Access Control Service (ACS), 204
compatibility with Windows Identity ASP.NET, 52
Foundation, 24–47 authorization, 36
.NET security HttpModules, 73
iPrincipal, 6 integration with WIF, 52
traditional approaches, 4 roles and authorization compatibility, 36
<policy> elements, 43 WIF processing pipeline, 58
<protocolMapping> element, 157 ASP.NET Development Server, 105
<saml:Assertion>, 66 ASP.NET membership provider, 35
<saml:Conditions>, 66 ASP.NET MVC framework, 216
<saml:SubjectConfirmation>, 67 AccountController class, 217
<securityTokenHandlers>, 89 Authorize, 217
<serviceTokenResolver>, 89 flow, 216–240
<wsFederation>, 85, 88 HttpModules, 218
parameters, 88 login, 219
Issuer, 85 LogOnCommon, 221
passiveRedirectEnabled, 85 logout, 220
realm, 85 project template, 217
requireHttps, 85 web.config, adding WIF, 218
WIF integration solutions, 216–240
ASP.NET Security Token Service Web Site
template, 104
241
242 ASP.NET STS
D H
delegation, 176 holder-of-key confirmation method, 151, 153
DevFabric, 187–213 holder of key tokens, 65
digital signatures for tokens, 63 homeRealm, 137
dynamic metadata generation, 205 Home Realm Discovery, 136
Howard, Michael, 4
HRD. See Home Realm Discovery
E HTML5, 147
encrypting tokens, 63 HttpContext.Current.User, 5
EndRequest event, 75, 77 HttpModules
end-to-end security, 150 ASP.NET, 73
enforcing authorization at the RP, 142 ClaimsAuthorizationModule, 73
Esposito, Dino, 73 SessionAuthenticationModule, 72
externalizing authentication, 16 WIF sign-in flow, 74
advantages, 39 WSFederationAuthenticationModule, 72
HttpModules pipeline, 74
F
FederatedAuthentication, 40 I
FederatedPassiveSignInStatus, 116 IClaimsIdentity, 18, 37, 110
federation Actor property, 176
providers, 101 ClaimType property, 19
relationships, 101 Issuer property, 19
scenarios, 102 Subject property, 20
federation metadata documents, 28 Value property, 19
FederationPassiveSignIn control, 81 IClaimsPrincipal, 18, 37, 110
federation provider role of IPs, 96 identity providers, 12, 97
Federation Providers, 99 allow list of RPs, 98
outsourcing functions, 204 federation provider role, 96
federation relationships, authentication flows, 101 multiple, 99
federation scenarios, 102 multiple STS endpoints, 98
Federation Utility Wizard, 26 roles, 96
creating a new STS project, 28 specifying, 32
No STS option, 28 standard example, 97
Using an existing STS, 28 unknown RP identity, 99
FedUtil.exe, 26, 39 IIdentity, 5
default configuration, 82 IIdentity extensions, 18
Forms authentication, 7, 114 IIS7, 84
FormsIdentity objects, 7 IIS authentication types, 6
FP. See Federation Providers Information Card Foundation Web site, 133
Full Trust mode, 188 intended audience of tokens, 63
Internet Information Services
vs. ASP.NET Development Server, 105
G Internet Information Services (IIS) authentication,
Generate New STS option, 103 6
generic identity transaction, 14 IP. See identity providers
GenericPrincipal extension, 5, 7 IP-FP-RP pattern, 126
GetOutputClaimsIdentity implementation, 111 IPrincipal, 5
GetScope method, 109 extensions, 5
GetTokenTypeIdentifiers method, 93 populating, 6
IP-STS, 97, 106, 111
244 IsInRole
IsInRole, 6
issued tokens, 64, 100
N
Issue method, 149 named <microsoft.identityModel/Service>
IssuerNameRegistry, 94 sections, 199
Issuer property, 20 NASCAR problem, 232
network load balanced (NLB) environments, 191
network load balancing (NLB)–friendly sessions,
J 125
JavaScript, 147 nonrepudiation, 150
K O
Kerberos, 97, 114 OASIS Identity Metasystem Interoperability
constrained delegation, 171–184 Technical Committee, 228
Kerberos tokens, 65 OAuth 2.0 protocol, 233
keying strategies, 191 Authorization Server role, 234
Client role, 234
implementation for WIF, 238
L profiles, 235
Protected Resource role, 234
LeBlanc, David, 4
Resource Server role, 234
lifetime property, 122
WS-Trust integration, 237
logical identity layer, 11
OAuth WRAP, 204, 234
logical layer of identity, 11
OnBehalfOf, 174
OpenID
M implementing in WIF, 232
OpenID moniker, 232
man-in-the-middle attacks, 151
OpenID provider (OP), 232
MembershipProvider, 7
outsourcing FP functions, 204
MembershipUserNameSecurityTokenHandler, 93
message-based security, 150
end-to-end security, 150 P
nonrepudiation applied to single messages, 150
Page_PreRender handler, 106
properties, 150
passive clients, 56, 147
vs. transport security, 150
HTTPS security option, 150
metadata, 112
PassiveRequestorEndpoint, 70, 72
dynamic generation in the cloud, 205
passive systems vs. active, 146–184
generating documents programmatically, 112
pass-through claims, 134
metadata documents, 69
personally identifiable information, 122
Microsoft Excel, 148
PFX (Personal Information Exchange) format, 189
Microsoft.IdentityModel.Claims namespace, 41
PII. See personally identifiable information
Microsoft.IdentityModel.dll, 24
policies, 13
Microsoft Outlook, 148
PostAuthenticateRequest event, 76
Microsoft Silverlight, 147
primitive tokens, 65
Microsoft Visual Studio, 6
Principal, 42
default authentication mode, 6
processing pipeline in ASP.NET, 58
Windows Azure templates, 187–213
proof of possession, 153
Microsoft Windows Communication Foundation,
proof token, 153
7
protocol transition STS, 204
Microsoft Word, 148
multiple identity providers, 96
multiple RP applications, 113
multitenant applications, 137
R
RBAC. See Role-Based Access Security
Silverlight 245
ReadToken, 93 duplication, 63
redirect-based protection vs. login page, 80 encryption and decryption, 63
RedirectingToIdentityProvider event, 139 expiration, 63
relying party, 12 format, 62, 64
endpoint identity, 192 holder of key, 65
load-balanced environments, 124 integrity, 63
Relying Party Trust, 98 intended audience, 63
remote services, 148 issued, 64
Request for Security Token Response (RSTR), 149 Kerberos, 65
Request for Security Token (RST), 149 primitive, 65
RequestSecurityToken, 183 SAML format, 64
RequestSecurityToken.Claims collection, 111 structure, 64
RequestSecurityTokenResponse, 183 subelements, 66
Resource collection, 42 trusted source, 63
REST, 55, 230 Username, 65
restricting resources and actions, 33 validity period, 63
REST service, 205 verifying, 62
REST Web services, 204 WS-* specification definition, 64
rich clients, 148 X.509, 65
rich stacks, 147 SecurityTokenService, 107, 108
Role-Based Access Control, 142 SecurityTokenServiceEndpoint element, 72
Role-Based Access Security, 35 SecurityTokenServiceType, 72
role-based authorization, 36 SecurityTokenVisualizerControl sample ASP.NET
RoleDescriptor, 70, 72 control, 68
roles, 35 serializing and deserializing tokens, 93
RP. See relying party SessionAuthenticationModule, 72, 91
RST. See Request for Security Token sessions, 122, 191
RSTR. See Request for Security Token Response keeping alive, 116
R-STS, 111 lifetime property, 122
network load balancers, 124
session tokens, 122
S single sign-in, 112
SAM. See SessionAuthenticationModule single sign-out, 115
SAML 2.0 protocol, 229–230 sliding, 122
WIF integration, 229 state, 116
Saml2SecurityTokenHandler, 93 sticky, 124
Saml2TokenHandler, 93 SessionSecurityTokenCookieSerializer, 191
Saml11SecurityTokenHandler, 93 SessionSecurityTokenHandler, 93, 192
Saml11TokenHandler, 93 SessionSecurityTokens, 93, 122
SAML tokens, 66 SharePoint 2010, 97
Secure Sockets Layer (SSL) certificates, 7 sign-in, 57
securing Microsoft .NET applications, 3 WF-Federation sequence, 58
Security Assertion Markup Language protocol, 55 WS-Federation sequence, 58
SecurityTokenCacheKey class, 191 sign-in flow in WIF, 74
SecurityTokenHandler class, 93, 168 signing in. See Single Sign-in
security tokens, 13, 62 signing in across multiple Web sites, 230
authentication level verification, 64 signing out. See Single Sign-out
bearer, 65 SignInRequestMessage, 107
claims, 64 Silverlight, 223
descriptor, 66 DisplayToken, 228
deserializing, 62 making claims available to applications, 227
digital signatures, 63 WIF integration, 224
246 Simple Object Access Protocol (SOAP) Web services
In 2005, Vittorio moved to Redmond, where he helped to launch the .NET Framework 3.5 by
working with Fortune 100 and Global 100 companies on cutting-edge SOA projects based on
WCF, WF, and CardSpace. He became more and more focused on identity themes, eventually
undertaking his current mission of evangelizing claims-based identity into mainstream use.
In the last five years, this mission has led him to speak about identity in 23 countries and
4 continents. Vittorio is a regular speaker at conferences such as Microsoft PDC, TechEd
USA, TechEd Europe, TechEd Australia, TechEd New Zealand, TechEd Japan, TechDays Belux,
Gartner Summit, European Identity Conference, IDWorld, OreDev, NDC, IASA, Basta and
many others.
Vittorio is a published author, both in the academic and industry worlds, and has written
many articles and papers. He is co-author of A Guide to Claims-Based Identity and Access
Control (Microsoft Press, 2010) and Understanding Windows CardSpace (Addison-Wesley,
2008). He is a prominent authority/blogger on identity, Windows Azure, .NET development,
and related topics, and he shares his thoughts at www.CloudIdentity.net.
Vittorio lives in the lush, green city of Redmond with his wife, Iwona. He doesn’t mind the
gray skies too much, but every time he has half a chance he flies to some beach place, be it
Hawaii or Camogli, his home town in Italy.
What do
you think of
this book?
We want to hear from you!
To participate in a brief online survey, please visit:
microsoft.com/learning/booksurvey
Tell us how well this book meets your needs—what works effectively, and what we can
do better. Your feedback will help us continually improve our books and learning
resources for you.
Stay in touch!
To subscribe to the Microsoft Press® Book Connection Newsletter—for news on upcoming
books, events, and special offers—please visit:
microsoft.com/learning/books/newsletter