| Comments

Now that Silverlight 2 has been released, one of the features (or should I say fixes) that is included is the ability for non-secure applications to call secure services.  Previously this was not allowed and we referred to it as “cross-scheme violation.”  That means that a particular protocol scheme (file, http, https) could not access another.  Prior to release this meant that a XAP hosted in an HTTP context could not call a secure service.  Now we no longer have that restriction with the release.  There are some things you have to do, so let me take a brief moment to demonstrate.

First, let’s assume this environment:

We have our application that is served from our web server via HTTP.  so our site is hosting the app on http://foo.com/MyApp.XAP.  Our service is hosted on a secure endpoint which represents our segmented API. 

NOTE: For sake of simplicity and lack of “real” hardware to actually segment out a totally representative environment.  Translated: I only have one SSL certificate and wanted to keep hosting simple…the important note is that we have two separate domains.

And what we have created here is a double-whammy – a cross-domain, secure service request.  So even though when you look at the diagram above, you might ask isn’t the client machine making the request?  Yes, but from an application with a different source-of-origin, which is what creates this scenario.  Let’s continue, shall we?

Prior to release, this simply wasn’t enabled yet.  Now that it is enabled, we can have our MyApp.xap application call our secure service (in this example is a SOAP service hosted in ASP.NET).  In Silverlight 2, the service owner still has to opt-in for this to occur.  We make use of the clientaccesspolicy.xml file which is leveraged for cross-domain scenarios (more information about cross-domain and policy files can be found here including a code snippet for Visual Studio to generate them).  In our case here we need that to support our cross-domain scenario anyway, but we’re also going to leverage it to enable non-secure callers to our service. 

Let me make that clear:  even if your secure service was hosted on the same domain as your non-secure caller, you would still need a policy file in place to enable non-secure callers.

What does the clientaccesspolicy.xml file look like then?  Here’s what we’re using for our application:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <access-policy>
   3:   <cross-domain-access>
   4:     <policy>
   5:       <allow-from http-request-headers="SOAPAction">
   6:         <domain uri="http://*"/>
   7:         <domain uri="https://*" />
   8:       </allow-from>
   9:       <grant-to>
  10:         <resource include-subpaths="false" path="/"/>
  11:       </grant-to>
  12:     </policy>
  13:   </cross-domain-access>
  14: </access-policy>

Now that this is in place, we’re done.  Notice the two (2) domain nodes there?  I couldn’t have just put “*” in there as we require you to explicitly allow non-secure callers in this scenario.  And once you do that, if you didn’t add the secure callers (https://*) then you’d leave them out.  So although it looks a little weird (as if to say Tim, in my mind that reads “*”), it is correct.  That’s right, there isn’t anything more you need to do.  Our code would look the same.  When we add a service reference to our Silverlight application, you’ll see that the ServicesReferences.clientconfig makes note of the secure transport:

   1: <configuration>
   2:     <system.serviceModel>
   3:         <bindings>
   4:             <basicHttpBinding>
   5:                 <binding name="fooSoap" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
   6:                     <security mode="Transport" />
   7:                 </binding>
   8:             </basicHttpBinding>
   9:         </bindings>
  10:         <client>
  11:             <endpoint address="https://www.timheuer.com/foo.asmx" binding="basicHttpBinding"
  12:                 bindingConfiguration="fooSoap" contract="Bar.fooSoap" name="fooSoap" />
  13:         </client>
  14:     </system.serviceModel>
  15: </configuration>

Here’s the rest of the code I’m using in XAML:

   1: <UserControl x:Class="XDomain.Page"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:     Width="300" Height="300">
   5:     <Grid x:Name="LayoutRoot" Background="White">
   6:         <StackPanel>
   7:             <TextBox x:Name="MyName" FontSize="24" />
   8:             <Button Content="Repeat" FontSize="24" Width="150" Height="50" 
   9:                     Click="Button_Click" />
  10:             <TextBlock FontSize="24" x:Name="RepeatedName" />
  11:         </StackPanel>
  12:     </Grid>
  13: </UserControl>

and the code for the event handler on the button:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Net;
   5: using System.Windows;
   6: using System.Windows.Controls;
   7: using System.Windows.Documents;
   8: using System.Windows.Input;
   9: using System.Windows.Media;
  10: using System.Windows.Media.Animation;
  11: using System.Windows.Shapes;
  13: namespace XDomain
  14: {
  15:     public partial class Page : UserControl
  16:     {
  17:         public Page()
  18:         {
  19:             InitializeComponent();
  20:         }
  22:         private void Button_Click(object sender, RoutedEventArgs e)
  23:         {
  24:             Bar.fooSoapClient foo = new XDomain.Bar.fooSoapClient();
  25:             foo.SayMyNameCompleted += (sdr, args) =>
  26:                 {
  27:                     RepeatedName.Text = args.Result;
  28:                 };
  29:             foo.SayMyNameAsync(MyName.Text);
  30:         }
  31:     }
  32: }

So there you have it.  Add a simple policy file and you are enabled!  I hope this helps!  You can download a copy of this VS project here: XDomain.zip

| Comments

In IIS7 you can do very simple testing for SSL related site hosting.  It literally is like a 2 click process:

Enter a name for the cert and done, you now have SSL on your box.  Of course this is a self-issued/signed certificate so it will do you know good in the real world, but for most of the developer world it will work fine.  There may be those times, however, where things may not be quite working right and you want to eliminate the self-signed cert form the equation to make sure it isn’t the issue.

This was the need in my case.  I’ve been doing some messing around with secure services and Silverlight scenarios and ran into one issue that I needed to eliminate the self-signed cert and get a ‘real’ one.  Self-signed certs have a quirky behavior in browsers and I just wanted to eliminate that in my test.

I shouted out on Twitter an ask of “cheap ssl providers?” and got a few responses:

I always forget about GoDaddy when it comes to anything but domain registrations but they do have a lot of other services and this reminded me that they do have a good price on SSL certs ($30/year).  Having had previous experience (and happy with) InstantSSL I knew of their offering as well.  My goal was not to secure a beefy e-commerce system, or help secure personal information, etc.  I needed “https:” and that little icon :-) -- that’s it.  So for me, low cost was what I was seeking – I had no need for any of the deluxe offerings.

