Security

Want some extra security? We got you.


Why?

By default, signed URLs aren't necessary. When you add a image source on your dashboard, ImageBoss already act as a safe proxy to your private images, enabling you to deliver your images without exposing the origin of your sources to the internet.

But there are some use-cases where you don't want to allow users to change the original URL or remove any parameters. If you deliver a image with a Watermark you might want to project the real image behind it.

If this is your case, you can enable this feature for your image source on your Dashboard.

Enabling Signed URLs

1) When you are creating or editing a source on your Dashboard (Dashboard ⟶ Sources). At the bottom of your form, check the field "I want extra security. My URLs needs to be signed".
2) A Secret Token will be displayed. This is the secret you need to sign your URLs.

Be careful if your are editing an existing source. If your are already deliverying images to your users with this source make to setup the tokens first. You can just copy your secret and activate it later.


Signing your URLs

In case you are using a language we currently don't have a official client you can still generate your token. It's HMAC SHA-256 token generated based on the PATH of your image URL.

Ruby

ImageBoss for Ruby
client = ImageBoss::Client.new(source: 'mysecureimages', secret: '<MY_SECRET>')
image_url = client.path('/images/img01.jpg').operation(:width, width: 100)

//=> https://img.imageboss.me/mysecureimages/width/100/images/img01.jpg?bossToken=ff74a46c7228ee4262c39b8d501c488293c5be9d433bb9ca957f32c9c3d844ab

Plain Ruby
require 'openssl'
secret = '<YOUR_SECRET>'
imagePath = '/mysecureimages/width/500/01.jpg'
bossToken = OpenSSL::HMAC.hexdigest('sha256', secret, imagePath)

Node.js

const crypto = require('crypto');
const secret = '<YOUR_SECRET>';
const hmac = crypto.createHmac('sha256', secret);
const imagePath = '/mysecureimages/width/500/01.jpg';
const bossToken = hmac.update(imagePath).digest('hex');

PHP

$secret = '<YOUR_SECRET>'
$imagePath = '/mysecureimages/width/500/01.jpg'
$bossToken = hash_hmac('sha256', $imagePath, $secret)

Now all you need to do is add a Query String parameter on your URL called bossToken:


Expiring signed URLs

You can also create time-limited signed URLs. Add an expires parameter with a Unix timestamp (in seconds) and compute the bossToken using both the path and this timestamp. After that time the URL becomes invalid and the response is not cached beyond the expiration time.


expires only controls the validity of the link; it does not purge the cached master images and assets associated with it. To clean the cache, see the Caching section.


Parameters

  • bossToken query string parameter that contains the HMAC-SHA256 signature of the URL in hex. Required when using signed URLs.

  • expires optional query string parameter with a Unix timestamp in seconds indicating when the token becomes invalid. Omit for non-expiring URLs.


How to compute the token (expiring URLs)

Use the same secret and path as above. For time-limited links, concatenate the path and the expires timestamp with a pipe (|) before signing:

payload   = path + '|' + expires  # expires = Unix timestamp (seconds)
bossToken = HMAC-SHA256(secret, payload)  # hex

Example URL (valid for 1 hour):

https://img.imageboss.me/mysecureimages/width/500/images/photo.jpg?bossToken=abc123...&expires=1735689600

Example (Node.js)

const crypto = require('crypto');

const path = '/mysecureimages/width/500/images/photo.jpg';
const secret = '<YOUR_SECRET>';
const expires = Math.floor(Date.now() / 1000) + 3600; // 1 hour from now

const payload = `${path}|${expires}`;
const bossToken = crypto
  .createHmac('sha256', secret)
  .update(payload)
  .digest('hex');

const url = `https://img.imageboss.me${path}?bossToken=${bossToken}&expires=${expires}`;

CDN Caching

When expires is used, cache headers respect the same expiration date instead of the default. URLs that only use bossToken (without expires) keep their current caching behavior.