Share via


Message Security Anonymous

Download sample

The Anonymous sample demonstrates how to implement a Windows Communication Foundation (WCF) application that uses message-level security with no client authentication but that requires server authentication using the server's X.509 certificate. All application messages between the client and server are signed and encrypted. This sample is based on the WSHttpBinding. This sample consists of a client console program (.exe) and a service library (.dll) hosted by Internet Information Services (IIS). The service implements a contract that defines a request-reply communication pattern.

NoteNote:

The setup procedure and build instructions for this sample are located at the end of this topic.

This sample adds a new operation to the calculator interface that returns True if the client was not authenticated.

public class CalculatorService : ICalculator
{
    public bool IsCallerAnonymous()
    {
        // ServiceSecurityContext.IsAnonymous returns true if the caller is not authenticated.
        return ServiceSecurityContext.Current.IsAnonymous;
    }
    ...
}

The service exposes a single endpoint for communicating with the service, defined using a configuration file (Web.config). The endpoint consists of an address, a binding, and a contract. The binding is configured with a wsHttpBinding binding. The default security mode for the wsHttpBinding binding is Message. The clientCredentialType attribute is set to None.

<system.serviceModel>
  <services>
    <service name="Microsoft.ServiceModel.Samples.CalculatorService"
             behaviorConfiguration="CalculatorServiceBehavior">
     <!-- This endpoint is exposed at the base address provided by-->
     <!--the host: https://localhost/servicemodelsamples/service.svc.-->
      <endpoint address=""
        binding="wsHttpBinding"
        bindingConfiguration="Binding1" 
        contract="Microsoft.ServiceModel.Samples.ICalculator" />
        ...
    </service>
  </services>

  <bindings>
    <wsHttpBinding>
     <!-- 
     <!--This configuration defines the security mode as Message and-->
      <!--the clientCredentialType as None. This mode provides -- >
      <!--server authentication only using the service certificate.-->
      <binding name="Binding1">
        <security mode = "Message">
          <message clientCredentialType="None"/>
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  ...
</system.serviceModel>

The credentials to be used for service authentication are specified in the behavior Element. The server certificate must contain the same value for the SubjectName as the value specified for the findValue attribute as shown in the following sample code.

<behaviors>
  <serviceBehaviors>
    <behavior name="CalculatorServiceBehavior">
      <!-- 
    The serviceCredentials behavior allows you to define a service certificate.
    A service certificate is used by a client to authenticate the service and provide message protection.
    This configuration references the "localhost" certificate installed during the setup instructions.
    -->
      <serviceCredentials>
        <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
      </serviceCredentials>
      <serviceMetadata httpGetEnabled="True"/>
      <serviceDebug includeExceptionDetailInFaults="False" />
    </behavior>
  </serviceBehaviors>
</behaviors>

The client endpoint configuration consists of an absolute address for the service endpoint, the binding, and the contract. The client security mode for the wsHttpBinding binding is Message. The clientCredentialType attribute is set to None.

<system.serviceModel>
  <client>
    <endpoint name=""
             address="https://localhost/servicemodelsamples/service.svc" 
             binding="wsHttpBinding" 
             behaviorConfiguration="ClientCredentialsBehavior"
             bindingConfiguration="Binding1" 
             contract="Microsoft.ServiceModel.Samples.ICalculator" />
  </client>

  <bindings>
    <wsHttpBinding>
      <!--This configuration defines the security mode as -->
      <!--Message and the clientCredentialType as None. -->
      <binding name="Binding1">
        <security mode = "Message">
          <message clientCredentialType="None"/>
        </security>
      </binding>
    </wsHttpBinding>
  </bindings> 
  ...
</system.serviceModel>

The sample sets the CertificateValidationMode to PeerOrChainTrust for authenticating the service's certificate. This is done in the client's App.config file in the behaviors section. This means that if the certificate is in the user's Trusted People store, then it is trusted without performing a validation of the certificate's issuer chain. This setting is used here for convenience so that the sample can be run without requiring certificates issued by a certificate authority (CA). This setting is less secure than the default, ChainTrust. The security implications of this setting should be carefully considered before using PeerOrChainTrust in production code.

The client implementation adds a call to the IsCallerAnonymous method and otherwise does not differ from the WSHttpBinding.

// Create a client with a client endpoint configuration.
CalculatorClient client = new CalculatorClient();

// Call the GetCallerIdentity operation.
Console.WriteLine("IsCallerAnonymous returned: {0}", client.IsCallerAnonymous());

// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);

...

//Closing the client gracefully closes the connection and cleans up resources.
client.Close();

Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate client.");
Console.ReadLine();
 

When you run the sample, the operation requests and responses are displayed in the client console window. Press ENTER in the client window to shut down the client.

IsCallerAnonymous returned: True
Add(100,15.99) = 115.99
Subtract(145,76.54) = 68.46
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Press <ENTER> to terminate client.

