(X) Hide this
    • Login
    • Join
      • Say No Bots Generate New Image
        By clicking 'Register' you accept the terms of use .

Windows Phone 7 Data Access Strategies: Security

(3 votes)
Andrea Boschin
>
Andrea Boschin
Joined Nov 17, 2009
Articles:   91
Comments:   9
More Articles
1 comments   /   posted on Sep 20, 2011
Categories:   Windows Phone

Tweet This!In the previous three articles I’ve illustrated the multiple ways you can use, to retrieve and send data from and to the server from a Windows Phone device. I’ve spoken about WebClient and HttpWebRequest but finally I’ve illustrated the simplicity of Windows Communication Foundation. 

It is sure that with these tools you can satisfy every needs but up to here I’ve never discussed about securing the communication channels. In this article I would like to focus on this important topic discussing about the limitations of Windows Phone 7 and, finally, show an example based on WCF from which you can for sure extract some guidelines for securing network communications.

Unsecure out-of-the-box

The term “security” includes a number of topics that usually work together to ensure the protection of sensitive information. In a client-server scenario, where the client and the server boundaries are connected by a network, usually security involve the reciprocal knowledge of client and server and the encryption of information send over the wire. The identification grants that the information is not stolen claiming a false identity and the encryption grants that it is not captured during its travel across the boundaries.

From this point of view we have to say that Windows Phone is unsecure out-of-the-box because both the identification and the transmission are not protected by default. Also using WCF we can’t rely on secure communications that are proper of this foundation but we only rely on basic authentication schemes and basicHttpBinding that are sent over the wire in plain text. Basic authentication is made simply by sending credentials without any kind of protection and data are always transferred between client and server clearly, so they are readable if someone intercept the communication stream.

Fortunately the phone includes an implementation of the Secure Socket Layer (SSL) that you can use to secure the channel, applying a strong encryption to the information that are send using the HTTP protocol. Currently it is the sole way you have to communicate securely without the need of dealing with encryption algorithms.

The implementation of SSL in Windows Phone only grants the identification of the server certificate but is currenlty unable to deal with client certificates so you can for sure secure the data but the client identity is always transmitted with credentials sent over the encrypted channel.

Using SSL endpoints with WCF

After you have secured the channel with a certificate and you made some tests with the browser to ensure the configuration is working fine, the first thing you have to do is to configure both server and client endpoints to use the https endpoint. Given that we are using IIS to publish the endpoint, on the server side you have to activate the enpoint changing a little the configuration:

   1: <system.serviceModel>
   2:  
   3:   <bindings>
   4:     <basicHttpBinding>
   5:       <binding name="NamesService_basicHttpBinding" allowCookies="True">
   6:         <security mode="Transport" />
   7:       </binding>
   8:     </basicHttpBinding>
   9:   </bindings>
  10:  
  11:   <behaviors>
  12:     <serviceBehaviors>
  13:       <behavior name="">
  14:         <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
  15:         <serviceDebug includeExceptionDetailInFaults="true" />
  16:       </behavior>
  17:     </serviceBehaviors>
  18:   </behaviors>
  19:  
  20:   <services>
  21:     <service name="SilverlightPlayground.DataAccessStrategies.Web.Code.NamesService">
  22:       <endpoint address=""
  23:                         binding="basicHttpBinding" bindingConfiguration="NamesService_basicHttpBinding"
  24:                         contract="SilverlightPlayground.DataAccessStrategies.Web.Code.INamesService" />
  25:     </service>
  26:   </services>
  27:  
  28:   <serviceHostingEnvironment aspNetCompatibilityEnabled="True" multipleSiteBindingsEnabled="true" />
  29: </system.serviceModel>

The first change is in the <binding> section where I've changed the security mode from None to Transport. Then I've enabled the https get setting the httpsGetEnabled attribute to true in the <serviceMetadata> section. In this element you can choice if leaving enabled the http or relaying only on https according with the configuration of the web server. If you only request for the SSL protocol you have to disable http setting the httpGetEnabled attribute to false. Since there is nothing else to do on the server side, now we have to change the client configuration in the ServiceReference.ClientConfig file, on the Windows Phone project.

   1: <configuration>
   2:     <system.serviceModel>
   3:         <bindings>
   4:             <basicHttpBinding>
   5:                 <binding name="BasicHttpBinding_INamesService"
   6:                          maxBufferSize="2147483647"
   7:                          maxReceivedMessageSize="2147483647">
   8:                     <security mode="Transport" />
   9:                 </binding>
  10:             </basicHttpBinding>
  11:         </bindings>
  12:         <client>
  13:             <endpoint name="BasicHttp"
  14:                       address="https://localhost/wp7security/names.svc"
  15:                       binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_INamesService"
  16:                       contract="Services.INamesService" />
  17:         </client>
  18:     </system.serviceModel>
  19: </configuration>

On the client the changes are less than the server. In the binding you have to synchronize the security mode with the server specifying the Transport mode, then you have to change the url of the endpoint using the https protocol instead of the http. If you decide to use a self-signed certificate for development purposes you have to remove the enableHttpCookieContainer attribute because is seems there is a bug in the http stack and an ArgumentNullException is raised at each call.

Authenticating the user

After the SSL channel is configured, you can send your credentials over this channel without being concerned about someone can intercept them. With basicHttpBinding configured to run over SSL you can, for example, rely on UserName authentication that is pretty simple. Once you configured this kind of authentication WCF will automatically check the credentials, no matter what is the method you are calling. Also you are able to provide a class that perform the authentication on your preferred credential storage. The first thing to do is to create a class that implements UserNamePasswordValidator:

   1: public class CustomUserNamePasswordValidator : UserNamePasswordValidator
   2: {
   3:     public override void Validate(string userName, string password)
   4:     {
   5:         if (userName != "andrea" && password != "p@assw0rd")
   6:             throw new FaultException("Username or passwors mismatch");
   7:     }
   8: }

