Advanced Auth

Websolr features per-request authorization for requests made to your Solr index. This feature is perfect for anyone who needs to guarantee complete cyptographically secure access to their index – or for anyone who wishes to expose their Solr URL for public read-only access while still protecting updates.

Websolr advanced authorization is an opt-in feature available to production-level subscriptions. Upon enabling this feature for your index you, will be issued a secret token. This token is used with the HMAC-SHA1 algorithm as described below.

Enabling Authentication

The Advanced Auth dashboard looks like this:

You can enforce authentication for reads and writes independently, which will generate a unique SECRET for each operation. You can also set a Master Token, which will set the same SECRET for each operation.

When you have enabled authentication for a set of operations, you will see a token for that operation along with some other buttons:

You can regenerate the SECRET for an operation by clicking on the "Regenerate" button, and you can clear the SECRET by clicking on the "Clear" button.

If you set a Master Token, then the SECRET for will be the same for all operations:

You will also be able to regenerate or clear authentication for all operations, or individually. If you have set a Master Token and click on the "Regenerate All" button, it will create a new Master token.

If you have independent SECRETs for different operations, you will see something like this:

You are able set a Master Token, which will create a new SECRET that is the same across all operations. If you click on "Regenerate All," it will create new SECRETs each for read and write operations, preserving their independence.

The "Clear All" button will clear all SECRETs for all operations.

How Does It Work?

The authorization scheme works by including three additional HTTP headers with each request to Solr:

X-Websolr-Time

The current Unix time – seconds since epoch. This value helps to guarantee uniquness over time, and must be within one minute of our server time to prevent replay attacks. (Regex: /[0-9]+/)

X-Websolr-Nonce

Any random non-whitespace string. This value further guarantees the uniqueness of each generated authorization token. (Regex: /\S+/)

X-Websolr-Auth

The hexadecimal HMAC-SHA1 digest of your shared secret and the concatenation of the above time and nonce.

For example, in Ruby:

OpenSSL::HMAC.hexdigest('sha1', SECRET, "#{time}#{nonce}")

Setting your URL

We recommend setting your URL as an environment variable rather than hard-coding it into the app for security reasons. Heroku users will already have a WEBSOLR_URL environment variable set up, and users of other platforms/frameworks should set one up as well. If you’re not on Heroku, then something like this should work:

$ export WEBSOLR_URL="<the URL for your index>"

Websolr uses standard ports for communicating with an index, so we don’t explicitly set those in the URL by default. Most clients can infer the correct port based on the protocol. However, some clients will default to port 80 unless instructed otherwise. This can lead to connectivity problems if the app tries to contact the index over port 80 using TLS/SSL. If you have trouble with this, feel free to set the port manually. We’re using:

  • 443 for HTTPS (TLS/SSL) protocol. This provides end-to-end encryption during data transmission.
  • 80 for HTTP protocol. This is for plaintext data transmission (not recommending if you’re following this guide)

Some examples of valid URLs:

# Plaintext:
$ export WEBSOLR_URL="http://index.websolr.com/solr/a1b2c3d4e5f"
$ export WEBSOLR_URL="http://index.websolr.com:80/solr/a1b2c3d4e5f"

# Encrypted
$ export WEBSOLR_URL="https://index.websolr.com/solr/a1b2c3d4e5f"
$ export WEBSOLR_URL="https://index.websolr.com:443/solr/a1b2c3d4e5f"

Some invalid URLs:

$ export WEBSOLR_URL="http://index.websolr.com:443/solr/a1b2c3d4e5f"
$ export WEBSOLR_URL="https://index.websolr.com:80/solr/a1b2c3d4e5f"

Example with RSolr

require 'rsolr'
rsolr = RSolr.connect :url => ENV['WEBSOLR_URL']

def auth_headers(secret=ENV['WEBSOLR_AUTH'])
  time  = Time.now.to_i
  nonce = Time.now.to_i.to_s.split(//).sort_by{rand}.join
  auth  = OpenSSL::HMAC.hexdigest('sha1', secret, "#{time}#{nonce}")
  {
    'X-Websolr-Time'  => time.to_s,
    'X-Websolr-Nonce' => nonce,
    'X-Websolr-Auth'  => auth
  }
end

# Add a document
rsolr.add { :id => 1, :title => "Hello world" }, { :headers => auth_headers }

# Commit
rsolr.commit :headers => auth_headers

# Search
rsolr.get 'select', :params => { :q => "hello" }, :headers => auth_headers