Français English

Windows Phone authenticated push notifications

Tags: Windows Phone 8, Windows Phone, WP7, WP8

 

There are 2 limitation of the basic push notifications on windows phone :

  1. Limited to 500 notifications per day per subscription (which should be ok for most of us)
  2. Notification is not encrypted

 

If you want to lift those limitations, you need to use authenticated push notifications.

There are 5 steps to follow :

  1. Buy a certificate
  2. Install the certificate on the server that will send the notifications
  3. Send the certificate to the Windows Phone Dev Center
  4. Register a secure channel (Client side)
  5. Send a secure notification (server side)

 

Let’s detail it one by one. (I will use the sample from my Raw Notification article as support, but it can be used with any type of notification)

Buy a certificate

You need to buy a certificate from selected vendor. The list is here (I personally went with GoDaddy). You need to buy from them, as their root certificate are pre-installed on all phones.

Send the certificate to the Windows Phone Dev Center

Log in and go to your dashboard. Then go to Account/Certificate. You can upload it there.

Once you uploaded it, it is valid for 4 months. Once you register an app using it, you can link the app to the certificate (When submitting an app, go to App info, expand More Options and you can select your certificate in the MPNS combobox). It will then become permanent.

Install the certificate on your server

Launch MMC, go to File/Add Remove Snap-In and add the Certificate (Local Machine) one (It is better to install it machine-wide).

Then in Personnal/Certificates, right click and choose All Tasks/Import.

Import the private key with it. I am not totally sure if it is needed, but I made the private key exportable.

Register a secure channel (Client side)

That is very simple. When registering the channel, pass a second parameter. This parameter is the CN name of your certificate. Example :

channel = new HttpNotificationChannel(_channelName, "www.equinoxe-consulting.net");

Now your notification channel should start with HTTPS and have “unthrottled” in it.

Send a secure notification (Server side)

It is the same as sending a notification except you send the certificate (with its private key) with the notification request.

Example getting the certificate from the store

var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
// Change with your certificate thumbprint
var certificate = store.Certificates.Find(X509FindType.FindByThumbprint, "F8132A5AAB52469A0B8962FE1E01E2CB0AB64137", false)[0];

store.Close();

Once you have it, you send it with the request using the method ClientsCertificates.Add() :

 var sendNotificationRequest = (HttpWebRequest)WebRequest.Create(uri);

sendNotificationRequest.Method = "POST";

// add the certificate
sendNotificationRequest.ClientCertificates.Add(certificate);

// Set the notification payload to send.
var notificationMessage = Encoding.Default.GetBytes(rawMessage);

// Set the web request content length.
sendNotificationRequest.ContentLength = notificationMessage.Length;
sendNotificationRequest.ContentType = "text/xml";
sendNotificationRequest.Headers.Add("X-NotificationClass", "3");


using (var requestStream = sendNotificationRequest.GetRequestStream())
{   
   requestStream.Write(notificationMessage, 0, notificationMessage.Length);
}

// Send the notification and get the response.
var response = (HttpWebResponse)sendNotificationRequest.GetResponse();

And it’s done! The client should receive a notification. And since the channel uri is using HTTPS and has “unthrottled” in it, it is a secure one.

Troubleshouting

I spent lot of time on a stupid thing.

When I tried to send the notification request from the server, I had an HTTPRequestException:

The request was aborted: Could not create SSL/TLS secure channel

Not much information…So I checked in the Windows Event Viewer and I saw this :

Have error in event viewer schannel, event id 36888 the following fatal alert was generated 80. the internal error state is 301

OK…are we getting closer ?

After some time I realized that, in debug, when I tried to get the certificate private key with the PrivateKey property I got a

System.Security.Cryptography.CryptographicException with a message saying that the provider is not correct.

That is where I though about the security permissions…

There is a nice util where you can check/modify the permissions on the certificates : WinHTTPCertCfg

You can check the permissions that way (in an admin command line) :

WinHttpCertCfg.exe -l -c LOCAL_MACHINE\MY -s "www.equinoxe-consulting.net"

Then I got this :

The user my web service was using (.NET v4.5) has no right on the certificate. To add it :

WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s "www.equinoxe-consulting.net" -a ".NET v4.5"

And then everything went ok…

Conclusion

I made a sample app (well it is the authenticated version of the Raw Notification sample) here.

As with the original sample, you have to change the WCF service IP with your own on the client app and let the emulator connect to your host (check here). You also have to change the certificate CN and Thumbprint with your own.

 

Comments powered by Disqus