Authenticating Users and Services in an Internet Environment


Maintaining information about all users that can legitimately access a service and their credentials typically requires some form of database. In a Windows environment, Active Directory provides just such a database, and a WCF service can use Windows Integrated Security to help authenticate users that are part of the same Windows domain as the service. When client applications connect to the service across the Internet, this approach is not always feasible; a client application will probably not be running using the same security domain as the service (it might not even be a Windows application). In this environment, you can use several alternative approaches for maintaining a list of authenticated users for a WCF service. For example, you can employ the SQL Membership Provider to store a list of users and their credentials in a SQL Server database, together with the SQL Role Provider to associate users with roles. Alternatively, you can use the Authorization Store Role Provider to record users and roles in XML files. In the exercises in this chapter, you will make use of the SQL Membership Provider and SQL Role Provider.

Important 

Chapter 4 described how to use impersonation to enable a service to access resources. Impersonation requires that the service can identify the user as a Windows account in its local security domain, so it is not available when alternative authentication mechanisms such as the SQL Membership Provider are used.

Authenticating and Authorizing Users by Using the SQL Membership Provider and the SQL Role Provider

To make a WCF service available across the Internet, you would typically host it by using Microsoft Internet Information Services (IIS) as described in Chapter 1, “Introducing Windows Communication Foundation.” Hosting a WCF service in this way enables you to use the ASP.NET Web Site Administration Tool to easily create a SQL Server database containing the security information for the service and manage users and roles. You can then configure the WCF service to use the SQL Membership Provider to authenticate users, and the SQL Role Provider to retrieve role information for authorizing users. This is what you will do in the following set of exercises.

Note 

The procedure for creating a Web site that uses transport security based on SSL differs between Windows XP and Windows Vista. The exercises in this section call out the differences, so make sure you follow the appropriate steps for the operating system you are using.

The first exercise only applies to Windows Vista.

Configure IIS7 bindings (Windows Vista only)

  1. In the Windows Control Panel, click System and Maintenance, click Administrative Tools, and then double-click Internet Information Services (IIS) Manager.

  2. In the Internet Information Services (IIS) Manager, in the left pane, expand the node that corresponds to your computer, expand Web Sites, right-click Default Web Site, and then click Edit Bindings.

  3. In the Web Site Bindings dialog box, if https is not configured, click Add. In the Add Web Site Binding dialog box, set Type to https, set the SSL certificate to HTTPS-Server, and then click OK.

  4. In the Web Site Bindings dialog box, click Close.

  5. Leave the Internet Information Services (IIS) Manager open.

The next exercise applies to Windows Vista and Windows XP.

Create an ASP.NET Web site to host the WCF service

  1. Using Visual Studio 2005, create a new Web site.

  2. In the New Web Site dialog box, select the WCF Service template. Set the Location to HTTP, set the language to Visual C#, and then click Browse.

  3. In the Choose Location dialog box, click Local IIS. In the right pane, click Default Web Site, and then click the Create New Virtual Directory icon in the top right corner of the dialog box.

  4. In the New Virtual Directory dialog box, enter InternetProductsService for the Alias name. Click Browse adjacent to the Folder text box.

  5. In the Browse For Folder dialog box, move to the Microsoft Press\WCF Step By Step\Chapter 5 folder under your \My Documents folder. Click the Create New Folder icon in the toolbar.

  6. In the New Folder dialog box, enter the name InternetProductsService and then click OK.

  7. In the Browse For Folder dialog box, click Open.

  8. In the New Virtual Directory dialog box, click OK.

  9. In the Choose Location dialog box, click the InternetProductsService folder in the Default Web Site node. Check the Use Secure Sockets Layer check box at the bottom of the dialog box, and then click Open.

  10. In the New Web Site dialog box, verify that the address for the new Web site is https://localhost/InternetProductsService and then click OK.

The InternetProductsService Web site is configured to listen for requests by using the HTTPS protocol. This is good practice when building Web sites for hosting Web services that will be accessed from the Internet as it provides a much greater degree of privacy than using unencrypted communications.

Note 

You can still perform message level encryption as well if you need to provide end-to-end security rather than point-to-point. However, remember that encryption is a necessarily expensive operation. Encrypting at two levels will impact performance. Transport level encryption tends to be much faster than message level.encryption. So, if performance is a limiting factor and you have to make a choice, then go for transport level security.

Although you have specified that the Web site requires clients to connect by using HTTPS, you still need to perform some additional configuration of IIS. In particular, you must install a certificate that the IIS service and client applications can use for encrypting messages.

Important 

In the following exercise, you will use the same test certificate that you created in Chapter 4. It is worth emphasizing again that, in a production environment, you should procure a real certificate from a reputable certification authority.

The next exercise has two versions; one for Windows Vista and one for Windows XP.

Configure the IIS Web site to support HTTPS communications (Windows Vista only)

  1. Return to the Internet Information Services (IIS) Manager.

  2. In the left pane, right-click the Default Web Site folder, and then click Refresh.

  3. Click the InternetProductsService node in the Default Web Site folder and make sure the main panel in the console displays the Web Site in Features View (If the main panel is displaying the folders App_Code, and Add_Data, and the files image from book Service.svc and image from book Web.config, it is in Content View; right-click the InternetProductsService node, and click Switch to Features View.)

  4. In the IIS area in the main panel, double-click SSL Settings.

  5. In the SSL Settings pane, check Require SSL, but leave all the other properties at their default values.

  6. In the right pane, click Apply.

  7. In the Internet Information Services (IIS) Manager navigation bar, click Back. In the main panel, double-click Authentication.

  8. In the Authentication pane, click Basic Authentication. In the right pane, click Enable.

  9. Close the Internet Information Services (IIS) Manager.

Configure the IIS Web site to support HTTPS communications (Windows XP only)

  1. On the Windows Start menu, click Run.

  2. In the Run dialog box, type inetmgr and then click OK.

    The Internet Information Services console starts.

  3. In the Internet Information Services console, expand the node corresponding to your computer in the tree view and then expand Web sites.

  4. Right-click the Default Web Site node, and then click Properties.

  5. In the Default Web Site Properties dialog box, click the Directory Security tab.

  6. In the Directory Security page, under Secure communications, click Server Certificate.

    The Web Server Certificate Wizard starts.

  7. In the Welcome to the Web Server Certificate Wizard page, click Next.

  8. In the Server Certificate page, select Assign an existing certificate and then click Next.

  9. In the Available Certificates page, select the HTTPS-Server certificate and then click Next.

  10. In the Certificate Summary page, click Next.

  11. In the Completing the Web Server Certificate Wizard page, click Finish.

  12. In the Default Web Site Properties dialog box, click OK.

  13. In the Internet Information Services console, expand the Default Web Site node, right-click the InternetProductsService node, and then click Properties.

  14. In the InternetProductsService Properties dialog box, click the Directory Security tab.

  15. In the Directory Security page, under Secure communications, click Edit.

  16. In the Secure Communications dialog box, check Require secure channel (SSL), but leave other properties at their default value, as shown below, and then click OK.

    image from book

  17. In the Directory Security page, under Anonymous access and authentication control, click Edit.

  18. In the Authentication Methods dialog box, clear the Integrated Windows authentication check box and select the Basic authentication check box. When the Internet Service Manager message box appears warning that site should use HTTPS, click Yes. Click OK.

  19. In the InternetProductsService Properties dialog box, click OK.

  20. Close the Internet Information Services console.

