Claims based identity takes away the complexity from the plate of the application developer, and simplifies the life of the architects, security developers and administrators we maintain the broth in which the application is immersed.
While pretty much everybody can understand (& appreciate) the high level story about claims, it is not always easy to make it concrete for everybody. The developer who had to deal with code handling multiple credentials, or had to track down where a certain authorization decision happen, sees very clearly where and how claims can make his life easier: UI developers, however, may have found challenging to bridge the gap between understanding the general story and finding tangible ways in which claims make their work easier. Until now (at least i hope).
We have put together a demo which shows an example of what you could build on top of the Geneva Framework infrastructure and further raise the lever of abstraction, to the point that a web developer is empowered to take advantage of the information unlocked by the claims with just few clicks. This touches on the theme of customization, which somehow gets less attention that authentication and authorization (for obvious reasons) but that deserves its place nonetheless. In any case, it’s not rocket science: it is a simple ASP.NET control that can modify the value of properties of other controls on the page, according to the value of the incoming claims. Despite its simplicity, it allows a surprising range of tricks
The code of the demo is available on code gallery, at http://code.msdn.microsoft.com/ClaimsDrivenControl.
Below I paste the minimal documentation we have put together: expect to see some more posts in the next weeks about the control and its implications.
The Claims-Driven Modifier control is a simple ASP.NET server control which allows you to use identity for driving the behavior of your frontend UX, without requiring you to see even a single line of code.
This is made possible by the claims-based approach implemented by the Geneva Framework, which silently take care of all the underlying details and allows you to effortlessly take advantage of identity information about your user.
FCDMC being user for driving the value of a textbox
The principle followed by the control is very simple. When you use the Geneva Framework for handing access to your website, your application ends up receiving information about your current user: name, email, age, favorite color, anything that makes sense in your context. Those attributes are the famous claims. The behavior of some of the controls in your page will change according to your user’s attribute: one label will show the name of the user, the page theme will adapt to his or her favorite color, certain elements of the UI may disappear or be disabled, and so on. Traditionally you would need to write code for making all those things happen: with the Claims-Driven Modifier control (CDMC from now on), you don’t need to. Every time you want to drive the property of one control according to identity information, you drag a CDMC instance on the page: then you bind that instance to the control, in a similar way to what you would do with a classic ASP.NET validator, and you choose which property should be modified. At that point, you can edit the Expression property of the CDMC for describing how to use claims for modifying the control’s property: common examples are assigning a claim value to the Text property of a label, determining if a control’s Visible property should be true or false according to a condition on claim values (was the user born before 1982?) and so on.
This is much easier to show than to explain! Explore the sample provided and you’ll see how in few clicks you can achieve what would normally require quite a lot of coding on non-claims-based systems, and how easy it is to understand what the page does at a simple glance at the design surface.
Note: the Claims-Driven Modifier control is just one example of the kind of innovation that is enabled by the claims-based approach and by the infrastructure provided by the Geneva Framework. It is NOT part of the product and is not fit for being used “as is” in production.
The Control in Action in the Sample Website
The Fabrikam Airlines solution
Imagine you are developing a website for Fabrikam Airlines, our usual fictitious company. Currently you are working on a page that is part of a flight booking system for frequent flyers: besides the frequent flyers of Fabrikam Airlines, you need to handle customers of partner airlines that are part of the alliance Cloud Buddies.
As you can see from Figure 2, the page you are working on is quite identity-intensive: all the controls will change according to the identity of the current user. More precisely, your requirements are:
- The fields First Name, Last Name, Telephone, Email and the labels about frequent flyer info all need to have their Text property assigned to the corresponding user’s attribute
- The image in the middle of the form needs to change according to the frequent flyer level (gold, silver, etc)
- The panel Fabrikam Airlines FF Privileges must be visible only if the user is a Fabrikam Airlines customer and should not be shown if the user is form a partner airline
- The Mid-Flight massage checkbox should be enabled only if the user is a gold frequent flyer. We disable it instead of hiding it altogether because we want to remind the user that this is something that they could enjoy if only they’d fly with Fabrikam Airlines more often
In order to implement the above, you need to:
- Authenticate the user as a customer of an airline in the Cloud Buddies alliance
- Acquire the relevant user attributes
- Use the value of those attributes for achieving the UX behavior specified above
The first 2 bullets can be easily addressed by using what Geneva Framework offers already out of the box, while our Claims-Driven Modifier control can help for the third.
Authenticate the user and obtain user’s attributes
The FedUtil wizard is integrated in Visual Studio
The claims-based approach allows you to externalize authentication. You can look up the details in the identity developer training kit if you want to know more, but from the point of view of the website developer this just means that you can avoid writing a single line of code on authentication and just rely on an external entity to do the job for you. In this specific case, your users are profiled by the Cloud Buddies alliance: assuming that CloudBuddies is using claims-based identity as well, you can outsource in its entirety the burden of handling user authentication and attributes management.
All you need is the internet address of CloudBuddies: Geneva Framework extends Visual Studio with a wizard (see figure 3) which just needs that address for configuring your website to trust CloudBuddies to do all the authentication heavy lifting and just send you the user attributes you need, the famous claims. In the sample applications we provide a mock implementation of CloudBuddies, and we already ran the configuration wizard for you so Fabrikam Airlines is already set up.
Again, if you want to know more in detail how this work please refer to the Identity Developer Training Kit.
Use identity for driving the user experience
Great, now we are all set for receiving claims from our authenticated user. How should we use that information for complying with our requirements?
Geneva Framework makes it very easy to write code for doing so, thanks to its tight integration with the IPrincipal/IIdentity model that .NET uses for handling identity. In our example we lower the bar even further, providing a control that leverages the infrastructure provided by the Geneva Framework and that can automate some of the common UI customizations with just few clicks.
Let’s see how CDMC can be used for handling our requirements, considering three different categories: using claims for sourcing values, using claims for imposing conditions, and mapping claim values to internal values.
The FabrikamAirlines UI at design time
The FabrikamAirlines sample is already fully configured with the suitable CDMC instances.
Assigning Claims Values to Control Properties
A CDMC instance and its properties
Our requirement #1 asks us to assign to the Text property of some controls the value of specific claims containing identity attributes. In Figure 5 you can see one of such controls: the textbox in the screenshot is txtFirstName, and is supposed to hold the first name attribute of the current user. On the right of the textbox you can see a pentagon shaped icon, which represents a CDMC instance. Click on it: on the right side of the figure you can see the list of it properties. The most important are:
- ControlToDrive. This property represents the ID of the control we want to drive via CDMC: in this case, we can see it is already tied to txtFirstName
- PropertyToModify. Once the CDMC instance has been tied to a control, PropertyToModify will be populated with all the properties that the driven control features: in this case, we selected the property Text
- Expression. This property represents the criteria we want to apply for modifying the property of the driven control. You will rarely modify this property by typing: rather, you will click on the ellipsis and use the dialog shown in Figure 6
The expression designer in Claim value mode
The dialog is extremely straightforward: it shows that txtFirstName.text will get the value of the incoming claim givenname.
The claims collection from CloudBuddies
The list of available claims from CloudBuddies is populated automatically, thanks to the fact that we used Geneva Framework for configuring our application. If we want, we also have an option of defining custom claims if we know that we will receive them.
It’s that easy. We can repeat the procedure for all the other controls mentioned in the requirement #1, and we are done with this part.
Mapping Incoming Claims to Internal Values and Assign Them to Properties
The imgMembershipLevel control and its CDMC instance
Requirement #2 asks us to adapt the source of one image according to the membership level of our user. In figure 8 you can see that we have a CDMC tied to our image control, configured for driving the value of the ImageUrl property. However the strategy we used above will not work: we cannot expect CloudBuddies to know details that are private to our application, such as the relative path to our images.
In order to handle this case CDMC offers a new expression type, called mapping.
The expression editor in Mapping mode
A mapping expression is a collection of if-then clauses, which determine which string should be assigned to the driven property according to the values of incoming claims. In Figure 9 you can see how we use a Mapping expression for implementing our requirement. If the incoming claim FrequentFlyerLevel contains the value “gold” we will assign to the property imgMembershipLevel.ImageUrl the string “~/img/gold.png”; we do something equivalent for silver; and we could certainly go on. If you want to experiment yourself, try adding an if clause for copper.
This nicely takes care of requirement #2.
Controlling Boolean Properties of Controls with Conditions on Claims
The privileges panel and its CDMC
Requirements #3 requires us to hide or show a penal according to the Frequent Flyer program that the user belongs to. Figure 10 shows that we already hooked up a CDMC to the panel and its Visible property. However the Frequent Flyer program information is a string, while the visible property is a bool: the former approaches won’t work here. Once again, we have a different expression type that comes to the rescue: a Condition expression.
The expression editor in Condition mode
This is as intuitive as it gets: the result of the comparison will be assigned to the pnlPrivileges.Visible property. You may have noticed in the former points that the Condition option was disabled: this time it was available because the property we want to drive is a Boolean.
Requirement #4 is satisfied in the same way: there is a CDMC tied to the Mid-Flight Massage checkbox, the driven property is Enabled, and the condition is FrequentFlyerLevel==gold.
A Test Run
Let’s see the website in action. Press F5.
The CloudBuddies authentication page
Obedient to its configuration the website redirects us to CloudBuddies, where we can authenticate.
John, the default in this development version of the site, is a gold flyer with the partner ContosoAir. Let’s just click submit.
The page as it appear to John
Everything as expected: the Text properties are sourced, the image shows the right color, and the privileges panel is invisible because John is with ContosoAir. Let’s close the browser, hit F5 again and this time let’s access as Paul.
The page as it appears to Paul
Again, everything goes as planned. Text properties have been sourced, the image is now silver, and the privileges panel is visible; again according to expectations, the Mid-Flight Massage option is disabled since Paul is just at silver level.
The simple example presented here has shown how you can easily take advantage of the identity information provided by the Geneva Framework for driving the user experience in easy and intuitive fashion: true to our promise, it was not necessary to show a single line of code.
It is important to remember that this is just an example: it does not handle well borderline cases, does not do all the automation & validation it could do, it gets the list of claims from a single source (the passive federation metadata), and so on. The preferred way of handling things is programming directly with the Geneva Framework.
In this document we tried to use general terms instead of the identity jargon, and purposefully left out deeper explanations of how the control works. Our hope is that we succeeded in giving an idea of the possibilities that the claims based approach enables, and that every developer can benefit from those innovations without the need to become identity experts.
Now we will leave you a challenge: say that you want to play a prank on one of your colleagues whose name is Paul, and you want to hide the internet connection option whenever he uses the development site: how would you use the CDMC for modifying the behavior of the current page accordingly? We are sure you’ll do this in less than a minute. Have fun!
More details will be posted on https://channel9.msdn.com/identity/ and http://blogs.msdn.com/vbertocci/