Hands-On Lab

Web Services andIdentity for Visual Studio 2010 Developers

Lab version:1.0.0

Last updated:10/3/2018

Contents

Overview

Exercise 1: Using Windows Identity Foundation to Handle Authentication and Authorization in a WCF Service

Task 1 - Reviewing the Begin Solution

Task 2 - Using Windows Identity Foundation to Authenticate Calls to the Service

Task 3 - Using the Service

Exercise 1: Verification

Exercise 1: Summary

Exercise 2: Accepting Tokens from an Active Directory Federation Services (ADFS) STS

Task 1 - Modifying the Service to Accept Tokens Issued by an STS Published via Active Directory Federation Services (ADFS)

Task 2 - Modifying the Client in Order to Secure Calls to the Service via Issued Token

Task 3 - Using Claims for Authorizing the Service Call

Exercise 2: Verification

Exercise 2: Summary

Exercise 3: Invoking a WCF Service on the Backend via Delegated Access

Task 1 - Opening the Solution

Task 2 - Adding a Reference to the Backend Service

Task 3 - Calling the Backend Service

Exercise 3: Verification

Exercise 3: Summary

Summary

Overview

Security and identity management are among the most critical aspects of any SOA and distributed systems in general. Since its introduction in version 3.0 of the .NET Framework, WCF provided the necessary expressive power for taking advantage of WS-Security, WS-Trust and all the standard mechanisms which help you to develop and consume web services in interoperable manner.

Today Windows Identity Foundation (WIF), formerly known as Geneva,brings the approach further, abstracting away most of the complexity for application developer and providing a clear extensibility model for security developers. By introducing a unified approach to claims-based identity which applies both to WCF and ASP.NET, Windows Identity Foundationmakes claims a first-class citizen in the .NET framework; furthermore, the enhancements to Visual Studio integration guarantee that the use of advanced identity capabilities will easily blend within the familiar development practices of Visual Studio users.

During this Hands-on lab you will learn how to take advantage of the new model, classes and tools that constitute Windows Identity Foundation. Some tasks will show how to solve problems you are already familiar with, demonstrating the improvements in respect to the WCF-only model; some other task will show how to easily solve problems that in the past required very complex solutions, and that are now within reach of any developer. More specifically, you will learn how to:

  • Use the Windows Identity Foundationobject model to authenticate and authorize web service calls
  • Take advantage of production STSes for externalizing authentication and obtaining claims about the user
  • Authorize access to services by imposing conditions on incoming claims
  • [Optional] Leverage the .NET Access Control Service for handling claim transformations
  • Handle delegation scenarios

Windows Identity Foundationcan do much more than what we cover in this lab: we hope that the skills you will learn here will help you in your further explorations of identity development.

Objectives

In this Hands-On Lab, you will learn how to:

  • Authenticate and authorize web service calls
  • Trust tokens from a production STS
  • Authorize access to services by imposing conditions on incoming claims
  • Obtain delegated tokens and authorize calls protected by delegated tokens

System Requirements

You must have the following items to complete this lab:

  • Microsoft® Windows® Vista SP2 (32-bits or 64-bits) ,Microsoft® Windows Server 2008 SP2 (32-bit or 64-bit), Microsoft® Windows Server 2008 R2, Microsoft® Windows® 7 RTM (32-bits or 64-bits)
  • Microsoft® Internet Information Services (IIS) 7.0
  • Windows Feature WCF HTTP Activation
  • Microsoft® .NET Framework 4.0
  • Microsoft® Visual Studio 2010
  • Microsoft® Windows Identity Foundation Runtime
  • Microsoft® Windows Identity Foundation SDK 4.0

Setup

For convenience, much of the code used in this hands-on lab is available as Visual Studio code snippets. To check the prerequisites of the lab and install the code snippets:

  1. Open a Windows Explorer window and browse to the lab’sSource\Setupfolder.
  2. Double-click theDependencies.depfile in this folder to launch the Dependency Checkertool and install any missing prerequisites and the Visual Studio code snippets.
  3. If the User Account Control dialog is shown, confirm the action to proceed.