The remaining exercises apply to Windows Vista and Windows XP.

Import the code for the WCF service into the IIS Web site

  1. Return to Visual Studio displaying the InternetProductsService solution.

  2. In Solution Explorer, expand the App_Code folder and delete the file image from book Service.cs.

    The image from book Service.cs file contains code for a sample WCF Web service. You will not need this file, although you are welcome to look at it before removing it.

  3. In Solution Explorer, right-click the App_Code folder and then click Add Existing Item.

  4. In the Add Existing Item dialog box, move to the Microsoft Press\WCF Step By Step\Chapter 5\ProductsService folder under your \My Documents folder, select the image from book ProductsService.cs file, and then click Add.

    The image from book ProductsService.cs file contains the code for the ProductsService service. This is almost the same code that you used in Chapter 4 (the statements that display the user identity in the ListProducts method have been removed as you should not attempt to display an interactive message box from a WCF service hosted by IIS).

  5. In Solution Explorer, rename the image from book Service.svc file as image from book ProductsService.svc.

  6. Double-click the image from book ProductsService.svc file to display the service definition file in the code view window. Modify this file as shown in bold below:

     <% @ServiceHost Language=C# Debug="true" Service="Products.ProductsServiceImpl" CodeBe hind="~/App_Code/ProductsService.cs"%>

  7. In Solution Explorer, delete the image from book Web.config file.

  8. In the Website menu, click Add Existing Item. In the Add Existing Item dialog box, move to the Microsoft Press\WCF Step By Step\Chapter 5\ProductsService folder under your \My Documents folder, select the image from book App.config file, and then click Add.

    This is the configuration file used by the WCF host application in Chapter 4. You must rename this file as image from book Web.config for the Web service to recognize it properly.

  9. Using Solution Explorer, rename the image from book App.config file as image from book Web.config.

  10. Edit the image from book Web.config file by using the WCF Service Configuration Editor.

  11. In the WCF Service Configuration Editor, in the Services folder, expand the Products.ProductsServiceImpl node, expand the EndPoints folder, and delete the ProductsServiceTcpBinding endpoint and the ProductsServiceHttpEndpoint endpoint.

    This version of the WCF service is only going to be accessed by client applications using the HTTPS protocol over the wsHttpBinding binding to connect from the Internet.

    Important 

    It is good practice to remove any endpoints that a service is not going to use. They could expose unexpected vulnerabilities if an attacker manages to penetrate the network security of your organization.

  12. In the left pane, expand the Bindings folder. Delete both binding configurations located in this folder.

    These binding configurations are for the basicHttpBinding and netTcpBinding bindings that you have just removed.

  13. Right-click the Binding folder and then click New Binding Configuration. In the Create a New Binding dialog box, select wsHttpBinding and then click OK.

  14. In the right pane, set the Name property of the binding to ProductsServiceWSHttpBindingConfig.

  15. Click the Security tab. Set the Mode property of the binding to TransportWithMessageCredential, set the MessageClientCredentialType property to UserName, and set the TransportClientCredentialType to None.

    The host Web site is configured to use the HTTPS protocol, so the WCF service must be configured to support transport level security. The TransportWithMessageCredential mode uses HTTPS at the transport level to protect messages traversing the network and uses the server certificate to authenticate with the client. The user’s credentials are authenticated by using message level security–this is the level at which the SQL Role Provider operates.

  16. In the left pane, select the ProductsServiceWSHttpEndpoint endpoint in the Endpoints folder under the Products.ProductsServiceImpl node. In the right pane, set the BindingConfiguration property to ProductsServiceWSHttpBindingConfig.

    Note 

    IIS is hosting this service, so you can leave the Address property blank. The address IIS will use is a combination of the URL of the WCF service and the name of the service definition file, in this case, https://localhost/InternetProductsService/ProductsService.svc.

  17. In the left pane, expand the Advanced folder, expand the Service Behaviors folder, right-click the ProductsBehavior node, and then click Add Service Behavior Element Extension.

  18. In the Adding Behavior Element Extension Sections dialog box, select serviceMetadata and then click Add.

  19. Click the serviceMetadata node under ProductsBehavior. In the right pane, set the HttpsGetEnabled property to True but leave the HttpGetEnabled property set to False.

  20. Save the changes, and exit the WCF Service Configuration Editor.

  21. In Visual Studio 2005, in the Website menu, click Add Reference. In the Add Reference dialog box, click the Browse tab and add a reference to the Microsoft.Practices.EnterpriseLibrary.Data.dll assembly in the C:\Program Files\Microsoft Enterprise Library\bin folder.

    Note 

    This action automatically adds references to the Microsoft.Practices EnterpriseLibrary.Common.dll and Microsoft.Practices.ObjectBuilder.dll assemblies as these are referenced by the Microsoft.Practices.EnterpriseLibrary.Data.dll assembly.

  22. Start Internet Explorer and go to the Web site https://localhost/InternetProductsService/ProductsService.svc. Depending on how you have configured Internet Explorer on your computer, you might be prompted with a Security Alert message box. If so, click OK to acknowledge the message.

    Note 

    Windows Vista displays an error page with the message “There is a problem with this website’s security certificate.” This is because the certificate you used for configuring SSL was not issued by a recognized trusted certificate authority. If this was a commercial Web site, you should choose not to view it. However, in this case the Web site is perfectly safe, so click the link “Continue to this website (not recommended).”

    If another Security Alert message box appears, click Yes to accept the security certificate of the Web site.

    image from book

    Internet Explorer opens the page https://localhost/InternetProductsService/ProductsService.svc, as shown in the following image:

    image from book

  23. Close Internet Explorer.

Now that you have deployed, configured, and tested the WCF service by using IIS, you can use the ASP.NET Administration Tool to define the users and roles that will be permitted to access the service. To keep things simple, you will create roles (WarehouseStaff and StockControllers) and users (Fred and Bert) that mimic those you created by using Windows in Chapter 4.