The Setup.bat batch file included with the MessageSecurity samples enables you to configure the server with a relevant certificate to run a hosted application that requires certificate-based security. The batch file can be run in two modes. To run the batch file in the single-machine mode, type setup.bat at the command line. To run it in service mode, type setup.bat service. Use this mode when running the sample across machines. See the setup procedure at the end of this topic for details.

The following provides a brief overview of the different sections of the batch files.

  • Creating the server certificate.

    The following lines from the Setup.bat batch file create the server certificate to be used.

    echo ************
    echo Server cert setup starting
    echo %SERVER_NAME%
    echo ************
    echo making server cert
    echo ************
    makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
    

    The %SERVER_NAME% variable specifies the server name. The certificate is stored in the LocalMachine store. If the setup batch file is run with an argument of service (such as, setup.bat service) the %SERVER_NAME% contains the fully-qualified domain name of the computer. Otherwise it defaults to localhost.

  • Installing the server certificate into the client's trusted certificate store.

    The following line copies the server certificate into the client trusted people store. This step is required since certificates generated by Makecert.exe are not implicitly trusted by the client system. If you already have a certificate that is rooted in a client trusted root certificate—for example, a Microsoft-issued certificate—this step of populating the client certificate store with the server certificate is not required.

    certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
    
  • Granting permissions on the certificate's private key.

    The following lines in the Setup.bat batch file make the server certificate stored in the LocalMachine store accessible to the ASP.NET worker process account.

    echo ************
    echo setting privileges on server certificates
    echo ************
    for /F "delims=" %%i in ('"%MSSDK%\bin\FindPrivateKey.exe" My LocalMachine -n CN^=%SERVER_NAME% -a') do set PRIVATE_KEY_FILE=%%i set WP_ACCOUNT=NT AUTHORITY\NETWORK SERVICE
    (ver | findstr "5.1") && set WP_ACCOUNT=%COMPUTERNAME%\ASPNET
    echo Y|cacls.exe "%PRIVATE_KEY_FILE%" /E /G "%WP_ACCOUNT%":R
    iisreset
    
NoteNote:

If you are using a non-U.S. English edition of Microsoft Windows you must edit the Setup.bat file and replace the NT AUTHORITY\NETWORK SERVICE account name with your regional equivalent.

To set up, build, and run the sample

  1. Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

To run the sample on the same machine

  1. Ensure that the path includes the folder where Makecert.exe and FindPrivateKey.exe are located.

  2. Run Setup.bat from the sample install folder. This installs all the certificates required for running the sample.

    NoteNote:

    The setup batch file is designed to be run from a Windows SDK Command Prompt. It requires that the MSSDK environment variable point to the directory where the SDK is installed. This environment variable is automatically set within a Windows SDK Command Prompt.

  3. Verify access to the service using a browser by entering the address https://localhost/servicemodelsamples/service.svc.

  4. Launch Client.exe from \client\bin. Client activity is displayed on the client console application.

  5. If the client and service are not able to communicate, see Troubleshooting Tips.

To run the sample across machines

  1. Create a directory on the service machine. Create a virtual application named servicemodelsamples for this directory using Internet Information Services (IIS) management tool.

  2. Copy the service program files from \inetpub\wwwroot\servicemodelsamples to the virtual directory on the service machine. Ensure that you copy the files in the \bin subdirectory. Also copy the Setup.bat and Cleanup.bat files to the service machine.

  3. Create a directory on the client machine for the client binaries.

  4. Copy the client program files to the client directory on the client machine. Also copy the Setup.bat, Cleanup.bat, and ImportServiceCert.bat files to the client.

  5. On the server, run setup.bat service. Running setup.bat with the service argument creates a service certificate with the fully-qualified domain name of the machine and exports the service certificate to a file named Service.cer.

  6. Edit Web.config to reflect the new certificate name (in the findValue attribute in the serviceCertificate element of serviceCredentials), which is the same as the fully-qualified domain name of the machine**.**

  7. Copy the Service.cer file from the service directory to the client directory on the client machine.

  8. In the Client.exe.config file on the client machine, change the address value of the endpoint to match the new address of your service.

  9. On the client, run ImportServiceCert.bat. This imports the service certificate from the Service.cer file into the CurrentUser - TrustedPeople store.

  10. On the client machine, launch Client.exe from a command prompt. If the client and service are not able to communicate, see Troubleshooting Tips.

To clean up after the sample

  • Run Cleanup.bat in the samples folder once you have finished running the sample.
NoteNote:

This script does not remove service certificates on a client when running this sample across machines. If you have run Windows Communication Foundation (WCF) samples that use certificates across machines, be sure to clear the service certificates that have been installed in the CurrentUser - TrustedPeople store. To do this, use the following command: certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name> For example: certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com.

Footer image

Send comments about this topic to Microsoft.
© Microsoft Corporation. All rights reserved.