With that in mind I didn’t want to purchase a cert from each on of these just to see what the deal was.  That being said, this isn’t all too fair of a comparison of them all, but only 2.  Please keep that in mind.  GeoTrust was by far the most expensive and I can’t quite tell why to be honest.  RapidSSL was pretty on par with everyone else.  OpenSSL.  Well, it’s free if your time is.  I mean it isn’t necessarily integrated into every server environment (yes I know it likely is in Linux), so be aware that there is some setup there.  Remember my goal: fast and cheap.

GoDaddy was offering $15/year SSL certs and InstantSSL had 90-day free ones.  Both perfect for my needs.  I didn’t find out about GoDaddy’s deal until after I started down the path of InstantSSL (which you’ll see was quick).  GoDaddy’s $30 price tag for my purposes was enough for me to consider just doing the free 90-day one from InstantSSL. 

Both processes would require me to create a request from my server.  I’m taking that part out of the equation.  The time I’m talking about is from request to issuer to installation and operational. 

IntantSSL had a simple form.  I input my CSR text added my contact information and clicked submit. 

I was told I’d get two emails: one verifying me as the domain owner (pulling contact information from WHOIS…another reason to ensure you always keep this updated correctly) and once complete a second one with my cert.  By the time I was done reading that sentence, the verification email was in my inbox.  Click on a link, cut/paste a code, click submit.  Inbox now contained my cert and instructions.  Installation was a breeze as i just processed the request and pointed the file.  Seriously, the total time was < 8 minutes.  2 emails, one click.  Having been a previous customer I can assure you that the process is the same should I have opted for their 1 year basic SSL at $80.  Just as quick (adding the purchase step in).

In that time I saw a twitter that GoDaddy had a $15 deal promotion.  I figured, what the heck, that price removed any barrier for even my test use of the cert.  So I started their process.  It went something like this:

    1. Buy cert, add to cart
    2. Go through 3 screens of add-on service (clicking ‘no thanks’ each time)
    3. Checking out (fast/simple)
    4. Received email – instructions weren’t too clear on next step
    5. Logged into account
    6. Navigate to certificates…realized i bought a “credit”
    7. Activate “credit”
    8. Go to cert manager
    9. Enter request
    10. Wait for verification
    11. Recieve certs.

It still didn’t take very long, but was noticeably more steps and not clear direction for a lay person I’d have to say.  I received the cert in my email with a link to instructions.  I was warned of this on Twitter that there would be an extra step.  It isn’t that bad, but is an extra step.  GoDaddy needs some intermediate authorities to be on the box before your certificate is trusted.  They ship these with your cert so you don’t have to go digging.  This step does involve opening Management Console, etc.  and then going to finalize the request in the IIS manager.  Overall time for GoDaddy – I’d estimate 15-20 minutes.  Still not bad…and the price is right.

I’ll stick with my GoDaddy cert of course because at the $15 price I got a full year so no reason to change now.  I would have to say that GoDaddy and InstantSSL both offered the easiest and fastest route to request –> operational I could have hoped for in the process.  I imagine by the name ‘RapidSSL’ that they’d be similar.

One Twitter comment was:

instantssl is actually the best quality for the price I've seen.

And having seen their offerings and been through their process, I’d have to agree.  Either way there is a list of folks to look at.  I’d recommend InstantSSL first, then GoDaddy based on my experiences.

Oh yeah, OpenSSL is free…if someone can convince me that I could have set it up in < 10 minutes I would have tried.  It took me longer than that to figure out what I might even have to do!