Monday, December 01, 2008

JW Player, Security and EdgeCast

Hello kinder,

I'm currently doing some work with a company that wants to stream their media. Their site does not have that kind of bandwidth nor do they have the storage space so the next best solution was to outsource. They did trials with a few companies and www.edgecast.com won out. One of the criteria for choosing a streaming media company is security of files so that any 'Joe sixpack' or 'hockey mom' couldn't save the urls and send them to their friends therefore eating up your bandwidth and money.

So what does EdgeCast do for their security? They use token authentication. Essentially you can preshare a 'token' and then encrypt that along with other data to create an encrypted string that will be used to authorize the viewer. As 'integrationman' my job was to integrate ColdFusion and their token authentication. Surely this would be simple, well I was both wrong and right.

Process 1 - the official way + ColdFusion = failboat
The official way is to use their Blowfish binaries and exe to encrypt the string. Sure this would be simple enough with cfexecute if we weren't on a shared hosing provider (I feel the failboat waning). To add insult to injury I tried just using the built in ColdFusion <cfencrypt> tag with the blowfish algorythm and SALT etc, but that ultimately produced a string that would not match their encrypted string and therefore capsized my failboat. Finally after many hours of failing, one of their wizards said, "hey why don't they just use the SOAP api we have." Well DUH to me (I really wish they told me they had this many many hours earlier :sigh: )

Process 2 - the better way (aka SOAP)
So finally after they sent me the info on the SOAP calls this was a breeze to set up. The short part of this is that you can either use standard CF SOAP calls or go the easy route and just use CFHTTP since we only need to encrypt our token.
  1. Send CFHTTP request to:
    https://api.edgecast.com/v1/mediamanager.asmx/TokenEncrypt
  2. Pass 3 Parameters:
    • strCredential = string in the format:
      c:bas:YOURUSERNAME:YOURPASSWORD
      "c:bas:" is required and is not modified. Replace the username and password with your username and password specified in the "ADMINISTRATION -> USERS" section of the Control Panel. Make sure you do not give this user any privileges like file uploads since you will be putting the username/password either in a db or in the code.
    • strKey = preshared token
    • strArgs = any extra parameters you need to pass (minimum is "ec_expire=#####")
  3. That CFHTTP call will return an XML string that you will parse for the encrypted string and use in your JW player.
Example Code:

<!--- MAKE THE EXPIRE TIME 30 SECONDS FROM NOW --->
<CFSET VARIABLES.tmpDate = DateAdd("s", 30, Now()) />
<!--- CONVERT TO EPOCH TIME --->
<CFSET VARIABLES.expDate = DateDiff("s", "January 1 1970 00:00", VARIABLES.tmpDate) />


<!--- MAKE CFHTTP REQUEST TO GET ENCRYPTED TOKEN --->
<CFHTTP method="POST" URL="https://api.edgecast.com/v1/mediamanager.asmx/TokenEncrypt">
<CFHTTPPARAM NAME="strCredential" VALUE="c:bas:USERNAME:PASSWORD" TYPE="formfield" />
<CFHTTPPARAM NAME="strKey" VALUE="YOURSHAREDTOKEN" TYPE="formfield" />
<CFHTTPPARAM NAME="strArgs" VALUE="ec_expire=#variables.expDate#" TYPE="formfield" />
</CFHTTP>


<CFIF FindNoCase("200", CFHTTP.StatusCode)>
<!--- PARSE XML --->
<CFSET VARIABLES.xmlContent = xmlparse(CFHTTP.FileContent) />
<CFSET VARIABLES.encText = xmlContent.string.xmlText />
<!--- CREATE VIEWER --->
<script type="text/javascript" src="swfobject.js"></script>
<div id="container"><a href="http://www.macromedia.com/go/getflashplayer">Get the Flash Player</a> to see this player.</div>
<script type="text/javascript">
var s1 = new SWFObject("player.swf","ply","640","480","9","#FFFFFF");
s1.addParam("allowfullscreen","true");
s1.addParam("allowscriptaccess","always");
s1.addVariable('autostart', 'true');
s1.addVariable('type', 'video');
s1.addVariable('streamer', 'rtmp://flash.edgecastcdn.net/#####/YOURAUTHFOLDER/');
s1.addVariable("file",'mp4:YOURFILE.mp4?<CFOUTPUT>#VARIABLES.encText#</CFOUTPUT>');
s1.write("container");
</script>
</CFIF>


Notes:
  • When setting the 'streamer' variable in the JW Player make sure you use your path that is in the FLASH->FLASH STREAMING section of the admin. They automatically list "/videos/example" as the folder, however you need to choose a folder yourself that will be used for the authenticated videos. To do this, go into the FLASH->TOKEN AUTH section and add a PATH like "/protectedfiles" (make sure you create the folder first via ftp or the MEDIA MANAGER). Now wait a half hour or so like it says, then you can use this.
  • When setting the 'file' variable in the JW Player make sure you set it in the format: TYPE:FILENAME.EXTENSION?ENCRYPTEDSTRING
    i.e.: 'mp4:YOURFILE.mp4?asdfkl234234jsaf...
Hope this helps some other developers out there to get their job done quicker!

Happy coding!

1 comment:

LowerLevelInmate said...

Kevin great post. I also wrote an article that may be of help to the community. You can fine the article at http://fixtheglitch.blogspot.com/.

It details how to implement token based security with the JW Player, Flash Media Server and Asp .Net