Define users and roles for the WCF service

  1. In Visual Studio 2005, in the Website menu, click ASP.NET Configuration.

    The ASP.NET Web Site Administration Tool starts. This is actually another Web application that runs using the ASP.NET Development Server (a stand-alone Web server installed with Visual Studio 2005, and separate from IIS):

    image from book

    This tool provides pages enabling you to add and manage users for your Web site, specify Web application settings that you want to be stored in the application configuration file (not WCF settings), and indicate how security information such as user names and passwords are stored. By default, the ASP.NET Web Site Administration Tool stores security information in a local SQL Server database called ASPNETDB.MDF that it creates in the App_Data folder of your Web site.

  2. Click the Security tab.

    The Security page appears. You can use this page to manager users, specify the authentication mechanism that the Web site uses, define roles for users, and specify access rules for controlling access to the Web site.

    Note 

    The first time you click the Security link there will be a delay before the page is displayed. This is because the tool creates the ASPNETDB.MDF database at this point.

  3. In the Users section of the page, click the Select authentication type link.

    A new page appears asking how users will access your Web site. You have two options available:

    • From the Internet. This option enables you to define users and roles in the SQL Server database. Users accessing your application must provide an identity that maps to a valid user.

      Note 

      The explanation given for the From the internet option on the page assumes you are building an ASP.NET Web site rather than a WCF Web service, which is why it describes using forms-based authentication. A client application connecting to a WCF service can provide the user’s credentials by populating the ClientCredentials property of the proxy object being used to send requests to the WCF service.

    • From a local network. This option is selected by default. This option configures the Web site to use Windows authentication; all users must be members of a Windows domain that your Web site can access.

  1. Click From the internet, and then click Done.

    You return to the Security page.

  2. In the Users section, notice that the number of existing users that can access your Web site is currently zero. Click the Create user link.

    The Create User page appears.

  3. In the Create User page, add a new user with the values shown in the following table:

    Open table as spreadsheet

    Prompt

    Response

    User name

    Bert

    Password

    Pa$$w0rd

    Confirm password

    Pa$$w0rd

    E-mail

    Bert@Adventure-Works.com

    Security Question

    What was the name of your first pet

    Security Answer

    Tiddles

    image from book

    Note 

    You must supply values for all fields in this screen. The E-mail, Security Question, and Security Answer fields can be used by the ASP.NET PasswordRecovery control to recover or reset a user’s password. Detailed discussion of the PasswordRecovery control is outside the scope of this book.

  4. Ensure that the Active User box is checked and then click Create User.

    The message “Complete. Your account has been successfully created.” appears in a new page.

  5. Click Continue. The Create User page reappears, enabling you to add further users. Add another user using the information shown in the following table:

    Open table as spreadsheet

    Prompt

    Response

    User name

    Fred

    Password

    Pa$$w0rd

    Confirm password

    Pa$$w0rd

    E-mail

    Fred@Adventure-Works.com

    Security Question

    What was the name of your first pet

    Security Answer

    Rover

  6. Ensure that the Active User box is checked, and then click Create User.

  7. Click Back to return to the Security page. Verify that the number of existing users is now set to 2.

  8. In the Roles section of the page, click the Enable roles link.

  9. When roles have been enabled, click the Create or Manage roles link.

    The Create New Role page appears.

  10. In the New role name text box, type WarehouseStaff and then click Add Role.

    The new role appears on the page, together with links enabling you to add and remove users to or from this role.

  11. Click the Manage link.

    Another page appears, enabling you to specify the users that are members of this role. You can search for users or list users whose names begin with a specific letter and then add them to the role. Click the All link to display all users.

  12. Check the User Is In Role box for Bert and Fred, as shown in the following image:

    image from book

  1. Wait for the page to be redisplayed, and then click Back.

    Important 

    If you click Back before the page is redisplayed, the users might not be added to the roles correctly.

  2. In Create New Role page, in the New role name text box, type StockControllers and then click Add Role.

  3. Click the Manage link for the StockControllers role. Add Fred to the StockControllers role, wait for the page to be redisplayed, and then click Back.

  4. Close the Internet Explorer window displaying the ASP.NET Web Site Administration tool.

    Note 

    The ASP.NET Web Site Administration Tool modifies the image from book Web.config file of the Web service. When you return to Visual Studio, if you have the image from book Web.config file open for editing in the code view window, you will be alerted that the file has been modified. In the message box, click Yes to reload the file.

The next step is to modify the behavior of the WCF service to perform authorization by using the users and roles defined in the SQL Server database rather than by using Windows users and groups.

Configure the WCF service to use the SQL Role Provider and the SQL Membership Provider

  1. In Visual Studio 2005, in Solution Explorer, right-click the image from book Web.config file and then click Edit WCF Configuration.

  2. In the WCF Service Configuration Editor, expand the Advanced folder, expand the Service Behaviors folder, and then expand the ProductsBehavior node.

  3. Click the serviceAuthorization node under the ProductsBehavior node.In the right pane, set the PrincipalPermissionMode property to UseAspNetRoles and type AspNetSqlRoleProvider for the RoleProviderName property.

    The RoleProviderName property identifies a particular configuration for the identity role provider that will be used to map users to roles. The value “AspNetSqlRoleProvider” is actually defined in the Machine.config file and specifies the version of the SQL Role Provider to use to authorize users, together with information, about how to connect to the database holding the user and role information.

  4. In the left pane, right-click the ProductsBehavior node and then click Add Service Behavior Element Extension. In the Adding Behavior Element Extension Sections dialog box, select serviceCredentials and then click Add.

  5. In the left pane, click the serviceCredentials node. In the right pane, set the UserNamePasswordValidationMode property to MembershipProvider and type AspNetSqlMembershipProvider for the MembershipProviderName property. The membership provider is responsible for authenticating users based on their names and passwords stored in the SQL Server database. The value “AspNetSqlMembershipProvider” is defined in the Machine.config file.

    Note 

    Try not to get too confused by the role provider and the membership provider. WCF uses the membership provider for authenticating users, and it uses the role provider for authorizing users’ access to resources after they have been authenticated.

  6. Save the configuration, and then exit the WCF Service Configuration Editor.

You can now test the WCF service by using the client application developed in the previous chapters. First, you must make some changes so that the client application connects to the WCF service by using the correct binding and address.