Note:This process may require elevation.The .dep extension is associated with the Dependency Checker tool during its installation. For additional information about thesetupprocedure and how to install the Dependency Checker tool, refer to theSetup.docxdocument in theAssetsfolder of the training kit.

  1. After the code snippets installation completes, the setup script will proceed with the certificates installation. Press Y if you want to continue with the required certificates installation.

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 before proceeding with the lab's certificates installation.

Figure 1

Certificates installation finished

Note: If you are running Windows 7 or Windows 2008 R2 you might not see this window.

  1. When finished, press any key to close the setup console.

Note: In addition to the setup script inside the %YourInstallationFolder%\Labs\WebServicesAndIdentity\Source\Setup folder, 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. Using Windows Identity Foundationto Handle Authentication and Authorization in a WCF Service
  2. Accepting Tokens from anActive Directory Federation Services (ADFS) STS
  3. Invoking a WCF Service on the Backend via Delegated Access

Note:Each exercise is accompanied by a starting solution. These solutions are missing some code sections that are completedduring each exercise and therefore will not work if executed directly.

Inside each exercise folder, you will also find an end folder with the solution that you should obtain after completing the exercise. You can use it 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. Paste the following snippet at the end of the GetForecast method to return the image from the service.

(Code Snippet – Web Services and Identity Lab - Ex03 Returning theSatellite Image)

C#

return new WeatherResult

{

Forecast = forecast,

SatelliteImage = image

};

To add this code snippet in Visual Studio, you simply place the cursor where you would like the code to be inserted, start typing the snippet name, in this case WebServicesAndIdentityLabEx03ReturningTheSatelliteImage, 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 or any other XML document), right-click where you want the code snippet to be inserted, select Insert Snippetfollowed by My Code Snippetsand then select the relevant snippet.

To learn more about Visual Studio IntelliSense Code Snippets, including how to create your own, please see

Estimated time to complete this lab: 60 minutes.

Exercise 1: Using Windows Identity Foundationto HandleAuthentication and Authorization in a WCF Service

In this first exercise, you will gain familiarity with the way in which Windows Identity Foundation (WIF) handles authentication and authorization for web service calls. You may have used WCF classes in the past to obtain similar results: the Windows Identity Foundation (WIF) makes things simpler, and while it handles the same concepts (tokens, claims), it offers a more task-based approach.

Note that, for the sake of clarity, the web service in this exercise does not take advantage of issued tokens or claims: we secure the call with username and password so that we can illustrate differences between WCF’s and Windows Identity Foundation’s object model as crisply as possible. All subsequent exercises will instead take advantage of issued tokens and claims.

Figure 2

In this exercise the client invokes the serviceusing username & password credentials. The credentials are verified in a custom token handler, while the authorization policies (based on the name of the caller) are enforced via a custom implementation of ClaimsAuthorizationManager

Task 1 - Reviewing the Begin Solution

  1. Open Microsoft Visual Studio 2010 with administrator privileges. From Start | All Programs | Microsoft Visual Studio 2010, right-click Microsoft Visual Studio 2010and choose Run as administrator.
  2. Open the WeatherStation.sln solution file located in the %YourInstallationFolder%\Labs\WebServicesAndIdentity\Source\Ex1-SecuringWebService\Begin folder.

Note:Ensure that the WeatherStationService application of the newly created service has anonymous authentication enabled. To do this, go to IIS Manager and browse for %machine name% | Sites | Default Web Site | WeatherStationServiceEx01,select the application node in the Connections tree view and then double-click Authentication.Locate the Anonymous Authenticationitem in the list and check its status. To enable anonymous authentication, right-click its entry in the list view and select Enable.

  1. Review the initial solution.

Figure 3

Exercise 1 begin solution

Note:This solution represents a classic WCF web service-WinForm web service client scenario, implemented using Visual Studio 2010 templates defaults (hence just with the default security settings of wsHttpBinding).

