How to: Use the SQL Server Role Provider with Username Authentication in WCF Calling from Windows Forms

patterns & practices Developer Center

Applies to

  • Microsoft Windows Communication Foundation (WCF) 3.5
  • Microsoft Visual Studio 2008

Summary

This how-to article walks you through the process of using username authentication over the wsHttpBinding binding to authenticate your users against a Microsoft SQL Server® role provider. The article shows you how to configure the role provider, configure WCF, and test the service with a sample WCF client. Use of the SQL Server role provider requires that you first set up and use the SQL Server membership provider.

Contents

  • Objectives
  • Overview
  • Summary of Steps
  • Step 1: Create a WCF Service with Username Authentication Using the SQL Server Membership Provider
  • Step 2: Create a Role Store for the SQL Server Role Provider
  • Step 3: Grant Access Permission to the WCF Service Process Identity
  • Step 4: Enable and Configure the Role Provider
  • Step 5: Create Roles and Assign Users
  • Step 6: Implement Declarative Role-based Security
  • Step 7: Create a Test Client
  • Step 8: Add a WCF Service Reference to the Client
  • Step 9: Configure the Client to Set RevocationMode to NoCheck
  • Step 10: Test the Client and WCF Service
  • Additional Resources

Objectives

  • Learn how to configure the SQL Server membership provider.
  • Learn how to configure the SQL Server role provider.
  • Learn how to create a WCF service hosted in Microsoft Internet Information Services (IIS).
  • Learn how to create and configure a certificate for the service.
  • Learn how to expose the WCF service through wsHttpBinding.
  • Learn how to call the service from a test client.

Overview

Username authentication is suited for scenarios in which your users do not have domain credentials. In the scenario described in this How To article, users are stored in SQL Server and are authenticated first against the SQL Server membership provider and then against the SQL Server role provider. wsHttpBinding is used to provide support for message-based security, reliable messaging, and transactions, while also allowing the possibility that legacy clients can consume the service. WCF message security is used to support the scenario in which there may be intermediaries inspecting the message before final delivery. In general, you should always use transport security unless you need the additional flexibility that message security affords.

In order to use the SQL Server membership provider, you will first create a user store and populate it with your users. You will then configure the membership store to allow the WCF service process identity to have access. You will set the clientCredentialType attribute to UserName on wsHttpBinding in order to configure the WCF service to use username authentication. You will then install a certificate on the server and configure it for WCF so that messages sent between the client and server are encrypted. You will create a role store and populate it with your users and then configure the role store to grant access to the WCF process identity. You will use the PrincipalPermissionAttribute attribute in your WCF service code to specify which roles are allowed to access specific operations in your WCF service. For test purposes, you will set the revocationMode attribute to NoCheck so that the temporary test certificate works properly.

Summary of Steps

  • Step 1: Create a WCF Service with Username Authentication Using the SQL Server Membership Provider
  • Step 2: Create a Role Store for SQL Server Role Provider
  • Step 3: Grant Access Permission to the WCF Service Process Identity
  • Step 4: Enable and Configure the Role Provider
  • Step 5: Create Roles and Assign Users
  • Step 6: Implement Declarative role-based Security
  • Step 7: Create a Test Client
  • Step 8: Add WCF Service Reference to the Client
  • Step 9: Configure the Client to Set RevocationMode to NoCheck
  • Step 10: Test the Client and WCF Service

Step 1: Create a WCF Service with Username Authentication Using the SQL Server Membership Provider

In this step, you create a WCF service with username authentication using the SQL Server membership provider and message security.

  1. Create a user store for the SQL Server membership provider with the following command:

    aspnet_regsql -S .\SQLExpress -E -A m
    
  2. Grant the WCF service process identity permission to the aspnetdb database. You can accomplish this by creating a new SQL Server login for the WCF process identity (Network Service on Microsoft Windows Server® 2003 or ASPNET on Microsoft Windows® XP), create a new user in the aspnetdb database, and then add the user to the aspnet_Membership_FullAccess database role.

  3. Create a sample WCF service in Microsoft Visual Studio® 2008 by creating a new Web site project and selecting the WCF Service project template.

  4. Configure the WCF service to use username authentication and message security by using the WCF Configuration Editor.

  5. Configure the SQL Server membership provider to use username authentication by adding a connection string to the database in the service's web.config file and then adding a membership element to specify usage of the SQL Server membership provider.

  6. Create and install a temporary certificate for the service.

  7. Configure WCF to use the certificate by modifying the Service Credentials element in the WCF Configuration Editor.

