How to: Use Username Authentication with Transport Security 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 with transport security to authenticate your users against a Microsoft SQL Server® membership provider and optionally authorize users with the SQL Server role provider. The article shows you how to configure the membership provider and the role provider, create a custom HTTP module for authenticating users against the membership provider, and create a class that derives from IauthorizationPolicy so that WCF can authorize users.

Contents

  • Objectives
  • Overview
  • Summary of Steps
  • Step 1: Create a User Store for the SQL Server Membership Provider and a Role Store for the SQL Server Role Provider
  • Step 2: Grant Access Permission to the WCF Service Process
  • Step 3: Create a Sample WCF Service
  • Step 4: Configure basicHttpBinding with Transport Security and an Authentication Type of “None”
  • Step 5: Configure the WCF Service for ASP.NET Compatibility Mode
  • Step 6: Configure the SQL Server Membership Provider in the Web Configuration File
  • Step 7: Configure the SQL Server Role Provider and Enable It in WCF
  • Step 8: Create the User and Assign Roles
  • Step 9: Implement a Custom HTTP Module Class That Derives from IHttpModule to Authenticate Users with the SQL Server Membership Provider
  • Step 10: Configure the WCF Service to Use the HTTP Module for Authentication
  • Step 11: Implement a Class that Derives from IAuthorizationPolicy
  • Step 12: Configure the WCF Service to Use the Authorization Policy
  • Step 13: Configure Security Settings in IIS
  • Step 14: Implement Authorization Checks on Your Service
  • Step 15: Create a Test Client
  • Step 16: Add a WCF Service Reference and Web Service Reference to the Client
  • Step 17: Test the WCF/ASMX 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 custom HTTP module to authenticate the user by using the SQL Server membership provider with transport security in Internet Information Services (IIS).
  • Learn how to configure the custom HTTP module.
  • Learn how to call the service from a WCF test client and from an ASMX test client.

Overview

Username authentication is suited for scenarios in which your users do not have Microsoft Windows® credentials. In the scenario described in this How To article, users and roles are stored in SQL Server. Users are authenticated in ASP.NET against the SQL Server membership provider and optionally are authorized in the WCF service against the SQL Server role provider. The WCF service uses the basicHttpBinding binding type to provide compatibility with ASMX clients. Because transport security does not support username authentication, a custom HTTP module will be created for authentication, and the authentication type will be set to “None” in the WCF service.

To use the SQL Server membership provider and role provider, you will first create a user and role store and then populate it with your users and roles. You will then configure the store to allow access to the WCF service process, in order to authenticate and authorize the users. Finally, you must configure IIS and WCF security settings to allow users to be authenticated and authorized correctly in ASP.NET and the WCF service.

Summary of Steps

  • Step 1: Create a User Store for the SQL Server Membership Provider and a Role Store for the SQL Server Role Provider
  • Step 2: Grant Access Permission to the WCF Service Process
  • Step 3: Create a Sample WCF Service
  • Step 4: Configure basicHttpBinding with Transport Security and an Authentication Type of “None”
  • Step 5: Configure the WCF Service for ASP.NET Compatibility Mode
  • Step 6: Configure the SQL Server Membership Provider in the Web Configuration File
  • Step 7: Configure the SQL Server Role Provider and Enable It in WCF
  • Step 8: Create the User and Assign Roles
  • Step 9: Implement a Custom HTTP Module Class That Derives from IHttpModule to Authenticate Users with the SQL Server Membership Provider
  • Step 10: Configure the WCF Service to Use the HTTP Module for Authentication
  • Step 11: Implement a Class that Derives from IAuthorizationPolicy
  • Step 12: Configure the WCF Service to Use the Authorization Policy
  • Step 13: Configure Security Settings in IIS
  • Step 14: Implement Authorization Checks on Your Service
  • Step 15: Create a Test Client
  • Step 16: Add a WCF Service Reference and Web Service Reference to the Client
  • Step 17: Test the WCF/ASMX Client and WCF Service

Step 1: Create a User Store for the SQL Server Membership Provider and a Role Store for the SQL Server Role Provider