Modify the WCF client application to connect to the updated WCF service

  1. In Visual Studio, in Solution Explorer, right-click the InternetProductsService solution, point to Add, and then click Existing Project.

  2. In the Add Existing Project dialog box, move to the Microsoft Press\WCF Step By Step\Chapter 5\ProductsClient folder under your \My Documents folder, select the image from book ProductsClient.csproj project file, and then click Open.

  3. Use the WCF Service Configuration Editor to open the image from book app.config file for the ProductsClient project.

  4. In the WCF Service Configuration Editor, right-click the Bindings folder and then click the New Binding Configuration. In the Create a New Binding dialog box, select wsHttpBinding and then click OK.

  5. In the right pane, set the Name property to ProductsClientWSHttpBindingConfig.

  6. Click the Security tab, set the Mode property to TransportWithMessageCredential and set the MessageClientCredentialType property to UserName.

  7. In the left pane, in the Endpoints folder under the Client folder, select the WSHttpBinding_IProductsService endpoint.

  8. In the right pane, change the Address property to https://localhost/InternetProductsService/ProductsService.svc and set the BindingConfiguration property to Products ClientWSHttpBindingConfig.

  9. Save the configuration and then exit the WCF Service Configuration Editor.

  10. In Solution Explorer, open the image from book Program.cs file in the ProductsClient project. In the code view window, in the Main method of the Program class, change the statement that creates the proxy to refer to the WSHttpBinding_IProductsService endpoint, like this:

     ProductsServiceClient proxy =     new ProductsServiceClient("WSHttpBinding_IProductsService");

  11. Replace the three statements that set the Domain, UserName, and Password properties of the ClientCredentials.Windows.ClientCredential property of the proxy object with the following statements:

     proxy.ClientCredentials.UserName.UserName = "Bert"; proxy.ClientCredentials.UserName.Password = "Pa$$w0rd";

    The client application uses message level authentication to send the user’s credentials to the WCF service. You specify the credentials to send by using the ClientCredentials.UserName property of the proxy object.

    Important 

    To reiterate the point made in Chapter 4, this code is for illustrative purposes in this exercise only. You should never hard-code usernames and password directly into an application.

Test the WCF service

  1. In Solution Explorer, right-click the ProductsClient project and then click Set as Startup Project.

  2. Start the solution without debugging. When the client console window appears, press Enter to connect to the service.

    The first three tests should run successfully, but the final test fails with the error shown in the following image:

    image from book

    The PrincipalPermission attributes implementing security demands for the first three methods automatically use the currently configured role provider. In Chapter 4, they used the Windows Token Role Provider and authorized users based on their Windows identity. In these exercises, they are using the SQL Role Provider. The problem is that the method executed by test 4 does not use the PrincipalPermission attribute–the authorization check is performed by using code. In particular, the following statement attempts to retrieve the identity of the user assuming it was a Windows principal, which it no longer is:

     WindowsPrincipal user = new WindowsPrincipal(     (WindowsIdentity)Thread.CurrentPrincipal.Identity);

    Press Enter and return to Visual Studio 2005.

  3. Edit the image from book ProductsService.cs file in the App_Code folder of the WCF service project. Locate the ChangeStockLevel method, and modify the two lines of code that create the user variable and test this variable to determine whether the user is a member of the StockControllers role, as shown in bold below:

     // Determine whether the user is a member of the StockControllers role IIdentity user = ServiceSecurityContext.Current.PrimaryIdentity; if (!(System.Web.Security.Roles.IsUserInRole(user.Name,     "StockControllers"))) {     

    The ServiceSecurityContext class contains information about the current security context for the WCF operation being performed. This security context information includes the identity if the user requesting the operation, which is available in the Current.PrimaryIdentity property. You can use the name held in this identity object to determine the whether the user is a member of a specific role by using the IsInRole method of the System.Web.Security.Roles class. The Roles class accesses the data in the currently configured role provider for the WCF service to perform its work.

  4. Start the solution without debugging. Press Enter when the client application window appears. This time, test 4 fails with the error “Access is denied.” This is because Bert is not a member of the StockControllers role.

  5. Press Enter again to close the application.

  6. Edit the image from book Program.cs file in the ProductsClient project. Change the username sent to the WCF service through the proxy as follows:

     proxy.ClientCredentials.UserName.UserName = "Fred";

  7. Start the solution without debugging. Press Enter when the client application window appears. Fred is a member of the WarehouseStaff and StockControllers role, and all tests should run successfully.

  8. Press Enter to close the application.

Authenticating and Authorizing Users by Using Certificates

Using a username and password to identify a user provides a degree of security, but you are probably all too familiar with the shortcomings of many implementations that follow this approach. It is very easy to disclose a password (possibly unwittingly) to another user. Many people use passwords that are easy for them to remember, and typically passwords are often short, or easily guessed (how many times have you used “password,” or “1234,” or something equally insecure?). Even your mother’s maiden name, suitably scrambled, is not that secure–this information is frequently available in the public domain, which is why it is nonsense for banks to use this as a piece of information to identity yourself whenever you need to contact them (I will get off my security hobbyhorse now).

Using a public key infrastructure (PKI) can help to overcome some of the shortcomings of passwords. PKI provides a mechanism both for encrypting messages and for authenticating them.

PKI is based on pairs of keys (a key is a long sequence of random numbers): a public key that you can use to encrypt messages, and a private key that you can use to decrypt them again. These keys should be unique. If you want to communicate with a third party, you can send them a copy of your public key. The third party can encrypt their messages using this key and transmit them to you. You can decrypt these messages using your private key. The theory is that only your private key can decrypt a message encrypted by using your public key, so it does not matter if someone else intercepts the message because they will not be able to read it. In practice, it is possible to decrypt messages even if you don’t have the private key, but it takes a lot of effort, and the longer the key, the more time and effort it takes–use keys with 128 bits or more.

Public and private keys can also work the other way around. If you encrypt a message with your private key, anyone with the public key can decrypt it. This does not sound too useful until you consider that this provides a convenient mechanism for verifying the source of a message. If a third party receives an encrypted message that purports to come from you, but that it cannot decrypt by using the public key that you provided, then the chances are that this message was actually from someone else pretending to be you (only you can send messages that can be decrypted by using your public key). The third party should probably discard the message in this case.

Where do you get keys? Well, you can request a pair of keys in a certificate from a certification authority, or CA. The CA will perform various checks to ensure that you are whom you actually say you are, and if they are satisfied, they will issue you with a certificate containing a public key and a private key (you usually have to pay for this service). The certificate also contains other bits of identity information about you and about the CA itself.