For more information on these steps, see “How to: Use Username Authentication with the SQL Server Membership Provider and Message Security in WCF from Windows Forms” and follow Steps 1 through 7.

Step 2: Create a Role Store for the SQL Server Role Provider

The SQL Server role provider stores user information in a SQL Server database. You can create your SQL Server role store manually by using Aspnet_regsql.exe from the command line.

  • From a Visual Studio 2008 command prompt, run the following command.

    aspnet_regsql -S .\SQLExpress -E -A r
    

    In this command:

    • -S specifies the server, which is (.\SQLExpress) in this example.
    • -E specifies to use Windows authentication to connect to SQL Server.
    • -A r specifies to add only the role provider feature.

Step 3: Grant Access Permission to the WCF Service Process Identity

In Step 1, you granted the WCF service process identity access to the aspnetdb database. In this step, you add the Network Service database user to the aspnet_Roles_FullAccess role. You can do this either by using Enterprise Manager or by running the following script in SQL Query Analyzer:

-- Add user to database role
USE aspnetdb
GO
sp_addrolemember 'aspnet_Roles_FullAccess', 'Network Service'

Note

Notes:
If you are running on Windows XP, add the ASPNET database user instead of Network Service because the IIS process runs under the ASPNET account in Windows XP.
If you do not have Enterprise Manager or Query Analyzer, you can download Microsoft SQL Server Management Studio Express

Step 4: Enable and Configure the Role Provider

In this step, you configure the use of the SQL Server role provider in your WCF service.

  1. In the web.config file, verify that you have a connection string similar to the following:

    <connectionStrings>
      <add name="MyLocalSQLServer"
           connectionString="Initial Catalog=aspnetdb;
          data source=.\sqlexpress;Integrated Security=SSPI;" />
    </connectionStrings>
    
  2. Add a <roleManager> element inside the <system.web> element as shown in the following example. Note the use of the <clear/> element, which prevents the default provider from being loaded and then never used.

    ...
    <system.web>
      <roleManager enabled="true" defaultProvider="MySqlRoleProvider" >
        <providers>
          <clear/>
          <add name="MySqlRoleProvider"
               connectionStringName="MyLocalSQLServer"
               applicationName="MyAppName"
               type="System.Web.Security.SqlRoleProvider" />
        </providers>
      </roleManager>
    </system.web>
    ...
    
  3. Save the Web.Config file; otherwise the changes might get lost during execution of the following steps.

  4. Right-click the Web.config file of the WCF service and then click Edit WCF Configuration.

    If you do not see the Edit WCF Configuration option, on the Tools menu, select WCF Service Configuration Editor. Close the WCF Service Configuration Editor tool that appears. The option should now appear on the web.config context menu.

  5. In the Configuration Editor, expand the Advanced node, and then expand the Service Behaviors folder.

  6. Select the default behavior, ServiceBehavior.

  7. In the Behavior: ServiceBehavior section, click Add.

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

  9. In the Configuration section, under Service Behaviors, select the serviceAuthorization option.

  10. Set the principalPermissionMode attribute to UseAspNetRoles by choosing this option from the drop-down list.

  11. Set the roleProviderName attribute to MySqlRoleProvider, which you created above.

  12. In the Configuration Editor dialog box, on the File menu, select Save.

  13. In Visual Studio, verify your configuration, which should look as follows:

    …
    <behavior name="ServiceBehavior">
      <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false" />
           …
           <serviceAuthorization principalPermissionMode="UseAspNetRoles" 
                 roleProviderName="MySqlRoleProvider" />
           …
     </behavior>
    …
    

Step 5: Create Roles and Assign Users

In this step, you create roles for your application and assign users to those roles by using the ASP.NET Web Site Configuration Tool.

  1. In the Solution Explorer, select the WCF service project, and then on the Website menu, select ASP.NET Configuration.
  2. On the ASP.NET Web Site Administration Tool page, click the Security tab, and then click the Select authentication type link.
  3. On the page that appears, select the From the internet radio button and then click Done.
  4. Click the Create user link.
  5. On the Create User page, enter the details of the user you want to create in the SQL store, and then click Create User. If successful, a new user will be created.
  6. Click the Create or Manage roles link.
  7. Enter the New role name—for example, “Managers”—and then click Add Role. If successful, a new role will be created.
  8. On the Roles creation page, click the Manage link, choose the user created in the previous steps, and assign this user to the role by selecting the User Is In Role check box.