The SQL Server membership provider stores user information, and the SQL Server role provider stores role information, in a SQL Server database. The user and role information work independently and can be created in different SQL Server databases. For the purposes of this example, both will be created in the same database. You can create your SQL Server user and role store manually by using the Aspnet_regsql.exe command from the command line.

  • From a Microsoft Visual Studio® 2008 command prompt, run the following command:

    aspnet_regsql -S .\SQLExpress -E -A m -A r
    

    In this command:

    • -S specifies the database server, which is (.\SQLExpress) in this example.
    • -E specifies to use Windows authentication to connect to SQL Server.
    • -A m —A r specifies to add the membership and the role features.

Note

By default, a database with the name aspnetdb is created. Use the -d option to specify a different database name.

Step 2: Grant Access Permission to the WCF Service Process

In this step, you grant the WCF service process identity access to the Aspnetdb database. If you host the WCF service in Internet Information Services (IIS) 6.0 on Microsoft Windows Server 2003, the NT AUTHORITY\Network Service account is used by default to run the WCF service.

  1. Create a SQL Server login for NT AUTHORITY\Network Service.
  2. Grant the login access to the Aspnetdb database by creating a database user.
  3. Add the user to the aspnet_Membership_FullAccess database role.
  4. Add the user to the aspnet_Roles_FullAccess database role.

You can perform these steps by using the SQL Server Management Studio, or you can run the following script in SQL Query Analyzer:

-- Create a SQL Server login for the Network Service account
sp_grantlogin 'NT AUTHORITY\Network Service'

-- Grant the login access to the membership database
USE aspnetdb
GO
sp_grantdbaccess 'NT AUTHORITY\Network Service', 'Network Service'

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

USE aspnetdb
GO
sp_addrolemember 'aspnet_Roles_FullAccess', 'Network Service'

Note

If you are running on Microsoft Windows XP, create a SQL Server login for the ASPNET identity instead of the NT Authority\Network Service identity, as the IIS process runs under the ASPNET account in Windows XP.
If you do not have Management Studio or Query Analyzer, you can download Microsoft SQL Server Management Studio Express (SSMSE).

Step 3: Create a Sample WCF Service