When you wish to communicate with a third party, you can send them a message that includes a hash (a calculated summary, a bit like a checksum but more complicated) of the message contents encrypted with your private key–this is referred to as your signature. You can arrange for a copy of your certificate, minus your private key, to be installed in the certificate store on the third-party computer as an out-of-band operation by the administrator at that end or attach a copy of your certificate, minus the private key, with the message when you send it. When the third party examines your certificate, it can verify that it was issued by a recognized and trusted CA, and that it has not been revoked before continuing (a certificate can be withdrawn if the service no longer wishes to trust the client, and the service can maintain a list of withdrawn certificates in its certificate revocation list). If the third party does not recognize or trust the CA, they can simply reject the message. Assuming that the third party does trust the CA, it can use the public key from your certificate to decrypt the signature and verify the unencrypted hash against the message (the third party generates its own hash of the message contents using the same algorithm that you did and compares his hash to yours). If this is successful, the third party will then have a reasonable degree of assurance that the message was sent by you. It can also be very confident that the message has not been corrupted or otherwise tampered with as it passed across the network. The third party can use the identity information from your certificate to determine your level of authorization and process your request if you have the appropriate authority.

A service can also use a certificate to authenticate itself to a client application, reducing the likelihood of the client connecting to a spoof service.

Note 

This discussion has been primarily concerned with signing messages for authentication purposes. You can use certificates to encrypt messages as well but the process is slightly more complex. When a client application wants to send an encrypted and signed message to a service, it first signs the message by using its own private key and then encrypts the complete, signed message by using the service’s public key. The service decrypts the signed message using its private key and then authenticates the message by using the client application’s public key.

If the service sends an encrypted and signed response back to the client, the process is reversed; the service signs the message with its private key and encrypts the message with the client application’s public key. The client application decrypts the signed message with its private key and uses the service’s public key to authenticate the message.

You can see that communications that require the use of certificates include a complex protocol involving an initial exchange of certificates and keys. However, the additional security that using certificates provides makes this overhead very worthwhile.

You should always obtain the certificates that you use to identify yourself and secure your communications from a reputable certification authority that is trusted by you and those parties with whom you wish to communicate. And you should never ever disclose your own personal private key!

In the exercises in this section, you will see how you can use certificates to sign messages and authenticate users to a WCF service application.

Modify the WCF service to require client applications to authenticate by using certificates

  1. Using Visual Studio 2005, edit the image from book Web.config file for the WCF service project by using the WCF Service Configuration Editor.

  2. In the WCF Service Configuration Editor, expand the Bindings folder and then click the ProductsServiceWSHttpBindingConfig binding configuration.

  3. In the right pane, click the Security tab. Change the MessageClientCredentialType property to Certificate.

    The WCF service now requires that client applications supply a certificate to authenticate users. The NegotiateServiceCredential property on this page specifies how the client application sends the certificate to the WCF service. If this property is set to True (the default value), the WCF service expects the client application to include its certificate with the messages that it sends (actually, a series of initial messages occur while the client and WCF service exchange certificates). If this property is set to False, the administrator for the WCF service must install the client certificate manually in the Trusted People certificate store of the computer running the service. Set this property to False, as you will manually install the client certificates in a later step.

  1. In the left pane, expand the Advanced folder, expand the Service Behaviors folder, expand the ProductsBehavior behavior, expand the serviceCredentials node, and then click the clientCertificate node.

    The CertificateValidationMode property in the upper part of this page enables you to specify the how the WCF service verifies the trustworthiness of client certificates. It can have the following values:

    • ChainTrust (the default). The service will verify that the CA that issued the certificate is valid and can be trusted–the CA must either have a certificate that is stored in the Trusted Root Certification Authorities store on the service’s computer, or have a certificate that was issued by another CA that is recorded in the Trusted Root Certification Authorities store, or have a certificate that was issued by a CA that has a certificate that was issued by another CA recorded in Trusted Root Certification Authorities store, and so on. The service will navigate its way up the chain of CA certificates until it either finds a trusted CA or reaches the end of the chain. If the service fails to establish that the chain ends in a trusted CA, then the client certificate is not trusted, and it is rejected.

    • PeerTrust. The service searches the Trusted People store for the client certificate. If the service finds a matching certificate, the client is trusted. If not, the client request is rejected.

    • PeerOrChainTrust. The service deems that the client certificate is valid if it is in the Trusted People store, or it can verify that the certificate was issued by a trusted CA by using the ChainTrust mechanism described above.

    • Custom. The services uses a class that implements your own custom certificate validation process. You specify the class that implements the custom validation by using the CustomeCertificateValidatorType property.

    • None. The service does not attempt to verify the client certificate and just accepts it as valid.

    By default, the service will look in stores in the LocalMachine store location when validating certificates. This is useful if you are hosting the WCF service in IIS. If you are creating a self-hosted service running by using a specific user account, you can configure the WCF service to look in the CurrentUser store location instead by changing the TrustedStoreLocation property.

    The RevocationMode property specifies whether the service should also check to see whether the client certificate has been revoked (the client is no longer trusted). The service can query its online revocation list (Online), its cached revocation list (Offline), or not bother checking (NoCheck).

  2. In the right pane, set the CertificateValidationMode property to PeerTrust.

    Important 

    In the following exercises you will be using test certificates generated by using the makecert utility to identify users. These certificates do not have a trusted CA. To enable the WCF service to be able to use these certificates, you can either disable validation checking (which is very dangerous and never recommended) or arrange for the certificates to be placed in the Trusted People store, which is what you have specified here.

  3. Save the configuration, and close the WCF Service Configuration Editor.

You can now configure the client application to send a certificate to the WCF service.

Modify the WCF client application to authenticate with the WCF service by using a certificate

  1. Edit the image from book app.config file for the ProductsClient project by using the WCF Service Configuration Editor.

  2. Expand the Bindings folder, and then click the ProductsClientWSHttpBindingConfig binding configuration.

  3. In the right pane, click the Security tab. Set the MessageClientCredentialType property to Certificate, and set the NegotiateServiceCredential property to False.

  4. Save the configuration, and close the WCF Service Configuration Editor.

You can now create certificates for the two test users, Bert and Fred, and then modify the client application to send a certificate that identifies the user to the WCF service.

Create certificates to identify the test users

  1. On the Windows Start menu, point to All Programs, point to Microsoft Windows SDK, and then click CMD Shell.

  2. In the command prompt window, type the following command:

     makecert -sr CurrentUser -ss My -n CN=Bert -sky exchange

    This command creates a certificate with the subject “Bert,” and places it in the Personal store of the currently logged on user.

  3. In the command prompt window, type the following command:

     makecert -sr CurrentUser -ss My -n CN=Fred -sky exchange

    This command creates another certificate with the subject “Fred.”

The certificates for Bert and Fred are in the Personal certificate store of the current user. The WCF service requires the administrator to install a copy of these certificates into the Trusted People store of the local computer. In the next exercise, you will export a copy of the personal certificates to a pair of files and then import the certificates to the Trusted People store for the local computer.

