Image Security with Cloudinary

By  on  

When developers think about security within their web apps, seldom does image security top the list; not because securing media isn't important, of course, but because media security isn't always easy.  Some will even tell you that media security isn't important, but if you want to keep media owner information secure, want to cut down on bandwidth and hotlinking, or simply want credit for the media, it's incredibly important that you take steps to guard media s best you can.

Cloudinary recognizes that their users' media is important and provides various features to help developers keep images secure, watermarked, and used only as intended.  Let's have a look!

Basic Watermarking

The watermarking technique has been used by photographers and stock photo sites since the early days of the internet. There are a few different strategies for watermarking, all of which Cloudinary allows you to control:

  • Watermark in a certain spot over an image
  • Repeated 50% opacity watermark throughout the image
  • Text as watermark

Implementing each of these watermarking techniques is easy with Cloudinary:

Watermark On Image

https://.../l_logo,g_south_east,w_100,x_20,y_20,o_60/v1486595264/ringo.jpg

Repeated Watermark

https://.../l_logo,w_100,x_20,y_20,o_20,fl_relative.tiled/v1486595264/ringo.jpg

Text Watermark

https://.../l_logo,w_100,x_20,y_20,o_20,fl_relative.tiled/v1486595264/ringo.jpg

Invisible Watermarking

My friends at Cloudinary showed me an amazing technique for "invisible watermarking" using low opacity in the blue channel which is hard for the human eye to see.  Consider the following image:

<img src="https://res.cloudinary.com/demo-robert/image/upload/l_text:arial_30_bold_stroke:David%20Walsh%20Blog,bo_15px_solid_rgb:000000,a_45,e_screen,o_7,co_rgb:0000FF,fl_tiled/q_90/234_72_z_qpwsct.jpg">

You probably can't tell but the image above is watermarked.  If you upload this image to your Cloudinary account and applied a blue channel transformation, you would see your watermark as clear as day:

<img src="https://res.cloudinary.com/demo-robert/image/fetch/e_green:-100/e_red:-100/e_auto_contrast/https://res.cloudinary.com/demo-robert/image/upload/l_text:arial_30_bold_stroke:David%20Walsh%20Blog,bo_15px_solid_rgb:000000,a_45,e_screen,o_7,co_rgb:0000FF,fl_tiled/q_90/234_72_z_qpwsct.jpg">

This effect is amazing and a great way to tag your images whilst not adding distracting traditional watermarks. If someone takes a screenshot of your image, the blue technique will still see watermark text!

Token or Cookie-Based Authentication for Transformations

Securing content to a viewer by IP or token is common-place, oftentimes to provide previews of content before it goes live.  Whatever your reason for securing content by ID or token, Cloudinary allows you to limit image render by IP incredibly easily:

// Only allow users at 192.168.0.1 to see the image
cloudinary.image("contract.png", { 
  type: "authenticated",  
  auth_token: {
    key: "_key_", ip: "192.168.0.1"
  }, 
  sign_url: true });

If you're prefer not to isolate by IP (which is incredibly strict), you can instead limit image render to cookie! To secure image to cookie value, you create a CNAME which points Cloudinary, whereby Cloudinary can ensure a cookie is set on your main domain and then serve the image accordingly. Now *that's secure!

Signed URLS

One advantage to using Cloudinary is the ability to create images on the fly by simply modifying the image URL, but there may be times that you want signed image URLs so that additional transformations cannot be added to the image by another party; in that case, you'd use the sign_url parameter to sign an image:

cloudinary.image("yellow_tulip.jpg", {
  sign_url: true,
  width: 300,
  height: 200,
  crop: 'crop',
  gravity: 'center'
});

Which renders an image with a signature:

<img src="https://.../image/upload/s--o1_ZfmFP--/c_crop,g_center,h_200,w_300/yellow_tulip.jpg">

Trying to access a different transformation or including an invalid signature will result in a 401 error response!

Private Images

Cloudinary allows you to set a private parameter when you upload an image:

cloudinary.uploader.upload(
  'sheep.jpg', 
  result => {}, 
  {
    public_id: 'sheep', 
    type: 'private'
  });

Once the image is uploaded, if a user tries to hit a private image directly, it will not display!  If you want to allow the image to only displayed in certain dimensions and other transformations, you'll need to use Cloudinary's management console to create rules for strict transformations of your image:

With your strict image rules in place, you can display just the transformed image with the following URL:

<img src="https://res.cloudinary.com/private-demo/image/private/w_300,h_200,c_fill,r_20/sheep.jpg" alt=""gt;

EXIF Data Removal

Most people don't realize that when you take a photo with any modern photo or camera, the image file contains scores of metadata include where the image was taken, what device the image was taken with, much more.  I recently wrote about getting and removing EXIF data using exiftool, but if you're using a third party to manage or upload user media, you'll want to ensure they remove EXIF data, which Cloudinary does by default for new transformations.

If you'd like to keep metadata, add the keep_iptc flag to the image:

cloudinary.image('sample.jpg', {
  width: 300, 
  flags: 'keep_iptc', // keep EXIF data
  crop: 'scale'
});

I love that EXIF data is saved on raw image uploads but removed on transformed images -- it's the best way to keep your original image while keeping the uploader safe!

Referral-Based Whitelisting

Cloudinary allows you to provide a whitelist for image referrers:

This feature is available for our Premium plans only. In addition, a custom CNAME must be set-up for your account for this to work. You need to let us know the domains you want to be whitelisted for your account and following a short manual configuration on our side, any request for access to an image that does not come from a domain on the whitelist will be denied. Likewise any request for access to an image that comes from a domain on the blacklist will be denied.

If you really want to lock down your images, so as not to incur bandwidth fees, this seems like a really good idea.

There's a common misconception that there's nothing you can do to protect your media and intellectual property, especially when you play it on an external service. In reality, there's a lot you can do to protect media and Cloudinary offers numerous ways to do so. I can't speak highly enough of Cloudinary -- they provide every effect, API, and security set you could ever want!

Recent Features

  • By
    Responsive Images: The Ultimate Guide

    Chances are that any Web designers using our Ghostlab browser testing app, which allows seamless testing across all devices simultaneously, will have worked with responsive design in some shape or form. And as today's websites and devices become ever more varied, a plethora of responsive images...

  • By
    Write Better JavaScript with Promises

    You've probably heard the talk around the water cooler about how promises are the future. All of the cool kids are using them, but you don't see what makes them so special. Can't you just use a callback? What's the big deal? In this article, we'll...

Incredible Demos

  • By
    MooTools FontChecker Plugin

    There's a very interesting piece of code on Google Code called FontAvailable which does a jQuery-based JavaScript check on a string to check whether or not your system has a specific font based upon its output width. I've ported this functionality to MooTools. The MooTools...

  • By
    jQuery Wookmark

    The first thing that hits you when you visit Pinterest is "Whoa, the columns are the same width and the photos are cut to fit just the way they should."  Basic web users probably think nothing of it but as a developer, I can appreciate the...

Discussion

    Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!