The WeatherStationClient project is a WinForms application that uses the WeatherStationService WCF service to retrieve the forecast for the next 3 or 10 days and displays the results on the UI. In its initial state, the client is not wired up to the service: in this exercise we will add the necessary invocation code and secure it with username/password credentials. On the service side, we will authenticate the calls based on those credentials and will handle authorization according to the individual users.

Task 2 - UsingWindows Identity Foundationto AuthenticateCalls to the Service

  1. Right-click the project and select Add Reference.
  2. Select the Microsoft.IdentityModel assembly in the .NET tab.

Figure 4

Adding a reference to Microsoft.IdentityModel

Note: If you did not find the Microsoft.IdentityModel.dll assembly on the Add Reference dialog, you can add the reference including the following line in the configuration/system.web/compilation/assemblies section of the Web.config file:

<add assembly="Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

  1. Right-click the App_Code folder in the project and select Add New Item.
  2. Create a new Class and name it CustomUserNameSecurityTokenHandler.cs
  3. Replace the content of the new class with the following code to validate the user credentials in the issued token and assign the appropriate roles for each valid user.

(Code Snippet – Web Services And Identity Lab -Ex01 CustomUserNameSecurityTokenHandler)

C#

using System;

using System.IdentityModel.Tokens;

using Microsoft.IdentityModel.Claims;

using Microsoft.IdentityModel.Protocols.WSIdentity;

using Microsoft.IdentityModel.Tokens;

class CustomUserNameSecurityTokenHandler : UserNameSecurityTokenHandler

{

public override boolCanValidateToken

{

get

{

return true;

}

}

public override ClaimsIdentityCollectionValidateToken(SecurityToken token)

{

UserNameSecurityTokenusernameToken = token as UserNameSecurityToken;

if (usernameToken == null)

{

throw new ArgumentException("usernameToken", "The security token is not a valid username security token.");

}

string username = usernameToken.UserName;

string password = usernameToken.Password;

if (("paul" == username & "p@ssw0rd" == password) || ("john" == username & "p@ssw0rd" == password))

{

IClaimsIdentity identity = new ClaimsIdentity();

identity.Claims.Add(new Claim(WSIdentityConstants.ClaimTypes.Name, username));

return new ClaimsIdentityCollection(new IClaimsIdentity[] { identity });

}

throw new InvalidOperationException("The username/password is incorrect");

}

}

Note:If you have custom credential verification logic you want to use for authenticating calls, Windows Identity Foundationoffers you a mechanism for weaving it in the processing pipeline. The SecurityTokenHandler defines an interface for plugging custom token handling functionality, which you can use for controlling the credential verification process. Deriving your own class from SecurityTokenHandler you can add functionality to serialize, de-serialize, authenticate and create specific kinds of token. In our example, the CustomUserNameSecurityTokenHandler class derives from UserNameSecurityTokenHandlerthat handles standardized WS-Security UsernameTokens. The key method is ValidateToken: here we perform a simple check against hardcoded values.

  1. Now that we took care of the authentication part, we need to think about authorization. We are going to take advantage of MyClaimsAuthorizationManager,a class provided with the WindowsIdentity Federation SDK samples that allows you to express some simple condition on the incoming claims that must be satisfied in order to gain access to a resource. Right-click the App_Code folder of the project and selectAdd Existing Item.

Note:Windows Identity Foundation is not tied to a specific authorization engine: rather, it offers extensibility points that you can leverage for executing your custom authorization code within the invocation processing pipeline. The mechanism is somewhat similar to what we have seen in the authentication steps: you derive your own implementation from the ClaimsAuthorizationManager class, where you will use the CheckAccess method to verifythat the incoming claims satisfy the conditions assigned to the resource being invoked. Once your implementation of ClaimsAuthorizationManageris included in the pipeline (via config), returning “false” from CheckAccess will have the effect of stopping the call. Normally the authorization conditions are assigned to resources via external files, such as the application config, so that administrators are able to modify them without altering the application codebase.Furthermore, you can expect developers to assign conditions via Code Access Security style calls (i.e. decorating via attributes and so on). Both capabilities will require some coding support. Seasoned WCF developers will compare ClaimsAuthorizationManagerwithServiceAuthorizationManager: while the two can be used for similar purposes, it should be noted that ClaimsAuthorizationManager offers a simpler object model that abstracts away many details of the actual call mechanics.

  1. Select all the content in the %YourInstallationtFolder%\Labs\WebServicesAndIdentity\Source\Assets\ClaimsAuthorizationManager folder and click Add.

