GhostWire Studios - Flash/Flex UI Components Development And Consulting Services
Quality User Interface Controls For Flash Application DevelopmentAspireUI Components

Sep 03 2009

[AS3] Domain Locking SWFs

Published by at 12:16 pm under Flash,Flash AS3,Tips

By domain locking (or site locking), we are restricting the SWF to be run only from a certain domain, ie the SWF should execute normally only if it has been viewed from a certain domain. If it is loaded from other domains, the SWF should execute in an alternative manner – perhaps not run at all, or run with limited features (as the developer deems appropriate). This is usually done to prevent unauthorized re-distributions of SWF files.


Which SWF URL?
We can get the URL of a SWF by checking the url property of the LoaderInfo object of the main document class:

var swfURL:String = loaderInfo.url;

However, for the purpose of domain locking, we would want to look at the loaderURL property instead:

var ldrURL:String = loaderInfo.loaderURL;

This is because your SWF can be loaded via a Loader object in another SWF, possibly from another domain. In this case, the url property still reports the URL of your SWF file (since it is still being loaded/leeched from the original location) but the loaderURL property will not be the same.

For a SWF that is loaded directly, both the url and loaderURL properties report the same value.


What About HTML Page URL?
It is possible that your SWF may be loaded directly from an allowed domain, and yet viewed within another unauthorized domain. This can happen if a HTML page from a different domain embeds your SWF object directly. If you wish to know the URL of the HTML page containing the SWF, you need to use the flash.external.ExternalInterface class:

import flash.external.ExternalInterface;
 
var htmlURL:String;
if (ExternalInterface.available)
{
	htmlURL = ExternalInterface.call("window.location.href.toString");
}

That will give you the URL of the HTML page containing the loaded SWF, which you can test against when domain locking SWFs.

However, this depends on ExternalInterface to be available, which means it will only work with the following browsers:
* IE 5.0 and later
* Firefox 1.0 and later
* Mozilla 1.7.5 and later
* Netscape 8.0 and later
* Safari 1.3 and later
* any other browser that supports the NPRuntime interface.

Where ExternalInterface is unavailable, you should fall back to checking against the loaderURL.

import flash.external.ExternalInterface;
 
var url:String;
if (ExternalInterface.available)
{
	url = ExternalInterface.call("window.location.href.toString");
}
else
{
	url = loaderInfo.loaderURL;
}

You may also, if you wish, assume that if ExternalInterface is not available, then your SWF is being viewed under the wrong conditions and therefore it should not continue running. If you decide to go this (rather extreme) route, do consider showing a message to let the end-users know why, possibly telling them where they should go to view your application and which browsers they can use.

On the other hand, it is also possible that you may not want to test against the HTML page URL for domain locking purposes at all. Perhaps you want to allow other websites to show your SWF as long as the SWF is loaded from your server. For example, this can be the case if you have a widget that you want other websites to use but do not want the SWF to be re-distributed outside your domain. In such cases, knowing the HTML page URL is nevertheless useful for other reasons, such as tracking sites displaying your SWF.

Ultimately, which URL you should test against depends on the needs of your application.


Domain Locking – Single Domain
Once you get the proper URL to check against, your code can test to see if it is “qualified”. If it doesn’t match a pre-defined criteria, you would abort the rest of your application code, or run the application with limited features.

Here is the code you can use:

var allowedDomain:String = "www.ghostwire.com";
 
var allowedPattern:String = "^http(|s)://"+allowedDomain+"/";
var domainCheck:RegExp = new RegExp(allowedPattern,"i");
if (!domainCheck.test(url))
{
    // domain check failed, abort application
    stop();
    // abort();
}
else
{
    // domain okay, proceed
}
  • allowedDomain specifies the allowed domain
  • allowedPattern is the regular expression pattern that would be used – basically it says (i) the URL must start with “http://” or “https://”, (ii) followed by the allowed domain, (iii) followed by a slash “/” immediately after the domain name.
  • If you don’t expect your SWF to ever run via secured http, then the pattern can be “http://”+allowedDomain+”/”
  • Likewise if you expect your SWF to always run via secured http, then change the pattern to “https://”+allowedDomain+”/”
  • domainCheck is the RegExp object with pattern set to allowedPattern and using ignoreCase flag “i”.
  • domainCheck.test(url) returns true if the url contains the allowed domain name at the correct position in the string, false otherwise.


Domain Locking – Multiple Domains
What if we want to allow multiple domain names? With a little tweak to the regular expression, we can specify multiple domains using “|” as delimiter, as shown below:

var allowedDomains:String = "ghostwire.com|somewhere.net|elsewhere.org";
 
var allowedPattern:String = "^http(|s)://("+allowedDomains+")/";
var domainCheck:RegExp = new RegExp(allowedPattern,"i");
if (!domainCheck.test(url))
{
    // domain check failed, abort application
    stop();
    // abort();
}
else
{
    // domain okay, proceed
}
  • allowedDomains specifies one or more domain names to allow, with each domain name separated by alternator “|”.
  • allowedPattern has been changed to support the group of domain names.
  • This code works with single domain too.


Wild Cards
You can use regular expression wild cards when specifying allowedDomains:

var allowedDomains:String = ".*ghostwire.com";
// ghostwire.com and all subdomains

Likewise for multiple domains:

var allowedDomains:String = ".*ghostwire.com|.*somewhere.net|onlyhere.org";
// ghostwire.com and subdomains
// somewhere.net and subdomains
// onlyhere.org but none of its subdomains

There is no typo in the above – the dot (.) says match any character and the star (*) says zero or more matches.


Getting Domain Name
Let’s say you have allowed multiple domain names to run the SWF, but you would like to know which domain the SWF is loaded from. Perhaps your application may run with additional features if it is loaded from a certain domain. Whatever the reason may be, you can do so with the code below:

