Tag Archive for 'networking'

Silverlight 2 Beta2

Silverlight Beta2 is officially out in the wild! 

logo

All the required download links to get started are here:

 

Also, for the feature areas I drive, here are the major Beta2 updates:

Networking

  • Wider API set for WebClient
    • Upload methods for streams and strings
    • Set request headers on uploads
  • Threading Updates
    • HttpWebRequest & WebClient are callable on a background thread
    • HttpWebRequest’s delegates are called on a new non-UI thread.
      • Delegates were previously always called on the UI thread.
      • You must invoke back on to the UI thread if the data you’re retrieving will be consumed by a UI element.
      • For an example, see the updated networking post series (part one).
  • Progressive download support
    • When AllowReadStreamBuffering is set to false on HttpWebRequest and WebClient, the returned request stream supports progressive Stream.BeginRead() calls.
  • Cross domain URI & path character restrictictions
  • Cross domain policy files
    • Cross domain policy files do not allow you to send request headers by default.  You must explicitly opt in to request headers in the policy file.
    • For more details, see this updated networking post series (part three).

Control Model Customization

  • Easier control subclassing when you don’t want to change control visuals
    • The DefaultStyleKey property indicates the type that should be used to look up the built-in style (e.g. MyButton.DefaultStyleKey = typeof(MyButton)
      • The runtime looks up the generic.xaml in the assembly where the DefaultStyleKey’s Type value was defined.
      • It also uses the DefaultStyleKey to look up the built-in style w/in that generic.xaml’s ResourceDictionary
    • DefaultStyleKey should be set in the control’s constructor
    • If you sub class Button and do not set the DefaultStyleKey, you will "inherit" the Button’s built-in style
  • Expansion of the Parts and States model with VisualStateManager
    • This is a big one!  Look for a new post coming soon explains how we’ve made control visual state & transition management easier.

Silverlight HTTP Networking Stack - Part 3 (Configuring a Cross Domain Policy File)

Here’s the final post in this 3 part Silverlight HTTP networking series.

In the first post, we discussed basic site of origin HTTP communication.  In the second, we gave an overview of Silverlight’s cross domain communication support.

Today, we’ll drill in to how to configure your web service to enable Silverlight cross domain callers.  If you haven’t already, please be sure to read (at least) part 2 of this series - it provides a lot context for this discussion.

Note: this tutorial has been updated for Silverlight 2 RTW

 

(Series Links:  Part 1, Part 2, Part 3)

 

So, You Want To Make Your Web Service Callable By 3rd Parties…

Exposing your web service to 3rd parties is an important decision that should be done with care and diligence.  As you’re designing your web service APIs, please keep the following in mind:

1. Using cookies/auth on your main site?  Create a separate domain for your 3rd party-accessible APIs

In Silverlight, we send cookies & authentication with each cross domain request.  Because of this, web service authors need to be careful to separate their 3rd party accessible APIs from their main site.

Let’s look at example.  http://cool.com uses cookie authentication.  Once a user is logged on, she can access and update her public profile as well as her personal account information.

Now, http://cool.com wants to enable 3rd party apps to access public profile information.   However, they don’t want to these 3rd party apps to get at a user’s billing information.

If the primary site and the web service is hosted on the one domain, then once a user logs in, cookies & auth are sent from http://cool.com applications well as 3rd party applications.

This could allow 3rd party sites to access protected information on the user’s account.

Instead, the web service apis should be hosted on a separate domain.

This way, even though cookies and auth are always sent, 3rd party applications cannot call (authenticated) web services on the main site.

Do you want to expose your web service to more than one partner, or to the public at large?  If so, then basic/digest authentication and/or cookies aren’t sufficient for that web service  authentication.  Which leads us to…

2.  Requiring 3rd party apps to authenticate?  Use an in-message authentication approach.

You should not rely on cookies or basic/digest authentication to authenticate a request on a 3rd party exposed API.  This is because multiple 3rd parties will be using the same APIs, and the same cookies and/or auth will be sent to http://api.cool.com regardless of the specific caller.

Let’s say a user trusts http://bar.com and authenticates to http://api.cool.com from http://bar.com/app.xap.   That same user does NOT trust http://foo.com.

However, since http://api.cool.com uses cookie authentication, once the user has signed in, she is signed in for all calls from that browser session, not just a particular site.  This means  http://foo.com/app.xap can access private information, even though that wasn’t the user’s intent.

If you want to authenticate the particular application calling a web service method, it is better to use an in message authentication.  For instance, you could specify the particular application’s key as a parameter in the query string.

With an in-message approach to authentication, you can determine which 3rd party application is calling your web service.

3.  Set the cache policy on your cross domain policy file

As explained last time, we use the browser plugin networking APIs to issue requests for the cross domain policy file.  This means that the normal browser rules around request caching apply to the policy file.

We recommend that you do NOT allow the browser to cache the policy file - this makes changing the policy file at later time much easier.  Turning off client caching is done by configuring your server to set a “Cache-Control:no-cache” response header on the policy file.

Remember, we only check a site’s cross domain policy once per application session, so the bandwidth/latency cost of not caching the policy file is limited.

4.  Restrict the policy as much as possible

The last piece of advice is the easiest, but the one most prone to copy & paste mistake:  don’t open up a web service to everyone unless you *need* everyone to be able to call it.

If you’re just trying to enable certain particular partner apps to call your web service, allow access to that handful of domains.

Similarly, if you only really want public callers on a certain path, then just open up that subpath.

That being said, don’t configure a policy with 400 different <resource> tags - as that is also difficult to audit and maintain.  As always, good security is a balance between reducing surface area and maintaining simplicity.

 

Configuring a Silverlight Policy File

The Silverlight policy file is called clientaccesspolicy.xml.  A Silverilght policy file that opens up an entire domain to the public & allows Content-Type header to be sent looks like:

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

Specifying WHO is allowed by a policy

Within a policy, you specify allowed domains by:

  • a specific domain  (e.g. ‘http://bar.com’, ‘https://bar.com’)
    • Represents only the domain with that specific protocol, host name & port.
  • subdomain wildcard (e.g. ‘http://*.bar.com’)
    • Represents all subdomains
  • http wildcard (i.e. ‘http://*’)
    • Represents all http:// domains
  • general wildcard (i.e. ‘*’)
    • Represents all domains (http:// & https://), if an http service
    • Represents all secure domains (https://), if an https service

Note: If your service is an HTTPS service, you need to explicitly allow insecure HTTP callers with the ‘http://*’ literal.  Otherwise, allowing ‘*” will only grant access to secure HTTPS callers.

 

Specifying WHAT is allowed by a policy

Also, within a policy, you specify the granted resources on the server by either:

  1. Supplying a path and setting include-subpaths to be false.  This means that only requests that exactly match the specified path are allowed.
  2. Supplying a path and setting include-subpaths to be true.  This mean requests whose paths are prefixed by the specified path are allowed.

 

Specifying HOW a request can be sent

By default, no request headers can be sent.  You  can designate which request headers should be allowed on POSTs by:

  1. “*” wildcard representing all non-blacklisted headers
  2. a comma seperated list of headers (e.g. “SOAPAction, Content-Type”)

It’s also possible to specify more than one policy within a policy file.

 

Examples

Here are some more clientaccesspolicy.xml examples:

Example1:  http://cool.com/clientaccesspolicy.xml:

   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://sub.cool.com/"/>
   7:         <domain uri="http://partner.com"/>
   8:         <domain uri="http://friend.com"/>
   9:       </allow-from>      
  10:       <grant-to>      
  11:         <resource path="/shipments" include-subpaths="true"/>
  12:         <resource path="/creditcards" />
  13:       </grant-to>      
  14:     </policy>  
  15:   </cross-domain-access>
  16: </access-policy>

The above policy allows requests coming from Silverlight applications on:

They can send on POSTs:

  • SOAPAction request headers
  • Content-Type request headers.  (Is allowed by default.)

They have access to:

 

Note: The allowed domains do NOT have access to http://cool.com/creditcards/ or http://cool.com/creditcards/numbers.xml, as the “/creditcards” resource tag does not have an include-subpath=”true” attribute.

 

Example2:  http://cool.com/clientaccesspolicy.xml:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <access-policy>
   3:   <cross-domain-access>
   4:     <policy>
   5:       <allow-from>
   6:         <domain ur="http://sub.cool.com"/>
   7:       </allow-from>
   8:       <grant-to>
   9:         <resource path="/partner/feeds/favorites.rss" />
  10:       </grant-to>
  11:     </policy>
  12:   </cross-domain-access>
  13:   <cross-domain-access>
  14:     <policy>
  15:       <allow-from>
  16:         <domain ur="*"/>
  17:       </allow-from>
  18:       <grant-to>
  19:         <resource path="/api" include-subpaths="true"/>
  20:       </grant-to>
  21:     </policy>
  22:   </cross-domain-access>
  23: </access-policy>

The above policy file contains two policies.  Requests are allowed if…

  • they come from an app on http://sub.com.com and are requesting http://cool.com/partners/feeds/favorites.rss
  • OR they are for any subpath of http://cool.com/api

Note:  If you’re trying to create your own policy file, Tim Heuer has written a blog post that helps you get VS intellisense when authoring a clientaccesspolicy.xml.

 

Configuring a Silverlight-Supported Flash Policy File

The Flash policy file is called crossdomain.xml.  Silverlight supports crossdomain.xml files that allow public access to an entire domain.  Specifically, this mean supporting crossdomain.xml of the format:

   1: <?xml version="1.0"?>
   2: <!DOCTYPE cross-domain-policy SYSTEM
   3:      "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
   4: <cross-domain-policy>
   5:   <allow-access-from domain="*"/>
   6: </cross-domain-policy>

So, that’s our 3 part HTTP networking series.  Hope you found it useful.  Like always, we love to hear your feedback.

Can’t wait to see the applications you’re going to build!

Silverlight HTTP Networking Stack - Part 2 (Cross Domain Communication Overview)

In part 1, we discussed how Silverlight applications talk to their site of origin server.  In this post, we’ll dive into the high level concepts around Silverlight’s cross domain HTTP communication.  Then next time, we’ll go into details of how to set up a cross domain policy file.

Note: this tutorial has been updated for Silverlight 2 RTW.

 

(Series Links:  Part 1, Part 2, Part 3)

 

What is Cross Domain Communication?

As mentioned last time, your Silverlight application by default can only talk back to its site of origin server.  This is in line with the general browser sandbox, and is designed to prevent cross site forgery.

The site of origin server is determined by the app’s deployment URI: the location of the XAP for managed applications, the address of the XAML page for javascript applications.

If a HTTP request matches the origin server’s domain, protocol, and port number, then it’s considered a site of origin request and is allowed.  Otherwise, it’s classified as a cross domain call.

Silverlight’s Cross Domain Policy Support

In order for a cross domain request to a particular web service to succeed, that web service needs to explicitly opt-in to 3rd party callers.

In Silverlight 2, the primary way of enabling cross domain calls is through a policy file placed at the root of the server.  We support two types of policy files:

  1. Silverlight Cross Domain Policy File (clientaccesspolicy.xml)
  2. (A subset of the) Flash Cross Domain Policy File (crossdomain.xml)

What Can You Say to a Cross Domain Server?

Basic Capabilities

So, you’ve got permission from the appropriate policy file to make a cross domain request .  What can you do with that request?

  • Scheme:  HTTP and HTTPS    (file:// and other protocols are not supported)
  • Verb support:  GET & POST
  • Status codes:  200 (OK) or 404 (NotFound) only

Request Headers

By default, only Content-Type request headers are allowed to be sent.  A policy file can explicitly opt in to setting certain headers.  There is also a set of blacklist headers that can never be sent.

Request headers can only be sent on POSTs, not GETs.

Cookies & Authentication

All the requests you send will have have cookies and authentication sent with them.  This is a significant point, and we’ll dig into it deeper in the part 3 of this post series.

The above capabilities are determined by the browser plugin’s networking APIs.  Please see Part 1 for a deeper discussion of networking stack implementation.

 

Path Character Restrictions

Silverlight has placed certain restrictions on the path portion of a cross domain URI.

Specifically, a cross domain request path CANNOT contain:

  • “..”    (consecutive dots)
  • “./”    (dot and a forward slash)
  • “%”    (percent sign, thus preventing %-encoding)

This restriction was done to prevent attacks around path manipulation and %-encoded path manipulation, which malicious apps could use to try to escape out of an allowed path into a disallowed path. 

Where does Silverlight Look for the Cross Domain Policy File?

When a request is detected as a cross domain request, we look first for a Silverlight policy file at the root of the request’s server.

Request URI Policy File Checked
http://foo.com/bar/data http://foo.com/clientaccesspolicy.xml
http://sub.foo.com/bar/data http://sub.foo.com/clientaccesspolicy.xml
http://foo.com:8080/bar/data http://foo.com:8080/clientaccesspolicy.xml

If such a clientaccesspolicy.xml file does not exist or is malformed, we then look for a crossdomain.xml file at the same location.

“Caching” Of Policy Files

Silverlight looks up the cross domain policy file for a particular server ONCE per application session.  (Where an application session is the lifetime of a particular xap or xaml page instance in memory.)

Also, we use the browser networking stack to issue the request for the policy file, so the normal browser caching of the request happens under the covers.

Redirects

Redirects for the policy file itself are not allowed.

Request URIs redirects will only be successful if the original and final URIs are allowed via the appropriate cross domain policy.  (Note:  The browser handles handles the actual redirect logic itself and ensures it matches w3 spec.)

So that’s the high level cross domain behavior overview.  Next time, we’ll drill into how to set up a cross domain policy file.