Our EdgeSecurity™ solution controls the exact clients who are allowed to view a secure resource. From digital product protection to time-expiring links, ensure your content is available for authorized eyes only.

What is a Secure Token?

Imagine having a PDF file you want to ensure isn’t linked from elsewhere, to do this we need to add a unique token and an expiration date. In this how-to we will be showing you how to enable Secure Tokens, show example responses and generate sample code to create secure links.

Enable EdgeSecurity™ Secure Token

  1. Log into your Control Panel and click on Zones.

  2. On the right hand side, click Get EdgeSecurity.

  3. Checkout and pay for EdgeSecurity.

  4. Click Manage on the zone you wish to add EdgeSecurity to.

  5. Click the Security tab.

  6. Enable EdgeSecurity, and type in a secure key. Note that this key has a limit set to 32 characters. Once done, update the settings.

  7. You have successfully added EdgeSecurity to a zone.

Example Responses

  1. cURL without secure link:

    $ curl -I zone.alias.netdna-cdn.com/foo.pdf
          HTTP/1.1 403 Forbidden
          Server: NetDNA-cache/2.2
  2. cURL without secure link:

    $ curl -I zone.alias.netdna-cdn.com/foo.pdf?st=YNcnQ1H0tpgCzaLQ&e=1355776589
          HTTP/1.1 200 OK
          Server: NetDNA-cache/2.2
  3. cURL with EXPIRED secure link:

    $ curl -I zone.alias.netdna-cdn.com/foo.pdf?st=YNcnQ1H0tpgCzaLQ&e=1355776589
          HTTP/1.1 410 Gone
          Server: NetDNA-cache/2.2