In this step, you create a WCF service in Visual Studio.

  1. In Visual Studio, on the File menu, click New Web Site.
  2. In the Templates section, select WCF Service. Make sure that the Location is set to Http and specify the virtual directory to be created in the Path (e.g., https://localhost/WCFTestService).
  3. In the New Web Site dialog box, click OK to create a virtual directory and a sample WCF service.
  4. Change the service metadata to be published via HTTPS instead of HTTP. Double-click the Web.config file, scroll down to service metadata, and change the entry <serviceMetadata httpGetEnabled="true"/> to <serviceMetadata httpsGetEnabled="true"/>.

Step 4: Configure basicHttpBinding with Transport Security and an Authentication Type of “None”

In this step, you configure the WCF service to use transport security and an authentication type of “none.”

  1. In the Solution Explorer, 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, click the Tools menu and then click WCF Service Configuration Editor. Close the WCF Service Configuration Editor tool that appears. The option should now appear on the web.config context menu.

  2. In the Configuration Editor, in the Configuration section, expand Service and then expand Endpoints.

  3. Select the first node [Empty Name]. Set the name attribute to basicEndpoint.

    By default, the name field will be empty because it is an optional attribute.

  4. Click the binding and change it from wsHttpBinding to basicHttpBinding.

  5. Click the Identity tab and then delete the Dns attribute value.

  6. Select the second node [Empty Name]. Set the name attribute to MexEndpoint.

    By default, the name field will be empty because it is an optional attribute.

  7. Click the binding and change it to mexHttpsBinding.

  8. In the Configuration Editor, select the Bindings folder.

  9. In the Bindings section, choose New Binding Configuration.

  10. In the Create a New Binding dialog box, select basicHttpBinding.

  11. Click OK.

  12. Set the Name of the binding configuration to some logical and recognizable name; for example, BasicBindingConfiguration.

  13. Click the Security tab and then set the Mode attribute to Transport.

  14. Set the TransportClientCredentialType to None by selecting this option from the drop-down list.

    Authentication will be done by the HTTP module in ASP.NET.

  15. In the Configuration section, select the basicEndpoint node.

  16. Set the BindingConfiguration attribute to BasicBindingConfiguration by selecting this option from the drop-down list.

    This associates the binding configuration setting with the binding.

  17. In the Configuration Editor, on the File menu, select Save.

  18. In Visual Studio, open your configuration and delete the identity element under basicEndpoint node, if there is one.

  19. In Visual Studio, verify your configuration. The configuration should look as follows:

    <bindings>
          <basicHttpBinding>
            <binding name="BasicBindingConfiguration">
              <security mode="Transport" />
                <transport clientCredentialType="None" />
              </security>
            </binding>
    </basicHttpBinding>
    </bindings>
    <services>
          <service behaviorConfiguration="ServiceBehavior" name="Service">
            <endpoint address="" binding="basicHttpBinding"
              bindingConfiguration="BasicBindingConfiguration"
              name="basicEndpoint" contract="IService" />
             <endpoint address="mex" binding="mexHttpsBinding" 
              bindingConfiguration=""
              contract="IMetadataExchange" />
          </service>
     </services>
    

Step 5: Configure the WCF Service for ASP.NET Compatibility Mode

In this step, you configure the WCF service for ASP.NET compatibility mode. This is required because authentication is done by the HTTP module and you must be able to get the principal and the identity from the HTTP context in order to authorize users either imperatively or declaratively in WCF.

  1. Right-click the Service.svc file and then click View Code.

  2. Add the following using statement to the list of other using statements:

    using System.ServiceModel.Activation;

  3. Add the following attribute on top of the Service class:

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

    public class Service : IService

  4. Open Web.config and add the following entry on the top, inside the <system.serviceModel> node:

    <system.serviceModel>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

Step 6: Configure the SQL Server Membership Provider in the Web Configuration File

In this step, you configure the SQL Server membership provider in the Web Configuration file.

  1. In the Web.config file, replace the existing single <connectionStrings/> element with the following to point to your SQL Server membership provider database:

    <connectionStrings>
      <add name="MyLocalSQLServer"
           connectionString="Initial Catalog=aspnetdb;
          data source=.\sqlexpress;Integrated Security=SSPI;" />
    </connectionStrings>
    
  2. Add a <membership> element inside the <system.web> element as shown in the following example.

    Note that the use of the <clear/> element prevents the default provider from being loaded and then never used. Make sure that the connection string name points to your previous connection string setting.

    ...
    <system.web>
      ...
      <membership defaultProvider="MySqlMembershipProvider" >
        <providers>
          <clear/>
          <add name="MySqlMembershipProvider"
               connectionStringName="MyLocalSQLServer"
               applicationName="MyAppName"
               type="System.Web.Security.SqlMembershipProvider" />
        </providers>
      </membership>
    </system.web>
    ...
    
  3. Save the Web.Config file, to ensure that the changes do not get lost during the following steps.

Step 7: Configure the SQL Server Role Provider and Enable It in WCF

In this step, you configure the use of the SQL Server role provider in the Web.configfile and enable it in your WCF service.

  1. 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 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>
    ...
    
  2. Save the Web.Config file; otherwise the changes might get lost during execution of the following steps.

  3. 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, select WCF Service Configuration Editor on the Tools menu. Close the WCF Service Configuration Editor tool that appears. The option should now appear on the web.config context menu.

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

  5. Select the default behavior, ServiceBehavior.

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

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

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

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

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

  11. In the Configuration Editor, on the File menu, click Save.

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

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

Step 8: Create the User and Assign Roles

In this step, you create the user and assign a newly created role 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 Server 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 step, and assign this user to the role by selecting the User Is In Role check box.

Step 9: Implement a Custom HTTP Module Class That Derives from IHttpModule to Authenticate Users with the SQL Server Membership Provider

In this step, you implement a custom HTTP module to authenticate users by using the SQL Server membership provider. You will create a Windows class library that will derive from IHttpModule.

  1. Open a new instance of Visual Studio, leaving your WCF service solution open.

  2. In the new instance of Visual Studio, click File, click New, and then click Project.

  3. Expand Visual C#, click Windows, and then select Class Library.

  4. In the Name field, enter UserAuthenticator and then click OK.

  5. In the Solution Explorer, right-click References, click Add Reference, select the .NET tab, select System.Web, and then click OK.

  6. Copy and paste the code below inside the Class1.cs file. This class has the following characteristics:

    1. It subscribes to the event handlers Authenticate Request, which will execute when the request starts to authenticate the user, and End Request, which will execute when Authenticate Request has finished.
    2. It checks for the authorization header. If it is not present, it sends a response back to the client with the header “WWW-Authenticate” to challenge the client to send credentials. If it is present, it extracts the username and credentials from the header and authenticates them against the SQL Server membership provider.
    3. If authentication fails, it returns status 401 to flag authentication failure. If authentication succeeds, it builds the generic principal and assigns it to the HTTP application context current user, to be used for later WCF authorization.
  7. Build the class solution.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Web;
    using System.Web.Security;
    using System.Security.Principal;
    
    namespace Module
    {
        public class UserNameAuthenticator: IHttpModule  
        {
    
    
            public void Dispose()
            {
            }
    
            public void Init(HttpApplication application)
            {
                application.AuthenticateRequest += new 
    EventHandler(this.OnAuthenticateRequest);
                application.EndRequest += new 
    EventHandler(this.OnEndRequest);
            }
    
            public void OnAuthenticateRequest(object source, EventArgs 
    eventArgs)
            {
    
                HttpApplication app = (HttpApplication)source;
    
                //the Authorization header is checked if present
                string authHeader = app.Request.Headers["Authorization"];
                if (!string.IsNullOrEmpty(authHeader))
                {
                    string authStr = app.Request.Headers["Authorization"];
    
                    if (authStr == null || authStr.Length == 0)
                    {
                        // No credentials; anonymous request
                        return;
                    }
    
                    authStr = authStr.Trim();
                    if (authStr.IndexOf("Basic", 0) != 0)
                    {
                        // header is not correct...we'll pass it along and 
                        // assume someone else will handle it
                        return;
                    }
    
    
                    authStr = authStr.Trim();
    
    
                    string encodedCredentials = authStr.Substring(6);
    
                    byte[] decodedBytes = 
                    Convert.FromBase64String(encodedCredentials);
                    string s = new ASCIIEncoding().GetString(decodedBytes);
    
                    string[] userPass = s.Split(new char[] { ':' });
                    string username = userPass[0];
                    string password = userPass[1];
                    //the user is validated against the 
                    //SqlMemberShipProvider
                    //If it is validated then the roles are retrieved from 
                    // the role provider and a generic principal is created
                    //the generic principal is assigned to the user context
                    // of the application
    
    
                    if (Membership.ValidateUser(username, password))
                    {
                        string[] roles = Roles.GetRolesForUser(username);
                        app.Context.User = new GenericPrincipal(new 
                        GenericIdentity(username, "Membership Provider"), 
                                        roles);
    
                    }
                    else
                    {
                        DenyAccess(app);
                        return;
    
                    }
    
    
    
                }
                else
                {
                    app.Response.StatusCode = 401;
                    app.Response.End();
    
    
                }
     }
            public void OnEndRequest(object source, EventArgs eventArgs)
            {
                //the authorization header is not present
                //the status of response is set to 401 and it ended
                //the end request will check if it is 401 and add
                //the authentication header so the client knows
          //it needs to send credentials to authenticate
                if (HttpContext.Current.Response.StatusCode == 401)
                {
                    HttpContext context = HttpContext.Current;
                    context.Response.StatusCode = 401;
                    context.Response.AddHeader("WWW-Authenticate", "Basic Realm");
                }
            }
    
            private void DenyAccess(HttpApplication app)
            {
                app.Response.StatusCode = 401;
                app.Response.StatusDescription = "Access Denied";
    
                // Write to response stream as well, to give user visual 
                // indication of error during development
                app.Response.Write("401 Access Denied");
    
                app.CompleteRequest();
            }
    
    
    
        }
    }
    

Step 10: Configure the WCF Service to Use the HTTP Module for Authentication

In this step, you configure the WCF service to use the HTTP module for authentication.

  1. Right-click Web site and then click Add Reference. Select the Browse tab, navigate to the directory containing the UserNameAuthenticator.dll file, select the file, and then click OK.

  2. Configure the HTTP module in Web.Config. Open Web.Config in the Visual Studio editor and locate the httpModules node. If there is one, add the authentication module only as shown below. If it is not present, create an httpModules entry with the authentication module as shown below:

    <httpModules>
          …
          <add name="BasicAuthenticationModule"
          type="Module.UserNameAuthenticator,UserAuthenticator" />   
        </httpModules>
    

Step 11: Implement a Class that Derives from IAuthorizationPolicy

In this step, you implement a class that derives from IAuthorizationPolicy, which will assign the principal to the thread current principal and the identity to the WCF context. This will allow declarative authorization and retrieval of the caller's identity from the WCF security context.

  1. Open a new instance of Visual Studio, leaving your WCF service solution open.

  2. In the new instance of Visual Studio, click File, click New, and then click Project.

  3. Expand Visual C#, click Windows, and then select Class Library.

  4. In the Name field, enter AuthorizationPolicy and then click OK.

  5. In the Solution Explorer, right-click References and then click Add Reference. Select the .NET tab, select System.Web, select System.IdentityModel,System.IdentityModel.Selectors, and then click OK.

  6. Copy and paste the code below inside the Class1.cs file.

    This class has the following characteristics:

    1. It implements Evaluate method, which retrieves the principal from Httpcontext and assigns it to the evaluation context of WCF, so that WCF can do declarative authorization checks.
    2. It implements Evaluate, which retrieves the identity from Httpcontext and assigns it to the evaluation context of WCF, so that WCF can retrieve the identity of the caller from the WCF security context; otherwise, it will not be available and you will need to get the identity from HttpContext.
  7. Build the class solution.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IdentityModel.Claims;
    using System.IdentityModel.Policy;
    using System.Web;
    using System.Security.Principal;
    
    
    namespace AuthorizationPolicy
    {
        // syncs Thread.CurrentPrincipal in WCF with whatever is set 
        // by the HTTP pipeline on Context.User (optional)
        public class HttpContextPrincipalPolicy : IAuthorizationPolicy
        {
            public bool Evaluate(EvaluationContext evaluationContext, ref
                                 object state)
            {
                HttpContext context = HttpContext.Current;
    
                if (context != null)
                {
                    evaluationContext.Properties["Principal"] = 
                    context.User;
                    evaluationContext.Properties["Identities"] =
                       new List<IIdentity>() { context.User.Identity };
                }
    
                return true;
            }
    
            public System.IdentityModel.Claims.ClaimSet Issuer
            {
                get { return ClaimSet.System; }
            }
    
            public string Id
            {
                get { return "HttpContextPrincipalPolicy"; }
            }
        }
    }
    

Step 12: Configure the WCF Service to Use the Authorization Policy

In this step, you configure the WCF service to use the authorization policy.

  1. Right-click Web site and then click Add Reference. Select the Browse tab, navigate to the directory containing the AuthorizationPolicy.dll file, and then click OK.

  2. 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, select WCF Service Configuration Editor on the Tools menu. Close the WCF Service Configuration Editor tool that appears. The option should now appear on the web.config context menu.

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

  4. Select the default behavior, ServiceBehavior.

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

  6. Click the AuthorizationPolicies tab and then click new. Navigate to the bin directory of the Web site and select AuthorizationPolicy.dll.

  7. Select the AuthorizationPolicy.HttpContextPrincipalPolicy type and then click OK.

  8. In the Configuration Editor, on the File menu, click Save.

    The configuration file should now include the following configuration:

      <serviceAuthorization principalPermissionMode="UseAspNetRoles"
                roleProviderName="MySqlRoleProvider">
                <authorizationPolicies>
                  <add 
               policyType="AuthorizationPolicy.HttpContextPrincipalPolicy, AuthorizationPolicy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                </authorizationPolicies>
      </serviceAuthorization>
    

Step 13: Configure Security Settings in IIS

In this step, you configure the Web site in IIS to use Secure Sockets Layer (SSL) encryption and anonymous security. You will need to have created a certificate for SSL security. To create a temporary certificate for SSL, see How to: Create and Install Temporary Certificates in WCF for Transport Security During Development.

  1. Click Start and then click Run.

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

  3. In the Internet Information Services (IIS) Manager dialog box, expand the (local computer) node, and then expand the Web Sites node.

  4. Right-click Default Web Site and then click Properties.

  5. In the Default Web Site Properties dialog box, click the Directory Security tab, and then in the Secure Communications section, click Server Certificate.

  6. On the Welcome screen of the Web Server Certificate Wizard, click Next to continue.

  7. On the Server Certificate screen, select the Assign an existing certificate radio button option, and then click Next.

  8. On the Available Certificates screen, select the certificate you created and installed, and then click Next.

  9. Expand the Default Web Site node, right-click the virtual directory on your WCF service Web site, and then click Properties.

  10. In the Web site properties dialog box, click the Directory Security tab, and then in the Anonymous access and authentication control section, click Edit. Select only the Enable Anonymous Access option. Clear the other options.

  11. In the WCF service project, double-click the Web.config file and set Authentication to None.

    The following XML fragment contains the example:

    <system.web>
    …
    <authentication mode="None" /> 
    

Step 14: Implement Authorization Checks on Your Service

In this step, you authorize the user in WCF, either declaratively or imperatively.

Declarative check

  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);
    }
    