This example is really silly because use hard coded credentials but, as you undersyand for sure, this is not a good way for securing your application. In the Validate method you have to connect to your authentication service and validate the passed credentials.

After the class has been created and referenced by the web project you can change the WCF configuration to instruct the runtime to use this class to validate the credentials:

   1: <serviceBehaviors>
   2:   <behavior name="">
   3:     <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
   4:     <serviceDebug includeExceptionDetailInFaults="true" />
   5:     <serviceCredentials>
   6:       <userNameAuthentication userNamePasswordValidationMode="Custom"
   7:                               customUserNamePasswordValidatorType="SilverlightPlayground.DataAccessStrategies.Web.Code.CustomUserNamePasswordValidator,SilverlightPlayground.DataAccessStrategies.Web" />
   8:     </serviceCredentials>
   9:   </behavior>
  10: </serviceBehaviors>

In the serviceBehaviors you have to add a section called serviceCredentials, where you have to provide a reference to the type you have created. Then you have also to change again the <security> mode and enable the use of the UserName authentication for the basicHttpBinding

   1: <basicHttpBinding>
   2:   <binding name="NamesService_basicHttpBinding" allowCookies="True">
   3:     <security mode="TransportWithMessageCredential">
   4:       <message clientCredentialType="UserName" />
   5:     </security>
   6:   </binding>
   7: </basicHttpBinding>

The TransportWithMessageCredentials mode mix the SSL channel with a set of credentials that are send over the wire with the message. So in the <message> element we specify UserName ad clientCredentialType to connect this binding configuration with the UserNamePasswordValidator.

Obviously now you have to change again the same part of the configuration on the client side. There is not any need of configuring the client for UserName authentication because it is performed completely on the server side. You have only to specify the TransportWithMessageCredentials on the binding:

   1: <basicHttpBinding>
   2:     <binding name="BasicHttpBinding_INamesService"
   3:              maxBufferSize="2147483647"
   4:              maxReceivedMessageSize="2147483647">
   5:         <security mode="TransportWithMessageCredential" />
   6:     </binding>
   7: </basicHttpBinding>

Now that the channel has been configured you can add a couple of lines to the C# code that calls the service to provide the username and password. Thanks to the common initialization of the client I have done in the wrapper class, there is only a single point where you have to add the credentials:

   1: public DataProviderWCF(BindingMode mode)
   2: {
   3:     this.Client = new NamesServiceClient(mode.ToString());
   4:     this.Client.ClientCredentials.UserName.UserName = "andrea";
   5:     this.Client.ClientCredentials.UserName.Password = "p@assw0rd";
   6: }

Is is really obvious that you have to ask the user for credentials and do not hard code them, like I did in this example. Once the SSL channel has been established there are lot of ways to provide credentials. You can use the UserNamePasswordValidator as I showed in my example joined with a MembershipProvider but you can also specify your credentials as a parameter with every method and continue to have the same level of security that is granted by the SSL protocol. But I think the UserNamePasswordValidator have the additional advantage of simplify the development because once it is in place it works for every method you create.

Storing credentials

Another problem with security, not directly related with network communications is the way you store the credentials in the phone. Given that the phone is an object you bring around during the day you have to take into serious consideration that it may be lost or stolen and the saved credentials may become available to someone else. It is important that you use a sort of encryption when you save the credentials to prevent the user from entering the username and password every time.

In Windows Phone 7.1 "Mango" there will be a new ProtectedData class that available to encrypt sensitive informations. This class is already available on the .NET Framework and Silverlight and is able to protect and unprotect some user data. It use is very simple:

   1: private byte[] entrophy = new byte[] { 1, 5, 33, 2, 5, 6 };
   2:  
   3: private void EncryptCredentials(string username, string password)
   4: {
   5:     string credentials = username + ":" + password;
   6:     byte[] data = Encoding.UTF8.GetBytes(credentials);
   7:     byte encrypted = ProtectedData.Protect(data, entrophy);
   8:     IsolatedStorageSettings.ApplicationSettings["storedCredentials"] = encrypted;
   9:     IsolatedStorageSettings.ApplicationSettings.Save();
  10: }

The method simply concatenates the username and password, converts them to a byte array and then use the Protect method to apply an encryption with an additional "entrophy" array that is used to scramble the data. So, in a later time, this you can read this information, stored in the IsolatedStorage, with the symmetric method Unprotect that accept the same "entrophy" argument.

A side note

As a side note I have to inform you that, to try the example I've illustrated, you have to configure your webserver with a valid certificate that is trusted by the phone. Unfortunately I was unable to configure a self-signed certificate in this way, also if there are some examples on the internet. There is lot of vendors of low-cost certificates so the better is to buy one and use it during the development.


Subscribe

Comments

  • SocalSam

    Re: Windows Phone 7 Data Access Strategies: Security


    posted by SocalSam on Feb 27, 2012 20:08

    Hi Andrew,

    Great article, too bad you couldn't get the self-signed certificates.  But the advice to buy a certificate is a the better way to go.  Companies like Go-Daddy provide certificates, and since many people use GoDaddy, then developers should get used to working with those companies.  Self-Signed certs are fine to a point, but using certs supplied from companies like GoDaddy are likely a better way to go.

    See my blog at: http://blogs.msdn.com/b/socal-sam/archive/2012/02/27/silverlight-windows-phone-7-5-and-security.aspx

    Good work, looking forward to more articles.

     

    Sam stokes

Add Comment

Login to comment:
  *      *       

From this series