How to: Use Message Credentials to Secure a Service for Silverlight Applications

Microsoft Silverlight will reach end of support after October 2021. Learn more.

This topic describes how to use message credentials to secure access to services that are intended to be used from Silverlight version 4 applications.

Many authentication methods, such as cookie-based ASP.NET forms authentication or Windows authentication, rely on the Web browser to automatically inject authentication information into each message. This is convenient, because it requires little or no specific Silverlight code, and it enables a single login to both a Silverlight application and the HTML page that hosts it.

However, browser-based authentication is typically not secure for cross-domain access. If you secure a service using a browser-based technique, and publish a cross-domain policy file that allows access from domains that you do not control, you are exposing the service to cross-domain attacks.

Thus, a different mechanism is required to secure services that are to be accessed in a cross-domain fashion. The message credentials feature provides just such a mechanism for SOAP services.

Dd833059.note(en-us,VS.95).gifNote:
When designing a REST-based service for safe cross-domain access from any domain, similar considerations apply. Make sure that you rely on the contents of the request URL or the message body for authenticating the user. Do not rely on anything that is automatically provided by the Web browser, such as HTTP cookies or the HTTP authorization header.

When message credentials authentication is used in Silverlight, every request message will contain a SOAP header that conforms to the WS-Security protocol. The header will contain an unencrypted token with a user name and a password. You must provide them in your Silverlight code.

Because the user name and password credentials are sent in plaintext (that is, unencrypted) form, you must use a secure transport (such as HTTPS) to prevent attackers from stealing the credentials while they are in transit. If you attempt to use this feature with a non-secure transport (such as HTTP), an exception will be thrown.

The first step is to configure your service to use message credentials. If the service is based on a non-Windows Communication Foundation (WCF) technology, refer to the documentation that is specific to the technology with which you are configuring the service to use WS-Security authentication with a user name and password token. If the service is a WCF service, use the steps in the following procedure.

To configure a WCF service to use message credentials

  1. Make sure the service is hosted on a secure (HTTPS-based) site and that HTTPS is properly configured.

  2. Change the binding configuration in the <bindings> element of the <system.serviceModel> section to support message credentials authentication. The following example shows how to do this when configuring a CustomBinding binding.

            <customBinding>
              <binding name="myBinding">
                <security authenticationMode="UserNameOverTransport"/>
                <binaryMessageEncoding/>
                <httpsTransport/>
              </binding>
            </customBinding>
    

    The following example shows how to do this when configuring a standard BasicHttpBinding binding.

            <basicHttpBinding>
              <binding name="myBinding">
                <security mode="TransportWithMessageCredential">
                  <message clientCredentialType="UserName"/>
                </security>
              </binding>
            </basicHttpBinding>
    
  3. On the target service, make sure that your service <endpoint> element in the <service> element of the <system.serviceModel> section in the Web.config file is configured with the binding configuration you defined above.

    <endpoint 
       address="" 
       binding="basicHttpBinding" 
       bindingConfiguration="myBinding" 
       contract="SilverlightApplication2.Web.Service1" />
    
  4. At this point, you can use any of the usual WCF mechanisms for authorization outlined in Authorization. The following example shows how to use the OperationContext.Current.ServiceSecurityContext.PrimaryIdentity to access the current user’s identity.

      [OperationContract]
            public int GetAccountBalance()
            {
    //Block unauthorized users. SecurityException will return the correct SOAP Fault for this situation.
                if (!OperationContext.Current.ServiceSecurityContext.PrimaryIdentity. IsAuthenticated) throw new SecurityException();
    
    //Retrieve the data for the current user.
                return Database.GetBalanceForUser(OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name);
    
            }
    
  5. (Optional) Verify that there are no errors in the service configuration. A convenient way to do this in Visual Studio 2010 is to right-click the .svc file in the Solution Explorer and select View in Browser (or press CTRL + F5) to display a test page for the service. Many HTTPS-related and authentication-related configuration errors are easy to catch at this stage but difficult to debug directly from a Silverlight 4 application.

    Dd833059.note(en-us,VS.95).gifNote:
    You can also use the approach described in this section for Windows Communication Foundation (WCF) services that are hosted in ASP.NET but that are not running in ASP.NET Compatibility Mode, so that not all ASP.NET features are supported.

To access the service from a Silverlight application

  1. Generate the proxy as usual using the Add Service Reference tool or by using the Service Model Proxy Generation Tool (SLsvcutil.exe). If you need guidance on these procedures, see How to: Access a Service from Silverlight and Using SLsvcUtil.exe to Access a Service.

    Dd833059.note(en-us,VS.95).gifNote:
    Note that if there is a problem with your HTTPS certificate, SLsvcutil.exe will fail, while the Add Service Reference tool will inform you of the error but allow you to continue.
  2. To use the proxy, you must specify the user name and password credentials using the ClientCredentials property. You need to do it only once per proxy object, after which the credentials will automatically be applied to all calls. The following example shows code for setting the user name and password.

    var proxy = new MyBankingServiceClient();
    proxy.ClientCredentials.UserName.UserName = textboxUserName.Text;
    proxy.ClientCredentials.UserName.Password = textboxPassword.Text;
    
    // After credentials are set, every call automatically takes advantage of them.
    proxy.GetAccountBalanceAsync();
    proxy.GetAccountHistoryAsync();
    
  3. By default, a maximum time difference is enforced between the client and the server when using message credentials authentication. The default value is 5 minutes, which might not be enough for public Internet applications. To turn off this mechanism, examine the generated ServiceReferences.ClientConfig file. If a custom binding has been generated, check that the includeTimestamp attribute is set to false on the <security> of the <customBinding> element.

    <security 
       authenticationMode="UserNameOverTransport" 
       includeTimestamp="false"/>
    
    Dd833059.note(en-us,VS.95).gifNote:
    If a standard BasicHttpBinding has been generated, you might need to convert it to a custom binding to turn off the time difference enforcement mechanism.

Cross-domain Considerations

  1. When message credentials authentication is in use, you can safely publish a full-access cross-domain policy file (<domain uri=”*”/>) for the domain where the service is hosted. Of course, this assumes that there are no other services or pages on the domain that are not safe for cross-domain consumption. For more information about cross-domain policies, see Making a Service Available Across Domain Boundaries.

Send comments about this topic to Microsoft.

Copyright © 2010 by Microsoft Corporation. All rights reserved.