var allowedDomains:String = "ghostwire.com|somewhere.net|elsewhere.org";
 
var allowedPattern:String = "^http(|s)://(?P<name>"+allowedDomains+")/";
var domainCheck:RegExp = new RegExp(allowedPattern,"i");
var domainCheckResult:Object = domainCheck.exec(url);
if (domainCheckResult == null)
{
    // domain check failed, abort application
    stop();
    // abort();
}
else
{
    // domain okay, proceed
    trace(domainCheckResult.name) // the domain name
    // trace(domainCheckResult.name.toLowerCase()) // in lower case
}
  • We have used a named group in the regular expression for easy access to the matched domain name. This is done using (?P and ) to define the named group.
  • We use domainCheck.exec(url) instead of domainCheck.test(url) here.


Preventing SWFs From Running Locally
Because the pattern checks the URL to see if it starts with “http://” or “https://”, by domain locking you would also prevent the SWF from running locally (the URL will start with “file:///”).

If no domain locking is intended (ie, you want your SWF to be freely distributed and run online) but not run locally, you can use the following code:

var domainCheck:RegExp = new RegExp("^http(|s)://");
if (!domainCheck.test(url))
{
    // domain check failed, abort application
    stop();
    // abort();
}
else
{
    // domain okay, proceed
}

For other alternatives, see the post “Preventing SWFs From Running Locally”.

pixelstats trackingpixel
Be Sociable, Share!
           

    13 responses so far

    13 Responses to “[AS3] Domain Locking SWFs”

    1. Jesseon 02 Oct 2009 at 10:53 pm

      Thanks for this post! I was looking for this information and had trouble finding it until I discovered your article. Sometimes, after you’ve spent enough time creating an application, you don’t want other people to be able to re-post it on their site for free… Your insight is appreciated.

    2. johnon 06 Nov 2009 at 5:27 pm

      it is awesome! good job :)

    3. Jeffry Houseron 02 Jan 2010 at 8:05 pm

      Have you [or anyone] tested this?

      I was under the impression that cross domain issues would prevent a SWF’s ExternalInterface from making calls to a page that was not served on the same domain as the SWF.

      Otherwise, I would expect this could be a serious cross site scripting violation.

    4. sunnyon 03 Jan 2010 at 1:45 am

      Have you tested yourself? Otherwise, your question smacks of irony, don’t you think so?

      ; )

    5. Josh Strikeon 07 Feb 2010 at 6:07 am

      What stops someone from just decompiling the SWF and commenting out these lines?

    6. happyon 12 Mar 2010 at 9:38 pm

      @JOSH – SWF Encyption would! The process oulined here should be part of many measure to secure a swf. A combination of asp and client side code would mean that even if you decompile th eswf still cant be viewed.

      Nice post

    7. Julienon 03 May 2010 at 11:22 am

      @ Jeffry Houser – I was wondering the same… But I guess there is no really “cross site scripting violation” since the user that embed the swf need to specify the following HTML :

      (defaut value is “samedomain”)

      I suppose this is the only way to allow foreign swf to send stuff out to the page.

      Actually, with this important HTML condition, the piece of code above just works perfect.
      Thank you Sunny.

    8. Julienon 03 May 2010 at 11:28 am

      Damn… I forgot HTML corrector and the code has been eaten.

      So again : the following HTML code needs to be applyed if the swf isn’t on the same domain than the page that stand the embed.

      param name=”allowscriptacess” value=”always”…

      This allows foreign swf to send stuff out to the page. By Default the value is “samedomain”.
      ++

    9. Ianon 10 Sep 2010 at 7:21 pm

      One issue I found with your solution is for allowing subdomains is it will also allow domains that end with the same character sequence to pass. Probably not a big deal, but if you use “(|.*[.])” instead of “.*” in front of your domain name it will not allow invalid domains to pass.

      For example: .*ghostwire.com will allow notghostwire.com to pass. But (|.*[.])ghostwire.com will only allow the primary domain and subdomains to pass.

    10. Matton 09 Jan 2011 at 11:09 pm

      Thanks for the post!

      @Josh Strike – My guess is nothing. But that comes down to the age-old question: “what can you do to stop someone decompiling the SWF?” And the answer to that is of course – (basically) nothing.

    11. julienon 09 May 2011 at 9:23 pm

      Hi Matt, Hi all.

      Just to let know some readers, decompilation is prevented by obfuscation…

      I guess there are pretty good softwares out here that will cost you a good ride for your money if you try to use any kind of decompiler to read the code.

      By the way. One other point : if the domain is “ghostwire.com” be carefull not to test it with “^http(|s)://(“+allowedDomains+”)/”;
      because the last / is preventing from succes….

      Do use “^http(|s)://(“+allowedDomains+”)”; instead or compare with “ghostwire.com/”

      ++

    12. Jacksonon 05 Jun 2012 at 9:13 pm

      will this work for other domain like: mysite.nl, mysite.de, mysite.co.uk ?
      because I am trying to use the Domain Locking – Multiple Domains

      var allowedDomains:String = “mysite.nl|mysite.de|mysite.co.uk”;

      But they all are still blokced, insted of allowed them to load and open the swf file.

      PS SWF is hosted on their own serverhost.

      Thanks.

    13. eprevoton 24 Jan 2013 at 3:36 pm

      Do you know how to force a html wrapper to open the swf ?
      I mean, the swf would be able to detect if a html wrapper loaded it or if someone entered the swf path in the url input of its browser.
      I was surprised to see ExternalInterface.available=true when you load the swf directly in the browser.
      There is no difference in the swf loaderInfo, when you load it from html or directly.

    Comments RSS

    Leave a Reply

    *
    To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
    Click to hear an audio file of the anti-spam word