--- layout: manual_3.4 title: Access Control ---

Access Control

Authentication

To enable HTTP Basic authentication on image and information endpoints, set the following configuration keys:

{% highlight properties %} endpoint.public.auth.basic.enabled = true endpoint.public.auth.basic.username = myusername endpoint.public.auth.basic.secret = mypassword {% endhighlight %}

Authorization

A custom delegate method can be used to implement authorization logic ranging from simple to complex. The method will be invoked upon every image request. Depending on its return value, it can either:

The delegate method is named authorized?(). A skeleton with documented parameters and return values is present in the delegates.rb.sample file. By default, it just returns true, authorizing all requests.

Notes

Examples

Inspect the parameters

This method will print the method arguments to the console.

{% highlight ruby %} module Cantaloupe def self.authorized?(identifier, full_size, operations, resulting_size, output_format, request_uri, request_headers, client_ip, cookies) puts "identifier: #{identifier}" puts "full_size: #{full_size}" puts "operations: #{operations}" puts "resulting_size: #{resulting_size}" puts "output_format: #{output_format}" puts "request_uri: #{request_uri}" puts "request_headers: #{request_headers}" puts "client_ip: #{client_ip}" puts "cookies: #{cookies}" true end end {% endhighlight %}

Allow only requests for half-scale images or smaller

{% highlight ruby %} module Cantaloupe def self.authorized?(identifier, full_size, operations, resulting_size, output_format, request_uri, request_headers, client_ip, cookies) scale = operations.select{ |op| op['class'] == 'Scale' }.first if scale max_scale = 0.5 return scale['width'] <= full_size['width'] * max_scale and scale['height'] <= full_size['height'] * max_scale end false end end {% endhighlight %}

Allow only requests for identifiers matching a certain pattern

{% highlight ruby %} module Cantaloupe def self.authorized?(identifier, full_size, operations, resulting_size, output_format, request_uri, request_headers, client_ip, cookies) # Allow only identifiers that don't include "_restricted" return !identifier.include?('_restricted') # Allow only identifiers that start with "_public" return identifier.start_with?('public_') # Allow only identifiers matching a regex return identifier.match(/^image[5-9][0-9]/) end end {% endhighlight %}

Allow only requests for images set as "public" in a MySQL database

(You will need to install the MySQL JDBC driver first.)

Note: The parameters passed to authorized? are not guaranteed to be safe. identifier, for example, will be exactly as the application receives it. Prefer prepared statements over string concatenation in order to reduce vulnerability to injection attacks.
{% highlight ruby %} module Cantaloupe def self.authorized?(identifier, full_size, operations, resulting_size, output_format, request_uri, request_headers, client_ip, cookies) require "rubygems" require "jdbc/mysql" require "java" authorized = false Java::com.mysql.jdbc.Driver url = "jdbc:mysql://HOST/DATABASE" conn = java.sql.DriverManager.get_connection(url, "USERNAME", "PASSWORD") stmt = conn.create_statement begin query = %q{SELECT is_public FROM image WHERE identifier = ? LIMIT 1} stmt = conn.prepare_statement(query) stmt.setString(1, identifier); result_set = stmt.execute_query while result_set.next do authorized = result_set.getBoolean(1) end ensure stmt.close conn.close end authorized end end {% endhighlight %}

Allow only JPEG output

{% highlight ruby %} module Cantaloupe def self.authorized?(identifier, full_size, operations, resulting_size, output_format, request_uri, request_headers, client_ip, cookies) output_format['media_type'] == 'image/jpeg' end end {% endhighlight %}

Allow only certain user agents

This is not foolproof—if a client knows what User-Agent you are checking for, they can spoof it.
{% highlight ruby %} module Cantaloupe def self.authorized?(identifier, full_size, operations, resulting_size, output_format, request_uri, request_headers, client_ip, cookies) agent = request_headers.select{ |h, v| h.downcase == 'user-agent' }.first agent.start_with?('MyAllowedUserAgent/') end end {% endhighlight %}

Allow only requests that supply a valid token in a header

{% highlight ruby %} module Cantaloupe def self.authorized?(identifier, full_size, operations, resulting_size, output_format, request_uri, request_headers, client_ip, cookies) headers['X-MyToken'] == ... # write code to authorize the token end end {% endhighlight %}

Restrict a region of an image

In this example, requests for images containing any part of the bottom right quadrant of the source image will be denied.

(Also see redaction.)

{% highlight ruby %} module Cantaloupe def self.authorized?(identifier, full_size, operations, resulting_size, output_format, request_uri, request_headers, client_ip, cookies) crop = operations.select{ |op| op['class'] == 'Crop' }.first if crop max_x = full_size['width'] / 2 max_y = full_size['height'] / 2 return !(crop['x'] + crop['width'] > max_x and crop['y'] + crop['height'] > max_y) end false end end {% endhighlight %}

Redirect to another URL

{% highlight ruby %} module Cantaloupe def self.authorized?(identifier, full_size, operations, resulting_size, output_format, request_uri, request_headers, client_ip, cookies) { 'location' => 'http://example.org/some-other-url', 'status_code' => 302 } end end {% endhighlight %}