Note 

The certmgr command that you use in the following exercise provides options enabling you to copy a certificate directly from one store to another in a single command. However, in the real world you would more likely export a certificate to a file, transport the file (in a secure manner) to the computer hosting the service, and then import the certificate into the certificate store. This is the approach used in the following exercise.

Export the users’ certificates, and import them into the server’s certificate store

  1. In the command prompt window, type the following command:

     certmgr -put -c -n Bert -r CurrentUser -s My bert.cer

    This command retrieves a copy of Bert’s certificate from the Personal store (My) for the current user and creates a file called Bert.cer. This file contains a copy of the certificate including its public key, but NOT the private key.

  2. Type the following command:

     certmgr -add bert.cer -c -r LocalMachine -s TrustedPeople

    This command imports the certificate into the Trusted People store for the local computer.

  3. Type the following commands to export Fred’s certificate and import it into the Trusted People store for the local computer:

     certmgr -put -c -n Fred -r CurrentUser -s My fred.cer certmgr -add fred.cer -c -r LocalMachine -s TrustedPeople

  4. Close the command prompt window.

Update the WCF client application to send a certificate to the WCF service

  1. In Visual Studio 2005, open the image from book Program.cs file in the ProductsClient project to display it in the code view window.

  2. In the Main method of the Program class, replace the two statements that set the UserName and Password properties of the ClientCredentials.UserName property of the proxy object with the following statement:

     proxy.ClientCredentials.ClientCertificate.SetCertificate(     StoreLocation.CurrentUser, StoreName.My,     X509FindType.FindBySubjectName, "Bert");

    This statement retrieves Bert’s certificate from the Personal store of the current user and adds it to the credentials sent to the WCF service.

  3. Start the solution without debugging. In the client console window, press Enter.

    The first test fails with the message “Access is denied.” The WCF service has authenticated the client certificate (you would get a different exception if the authentication had failed), but the service is still attempting to authorize users based on the information stored in the SQL Server database used by the SQL Role Provider.

  4. Press Enter to close the client console window.

You need to modify the definitions of the users and roles in the SQL Server database to map user identities retrieved from user’s certificates to roles. But first, you need to understand the identifiers that the WCF service uses when clients authenticate by using certificates.

Investigate the identities of users authenticated by using certificates

  1. Open the image from book ProductsService.cs file in the App_Code folder in the WCF service project.

  2. Comment out the PrincipalPermission attribute for the ListProducts method in the ProductsServiceImpl class. Add the statements shown in bold to the start of the method:

     //[PrincipalPermission(SecurityAction.Demand, Role="WarehouseStaff")] public List<string> ListProducts() {   string userName = ServiceSecurityContext.Current.PrimaryIdentity.Name;   List<string> tempList = new List<string>();   tempList.Add(userName);   return tempList;    }

    The Current.PrimaryIdentity.Name property of the ServiceSecurityContext object contains the name of the currently authenticated user. This code returns a list of one string, containing the user’s name.

    Note 

    Using an existing operation in the WCF service means that you don’t need to regenerate the proxy for the client. Visual Studio will generate a warning, “Unreachable code detected,” for the remaining code in the method. You can ignore this warning, as you will remove the statements you have just added when you have finished with them.

  3. Start the solution without debugging. In the client console window, press Enter. Test 1 now succeeds and displays the identity of the user, as shown below:

    image from book

    The authenticated user name consists of two parts: the subject name, and the thumbprint of the certificate. The thumbprint uniquely identifies the certificate (multiple certificates can have the same subject name), so yours will probably be different from the one shown here. This is the information that you need to store in the SQL Server database, so make a note of the thumbprint.

  4. Press Enter to close the client console window.