Step 6: Implement Declarative Role-based Security

In this step, you provide authorized access to the GetData method only for users in the Managers role.

  1. Open the Service.cs file and add the following statement for using the System.Security.Permissions namespace:

    using System.Security.Permissions;
    
  2. Add the PrincipalPermissionAttribute to authorize users in the Managers role, with the SecurityAction as Demand to the GetData method.

    [PrincipalPermission(SecurityAction.Demand, Role="Managers")]
    public string GetData(int value)
    {
    return string.Format("You entered: {0}", value);
    }
    

Step 7: Create a Test Client

In this step, you create a Windows Forms application to test the WCF service.

  1. Right-click your solution, click Add, and then click New Project.
  2. In the Add New Project dialog box, in the Templates section, select Windows Application.
  3. In the Name field, type Test Client and then click OK to create a Windows Forms application.

Step 8: Add a WCF Service Reference to the Client

In this step, you add a reference to your WCF service.

  1. Right-click your Client project and then click Add Service Reference.

  2. In the Add Service Reference dialog box, set the URL to your WCF service—for example, https://localhost/WCFTestService/Service.svc—and then click Go.

  3. In the Namespace field, change ServiceReference1 to WCFTestService and then click OK.

    A reference to WCFTestService should now appear beneath Service References in your Client project.

Step 9: Configure the Client to Set RevocationMode to NoCheck

This step is required because you installed a temporary service certificate in Step 1.

  1. Right-click the client configuration (App.config) file and then click Edit WCF Configuration.

  2. In the Configuration Editor, expand the Advanced node and then select New Endpoint Behavior Configuration.

  3. Click Add.

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

  5. Expand the clientCredentials node, expand the serviceCertificate node, and then select Authentication below this node.

  6. Set the RevocationMode attribute to NoCheck by choosing this option from the drop-down list.

  7. In the Configuration Editor, expand the Client node, expand the Endpoints node, and then select the wsHttpEndpoint node.

  8. Set the BehaviorConfiguration attribute to NewBehavior by choosing this option from the drop-down list.

    This is the endpoint behavior you just created.

  9. In the Configuration Editor dialog box, on the File menu, select Save.

  10. In Visual Studio, verify your configuration, which should look as follows:

    …
    <behaviors>
        <endpointBehaviors>
            <behavior name="NewBehavior">
                <clientCredentials>
                    <serviceCertificate>
                        <authentication revocationMode="NoCheck" />
                    </serviceCertificate>
                </clientCredentials>
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <client>
        <endpoint address="http://<<fully qualified machine name>>/WCFTestService/Service.svc"
            behaviorConfiguration="NewBehavior" binding="wsHttpBinding"
            bindingConfiguration="wsHttpEndpoint" contract="WCFTestService.IService"
            name="wsHttpEndpoint">
            <identity>
                <certificate encodedValue="SomeEncodeValue" />
            </identity>
        </endpoint>
    </client>
    …
    

Note

Important: This should be done in development only, when using the makecert utility for creating the certificates. In a real-world production environment, you should not overwrite the RevocationMode settings.

Note

If your client application is on a separate machine, you will need to install the Root Authority certificate created in Step 6 on your client machine as well.

Step 10: Test the Client and WCF Service

In this step, you access the WCF service as a legacy ASMX Web service and make sure that it works.

  1. In your Client project, drag a button control onto your Form.

  2. Double-click the button control to show the underlying code.

  3. In the code behind the button click, create an instance of the proxy; pass the credentials of a user with the Managers role created in previous steps, and then call the GetData operation of your WCF service. The code should look as follows:

    private void button1_Click(object sender, EventArgs e)
    {
          WCFTestService.ServiceClient myService = new
                        WCFTestService.ServiceClient();
    //pass the credentials of a user in Manager's role
          myService.ClientCredentials.UserName.UserName = "username";
          myService.ClientCredentials.UserName.Password = "p@ssw0rd";
          MessageBox.Show(myService.GetData(123));
          myService.Close();
    }
    
  4. Right-click the Client project and then click Set as Startup Project.

  5. Run the Client application by pressing F5 or CTRL+F5. When you click the button on the form, the message “You entered: 123” should appear.

  6. Test the application by passing the credentials of a user belonging to a different role (e.g., Employee) and you should receive the security exception Access Denied.

    This is because the GetData operation can be accessed only by the users who belong to the Managers role.

Additional Resources