Sample Code

  1. PHP:

    <?php
          $secret = 'jsdkhf8fh3fewk';
          $path = '/foo.pdf';
          $expire = time() + 3600; // one hour valid
          $md5 = base64_encode(md5($secret . $path . $expire, true)); // Using binary hashing.
          $md5 = strtr($md5, '+/', '-_'); // + and / are considered special characters in URLs, see the wikipedia page linked in references.
          $md5 = str_replace('=', '', $md5); // When used in query parameters the base64 padding character is considered special.
          $url = "http://zone.alias.netdna-cdn.com{$path}?st={$md5}&e={$expire}"; // use this as DL url
    
          echo $url;
          echo "\n\n";
          ?>
  2. Python

    from time import time
            import base64
            from hashlib import md5
    
            secret = 'jsdkhf8fh3fewk'
            path = "/foo.pdf"
            expire = int(time()) + 3600
            hashed_string = base64.encodestring(
                              md5(
                                "%s%s%s" % (secret, path, expire)
                              ).digest()
                            ).replace("\n", "").replace("+", "-").replace("/", "_").replace("=", "")
            url = "http://zone.alias.netdna-cdn.com%s?st=%s&e=%s" % (path, hashed_string, expire)
    
            print url
  3. Ruby:

    require 'base64'
          require 'digest/md5'
    
          secret = 'jsdkhf8fh3fewk'
          path = "/foo.pdf"
          expire = Time.now.to_i + 3600
          hashed_string = Base64.encode64(
                            Digest::MD5.digest(
                              "#{secret}#{path}#{expire}"
                            )
                          ).gsub("\n", "").gsub("+", "-").gsub("/", "_").gsub("=", "")
          url = "http://zone.alias.netdna-cdn.com#{path}?st=#{hashed_string}&e=#{expire}"
    
          puts url
  4. Java:

    import java.io.UnsupportedEncodingException;
          import java.security.MessageDigest;
          import java.security.NoSuchAlgorithmException;
          import java.util.Date;
          import org.apache.commons.codec.binary.Base64;
    
          public class MakeURL {
    
            private static String MakeBinaryHash(String secret, String path, Long expire) throws UnsupportedEncodingException, NoSuchAlgorithmException{
              String message = secret + path + expire.toString();
              byte[] bytesOfMessage = message.getBytes("UTF-8");
              MessageDigest md = MessageDigest.getInstance("MD5");
              byte[] thedigest = md.digest(bytesOfMessage);
              String encoded = Base64.encodeBase64URLSafeString(thedigest);
              return encoded;
            }
    
            public static void main(String[] args) throws Exception{
              String secret = "jsdkhf8fh3fewk";
              System.out.println("Secret : " + secret);
              String path = "/foo.pdf";
              System.out.println("Path : " + path);
              Date d = new Date();
              Long expire = (d.getTime()/ 1000) + 3600; //Divide by 1000 cause java date is in milliseconds . 1 hour in future
              System.out.println("expire : " + expire);
              String md5 = "" ;
              try {
                md5 = MakeBinaryHash(secret, path, expire);
                System.out.println("generated md5 : " + md5);
                String url = "http://zone.alias.netdna-cdn.com" + path + "?st=" + md5 + "&e=" + expire.toString() ;
                System.out.println("genrated url : " + url);
              } catch (Exception e){
                e.printStackTrace();
              }
    
            }
    
          }
  5. node.js

    var md5_digest = require('crypto'); //INCLUDE CRYPTO LIBRARY
          var secret = "secure_token"; // YOUR SECURE TOKEN SET IN CP
          var path = "/PATH/TO/FILE.EXT";
          var d = new Date();
          var t = d.getTime() / 1000; // JS TIME IS IN MILLISECONDS SO YOU HAVE TO DIVIDE IT BY 1000
          var expire = parseInt(t) + 3600; // EXPIRY IN 3600 SECONDS
          var md5 = md5_digest.createHash('md5').update(secret + path + expire).digest('base64'); //MD5 DIGEST
          md5 = md5.toString().replace("+","-").replace("/","_").replace(new RegExp("=","gm"),""); // REPLACE SPECIAL CHARACTERS +, /, =
          console.log("http://ZONENAME.ALIAS.netdna-cdn.com" + path + "?st=" + md5 + "&e=" + expire); //DISPLAY RESULTING URL
  6. javascript on client side
    You will need md5.js and encode-decode.js libraries to handle hashing and encoding.

    <script type="text/javascript" src="md5.js"></script> //INCLUDE MD5.JS FUNCTION
          <script type="text/javascript" src="encdec.js"></script> // INCLUDE FUNCTIONS FOR BAS64 ENCODE/DECODE
          <script>
          function run(){
          var secret = "secure_token";
          var path = "/PATH/TO/FILE.EXT";
          var d = new Date();
          var t = d.getTime() / 1000; // JS TIME IS IN MILLISECONDS SO YOU NEED TO DIVIDE IT BY 1000 TO GET SECONDS
          var expire = parseInt(t) + 3600; // ADD EXPIRY OF 3600 SECONDS
          var md5 = calcMD5(secret + path + expire); // CALCULATE MD5
          var base64 = decodeHex(md5); // HEX DECODE MD5 HASH
          var md5base64 = encodeBase64(base64).replace("+","-").replace("/","_").replace(new RegExp("=","gm"),""); //REPLACE SPECIAL CHARS +, /, =
    
          alert("http://ZONENAME.ALIAS.netdna-cdn.com" + path + "?st=" + md5base64 + "&e=" + expire); //DISPLAY RESULTING URL
          }
  7. .NET/C#

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Security.Cryptography;
    
    namespace securetokens
    {
        class Program
        {
            static void Main(string[] args)
            {
                var secret = "token";
                var path = "/favicon.ico";
                //generate unix timestamp and add one day in seconds - expiry time
                Int32 unixtimestamp = (Int32)(DateTime.UtcNow.AddDays(1).Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
                var expire = Convert.ToString(unixtimestamp);
                var md5 = MD5.Create();
    
                //load string into byte array and hash it
                byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(secret + path + expire));
                //get base64 encoded string
                var md = Convert.ToBase64String(data);
                //"+","/" and "=" are treated as special characters that need to be replaced/removed acordingly:
                md = md.Replace("+", "-").Replace("/", "_").Replace("=", "");
                //resulting secure link:
                Console.Write("http://ZONE.ALIAS.netdna-cdn.com" + path + "?st=" + md + "&e=" + expire);
                Console.ReadLine();
            }
        }
    }
    
  8. .NET/VB

    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.Security.Cryptography
    Module Module1
    
        Sub Main()
    
            Dim secret = "token"
            Dim path = "/favicon.ico"
            'generate unix timestamp and add one day in seconds - expiry time
            Dim unixtimestamp As Int32 = CType(Math.Truncate((DateTime.UtcNow.AddDays(1).Subtract(New DateTime(1970, 1, 1))).TotalSeconds), Int32)
            Dim expire = Convert.ToString(unixtimestamp)
            Dim md5__1 = MD5.Create()
    
            'load string into byte array and hash it
            Dim data As Byte() = md5__1.ComputeHash(Encoding.UTF8.GetBytes(secret & path & expire))
            'get base64 encoded string
            Dim md = Convert.ToBase64String(data)
            '"+","/" and "=" are treated as special characters that need to be replaced/removed acordingly:
            md = md.Replace("+", "-").Replace("/", "_").Replace("=", "")
            'resulting secure link:
            Console.Write("http://ZONE.ALIAS.netdna-cdn.com" & path & "?st=" & md & "&e=" & expire)
            Console.ReadLine()
    
        End Sub
    
    End Module