developing identity-driven silverlight...
Post on 05-Aug-2020
3 Views
Preview:
TRANSCRIPT
Hands-On Lab
Developing Identity-Driven Silverlight Applications
Lab version: 1.0.0 Last updated: 1/21/2011
CONTENTS
OVERVIEW ................................................................................................................................................... 3
EXERCISE 1: SINGLE SIGN ON, CLAIMS-DRIVEN EXPERIENCE AND SERVICE AUTHORIZATION
FOR IN-BROWSER SILVERLIGHT APPLICATIONS ................................................................................. 7 Task 1 – Creating a Silverlight Application ............................................................................................ 8
Task 2 - Externalizing Authentication to an Identity Provider ............................................................ 14
Task 3 – Making Claim Values Available to the Silverlight Application ............................................... 22
Task 4 – Creating a Silverlight-Enabled WCF Service and Consume It from the Silverlight application
............................................................................................................................................................ 34
Exercise 1 – Verification ...................................................................................................................... 49
Exercise 1: Summary ............................................................................................................................... 51
EXERCISE 2: IDENTITY AND OUT OF BROWSER APPLICATIONS ..................................................... 52 Task 1 – Updating the Silverlight Application to Run OOB (Out of Browser) and Rely on an Active STS
for Authentication ............................................................................................................................... 53
Exercise 2 – Verification ...................................................................................................................... 60
Exercise 2: Summary ............................................................................................................................... 66
EXERCISE 3: CALLING SERVICES IN OTHER DOMAINS ..................................................................... 66 Task 1 – Creating an "External" WCF Service ...................................................................................... 67
Task 2 – Updating the Silverlight Application to Consume the “External” WCF Service .................... 79
Exercise 3 – Verification ...................................................................................................................... 82
Exercise 3: Summary ............................................................................................................................... 85
SUMMARY .................................................................................................................................................. 85
Overview
Claims-based identity is increasingly being adopted as the preferred way of securing level of business
applications. The advantages it offers in term of reuse of existing identity stores, combined with the
claims object model which abstracts complexity away and works consistently across the on-premises-
cloud spectrum, are very attractive to developers of every focus and skill level. Windows Identity
Foundation, the extension to .NET Framework which enables developers to develop claims-aware
applications, is the platform of choice for implementing claims-based identity solutions on the Windows
platform.
With their subdivision between rich presentation layer on the client and associated website, Silverlight
based applications do not fit the classic client-service tiers model. As a result, Silverlight applications
were not among the first wave of scenarios that were enhanced with claims-based capabilities.
This hands-on lab will suggest you ways in which you can take advantage of claims-based identity from
within your Silverlight application. From leveraging existing identity stores to achieve single sign on to
your application, to using claims for guaranteeing your users a custom-tailored experience, you will
learn how to adapt to the Silverlight environment the Windows Identity Foundation programming
model that is already being successfully used with web sites and web services.
The purpose of the lab is to allow you to experiment with claims-based identity in Silverlight already
today. Currently the integration between the two products is not yet complete, hence there will be
times in which custom adapter code will be necessary; that is a function of the current stage in the
products roadmaps, and you can expect things to get simpler as we go forward.
Objectives
In this Hands-On Lab, you will learn how to:
Take advantage of an existing identity provider (exposed via passive STS) for externalizing
authentication for a in-browser Silverlight application
Access claims values from the code of a Silverlight application and use them for user experience
customization
Handle authorization for WCF services hosted in a Silverlight website using the WIF
programming model
Take advantage of an existing identity provider (exposed via active STS) for externalizing
authentication for an out-of-browser Silverlight application
Invoke services on other domains using SAML tokens from a Silverlight application
System Requirements
You must have the following items to complete this lab:
Microsoft® Windows® Vista SP2 (32-bits or 64-bits), or Microsoft® Windows Server 2008 SP2
(32-bit or 64-bit), or Microsoft® Windows® 7 (32-bits or 64-bits) or Microsoft® Windows Server
2008 R2 (64-bits).
Microsoft® Internet Information Services (IIS) 7.0 (with ASP.NET component, Static Content
Support, and a Localhost SSL certificate installed)
Microsoft® .NET Framework 4
Microsoft® Visual Studio 2010
Microsoft® Silverlight 4 Tools for Visual Studio 2010
Microsoft® Windows Identity Foundation Runtime
Microsoft® Windows Identity Foundation SDK
Setup
You must perform the following steps to prepare your computer for this lab.
1. Open a Windows Explorer window and browse to the lab’s Source\Setup folder.
2. Double-click the Dependencies.dep file in this folder to launch the Dependency Checker tool
and install any missing prerequisites. This will also install some code snippets that will be used
across the lab and the localhost certificate used in the second exercise by the local STS.
Note: This process may require elevation. The .dep extension is associated with the
Dependency Checker tool during its installation. For additional information about the setup
procedure and how to install the Dependency Checker tool, refer to the Setup.docx document
in the Assets folder of the training kit.
3. Click Close to dismiss the confirmation dialog.
Note: Next, the setup script will proceed by replacing any existing localhost certificate with a
new one. If you already have a "localhost" certificate needed by another application, ensure to
make a backup copy of it before continue with the lab's certificates installation.
4. Once closed the code snippets installer, the setup script will proceed with the certificates
installation. Press Y if you want to continue with the required certificates installation.
Figure 1
Certificates installation finished
Note: If you are running Windows 7 or Windows 2008 R2 you might not see this window.
5. When finished press any key to close the setup console.
Note: In addition to the setup script, inside the Source\Setup folder of this lab, there is a
Cleanup.cmd file you can use to uninstall all the code snippets installed by the SetupLab.cmd
script.
Exercises
The following exercises make up this Hands-On Lab:
1. Single Sign on, Claims-Driven Experience and Service Authorization for In-Browser Silverlight
applications
2. Identity and Out of Browser Applications
3. Calling Services in Other Domains
Note: Each exercise is accompanied by a starting solution. These solutions are missing some code
sections that are completed during each exercise and therefore will not work if executed directly.
Inside each exercise you will find an end folder where you find the resulting solution you should obtain
after completing the exercises. You can use this solution as a guide if you need additional help working
through the exercises.
Using the Code Snippets
With code snippets you have all the code you need at your fingertips. The lab document will tell you
exactly when you can use them. For example,
1. Enable anonymous access to the AuthenticationService service by adding the following element
on the Web.config file of the https://localhost/GymFabrikamClientWebEx01 project.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 AuthenticationService location element)
XML
<connectionStrings />
<location path="FederationMetadata">
...
</location>
<location path="AuthenticationService.svc">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<system.web>
...
</system.web>
To add this code snippet in Visual Studio you simply place the cursor where you'd like the code
to be inserted, start typing the snippet name, in this case
SilverlightAndIdentityLabEx01AuthenticationServicelocationelement, watch as Intellisense picks
up the snippet name, and hit the TAB key twice once the snippet you want is selected. The code
will be inserted at the cursor location.
To insert a code snippet using the mouse rather than the keyboard (i.e. for web.config file and any other
XML document), right-click where you want the code snippet to be inserted, select Insert Snippet... then
My Code Snippets and then select the relevant snippet.
To learn more about Visual Studio IntelliSense Code Snippets, including how to create your own, please
see http://msdn.microsoft.com/en-us/library/ms165392.aspx.
Note about XAML Code Snippets: Since this lab uses XAML Code Snippets and Visual Studio 2010 does
not support them, code snippets for XAML have a different header specifying the path of a txt file that
contains the code that you should add to the solution.
To use them, navigate to the folder that the header specifies, open the txt file, copy the content and
paste it on Visual Studio.
Estimated time to complete this lab: 60 minutes
Exercise 1: Single Sign on, Claims-Driven
Experience and Service Authorization for
In-Browser Silverlight applications
In the first exercise of the lab you will deal with a Silverlight application designed to be hosted in a
browser. The application has been developer for Fabrikam Gym, a health club franchise, and is intended
to enhance the experience of the club members and help them to get the most from their membership.
Identity is central to the application, as summarized by the three requirements below:
You need to ensure that only club members can use the application
The application look & feel must reflect the characteristic of the current user, so that every
member has the feeling that is custom-tailored to his or her needs
What can be done with the application must reflect the membership level: gold members
pay a premium, hence they enjoy a wider range of features
All those activities would normally require you to write a great deal of code, both difficult to develop
and maintain. With claims-based identity, however, you can avoid the problem by literally telling your
application to outsource the authentication operations to some external entity (called identity provider,
or IP, in identity jargon) that has your trust. Claims-based identity describes standard ways of exposing
authentication operations and data, which can be consumed by one application just like a printer driver
can be used for printing pages (even without really knowing the details of the specific printer model
available). Windows Identity Foundation (WIF) is what enables you, the developer, to tap into the
claims-based identity model without really having to know the details of the underlying security
protocols. As of today WIF and Silverlight are not entirely integrated, hence the abstractions boundaries
aren’t perfect: however the lab provides some ready code tor taking care of the bulk of the work.
Your first job is to create a Silverlight application and outsource its authentication to the Fabrikam IP.
With the authentication taken care of, you will learn how to use the claims from the IP to drive the
behavior of the application UI. Finally, you will use the same information on the application services for
enforcing authorization criteria without having to touch the services authorization logic.
Figure 2
A visual summary of the scenario you will build in Exercise 1
Task 1 – Creating a Silverlight Application
In the first task you will create a Silverlight application. This is mainly for providing the project structure:
later in the lab we will supply you with a ready UI.
1. Open Microsoft Visual Studio 2010 with administrator privileges. From Start | All Programs |
Microsoft Visual Studio 2010, right-click on Microsoft Visual Studio 2010 and select Run as
administrator.
2. In the File menu, choose Open and then Project/Solution.
3. In the Open Project dialog, navigate to Ex1-InBrowserApplications\Begin folder inside the
Source folder of this lab. Select the InBrowserApplications.sln file and click Open.
Figure 3
Opening Ex01 Begin Solution
4. The initial solution looks like the following:
Figure 4
Begin Solution structure
Note: You start exercise 1 with three initial assets. Here there’s an explanation of what they
contains: note that for the purposes of completing the lab you don’t need to understand (or
even know) what is in there, although you can feel free to take a peek if you are curious about
the internals. As the integration between WIF and Silverlight goes forward, the need for the
last two assets will wane.
GymFabrikamP_Sts represents, in identity jargon, Fabrikam’s identity provider (IP). One IP is
one web service or web site which knows about a set of users, is able to authenticate them
and make statements about them (claims). Claims can be literally anything that defines the
user in the context, from personal attributes such as name and address to traditional roles.
The IP exposes those capabilities through a standard programmatic interface endpoint,
commonly called Security Token Service (STS). Having an IP factors out authentication
management from all the applications that are used by the user population it serves: now
every application can outsource authentication to it, instead of having to write its own code.
That’s exactly what you are going to do in this exercise. Thanks to WIF tooling it will be really
easy!
SL.IdentityModel is an assembly containing the claims object model you will use from your
application. WIF’s assembly DLL is not present in Silverlight, hence for the purpose of this
exercise we provided a provisional assembly that allows you to use a subset of the same
programming model
SL.IdentityModel.Server is another assembly which contains logic that can trigger
authentication when necessary and handles communications with the website hosting the
Silverlight application
5. You will now create the “GYM Fabrikam” website that will host the Silverlight client. Right-click
the solution and select Add | New Web Site.
6. In the Add New Web Site dialog, select the ASP.NET Empty Web Site template, set the location
to https://localhost/GymFabrikamClientWebEx01 and press OK.
Figure 5
Creating an empty Web Site
7. Right-click the solution again, but this time, select Add | New Project.
8. In the Add New Project dialog, expand Visual C# in the project types list and select Silverlight.
9. In the Templates list, select Silverlight application. Enter GymFabrikamClient as project name
and click OK to create the project.
Figure 6
Adding a new Silverlight application
10. In the New Silverlight application dialog, select the GymFabrikamClientWebEx01 web site to
host the Silverlight application. Also, make sure that the Silverlight Version is Silverlight 4. Click
OK to add the new Silverlight application to the solution.
Figure 7
Configuring Silverlight application to be hosted on GymFabrikamClientWebEx01
11. Add a reference to the SL.IdentityModel.Server project on the
https://localhost/GymFabrikamClientWebEx01 project. To do this, right-click it in the Solution
Explorer and select Add Reference. In the Add Reference dialog, click the Projects tab, select
the SL.IdentityModel.Server project and press OK.
Figure 8
Adding a reference to SL.IdentityModel.Server on https://localhost/GymFabrikamClientWebEx01
12. Add a reference to the SL.IdentityModel project but this time, on the GymFabrikamClient
project. To do this, right-click the GymFabrikamClient project in the Solution Explorer and
select Add Reference. In the Add Reference dialog, click the Projects tab, select the
SL.IdentityModel project and press OK.
Figure 9
Adding a reference to SL.IdentityModel on GymFabrikamClient
13. In the https://localhost/GymFabrikamClientWebEx01 project, delete the
GymFabrikamClientTestPage.html page. To do this, right-click it, select Delete and confirm the
deletion dialog.
14. Right-click the GymFabrikamClientTestPage.aspx page and select Rename. Set the new name
to Default.aspx and press Enter.
Task 2 - Externalizing Authentication to an Identity Provider
You are now going to use the WIF tooling for configuring your application to outsource authentication to
the Fabrikam identity provider, represented by the https://localhost/GymFabrikamP_Sts web site. To
be more precise, you will apply the configuration to the web site which hosts the application,
https://localhost/GymFabrikamClientWebEx01.
1. Right-click the https://localhost/GymFabrikamClientWebEx01 project and select Add STS
reference.
2. The Federation Utility wizard window will be displayed. Leave the default values on the first
screen, which are simply references to which configuration file will be modified, and press Next.
Figure 10
Federation Utility Welcome page
Note: Note through the wizard you will encounter many options for which we are simply going
to accept the defaults and move forward. We are not going to give details about those: if you
are interested in a deeper discussion about those, please consider going through the Web
Sites and Identity and Web Services and Identity labs in the Identity Developer Training Kit.
3. A ready-to-use IP was provided as part of the initial solution, hence you need to select the Use
an Existing STS option. Set the metadata document location to
https://localhost/GymFabrikamP_Sts and press Next.
Figure 11
Using existing STS to federate https://localhost/GymFabrikamClientWebEx01
4. In Security token encryption, choose No encryption and press Next to continue with the
wizard.
Figure 12
Configuring No encryption for the communication with the STS
5. Press Next in the Offered Claims Wizard step.
Figure 13
Showing Offered claims by the STS
Note: Those are the claims we are going to get about the current user, upon successful
authentication. The identity provider knows the value of those attributes for every user, and
packages them into claims that are delivered to the application as soon as the user successfully
authenticated. That means that you don’t need to store any user profile if you don’t want to,
since everything the application needs to know about the user is provided at every logon.
6. Check the Wizard summary, and press Finish.
Figure 14
Checking the Federation Utility Summary
7. Open the web.config file of the https://localhost/GymFabrikamClientWebEx01/ project by
double-clicking it in the Solution Explorer.
8. Add the following validation element inside the system.webServer section:
XML
<configuration>
...
<system.webServer>
<validation validateIntegratedModeConfiguration=”false” />
<modules>
...
</modules>
</system.webServer>
...
<configuration>
9. At this point, your solution should look like the following:
Figure 15
Current solution structure
10. You have finished configuring the https://localhost/GymFabrikamClientWebEx01 project to be
federated with the Gym Fabrikam STS. To test how it works, right-click the
https://localhost/GymFabrikamClientWebEx01 project and select Set as StartUp Project.
11. Press Ctrl + F5 to run the web site. Your default browser should be launched displaying the STS’s
login page. Leave the default credentials (john) and press Submit.
Figure 16
STS’s login page
Note: The wizard you just went through configured the website to redirect unauthenticated
users to the STS pages. Here the STS can do whatever it deems necessary for authenticating
the user, in this case the auto-generated STS presents a fake username/password form. Once
the user successfully authenticated, the outcome of the authentication and the claims are
packaged and sent back to the original site. Here they are verified, and if everything looks OK
the user is granted access to the page and its content (including the Silverlight application).
12. You will be redirected to the Default.aspx page of the
https://localhost/GymFabrikamClientWebEx01 web site which hosts the Silverlight application.
Since it is not implemented yet, you will see a blank page.
Figure 17
The empty UI of the Silverlight application inside the Default.aspx page
13. Close the browser.
Task 3 – Making Claim Values Available to the Silverlight Application
There is a little catch in what we have done so far. The Federation Utility Wizard configured the website
hosting the Silverlight application to outsource authentication to the Fabrikam’s IP; and given the fact
that without authenticating to the web site you can’t get to the Silverlight app, the latter ends up being
protected by the same mechanism. However that means that the claims about the user, issued by the IP
upon successful authentication, are sent to the web site rather than the Silverlight client. Claims travel in
specialized structures, called Security Tokens, which may be encrypted; in that case the intended
recipient, the web site, can decipher the token and read the claim but for anybody else (including the
Silverlight app) those are unreadable gibberish. That works well when the consumer of the claims is a
traditional web site or web service, but that’s not our case here.
If we want to have access to the claim values from the Silverlight app, we have to ask to the web site
(the actual recipient of the claims) to communicate them back to the client. That’s what you are going to
do in this task.
1. Right-click the https://localhost/GymFabrikamClientWebEx01 project and select Add New
Item. In the Add New Item dialog, select the Silverlight-enabled WCF Service template, set the
name to AuthenticationService.svc and click Add.
Figure 18
Adding the AuthenticationService Silverlight-enabled WCF Service
2. The SL.IdentityModel.Server project provides as initial asset contains a class which will be used
as implementation of the AuthenticationService service. In this case, the service will be used by
the Silverlight app for obtaining the value of the user claims from the web site. Double-click the
AuthenticationService.svc file inside the https://localhost/GymFabrikamClientWebEx01
project and replace its content with the following code:
XML
<%@ ServiceHost Language="C#" Debug="true" Service="AuthenticationService"
CodeBehind="~/App_Code/AuthenticationService.cs" %>
<%@ ServiceHost Language="C#" Debug="true"
Factory="SL.IdentityModel.Server.AuthenticationServiceServiceHostFactory"
Service="SL.IdentityModel.Server.SL.IdentityModel.Server"
%>
3. When you added a new service, Visual Studio created the AuthenticationService.cs file inside
the App_Code folder of the https://localhost/GymFabrikamClientWebEx01 project. Normally
you would use AuthenticationService.cs for implementing the service logic, however
AuthenticationService.svc points to the service implementation provided in the
SL.IdentityModel.Server project, hence you don’t need the .cs file anymore. Right-click on
AuthenticationService.cs inside the App_code folder, select Delete and confirm the deletion
dialog.
Figure 19
Deleting the AuthenticationService.cs file
4. Enable anonymous access to the AuthenticationService service by adding the following element
on the web.config file of the https://localhost/GymFabrikamClientWebEx01 project.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 AuthenticationService location element)
XML
<connectionStrings />
<location path="FederationMetadata">
...
</location>
<location path="AuthenticationService.svc">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<system.web>
...
</system.web>
5. Inside the GymFabrikamClient project, open the App.xaml file by double-clicking it in the
Solution Explorer.
6. Update the content to use the SL.IdentityModel.Services namespace.
Note: As it was explained on the overview, code snippets for XAML have a different header
specifying the path of a txt file that contains the code that you should add to the solution.
To use them, navigate to the folder that the header specifies, open the txt file, copy the
content and paste it on Visual Studio.
(Source\Assets\XAML Code Snippets\Ex01 SL.IdentityModel.Services namespace.txt)
XAML
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="GymFabrikamClient.App"
xmlns:id="clr-
namespace:SL.IdentityModel.Services;assembly=SL.IdentityModel">
<Application.Resources>
</Application.Resources>
</Application>
7. Add a ClaimsIdentitySessionManager application service inside the
Application.ApplicationLifetimeObjects section.
(Source\Assets\XAML Code Snippets\Ex01 ClaimsIdentitySessionManager for Passive STS.txt)
XAML
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="GymFabrikamClient.App"
xmlns:id="clr-
namespace:SL.IdentityModel.Services;assembly=SL.IdentityModel">
<Application.Resources>
</Application.Resources>
<Application.ApplicationLifetimeObjects>
<id:ClaimsIdentitySessionManager>
<id:ClaimsIdentitySessionManager.IdentityProvider>
<id:WSFederationSecurityTokenService/>
</id:ClaimsIdentitySessionManager.IdentityProvider>
</id:ClaimsIdentitySessionManager>
</Application.ApplicationLifetimeObjects>
</Application>
Note: The ClaimsIdentitySessionManager class registers an object in the application resources
which will be used for accessing claims from anywhere in the app. The property
IdentityProvider indicates from where we expect claims to originate from. In this case, we
expect the hosting web site to take care of outsourcing authentication to the identity provider;
later in the lab the Silverlight application will have to handle the relationship with the IP
directly, in which case the IdentityProvider property will be set to an object which contains
more information about the IP.
8. You will now replace the current MainPage.xaml file with one provided with the lab, already
predisposed to take advantage in the UI of the claims about the user. Delete the current
MainPage.xaml file by right-clicking it inside the GymFabrikamClient project, selecting Delete
and confirming the deletion dialog.
9. Add the new MainPage.xaml from the Assets folder of this lab. Right-click the
GymFabrikamClient project and select Add | Existing Item. In the Add Existing Item dialog,
navigate to the Assets\GymFabrikamClient folder and select the MainPage.xaml file. Press Add
to include it in the project.
Figure 20
Adding the improved MainPage.xaml version
10. The improved version of the Mainpage.xaml file uses some images that should be placed inside
an Images folder. Right-click the GymFabrikamClient project and select Add | New Folder. Set
its name to Images and press Enter.
11. Add the required images by the Gym Application’s UI to the recently created folder. To do this,
right-click the Images folder and select Add | Existing Item. In the Add Existing Item dialog,
navigate to the Assets\GymFabrikamClient\Images folder and select all the files available
there. Press Add to include them inside your Images folder.
Figure 21
Adding the required images for the improved UI
12. Open the MainPage.xaml Code-Behind. To do this, right-click the MainPage.xaml file inside the
GymFabrikamClient project and select View Code.
13. Add the following code to the ShowUserInfo method to update the UI based on the user’s
gender and show his/her name.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 ShowUserInfo method 1)
C#
private void ShowUserInfo()
{
if (ClaimsIdentitySessionManager.Current.User.Identity.IsAuthenticated)
{
// Gender
Claim genderClaim = ClaimsIdentitySessionManager.Current
.User
.ClaimsIdentity
.Claims
.Where<Claim>(c => c.ClaimType == ClaimType.Gender)
.SingleOrDefault();
this.UpdateBackgroundColor(genderClaim.Value);
// User name
string userName =
ClaimsIdentitySessionManager.Current.User.Identity.Name;
this.userNameLabel.Text = string.Format("Hi {0}!", userName);
}
}
Note: The Current_GetClaimsIdentityComplete handler fires when all the claims have been
received. Claims contain information about your user, which you can easily use for
customizing the appearance of the UI and deliver a personalized experience. The current
implementation calls directly to the ShowUserInfo method.
The first line of the ShowUserInfo method shows how you can use a LINQ query on the claims
collection for extracting a specific attribute, in this case the gender of the user, and drives the
background color with that. Note that here you are not exposed to any of the details of how
the user authenticated, or which protocol was used to obtain the claim values: your code is
decoupled from those details, saving you from the hassle of having to know about security and
making your application resilient to external changes. There’s more: this is practically the same
code you would write in other kind of applications, like web sites or web services. Once you
learn how to use claims, you can reuse the skill practically everywhere.
The last two lines show how certain claims, like the name, can be accessed directly.
14. Now that you understand how to work with claims, let’s make things more interesting. Insert
the following code below the last line inserted above to show the user’s picture, heart rate at
rest, maximum lift and enable the trainingSessionsButton button only if the current user is
purchased a Gold membership to the gym.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 ShowUserInfo method 2)
C#
private void ShowUserInfo()
{
if (ClaimsIdentitySessionManager.Current.User.Identity.IsAuthenticated)
{
...
this.userNameLabel.Text = string.Format("Hi {0}!", userName);
// User picture
Claim userPictureClaim = ClaimsIdentitySessionManager.Current
.User
.ClaimsIdentity
.Claims
.Where<Claim>(c => c.ClaimType == UserPictureClaimType)
.SingleOrDefault();
this.userImage.Source =
GetBitmapSourceFromBase64(userPictureClaim.Value);
// Heart Rate at Rest
Claim hrRestClaim = ClaimsIdentitySessionManager.Current
.User
.ClaimsIdentity
.Claims
.Where<Claim>(c => c.ClaimType == HeartRateAtRestClaimType)
.SingleOrDefault();
this.hrRestLabel.Text = string.Format("HRrest = {0} bpm",
hrRestClaim.Value);
// Maximum Lift
Claim maximumLiftClaim = ClaimsIdentitySessionManager.Current
.User
.ClaimsIdentity
.Claims
.Where<Claim>(c => c.ClaimType == MaximumLiftClaimType)
.SingleOrDefault();
this.UpdateMaximumLiftInfo(int.Parse(maximumLiftClaim.Value));
// Membership
Claim membershipLevelClaim = ClaimsIdentitySessionManager.Current
.User
.ClaimsIdentity
.Claims
.Where<Claim>(c => c.ClaimType == MembershipLevelClaimType)
.SingleOrDefault();
if (membershipLevelClaim.Value == "gold")
{
this.trainingSessionsButton.IsEnabled = true;
}
else
{
this.goldMembershipOnlyLabel.Visibility = Visibility.Visible;
}
this.ShowControls();
}
}
Note: Do not think, even for a small second, that disabling the trainingSessionsButton button
is equivalent to perform authorization! The reason for which we do that is that we want to
guide the user though the application experience, and we want to make sure that he or she is
aware of the fact that the corresponding operation is not available. However you still need to
enforce the gold membership condition at the service, otherwise something as simple as
creating a different client (or somehow fooling the UI) would suffice for circumventing the
condition.
15. Your Silverlight application is ready to run. You will verify it by running again the Web site that
host the Silverlight application. Press Ctrl + F5 to run the Web Site. In the STS’s login page, press
Submit to login as “john”.
Figure 22
Login as “john” on the STS’s login page.
16. The improved Silverlight application will be shown and it is automatically customized based on
the john’s claims. Also, since John is a gold member of Gym Fabrikam, he is able to click the Get
Training Sessions. The button has still no effect, we will be providing the associated
implementation a bit later.
Figure 23
Silverlight application customized based on John’s claims.
Note: This time the appearance of the application reflects the user attributes, as established
by the claim processing code you wrote. There is quite a lot of activity under the hood leading
to that; for the ones who are interested in understanding how the process unfolds, here
there’s quick summary. The ClaimsIdentitySessionManager detects that successful
authentication took place. It is configured with the WSFederationSecurityTokenService type of
IP, which implies that the token with the claims is available at the web site which hosts the
Silverlight application. Hence ClaimsIdentitySessionManager invokes the AuthenticationService
you previously added to the web site, and uses it for retrieving the claim values. Once the
claim values are successfully retrieved, the GetClaimsIdentityComplete event is raised, giving
you a chance to use the claims in your application as shown in step 12.
17. Close the browser and press Ctrl+F5 again to start a new instance of the Web Site. In the STS’s
login page, set the User name to “mary” and press Submit.
Figure 24
Login as “mary” on the STS’s login page
18. The Silverlight application will be shown again but this time you will notice how the UI changed
based on the claims issued for Mary: the background is pink, the dumbbell icon is different, and
so on. The Get Training Sessions button is disabled, since Mary is not a gold member.
Figure 25
Silverlight application customized based on Mary’s claims
19. Close the browser.
Task 4 – Creating a Silverlight-Enabled WCF Service and Consume It from the Silverlight application
Our presentation layer is practically ready. What is still missing is the service layer, that is to say the
server-side logic which implements the actual application behavior.
As mentioned in the exercise introduction, the purpose of the application is to help members to get the
most from their gym experience. In order to achieve that, the application is going to provide the
following functionalities:
Show news about the gym in a sort of digital corkboard
Only for gold members, show the recordings of their heart rate for every training session (on
the treadmill and outdoor) so that they can track their progress
Both functions are implemented by exposing a Silverlight-enabled WCF service, hosted in the same web
site as the Silverlight application. We will need to flow identity information, so that the appropriate
authorization enforcement can take place.
1. Right-click the https://localhost/GymFabrikamClientWebEx01 project and select Add New
Item. In the Add New Item dialog, select the Silverlight-enabled WCF Service template, set the
name to GymService.svc and click Add.
Figure 26
Adding the GymService Silverlight-enabled WCF Service
2. In the interest of time, one implementation for the service is provided for you as lab asset.
Remove the GymService.cs file inside the App_Code folder of the
https://localhost/GymFabrikamClientWebEx01 project. Right-click GymService.cs, select
Delete and confirm the deletion dialog.
3. Right-click the App_Code folder inside the https://localhost/GymFabrikamClientWebEx01
project and select Add Existing Item. In the Add Existing Item dialog, navigate to the
Assets\GymFabrikamClientWebEx01 folder inside the Source folder of this lab. Select the
GymService.cs and Contracts.cs files and press Add.
Figure 27
Adding the GymService implementation and its contracts
4. Double-click the GymService.cs file that you just added to the App_Code folder. Check the
implementation and notice that there is not authentication code inside the different methods.
C#
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class GymService
{
[OperationContract]
public IEnumerable<TrainingSession> GetTrainingSessions()
{
List<TrainingSession> trainingSessions = new List<TrainingSession>();
trainingSessions.Add(
new TrainingSession
{
SessionId = new Guid("8EF3B2A8-88E2-45fc-8F4C-AE97B6D588C7"),
SessionDate = DateTime.Now.AddDays(-
1).AddHours(5).AddMinutes(4).AddSeconds(3),
Time = TimeSpan.FromMinutes(60),
Distance = 5.44,
AverageHR = 137,
MaxHR = 151,
HrGraph =
});
...
return trainingSessions.OrderByDescending(s => s.SessionDate);
}
[OperationContract]
public IEnumerable<Announcement> GetAnnouncements()
{
List<Announcement> announcements = new List<Announcement>();
announcements.Add(
new Announcement
{
Title = "Save up to 40% on your gym membership",
Date = DateTime.Now.AddDays(-
5).AddHours(8).AddMinutes(10).AddSeconds(25),
Description = "New Year is the time when many people decide to
join a gym, or revisit a neglected gym membership, so now is a good time to
return to GYMFabrikam and get 40% off."
});
...
return announcements.OrderByDescending(a => a.Date);
}
}
Note: The service serves back some hardcoded data. The most notable thing is that… there is
nothing notable! The service does not contain ANY logic for enforcing authorization checks,
and just performs the business function it has been designed to: serving a list of
announcements and a list of training sessions recordings. As service developer you don’t need
to worry about authorization details: they will be taken care of outside of the proper service
code, as you will see few steps ahead. Another obvious advantage of this approach is that the
authorization policies can be changed to adapt to different deployments and changing
requirements without having to touch the service code itself.
5. The provided version of the GymService uses some images as heart rate graphs that should be
placed inside a Graphs folder. Right-click the https://localhost/GymFabrikamClientWebEx01
project and select New Folder. Set its name to Graphs and press Enter.
6. Add the required images by the GymService to the recently created folder. To do this, right-click
the Graphs folder and select Add Existing Item. In the Add Existing Item dialog, navigate to the
Assets\GymFabrikamClientWebEx01\Graphs folder and select all the files available there. If
you don’t find the images inside the folder, make sure that the Image Files filter is selected.
Press Add to include them inside your Graphs folder.
Figure 28
Adding the required images for the GymService
7. Update the service binding to use https and allow cookies. To do this, Open the web.config file
inside the https://localhost/GymFabrikamClientWebEx01 project and replace the
httpTransport element for an httpsTransport allowing cookies inside the binding named
GymService.customBinding0 like is shown below.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 httpsTransport element)
XML
<system.serviceModel>
<behaviors>
...
</behaviors>
<bindings>
<customBinding>
<binding name="AuthenticationService.customBinding0">
<binaryMessageEncoding />
<httpTransport />
</binding>
<binding name="GymService.customBinding0">
<binaryMessageEncoding />
<httpTransport />
<httpsTransport allowCookies="True"/>
</binding>
</customBinding>
</bindings>
...
<system.serviceModel>
Note: We need HTTPS for obvious reasons, the application is handling personally identifiable
information (PII) hence we need to protect data in transit. We allow cookies for a different
reason. When a user obtains a security token and presents it to the web site at authentication
time, WIF generates a cookie which is used to maintain the security session. The cookie
contains, among other things, the claims obtained from the IP. Enabling cookies allows the
WCF services hosted on the same websites to have access to the same cookie, hence to the
claim values; in turn, this makes possible for WIF to enforce authorization conditions on
service access according to claim values, exactly what we wanted to obtain.
8. In analogy to what you did for the AuthenticationService service, enable anonymous access to
the GymService service by adding the following location element.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 GymService location element)
XML
<connectionStrings />
<location path="FederationMetadata">
...
</location>
<location path="AuthenticationService.svc">
...
</location>
<location path="GymService.svc">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<system.web>
...
</system.web>
9. Change the GymService service to use a new behavior configuration called GymServiceBehavior
as it is shown below:
XML
<system.serviceModel>
...
<services>
<service name="AuthenticationService">
...
</service>
<service name="GymService"
behaviorConfiguration=”GymServiceBehavior”>
<endpoint address=""
binding="customBinding" bindingConfiguration="GymService.customBinding0"
contract="GymService" />
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
10. Change the endpoint address of the GymService to be
https://localhost/GymFabrikamClientWebEx01/GymService.svc
XML
<system.serviceModel>
...
<services>
<service name="AuthenticationService">
...
</service>
<service name="GymService" behaviorConfiguration=”GymServiceBehavior”>
<endpoint address=""
<endpoint
address="https://localhost/GymFabrikamClientWebEx01/GymService.svc"
binding="customBinding" bindingConfiguration="GymService.customBinding0"
contract="GymService" />
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
11. At this point the service is ready to serve requests; however we still need to do something for
ensuring that our authorization logic is enforced. You will include an existing class inside the
Assets folder that allows limiting the access to the GymService based on the user membership.
To do this, right-click App_Code folder of the https://localhost/GymFabrikamClientWebEx01
project and select Add Existing Item.
12. In the Add Existing Item dialog, navigate to the Assets\GymFabrikamClientWebEx01 folder
inside the Source folder of this lab and select the MyClaimsAuthorizationManager.cs file. Press
Add to include it inside the App_Code folder.
Figure 29
Adding the MyClaimsAuthorizationManager class to the GymFabrikamClientWebEx01 project
Note: The MyClaimsAuthorizationManager file you just added to the project contains one
implementation of the ClaimsAuthorizationManager class. ClaimsAuthorizationManager is the
mechanism that WIF offers you for integrating your authorization logic in the request
processing pipeline: you derive from ClaimsAuthorizationManager, embed authorization logic
in a method override, write some code to read the access policy associated to the resources
you want to protect and you are done. Once you have that class, you can easily insert it in the
processing pipeline by editing the configuration. If your development focus area is not
security, chances are that you’d receive this class ready to use from your security colleagues in
your company: at that point you’d just follow the same steps described here. If you are
interested in knowing more about how to write your own ClaimsAuthorizationManager please
refer to the other labs in the Identity Training Kit.
13. Add inside the Web.config file the required configuration so the WIF runtime can instantiate the
custom ClaimsAuthorizationManager class to check access to the GymService. Open the
web.config file of the https://localhost/GymFabrikamClientWebEx01 project and update the
microsoft.identityModel section to define a “GymService” service section specifying the custom
ClaimsAuthorizationManager class and the policies that it should take into account.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 GymService service element)
XML
<microsoft.identityModel>
<service name="GymService">
<claimsAuthorizationManager
type="ClaimsBasedAuthorization.MyClaimsAuthorizationManager">
<policy
resource="https://localhost/GymFabrikamClientWebEx01/GymService.svc"
action="http://tempuri.org/GymService/GetTrainingSessions">
<claim
claimType="http://gym.fabrikam.com/2010/03/identity/claims/membershiplevel"
claimValue="gold"/>
</policy>
<policy
resource="https://localhost/GymFabrikamClientWebEx01/GymService.svc"
action="http://tempuri.org/GymService/GetAnnouncements">
<or>
<claim
claimType="http://gym.fabrikam.com/2010/03/identity/claims/membershiplevel"
claimValue="gold"/>
<claim
claimType="http://gym.fabrikam.com/2010/03/identity/claims/membershiplevel"
claimValue="silver"/>
</or>
</policy>
</claimsAuthorizationManager>
</service>
<service>
<audienceUris>
...
</audienceUris>
...
</service>
</microsoft.identityModel>
Note: The policy above is pretty straightforward: calling the method GetTrainingSessions
requires the current user to present a claim of type
http://gym.fabrikam.com/2010/03/identity/claims/membershiplevel with value “gold”, while
the method GetAnnouncements can be invoked both by gold and silver members.
14. Add an extensions section to system.serviceModel to define a behavior extension that allows
define which service definition inside microsoft.identityModel should be used by the service.
To do this, add the following element to system.serviceModel below the behaviors section.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 system.serviceModel extensions section)
XML
<system.serviceModel>
<behaviors>
...
</behaviors>
<extensions>
<behaviorExtensions>
<add name="federatedServiceHostConfiguration"
type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtens
ionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</behaviorExtensions>
</extensions>
<bindings>
...
</bindings>
</system.serviceModel>
15. Add a service behavior named “GymServiceBehavior” to configure the GymService to use the
new service defined in the microsoft.identityModel section. To do this, add the following
behavior element on the servicebehaviors definition.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 GymServiceBehavior binding element)
XML
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
...
</behavior>
<behavior name="GymServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<federatedServiceHostConfiguration name="GymService" />
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
...
</extensions>
...
</system.serviceModel>
16. Disable multisite bindings to avoid problems when the service is hosted. To do this, update the
multipleSiteBindingsEnabled attribute to false inside the
system.serviceModel/serviceHostingEnvironment element.
XML
<system.serviceModel>
<bindings>
...
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="false" />
<services>
...
</services>
...
</system.serviceModel>
17. Press Ctrl + Shift + B to compile the solution.
18. Now the GymService service is truly ready. It’s time to hook the Silverlight application to it: we
are going to do it just like we would with any other service. Right-click the GymFabrikamClient
project and select Add Service Reference.
19. On the Add Service Reference dialog, press Discover to list the different available services in
the solution. Select the GymFabrikamClientWebEx01/GymService.svc service, change the
namespace to GymServiceReference and press OK.
Figure 30
Adding a reference to the GymService service from the Silverlight application
Note: If you get a warning saying that your certificate name does not match the DNS server
name of your machine, press Yes.
20. Only if you were prompted with the warning shown in the note above, open the
ServiceReferences.ClientConfig file inside the GymFabrikamClient project and replace the
address for the GymService with localhost instead of the full name of your machine, as shown
below.
XML
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_GymService">
<binaryMessageEncoding />
<httpsTransport maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint
address="https://yourmachinename.yourdomainname.com/GymFabrikamClientWebEx01/G
ymService.svc"
address="https://localhost/GymFabrikamClientWebEx01/GymService.svc"
binding="customBinding"
bindingConfiguration="CustomBinding_GymService"
contract="GymServiceReference.GymService"
name="CustomBinding_GymService" />
</client>
</system.serviceModel>
</configuration>
Note: If your machine is domain-joined, sometimes the Add Service Reference operation will
resolve your full machine name, which does not match with the localhost certificate you use in
the lab. Changing the endpoint address back to localhost will avoid any certificate conflicts.
21. On previous steps, you enabled anonymous access to the GymService service to be able to add
a service reference to it. Now that you did it, remove the GymService.svc location element from
the web.config file of the https://localhost/GymFabrikamClientWebEx01 project.
XML
<connectionStrings />
<location path="FederationMetadata">
...
</location>
<location path="AuthenticationService.svc">
...
</location>
<location path="GymService.svc">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<system.web>
...
</system.web>
22. Open the MainPage.xaml Code-Behind in the GymFabrikamClient project. To do this, right-click
the MainPage.xaml file inside the GymFabrikamClient project and select View Code.
23. Add a namespace directive to the GymServiceReference at the top of the class:
C#
using GymFabrikamClient.GymServiceReference;
24. Implement the call to the GymService service to retrieve the list of announcements at the
bottom of the ShowUserInfo method.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 ShowUserInfo Announcements)
C#
private void ShowUserInfo()
{
if (ClaimsIdentitySessionManager.Current.User.Identity.IsAuthenticated)
{
...
if (membershipLevelClaim.Value == "gold")
{
this.trainingSessionsButton.IsEnabled = true;
}
else
{
this.goldMembershipOnlyLabel.Visibility =
Visibility.Visible;
}
this.ShowControls();
// Announcements
GymServiceClient client = new GymServiceClient();
client.GetAnnouncementsCompleted += new
EventHandler<GetAnnouncementsCompletedEventArgs>(this.Client_GetAnnounc
ementsCompleted);
client.GetAnnouncementsAsync();
}
}
25. Implement the call to the GymService service on the TrainingSessionsButton_Click method.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 TrainingSessionsButton_Click method)
C#
private void TrainingSessionsButton_Click(object sender, RoutedEventArgs e)
{
GymServiceClient client = new GymServiceClient();
client.GetTrainingSessionsCompleted += new
EventHandler<GetTrainingSessionsCompletedEventArgs>(this.Client_GetTrainingSes
sionsCompleted);
this.announcementsList.Visibility = Visibility.Collapsed;
this.goldMembersArea.Visibility = Visibility.Visible;
try
{
client.GetTrainingSessionsAsync();
}
catch
{
this.trainingSessionsArea.Visibility = Visibility.Collapsed;
}
}
26. That’s pretty much it for what concerns the call. Next, you will implement the logic to change
the Training Session image when the user selects a different entry in the training sessions list.
Add the following code on the TrainingSessionsList_SelectionChanged method.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 TrainingSessionsList_SelectionChanged)
C#
private void TrainingSessionsList_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 0)
{
return;
}
var selectedItem = (TrainingSession)e.AddedItems[0];
this.heartRateImage.Source =
GetBitmapSourceFromBase64(selectedItem.HrGraph);
}
27. Add the Client_GetTrainingSessionsCompleted and Client_GetAnnouncementsCompleted
methods which will bind the information retrieved from the Gym Service to the different lists.
(Code Snippet – SilverlightAndIdentity Lab - Ex01 Data Binding methods)
C#
private void Client_GetTrainingSessionsCompleted(object sender,
GetTrainingSessionsCompletedEventArgs e)
{
if (e.Error == null)
{
this.trainingSessionsList.ItemsSource = e.Result;
this.trainingSessionsList.SelectedIndex = 0;
}
}
private void Client_GetAnnouncementsCompleted(object sender,
GetAnnouncementsCompletedEventArgs e)
{
if (e.Error == null)
{
this.announcementsList.ItemsSource = e.Result;
}
}
Exercise 1 – Verification
That’s it: the service is ready to serve content according to the user’s membership level, and the client
application is wired up to call the service as intended. All that’s left is giving it a spin and verify that it
behaves as expected.
1. Make sure that the https://localhost/GymFabrikamClientWebEx01 project is the StartUp
Project by right-clicking the https://localhost/GymFabrikamClientWebEx01 project and
selecting Set as StartUp Project.
2. Press Ctrl + F5 to run the Web Site. In the STS’s login page, press Submit to login as “john”.
Figure 31
Login as “john” on the STS’s login page
The Gym Fabrikam Silverlight application will be displayed inside the browser. Notice that a list
of Notes is displayed at the bottom of the page, a telltale sign that the call to the
GetAnnouncements method of GymService succeeded.
Figure 32
Improved UI showing notes from the Gym Service
3. John is a gold member of Gym Fabrikam, hence he is able to click the Get Training Sessions
button and get the list of his recorded training sessions. Click some item in the list and observe
that the associated Heart Rate graphic changes accordingly.
Figure 33
Showing Training Sessions is a privilege reserved to gold members
Note: Pressing the Get Training Sessionss button triggers the service call you coded earlier. The
service verifies that the caller has indeed an active gold membership by checking the claims in
the session cookie: upon successful authorization, the service returns a list of hardcoded
sessions with associated heart rate graphs.
4. Close the browser. For extra credits, repeat the verification process by signing in as Mary: you
will discover that Mary can see the news on the main page, but her membership level prevents
her from accessing the session recording features.
Exercise 1: Summary
In this first exercise you accomplished a lot! You solved the authentication problem by outsourcing
authentication to an external identity provider, allowing your user to reuse credentials while taking
advantage of interoperable standards and point & click tooling. You learned how to use claims for
retrieving attributes about the user, and take advantage of those for guaranteeing a highly personalized
experience. Discovered a way of using WIF for adding declarative authorization in front of your services,
driven by claim values. Many of those things were made possible by a Silverlight-WIF integration library,
available in the assets folder of the lab.
In the next exercise we will build on what we have seen so far, applying it to out-of-browser application
types.
Exercise 2: Identity and Out of Browser
Applications
The ease with which we externalized authentication in exercise 1 is impressive. However, the particular
technique we used in that case relies on redirects, which in turn assumes that the application is being
consumed from within a browser. Silverlight, on the other hand, supports out of browser applications :
what are the implications on what you have learned so far about claims based identity, is the technique
applicable to the out of browsers applications as well? Good news: the same technique can be applied
largely unchanged to the out of browser case as well. The only real difference lies in the way in which
the application contacts the identity provider: whereas in the former case this was done via WS-
Federation, a protocol which requires browser redirect, here we can use WS-Trust. In identity jargon you
would say that you would use an active STS. Substantially, that means that the identity provider
capabilities are exposed via a web service instead of a web page. All we need to do is calling that service
when a sign on is taking place; once we will have obtained the token, everything will be business as
usual.
Figure 34
A visual summary of what you will build in Exercise 2
Task 1 – Updating the Silverlight Application to Run OOB (Out of Browser) and Rely on an Active STS
for Authentication
The first task you’ll need to do is configuring the application to run out of browser, a task easily
accomplished via Visual Studio configuration and Silverlight runtime. The next step will be adapting your
code to outsource authentication to an identity provider exposed via web service. In practical terms this
means modifying the ClaimsIdentitySessionManager object in the application resources to point to the
desired STS: it also means that gathering user credentials and send them to the identity provider is now
your responsibility, although the authentication itself and managing the user store remain a duty of the
IP.
1. Open Microsoft Visual Studio 2010 with administrator privileges. From Start | All Programs |
Microsoft Visual Studio 2010, right-click on Microsoft Visual Studio 2010 and select Run as
administrator.
In the File menu, choose Open and then Project/Solution. In the Open Project dialog, navigate
to Ex2-OutOfBrowserApplications\Begin folder inside the Source folder of this lab. Select the
OutOfBrowserApplications.sln file and click Open.
Figure 35
Opening Ex02 Begin Solution
2. Right-click the GymFabrikamClient project in the Solution Explorer and select Properties.
3. Inside the Silverlight tab, check the Enable running application out of the browser option.
Figure 36
Enabling running the Silverlight application out of the browser
4. Click the Out-of-Browser Settings button to check the current properties for the Silverlight
application outside the browser. Leave the default values and press OK to close the dialog.
Figure 37
Silverlight application out of the browser settings page
5. Press Ctrl + S to save the changes and close the GymFabrikamClient properties page.
6. Open the App.xaml file inside the GymFabrikamClient project by double-clicking it in the
Solution Explorer.
7. Since the Gym Fabrikam application now can run out-of-browser, authentication cannot be
performed using web site federation. Fortunately, the ClaimsIdentitySessionManager offers
the capability of configuring the authentication to take place against one active STS (the begin
project already contains one ready for you to use). To do this, replace the current
ClaimsIdentitySessionManager definition with the following:
(Source\Assets\XAML Code Snippets\Ex02 ClaimsIdentitySessionManager for Active STS.txt)
XAML
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="GymFabrikamClient.App"
xmlns:id="clr-
namespace:SL.IdentityModel.Services;assembly=SL.IdentityModel">
<Application.Resources>
</Application.Resources>
<Application.ApplicationLifetimeObjects>
<id:ClaimsIdentitySessionManager>
<id:ClaimsIdentitySessionManager.IdentityProvider>
<id:WSFederationSecurityTokenService/>
</id:ClaimsIdentitySessionManager.IdentityProvider>
</id:ClaimsIdentitySessionManager>
<id:ClaimsIdentitySessionManager
ApplicationIdentifier="https://localhost/GymFabrikamClientWebEx02/" >
<id:ClaimsIdentitySessionManager.IdentityProvider>
<id:WSTrustSecurityTokenService
Endpoint="https://localhost/GymFabrikamA_Sts/Service.svc/IWSTrust13"
CredentialType="Username" />
</id:ClaimsIdentitySessionManager.IdentityProvider>
</id:ClaimsIdentitySessionManager>
</Application.ApplicationLifetimeObjects>
</Application>
Note: In exercise 1 we didn’t need to add any extra information: since authentication took
place at the hosting web site, the Silverlight application had no responsibilities in making that
happen. In the case of an out of browser application, the authentication step is an actual call
to a service (an STS is, after all, a special flavor of web service). As a result, at a minimum we
need to know the address of the service; furthermore, we need to know which protocol and
credential types to use for performing user authentication. The WSTrustSecurityTokenService
object holds the settings associated to a WS-Trust based STS; Endpoint represents the STS
endpoint, and CredentialType hints to the kind of credentials it requires. The
ApplicationIdentifier attribute is used for communicating to the STS for what application a
token is being requested.
8. At startup time Gym Fabrikam will have to gather user credentials in order to authenticate the
user against the GymFabrikamA_Sts STS.We have a credential gathering UI ready for you, the
Login.xaml Silverlight User Control provided inside the Assets folder of this lab. Right-click the
GymFabrikamClient project and select Add | Existing Item.
9. In the Add Existing Item dialog, navigate to the Assets\GymFabrikamClient folder inside the
Source folder of this lab and select the Login.xaml file. Press Add to include it in the project.
Figure 38
Adding the Login.xaml User Control to the GymFabrikamClient project
10. Inside the MainPage.xaml you will include some code to use the Login User Control. Double-
click MainPage.xaml inside the Solution Explorer to open it.
11. Inside the UserControl definition at the top of the file, add a namespace directive to
GymFabrikamClient as it is show below:
(Source\Assets\XAML Code Snippets\Ex02 GymFabrikamClient Namespace.txt)
XAML
<UserControl x:Class="GymFabrikamClient.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:GymFabrikamClient"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
...
</UserControl>
12. Add the Login control definition at the bottom of the MainPage.xaml.
(Source\Assets\XAML Code Snippets\Ex02 Login Control.txt)
XAML
<UserControl x:Class="GymFabrikamClient.MainPage"
...>
<Grid x:Name="LayoutRoot" Background="#FFFFFFFF">
<Grid x:Name="frame" Margin="5,5,5,5">
...
</Grid>
<local:Login x:Name="loginPopup" Visibility="Collapsed" />
</Grid>
</UserControl>
13. Modify the MainPage.xaml Code-Behind to use the Login User Control for gathering the user
credentials and use them to authenticate against the active STS, via the
ClaimsIdentitySessionManager control. To do this, right-click the MainPage.xaml file inside the
GymFabrikamClient project and select View Code.
14. Update the MainPage class constructor to look like the following:
(Code Snippet – SilverlightAndIdentity Lab - Ex02 MainPage class constructor)
C#
public MainPage()
{
InitializeComponent();
ClaimsIdentitySessionManager.Current.GetClaimsIdentityComplete += new
EventHandler<ClaimsIdentityEventArgs>(this.Current_GetClaimsIdentityComplete);
InitializeComponent();
ClaimsIdentitySessionManager.Current.SignInComplete += new
EventHandler<SignInEventArgs>(Current_SignInComplete);
this.loginPopup.OnLogInCompleted += (s, e) =>
{
ClaimsIdentitySessionManager.Current.SignInUsernameAsync(e.UserName,
e.Password);
};
this.loginPopup.Show();
}
15. Replace the signature of the Current_GetClaimsIdentityComplete to:
(Code Snippet – SilverlightAndIdentity Lab - Ex02 Current_SignInComplete signature)
C#
private void Current_GetClaimsIdentityComplete(object sender,
ClaimsIdentityEventArgs e)
private void Current_SignInComplete(object sender, SignInEventArgs e)
{
...
}
16. The https://localhost/GymFabrikamClientWebEx02 project is not using federation: the
authentication process is being driven directly from the Silverlight UI. As a result, we don’t need
to protect the pages hosting the Silverlight application: in fact you will need to enable
anonymous access to the Default.aspx page. Open the Web.config file inside the
https://localhost/GymFabrikamClientWebEx02 project and add the following location
element:
(Code Snippet – SilverlightAndIdentity Lab - Ex02 Default.aspx location element)
XML
<connectionStrings />
<location path="FederationMetadata">
...
</location>
<location path="AuthenticationService.svc">
...
</location>
<location path="Default.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<system.web>
...
</system.web>
Exercise 2 – Verification
That’s all you need to do for adapting the application to run out of browser. Let’s verify that everything
works as expected.
1. Make sure that the https://localhost/GymFabrikamClientWebEx02 project is the StartUp
Project by right-clicking the https://localhost/GymFabrikamClientWebEx02 project and
selecting Set as StartUp Project.
2. Press F5 to run the web site. Your default browser will be launched displaying the Default.aspx
page of the https://localhost/GymFabrikamClientWebEx02 web site which hosts the
GymFabrikamClient Silverlight application. The Login user control will be shown requesting the
user credentials.
Figure 39
Silverlight application requesting user credentials
3. Install the application in your machine to run it Out-of-Browser, right-click the Silverlight
application in your browser and select Install GymFabrikamClient Application onto this
computer...
Figure 40
Installing the Silverlight application on your computer
4. In the Install Application dialog, press OK.
Figure 41
Configuring Silverlight application Installation
5. The Silverlight application will now appear as is, without the browser chrome.
Figure 42
Silverlight application running Out-of-Browser
6. Set the username to john and the password to p@ssw0rd and press the Sign In button.
Figure 43
Logging as john in the Silverlight application
7. The Login user control disappears and the main Gym Fabrikam UI is shown. As expected, the
experience is customized according to the current user.
Figure 44
Silverlight application customized based on logged user
8. Click the Get Training Sessions button to retrieve the list of available training sessions.
Figure 45
Silverlight application retrieving the list of training sessions
9. Close the application.
Exercise 2: Summary
Running one application out of browser is a powerful feature, which comes in handy in a number of
occasions. This exercise walked you through the process of adapting the authentication mechanism to
the situation in which you cannot rely on browser-based redirects. As you had a chance to observe, the
change is minimal and substantially just entails taking care of gathering the user credentials and taking
advantage of one identity provider which offers an active STS endpoint.
Exercise 3: Calling Services in Other
Domains
The last exercise of the lab deals with a very common scenario, one that can easily become a headache:
invoking services in external domains from your Silverlight application.
Claims-based identity is perfect for the task. The idea of explicitly modeling trust between entities
(applications trusting identity providers to perform authentication), the use of security tokens as a way
of verifying that authentication took place elsewhere in a distributed system, and the chance of
transmitting claims that can be used for authorization are all you need for performing secure calls across
domains. Furthermore, with the work done in exercises 1 and 2 you already have most of the necessary
component in place. Silverlight’s default binding do not offer the expressive power which is necessary
for circulating tokens the way we need in this scenario: once again, the custom extensions provided with
the lab come to our aid. In our sample gym application scenario the external service will serve maps of
the path of outdoor jogging sessions, which will be paired to the heart rate traces for those members
who use GPS equipment.
Figure 46
A visual summary of what you will build in Exercise 3
Task 1 – Creating an "External" WCF Service
You are going to start with a solution which contains all the features shown in exercise 2. The first task
will be extending that solution with the external service we want to leverage from the application.
1. Open Microsoft Visual Studio 2010 with administrator privileges. From Start | All Programs |
Microsoft Visual Studio 2010, right-click on Microsoft Visual Studio 2010 and select Run as
administrator.
2. In the File menu, choose Open and then Project/Solution. In the Open Project dialog, navigate
to Ex3-CallingExternalServices\Begin folder inside the Source folder of this lab. Select the
CallingExternalServices.sln file and click Open.
Figure 47
Opening Ex03 Begin Solution
3. You will now create the “external” WCF Service that will provide images about where the
different training sessions will take place. Right-click the solution and select Add | New Web
Site.
4. In the Add New Web Site dialog, select the Claims-aware WCF Service template, set the
location to https://localhost/ExternalService and press OK.
Figure 48
Creating a Claims-aware WCF Service
5. As you did for the GymService, you will delete the default service implementation and use one
provided inside the Assets folder. Right-click the IService.cs and Service.cs files inside the
App_Code of the https://localhost/ExternalService project, select Delete and confirm the
deletion dialog for each of them.
6. Right-click the App_Code folder inside the https://localhost/ExternalService project and select
Add Existing Item. In the Add Existing Item dialog, navigate to the Assets\ExternalService
folder inside the Source folder of this lab. Select the IService.cs and Service.cs files and press
Add.
Figure 49
Adding the External WCF Service implementation
7. The provided version of the “external” service uses some images to show the location where
the different training sessions will be performed. Those should be placed inside a Maps folder.
Right-click the https://localhost/ExternalService project and select New Folder. Set its name to
Maps and press Enter.
8. Add the required images by the “external” service to the recently created folder. To do this,
right-click the Maps folder and select Add Existing Item. In the Add Existing Item dialog,
navigate to the Assets\ExternalService\Maps folder and select all the files available there. If
you don’t find the images inside the folder, make sure that the Image Files filter is selected.
Press Add to include them inside your Maps folder.
Figure 50
Adding the required images for the “external” service
9. Now you will establish a trust relationship between the external WCF service and the
GymFabrikamA_Sts STS: that simply means that the service will be configured to authenticate
users only if they present a token from GymFabrikamA_Sts. To do this, right-click the
https://localhost/ExternalService project and select Add STS Reference. You will notice that
the process closely resembles what you already did in exercise 1 for outsourcing authentication
for the hosting web site.
10. The Federation Utility wizard window will be displayed. Update the Application URI to be https,
and press Next.
Figure 51
Federation Utility Welcome page
11. Press Next in Application Information.
Figure 52
Application Information page
12. Select the Use an Existing STS option in the Select the STS location Wizard step. Set the
metadata document location to https://localhost/GymFabrikamA_Sts and press Next.
Figure 53
Using existing STS to federate the “external” WCF Service
13. In Security token encryption, choose Enable encryption and then Select an existing certificate
from store. Select the localhost certificate clicking the Select Certificate button and press Next
to continue with the wizard.
Figure 54
Configuring encryption for the communication with the STS
14. Press Next in the Offered Claims Wizard step.
Figure 55
Showing Offered claims by the STS
15. Check the Wizard summary, and press Finish.
Figure 56
Checking the Federation Utility Summary
16. Add a custom binding that will be used then by the “external” service. To do this, in Solution
Explorer double-click the Web.config file of the https://localhost/ExternalService project and
inside add the following code inside the system.serviceModel/bindings section removing the
current ws2007FederationHttpBinding binding.
(Code Snippet – SilverlightAndIdentity Lab - Ex03 customBinding)
XML
<system.serviceModel>
</extensions>
...
</extensions>
<bindings>
<ws2007FederationHttpBinding>
<binding
name="ExternalService.IService_ws2007FederationHttpBinding">
<security mode="Message">
<message>
<issuerMetadata
address="https://localhost/GymFabrikamA_Sts/Service.svc/mex" />
<claimTypeRequirements>
<add
claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
isOptional="true" />
<add
claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
isOptional="true" />
</claimTypeRequirements>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
<customBinding>
<binding name="customBinding0">
<binaryMessageEncoding />
<httpsTransport/>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
Note: ws2007FederationHttpBinding is not supported in Silverlight. The binding we are adding
here is a placeholder, which will allow you to refer to the service from the Silverlight project.
Once we will have established a service reference on the client, we will come back to this
config section and you will change the binding to take advantage of claims and raise the
security requirements for the call.
17. Update the service definition to use the new custom binding.
XML
<system.serviceModel>
<services>
<service name="ExternalService.Service"
behaviorConfiguration="ExternalService.ServiceBehavior">
<endpoint address="https://localhost/ExternalService/Service.svc"
binding="ws2007FederationHttpBinding"
binding="customBinding"
contract="ExternalService.IService"
bindingConfiguration="ExternalService.IService_ws2007FederationHttpBinding" />
bindingConfiguration="customBinding0" />
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
...
<behaviors>
</system.serviceModel>
Task 2 – Updating the Silverlight Application to Consume the “External” WCF Service
With the external service in place, you can now go ahead and create a service reference to it from the
Silverlight application.
1. Press Ctrl + Shift + B to compile the solution.
2. Add a reference to the external service from the Silverlight application. To do this, right-click the
GymFabrikamClient project and select Add Service Reference.
3. On the Add Service Reference dialog, press Discover to list the different available services in
the solution. Select the ExternalService/Service.svc service, change the namespace to
ExternalServiceReference and press OK.
Figure 57
Adding a reference to the “external” WCF service from the Silverlight application
4. Now that the reference has been established, we no longer need to keep the unsecure binding
in place. Go back to the Web.config file of the https://localhost/ExternalService project and fix
the custom binding to use claims-aware settings, by adding the following elements.
(Code Snippet – SilverlightAndIdentity Lab - Ex03 customBinding security element)
XML
<system.serviceModel>
</extensions>
...
</extensions>
<bindings>
<customBinding>
<binding name="customBinding0">
<security authenticationMode="IssuedTokenOverTransport"
messageSecurityVersion="WSSecurity11WSTrust13WSSecureConversation13WSSecurityP
olicy12BasicSecurityProfile10">
<issuedTokenParameters keyType="BearerKey" />
</security>
<binaryMessageEncoding />
<httpsTransport/>
</binding>
</customBinding>
</bindings>
</system.serviceModel>
5. The last thing we need to do before being able to give a test run is updating the method that
retrieves the training sessions from the GymService: from now on we will also get from the
external service images showing the maps of the places where jogging sessions took place. To
do this, right-click the MainPage.xaml file inside the GymFabrikamClient project and select
View Code.
6. Add the following namespace directives at the top of the class:
(Code Snippet – SilverlightAndIdentity Lab - Ex03 ExternalServiceReference using)
C#
using GymFabrikamClient.ExternalServiceReference;
using SL.IdentityModel.Protocols.WSTrust;
7. Add in the MainPage class constructor a handler for the UsernameRequired event of the
ClaimsIdentitySessionManager control.
(Code Snippet – SilverlightAndIdentity Lab - Ex03 UsernameRequired handler)
C#
public MainPage()
{
InitializeComponent();
ClaimsIdentitySessionManager.Current.SignInComplete += new
EventHandler<SignInEventArgs>(Current_SignInComplete);
ClaimsIdentitySessionManager.Current.UsernameRequired += new
ClaimsIdentitySessionManager.UsernameRequiredEventHandler(this.Current_Usernam
eRequired);
this.loginPopup.OnLogInCompleted += (s, e) =>
{
userName = e.UserName;
password = e.Password;
ClaimsIdentitySessionManager.Current.SignInUsernameAsync(e.UserName,
e.Password);
};
this.loginPopup.Show();
}
8. Add the Current_UsernameRequired method below the MainPage class constructor.
(Code Snippet – SilverlightAndIdentity Lab - Ex03 Current_UsernameRequired method)
C#
private UsernameCredentials Current_UsernameRequired(object sender, string
endpoint)
{
return new UsernameCredentials(userName, password);
}
9. Add the following code to the current implementation of the
TrainingSessionsList_SelectionChanged method.
(Code Snippet – SilverlightAndIdentity Lab - Ex03 TrainingSessionsList_SelectionChanged Maps)
C#
private void TrainingSessionsList_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 0)
{
return;
}
var selectedItem = (TrainingSession)e.AddedItems[0];
this.heartRateImage.Source =
GetBitmapSourceFromBase64(selectedItem.HrGraph);
if (this.showSessionMapsCheckBox.IsChecked.Value)
{
// Call external service
ServiceClient client = new ServiceClient();
client.GetSessionMapCompleted += new
EventHandler<GetSessionMapCompletedEventArgs>(this.Client_GetSessionMapComplet
ed);
this.loadingAlert.Visibility = Visibility.Visible;
this.sessionMap.Visibility = Visibility.Collapsed;
ClaimsIdentitySessionManager.Current.InvokeAsync(() =>
{
client.GetSessionMapAsync(selectedItem.SessionId);
},
client.InnerChannel,
WSTrust13Constants.KeyTypes.Bearer);
}
}
10. Add the Client_GetSessionMapCompleted method which will bind the maps retrieved from the
external WCF Service to show it in the Image control.
(Code Snippet – SilverlightAndIdentity Lab - Ex03 Client_GetSessionMapCompleted method)
C#
private void Client_GetSessionMapCompleted(object sender,
GetSessionMapCompletedEventArgs e)
{
if (e.Error == null)
{
this.sessionMap.Source = GetBitmapSourceFromBase64(e.Result);
}
this.loadingAlert.Visibility = Visibility.Collapsed;
this.sessionMap.Visibility = Visibility.Visible;
}
Exercise 3 – Verification
The expected behavior of the new application is equivalent to what we have seen in exercise 2, the only
difference will be that users will be able to see maps along with the old heart rate charts.
1. Make sure that the https://localhost/GymFabrikamClientWebEx03 project is the StartUp
Project by right-clicking the https://localhost/GymFabrikamClientWebEx03 project and
selecting Set as StartUp Project.
2. Press F5 to run the web site. Your default browser will be launched displaying the Default.aspx
page of the https://localhost/GymFabrikamClientWebEx03 web site which hosts the
GymFabrikamClient Silverlight application. Set the username to john and the password to
p@ssw0rd and press the Sign In button.
Figure 58
Logging as John in the Silverlight application
3. Click the Get Training Sessions button. The list of available training sessions will be shown at
the bottom. You will notice that there is a new check box called Show Sessions Maps at the left
of the Get Training Sessions button.
Figure 59
Silverlight application retrieving the list of training sessions
4. Check the Show Sessions Maps option and select other training session from the list. The map
showing the location where the session will be placed is shown below the Heart Rate graph.
Figure 60
Silverlight application retrieving the list of training sessions
5. You can select different sessions to get the location where they will be performed.
6. Close the browser.
Exercise 3: Summary
Using claims for invoking external services is very effective. The ease with which you added this
functionality to the application, and the fact that the new feature integrated smoothly with the app flow
without requiring extra password prompts, is another good property of taking advantage of identity
providers, trust relationships and claims.
A word of caution, though: for your convenience in this lab everything took place on the same machine,
in a real setup you would have to follow the usual practices around CientAccessPolicy.xml and
crossdomain.xml.
Summary
Using claims-based identity in your Silverlight application can save you the hassle of handling
authentication & authorization by yourself, decoupling you from complexity and change. Claims can help
you delighting your users with custom-tailored experiences modeled after their identities, without
taking any dependency on the environment. Furthermore, claims allow you to more securely tap on
data and services across domain and even platform boundaries.
By completing this Hands-On Lab you have learned how to:
Take advantage of an existing identity provider (exposed via passive STS) for externalizing
authentication for a in-browser Silverlight application
Access claims values from the code of a Silverlight application and use them for user experience
customization
Handle authorization for WCF services hosted in a Silverlight website using the WIF
programming model
Take advantage of an existing identity provider (exposed via active STS) for externalizing
authentication for an out-of-browser Silverlight application
Invoke services on other domains using SAML tokens from a Silverlight application
Some of the tasks above required the use of some custom extensions, provided with the lab starting
material. Those extensions provide further capabilities, such as the ability of using symmetric keys for
achieving higher levels of protection. Please feel free to comment on things you like and don’t like about
the model: as we move ahead toward a more complete integration between Silverlight and Windows
Identity Foundation, your feedback about the extensions demonstrated in the lab will be extremely
valuable.
We hope that the programming skills you learned in this and the other identity labs will enable you to
write solutions with the confidence that no matter which kind of application you choose to develop, you
took care of identity in consistent and effective manner.
top related