Imperative check

In the same GetData method, you can perform the imperative check with the call to Roles.IsUserInRole. The below example demonstrates the imperative check:

using  System.Web.Security;
...
public string GetData(int value)
{
        if(Roles.IsUserInRole("accounting"))
        {
           return string.Format("You entered: {0}", value);
        }
        else return “not authorized”  ;
}

You can also retrieve the identity of the user with a call to ServiceSecurityContext.Current.PrimaryIdentity.Name.

Step 15: Create a Test Client

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

  • Right-click your solution, click Add, and then click New Project.
  • In the Add New Project dialog box, in the Templates section, select Windows Forms Application.
  • In the Name field, type Test Client and then click OK.

Step 16: Add a WCF Service Reference and Web Service Reference to the Client

In this step, you add both a WCF and Web Service reference to your WCF service to test consuming your service from WCF and ASMX clients.

To add a WCF service reference

  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 (e.g., https://localhost/WCFTestService/Service.svc) and then click Go.

  3. You will be asked to enter a username and password. Provide a valid user name and password created in previous steps.

  4. In the Service reference name field, change ServiceReference1 to WCFTestService. Click OK.

    In your Client project, a reference to WCFTestService should now appear beneath Service References.

  5. Double-click the app.config file and change the authentication mode from None to Basic.

    <basicHttpBinding>
    <binding name="basicEndpoint" closeTimeout="00:01:00" />
    
        <security mode="Transport">
            <transport clientCredentialType="Basic"
            proxyCredentialType="None"
            realm="" />
         </binding>
    

To add a Web service reference

  1. Right-click your Client project and select Add Service Reference. Click the Advanced button then click Add Web Reference.

  2. In the Add Web Reference dialog box, set the URL to your WCF service (e.g., https://localhost/WCFTestService/Service.svc) and then click Go. You will be asked to enter a user name and password. Provide a valid user name and password created in previous steps.

  3. In the Web reference name field, change ServiceReference1 to ASMXTestService.

  4. Click AddReference.

    In your client project, a reference to WCFTestService should now appear beneath Web References.

Step 17: Test the WCF/ASMX Client and WCF Service

In this step, you access the WCF service, pass the user credentials, and make sure that the username authentication 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. Create an instance of the proxy, pass the credentials of the user created in Step 8, and then call the GetData operation of your WCF service. The code should look as follows:

    private void button1_Click(object sender, EventArgs e)
    {
          //WCF client call
         WCFTestService.ServiceClient myService = new
         WCFTestService.ServiceClient();
         myService.ClientCredentials.UserName.UserName = "username";
         myService.ClientCredentials.UserName.Password = "p@ssw0rd";
         MessageBox.Show(myService.GetData(123));
         myService.Close();
                //ASMX client call
               NetworkCredential netCred = new 
               NetworkCredential("username", " p@ssw0rd");
               ASMXTestService.Service proxy = new 
               basicreference.Service();
               proxy.Credentials = netCred;
               proxy.GetData(21, true);
    }
    
  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.

Additional Resources