BunnyCDN Support Hub

Guides, troubleshooting and support requests to help you get started with BunnyCDN.

How to set up CDN URL Token Authentication

URL Token Authentication allows you to generate secure URLs that expire after the set timestamp and are only accessible using a token generated using a secret key and an expiry timestamp. This guide will explain how to set up the CDN URL Token Authentication on BunnyCDN.

Step 1: Enable URL Token Authentication on your Pull Zone

To generate the secure token, you will first need to enable URL Token Authentication in the Dashboard and then copy your Token security key from the URL Token Authentication box.

Step 2: Generate the URL

To create a secure URL, you must add a token and expires query parameters to the URL that you want to access. The expires parameter is the UNIX timestamp marking until when the URL is accessible. After this passes, the URL will no longer be accessible.

The token parameter is a Base64 encoded MD5 hash based on the key, URL and any extra parameters. To generate the token, you can use the following algorithm. 

MD5(token_security_key + url_path + expiration). To properly format the token you have to then replace the following characters in the resulting Base64 string: '\n' with '', '+' with '-', '/' with '_' and '=' with ''

An example secure URL will then look like:

https://test.b-cdn.net/assets/favicon.ico?token=m0EMEkV3pNAKFB33gZuv_Q&expires=1456761770 

Code examples:

To make things easier, we also provide code examples for most popular languages below.

PHP Example

$securityKey = 'token_security_key';
$path = '/pathto/file.jpg';

// Set the time of expiry to one hour from now
$expires = time() + 3600; 

// Generate the token
$hashableBase = $securityKey.$path.$expires;

// If using IP validation
// $hashableBase .= "146.14.19.7";
$token = md5($hashableBase, true); $token = base64_encode($token); $token = strtr($token, '+/', '-_'); $token = str_replace('=', '', $token); // Generate the URL $url = "https://myzone.b-cdn.net{$path}?token={$token}&expires={$expires}";

C# .NET Example

var securityKey = "token_security_key";
var path = "/pathto/file.jpg";

// Load the current time
var unixBaseTime = new DateTime(1970,1,1,0,0,0,0,System.DateTimeKind.Utc);
var currentTime = ((long)(DateTime.UtcNow - unixBaseTime).TotalSeconds);

// Set the time of expiry to one hour from now
var expires = currentTime + 3600; 

// Generate the token
System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();

string hashableBase = securityKey + path + expires;

// If using IP validation
// hashableBase += "146.14.19.7";

byte[] outpufBuffer = md5.ComputeHash(Encoding.UTF8.GetBytes(hashableBase));
var token = Convert.ToBase64String(outpufBuffer);
token = token.Replace("\n", "").Replace("+", "-").Replace("/", "_").Replace("=", "");

// Generate the URL
var url = $"https://myzone.b-cdn.net{path}?token={token}&expires={expires}";

Node.JS JavaScript Example

var crypto = require('crypto'),
securityKey = 'token_security_key',
path = '/pathto/file.jpg';

// Set the time of expiry to one hour from now
var expires = Math.round(Date.now() / 1000) + 3600;

var hashableBase = securityKey + path + expires;

// If using IP validation
// hashableBase += "146.14.19.7";

// Generate and encode the token
var md5String = crypto.createHash("md5").update(hashableBase).digest("binary");
var token = new Buffer(md5String, 'binary').toString('base64');
token = token.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');

// Generate the URL
var url = 'https://myzone.b-cdn.net' + path + '?token=' + token + '&expires=' + expires;

Python Example

#!/usr/bin/env python3
import hashlib
from base64 import b64encode
from time import time

def generate_secure_url(security_key, path,
                        expire_timeframe=3600,
                        base_url=str(),
filtered_ip=""): """Generate BunnyCDN URL authentication token. Arguments: security_key (str): Generated token from the panel. path (str): /path/to/file.ext, with the initial slash included. expire_timeframe (int): Time until expiry, in seconds. base_url (str): CDN's base URL of the site, without ending slash. filtered_ip: The IP that should be included in the hash. Use this if doing IP validation.
Returns: str: URL """ expire_timestamp = int(time()) + 3600 token_content = '{key}{path}{timestamp}{filtered_ip}'.format(key=security_key,path=path,timestamp=expire_timestamp) md5sum = hashlib.md5() md5sum.update(token_content.encode('ascii')) token_digest = md5sum.digest() token_base64 = b64encode(token_digest).decode('ascii') token_formatted = token_base64.replace('\n', '').replace('+', '-').replace('/', '_').replace('=', '')
// Build the URL url = '{base_url}{path}?token={token}&expires={expire_timestamp}'.format( base_url=base_url, path=path, token=token_formatted, expire_timestamp=expire_timestamp) return url # Example usage: // Returns: '/index.html?token=IuNSzXOiYkL-LmGJcwxMQg&expires=1488672404' generate_secure_url('super-secret-code', '/index.html') // Returns: 'https://test.b-cdn.net/index.html?token=EuS4D8fFlTrT6zO4FymvUw&expires=1488672453' generate_secure_url('super-secret-code', '/index.html', 31536000, 'https://test.b-cdn.net')

5 Comments

  • 1
    Avatar
    Daniel Lo Nigro

    With .NET 4.6 or .NET Core, you can use DateTimeOffset.Now.AddHours(1).ToUnixTimeSeconds() instead of having to define that unixBaseTime variable.

  • 0
    Avatar
    User 009ea

    Does this feature allow partial suffix files to use Token, while other suffix files are unrestricted?

  • 0
    Avatar
    User 2bad3

    Is it possible to support the folder depth with token ? How to work with m3u8 file ? M3u8 has so many ts file inside and now it is not allow to access from m3u8.

  • 0
    Avatar
    Dejan Grofelnik Pelzel

    We are currently preparing the documentation for Token Version 2 which allows country code blocking, improved hashing security, and directory-based tokens. We hope to release this soon.

  • 0
    Avatar
    User 009ea

    When is directory based tokens expected to be released?

Please sign in to leave a comment.