Figure 5

ClaimsAuthorizationManager files

  1. Open the Web.config file of the project.
  2. Register the microsoft.IdentityModel section. Inside theconfigSections element add the following (shown in bold). If the configSections section does not exist, you should add it inside the configuration element.

(Code Snippet – Web Services And Identity Lab -Ex01 microsoft.IdentityModel section)

XML

<configuration>

configSections

...

<section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

</configSections

...

</configuration>

  1. Add the following settings for the microsoft.identityModel sectionjust before closing the configuration section.

(Code Snippet – Web Services And Identity Lab -Ex01 microsoft.IdentityModel settings)

XML

...

<microsoft.identityModel

<service>

<securityTokenHandlers

<remove type="Microsoft.IdentityModel.Tokens.WindowsUserNameSecurityTokenHandler, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add type="CustomUserNameSecurityTokenHandler, App_Code"/>

</securityTokenHandlers

</service>

</microsoft.identityModel

</configuration>

Note: Themicrosoft.identityModelelement isthe area of the application config that you can use to enable Windows Identity Foundation and drive its behavior. In the last step, we placed our custom username token handler in the handler’s collection. Next, we will add our implementation of ClaimsAuthorizationManager to the pipeline.

  1. Add the following setting to configure the ClaimsAuthorizationManagerinsidemicrosoft.identityModel/service.

(Code Snippet – Web Services And Identity Lab -Ex01 ClaimsAuthorizationManager)

XML

...

<microsoft.identityModel

<service>

<securityTokenHandlers

<remove type="Microsoft.IdentityModel.Tokens.WindowsUserNameSecurityTokenHandler, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

<add type="CustomUserNameSecurityTokenHandler, App_Code"/>

</securityTokenHandlers

<claimsAuthorizationManager type="ClaimsBasedAuthorization.MyClaimsAuthorizationManager">

<policy resource=" action="

<or>

<claim claimType=" claimValue="paul"/>

<claim claimType=" claimValue="john"/>

</or>

</policy>

<policy resource=" action="

<claim claimType=" claimValue="paul"/>

</policy>

</claimsAuthorizationManager

</service>

</microsoft.identityModel

</configuration>

Note:The MyClaimsAuthorizationManager sample defines a very rudimentary but effective syntax for expressing constraints. In the basic case, given a certain service and associated SOAPAction (resource and action in the schema, respectively), a user can invoke the corresponding method of the web service if and only if he presents an instance of a given claim type with the requested value. Conditions in this format can be combined via boolean operators to form composite authorization criteria. In this exercise, we donot really receive claims from an STS.However, we can consider the username as a claim and assign our authorization conditions on a per-user basis.

  1. Add the following bindingssection under system.serviceModelto specify the usage of WS-SecurityUsernameToken for client credentials.

(Code Snippet – Web Services And Identity Lab -Ex01 UsernameBinding)

XML

system.serviceModel

<bindings>

<wsHttpBinding

<binding name="UsernameBinding">

<security mode="TransportWithMessageCredential">

<message clientCredentialType="UserName"/>

</security>

</binding>

</wsHttpBinding

</bindings>

<behaviors>

...

</system.serviceModel

Addthe following services element to configure that the service endpoint uses the binding defined on the previous step.

(Code Snippet – Web Services And Identity Lab - Ex01 Endpoint Configuration)

XML

system.serviceModel

<services>

<service name="WeatherStationServiceEx01.Service">

<!-- Service Endpoints -->

<endpoint address="" binding="wsHttpBinding"

bindingConfiguration="UsernameBinding"

contract="WeatherStationServiceEx01.IService"/>