Update the user information in the SQL Server database

  1. In Visual Studio 2005, select the WCF service project in Solution Explorer. In the Website menu, click ASP.NET Configuration to run the ASP.NET Web Site Administration Tool .

  2. In the ASP.NET Web Site Administration Tool, click the Security tab and then click the Create user link.

  3. On the Create User page, set the User Name field to the value displayed by the client application in the previous exercise. Include the subject name prefixed with “CN=,” followed by a semicolon, a space, and the thumbprint of the certificate.

    Fill in the remaining fields with dummy values (the ASP.NET Web Site Administration Tool insists that you fill in all fields), and select the WarehouseStaff role. Click Create User when you have finished:

    image from book

  4. Click Continue. Leave the ASP.NET Web Site Administration Tool running (you will need it again shortly) and return to Visual Studio 2005.

  5. Run the solution again without debugging. In the client console window, press Enter.

    Test 1 still displays the user name, but tests 2 and 3 now succeed. The user has been identified as a member of the WarehouseStaff role, although test 4 still fails because the user is not a member of the StockControllers role.

  6. Press Enter to close the client console window.

  7. In Visual Studio 2005, return to the image from book Program.cs file in the ProductsClient project.

  8. In the Main method of the Program class, change the statement that sets the client credentials to use Fred’s certificate:

     proxy.ClientCredentials.ClientCertificate.SetCertificate(     StoreLocation.CurrentUser, StoreName.My,     X509FindType.FindBySubjectName, "Fred");

  9. Start the solution without debugging. In the client console window, press Enter. Make a note of the user name and thumbprint displayed by the first test. Test 2 fails, as you have not yet added the new credentials for Fred to the SQL Server database.

  10. Press Enter to close the client console window.

  11. Return to the ASP.NET Web Site Administration Tool. Add another user with the subject “CN=Fred” and the appropriate thumbprint. Make this user a member of the StockControllers and WarehouseStaff roles.

  12. When the user has been created, close the ASP.NET Web Site Administration Tool.

  13. In Visual Studio 2005, return to the image from book ProductsService.cs file containing the code for the WCF service.

  14. Uncomment the PrincipalPermission attribute for the ListProducts method, and comment out the four lines of code you added earlier, returning the method to its original state (more or less):

     [PrincipalPermission(SecurityAction.Demand, Role="WarehouseStaff")] public List<string> ListProducts() {   // string userName = ServiceSecurityContext.Current.PrimaryIdentity.Name;   //  List<string> tempList = new List<string>();   // tempList.Add(username);   // return tempList;   //Read the configuration information   Database dbAdventureWorks;    }

  15. Run the solution again without debugging. In the client console window, press Enter.

    All four tests should execute successfully.

  16. Press Enter to close the client console window.

You have seen how to use certificates to authenticate users, and how to authenticate users identified by certificates. Note that IIS also enables you to map client certificates to Windows accounts if you prefer not to use the SQL Role Provider. For more information, see the Enabling Client Certificates in IIS 6.0 page, on the Microsoft Technet Web site at http://technet2.microsoft.com/WindowsServer/en/Library/1033.mspx.

There is one further feature worth mentioning at this point. The client application currently hard-codes the details and location of the user’s certificate. This is almost as bad a practice as hard-coding usernames and passwords. However, it is also a little unreasonable to expect users to know the details of their certificates, so prompting them for this information is not a feasible alternative. In addition, an administrator might not actually want the user to know too much about their certificates; this information could be dangerous in the hands of a naive user. An alternative approach is for an administrator to put the details of the certificate in the application configuration file for the client. You can define a client endpoint behavior that contains the client credentials, and reference this behavior from the endpoint. The code below highlights the relevant fragments from a client application configuration file (you can, of course, create this behavior and attach it to the endpoint by using the WCF Service Configuration Editor):

 <?xml version="1.0" encoding="utf-8" ?> <configuration>   <system.serviceModel>     <behaviors>       <endpointBehaviors>         <behavior name="ClientCertificateBehavior">           <clientCredentials>               <clientCertificate findValue="Fred"                              x509FindType="FindBySubjectName"                              storeLocation="CurrentUser" storeName="My" />           </clientCredentials>         </behavior>       </endpointBehaviors>     </behaviors>     <bindings>       <wsHttpBinding>         <binding name="ProductsClientWSHttpBindingConfig">           <security mode="TransportWithMessageCredential">             <transport clientCredentialType="None"                        proxyCredentialType="None" />             <message clientCredentialType="Certificate" />           </security>         </binding>       </wsHttpBinding>     </bindings>     <client>       <endpoint         address="https://localhost/InternetProductsService/ProductsService.svc"         behaviorConfiguration="ClientCertificateBehavior"         binding="wsHttpBinding"         bindingConfiguration="ProductsClientWSHttpBindingConfig"         contract="ProductsClient.ProductsService.IProductsService"         name="WSHttpBinding_IProductsService" />     </client>   </system.serviceModel> </configuration>

Authenticating a Service by Using a Certificate

Using the HTTPS protocol with a service gives a client application a reasonable degree of confidence that communications with the service are secure. The service sends the client a certificate with a key that the client application uses for encrypting communications, and the client application verifies that the certificate sent by the service has originated from a trusted CA. However, HTTPS is primarily concerned with the confidentiality of communications. Authentication for the purpose of establishing an SSL session is not the same as performing message authentication, which can verify the identity of the message sender. The client application frequently assumes that it is sending messages in a secure manner to a specific, trusted service, but is this assumption always valid? The client might actually be securely exchanging messages with a totally different, spoof service–it is not unknown for hackers to infiltrate DNS servers and arrange for messages addressed to one server to be rerouted elsewhere. To alleviate concerns of this type, you can implement message level security with mutual authentication in place of using transport level security.

The protocol and mechanism used for authenticating a service to a client is very similar to that used by the service to authenticate a client. The service signs the messages it sends to the client application by using its private key. The client application uses a public key from a copy of the service’s certificate held in its own certificate store to decode and verify the signature. If the decoding fails, the service’s signature is not recognized (it is possibly a different service pretending to be the real service), and the client can reject the message from the service. All communications are also encrypted, as described when using message level security in Chapter 4.

In the following exercises, you will create another ASP.NET Web site to host a copy of the WCF service that implements message level security. You will then configure a certificate for the WCF service that the client application will use to authenticate the WCF service. The first exercise has different versions for Windows Vista and for Windows XP.

Create an ASP.NET Web site to host the WCF service that will implement message level security (Windows Vista only)

  1. Right-click the ASP.NET Development Server icon in the bottom right corner of the Windows toolbar, and then click Stop.

  2. Using Windows Explorer, move to the Microsoft Press\WCF Step By Step\Chapter 5 folder under your \My Documents folder.

  3. Create a copy of the InternetProductsService folder and rename it as MutualAuthenticationProductsService.

  4. In the Windows Control Panel, click System and Maintenance, click Administrative Tools, and the double-click Internet Information Services (IIS) Manager.

  5. In the Internet Information Services (IIS) Manager, in the left pane, expand the node that corresponds to your computer, expand Web Sites, right-click Default Web Site, and then click Add Application.

  6. In the Add Application dialog box, enter MutualAuthenticationProductsService for the Alias, set the Physical path to the Microsoft Press\WCF Step By Step\Chapter 5\ MutualAuthenticationProductsService folder under your \My Documents folder, and then click OK.

  7. Close the Internet Information Services (IIS) Manager.

Create an ASP.NET Web site to host the WCF service that will implement message level security (Windows XP)

  1. Right-click the ASP.NET Development Server icon in the bottom right corner of the Windows toolbar, and then click Stop.

  2. Using Windows Explorer, move to the Microsoft Press\WCF Step By Step\Chapter 5 folder under your \My Documents folder.

  3. Create a copy of the InternetProductsService folder and rename it as MutualAuthenticationProductsService.

  4. On the Windows Start menu, click Run. In the Run dialog box, type inetmgr and then click OK.

    The Internet Information Services console opens.

  5. In the Internet Information Service console, expand the node that corresponds to your computer, expand Web sites, right-click Default Web Site, point to New, and then click Virtual Directory.

    The Virtual Directory Creation Wizard appears.

  6. In the Welcome to the Virtual Directory Creation Wizard page, click Next.

  7. In the Virtual Directory Alias page, type MutualAuthenticationProductsService, and then click Next.

  8. In the Web Site Content Directory page, click Browse, select the folder Microsoft Press\WCF Step By Step\Chapter 5\MutualAuthenticationProductsService under your \My Documents folder, click OK, and then click Next.

  9. In the Access Permissions page, accept the default values, and then click Next.

  10. In the You have successfully completed the Virtual Directory Creation Wizard page, click Finish.

    The MutualAuthenicationProductsService virtual directory should appear under the Default Web site node in the Internet Information Services console.

  11. Close the Internet Information Services console.

The remaining exercises apply to Windows Vista and Windows XP.

Configure the WCF service to authenticate itself to client applications

  1. On the Windows Start menu, point to All Programs, point to Microsoft Windows SDK, and then click CMD Shell.

  2. In the command prompt window, type the following command:

     makecert -sr LocalMachine -ss My -n CN=localhost -sky exchange

    This command creates a certificate with the subject “localhost,” and places it in the Personal store of the local computer. The subject name for a service certificate should match the name of host computer in the URL that the client application uses to connect to the service.

    If you are hosting a WCF service by using IIS, as you are in this exercise, you must grant the ASPNET account read access to the certificate by using the procedure in the next step. If you are using a self-hosted service, then the following step is not necessary, depending upon the authority of the account you use to execute the self-hosted service.

  3. Type the following command:

     findprivatekey My LocalMachine -n CN=localhost -a

    The output from this command is the name of a private key file associated with the local host certificate in the certificate store. It should look something like this (the hexadecimal UUID identifying the certificate will be different on your computer):

     C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\ 7b90a71bfc56f2582e916a51aed

    This is the file that you need to grant read access on for the ASPNET account.

  4. Type the following command (replacing the UUID of the certificate with your own value):

     cacls "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\ MachineKeys\7b90a71bfc56f2582e916a51aed" / E /G ASPNET:R

    Note 

    Windows Vista runs Web applications by using the Network Service account rather than ASPNET. If you are using Windows Vista, replace ASPNET in this command with NETWORKSERVICE.

  5. Type the following command to stop and restart IIS:

     iisreset

    Leave the command prompt window open, as you will need it later.

  6. In Visual Studio 2005, in the Solution Explorer, right-click the InternetProductsService solution, point to Add, and then click Existing Web Site.

  7. In the Add Existing Web Site dialog box, ensure that Local IIS is selected, click the MutualAuthenticationProductsService site, clear the Use Secure Sockets Layer check box, and then click Open.

  8. Edit the image from book Web.config file of the MutualAuthenticationProductsService Web site by using the WCF Service Configuration Editor.

  9. In the WCF Service Configuration Editor, in the left pane, expand the Bindings folder and click the ProductsServiceWSHttpBindingConfig binding configuration.

  10. In the right pane, click the Security tab. Set the Mode property to Message.

  11. In the left pane, expand the Advanced folder, expand the Service Behaviors folder, expand the ProductsBehavior node, expand the serviceCredentials node, and then click the serviceCertificate node.

  12. In the right pane, set the FindValue property to localhost and set the X509FindType property to FindBySubjectName. Verify that the StoreLocation property is set to LocalMachine and that the StoreName property is set to My.

  13. Save the configuration, and close the WCF Service Configuration Editor.

You have now enabled the WCF service to authenticate itself to client applications by signing messages with its certificate. In the real world, the administrator for the computer hosting the WCF service would export this certificate and then distribute it to all computers running the client application. The next exercise simulates this process.

Export the WCF service certificate and import it into the client certificate store

  1. Return to the command prompt window and type the following command:

     certmgr -put -c -n localhost -r LocalMachine -s My localhost.cer

    This command retrieves a copy of the localhost certificate used by the WCF service to authenticate itself and creates a file called localhost.cer. Remember that this file contains a copy of the certificate including its public key but NOT the private key. The administrator can distribute this file to all client computers.

  2. Type the following command:

     certmgr -add localhost.cer -c -r CurrentUser -s My

    This command imports the certificate into the certificate store for the current user. This is typically what an administrator would do to make the certificate available to the client application.

    Leave the command prompt window open.

You can now configure the client application to authenticate the WCF service by using the localhost certificate in the CurrentUser certificate store.

Configure the WCF client application to authenticate the WCF service

  1. In Visual Studio 2005, edit the image from book app.config file of the ProductsClient project by using the WCF Service Configuration Editor.

  2. In the Client Configuration Editor, in the Endpoints folder under the Client folder, click the WSHttpBinding_IProductsService node.

  3. In the right pane, change the Address property to http://localhost/MutualAuthenticationProductsService/ProductsService.svc. This is the address of the WCF service. Notice that it uses the HTTP protocol, and not HTTPS.

  4. In the left pane, expand the Bindings folder and then select the ProductsClientWSHttpBindingConfig binding configuration.

  5. In the right pane, click the Security tab. Set the Mode property to Message.

  6. In the left pane, expand the Advanced folder, right-click the Endpoint Behaviors node, and then click New Endpoint Behavior Configuration.

  7. In the right pane, enter AuthenticationBehavior for the Name property and then click Add.

  8. In the Adding Behavior Element Extension Sections dialog box, select clientCredentials and then click Add.

  9. In the left pane, expand the clientCredentials node, expand the serviceCertificate node, and then click the defaultCertificate node.

  10. In the right pane, enter localhost for the FindValue property and set the X509FindType property to FindBySubjectName.

  11. Return to the WSHttpBinding_IProductsService endpoint in the Endpoints folder under the Client folder. Set the BehaviorConfiguration property to AuthenticationBehavior.

  12. Save the configuration, and close the WCF Service Configuration Editor.

  13. Edit the image from book Program.cs file for the ProductsClient application. In the Main method, comment out the code the overrides the validity check of the certificate exported by the HTTPS implementation of the WCF service–this statement is not required by this version of the client:

     // PermissiveCertificatePolicy.Enact("CN=HTTPS-Server");

Verify that the client application authenticates the WCF service

  1. Start the solution without debugging. In the client console window, press Enter.

    The client application should complete all four tests successfully.

    Tip 

    If the client application fails with a message stating that the service could not be activated, check to make sure that you provided the correct endpoint address for the service in the configuration file and that you have granted read permission over the correct certificate file to the ASPNET account.

  2. Press Enter to close the client console window.

  3. Return to the command prompt window, and type the following command:

     certmgr -del -c -n localhost -r LocalMachine -s My

    This command removes the localhost certificate from the LocalMachine certificate store.

  4. Type the following command:

     makecert -sr LocalMachine -ss My -n CN=localhost -sky exchange

    This command creates another certificate with the same subject name as before. When you run the WCF service, it will find this certificate and present it to the client application.

  5. Restart IIS by running the following command:

     iisreset

    When IIS has restarted, close the command prompt window.

  6. Return to Visual Studio 2005 and start the solution without debugging. In the client console window, press Enter.

    The client application should now fail with a MessageSecurityException “An unsecured or incorrectly secured fault was received from the other party .”

    The private key in the localhost certificate used by the WCF service to sign messages has changed, so the client cannot use the public key in its copy of the localhost certificate to verify the signature of the messages sent by the WCF service. This situation is analogous to a rogue version of the WCF service being placed at the same address as the real service and highlights the benefits of authenticating a service in a client application.

    Important 

    The only way the rogue service can imitate the real WCF service is if it has access to the same private key as the real WCF service. This shows once again the importance of keeping your private keys private.

  7. Press Enter to close the client console window.




Microsoft Windows Communication Foundation Step by Step
Microsoft Windows Communication Foundation Step by Step (Step By Step Developer Series)
ISBN: 0735623368
EAN: 2147483647
Year: 2007
Pages: 105
Authors: John Sharp

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net