Security

As always, our first goal is to make analytics via API powerful but simple. We want to make your life as easy as possible. Like any good service, Keen IO takes security seriously. Unfortunately, there’s a direct conflict between ease-of-use and security. Effectively securing an API almost always means making that API harder to use.

There’s not a lot of room for compromise here. A system is either following cryptographic best practices or it’s not. We follow best practices. That being said, we want you to be happy. Please let us know if you’re not!

API Keys

When you get your account, you’ll notice there are 3 different API Keys.

  • Master Key - The most powerful API key. It can be used to authenticate for any API call. It is required to perform administrative functions, such as deleting data.
  • Write Key - An API key specifically for writing data. Any API request that writes data to Keen IO can use this.
  • Read Key - An API key for querying and extracting data. Used to run analyses and extract data from Keen IO.

SSL

All HTTP requests to Keen IO should be done over SSL. SSL is the industry standard for securing HTTP traffic. Our website defaults to HTTPS and we do not recommend non-SSL (HTTP) traffic to our API.

SSL secures everything in the HTTP payload, which includes potentially sensitive information (like your project ID), and definitely sensitive information (like your API Key).

Protecting Your API Key

Your Keen IO Master Key, along with your username and password, is the holy grail of Keen IO. If you have that, you have access to all Keen IO API features. This includes querying data, changing data, and even deleting data.

Never give your Master Key to anybody. Keen IO team members will never ask you for it. And you should never expose the Master Key to your users. So, just to be clear - be careful with it! :)

Luckily, you’ll never need to expose your API Key. Read on for more details.

Client Security

Keen IO is used prominently in many clients (iOS, Android, Mobile Web, Desktop Web, etc.). Just like other analytics services, you embed a snippet of code into your application or site, and that snippet includes some identification about your account. At Keen IO, that’s your Project ID.

An unfortunate truth about client security is that any code embedded into a client is inherently not secure. The source can be viewed, decompiled, or unobfuscated. Or the binary itself can be analyzed. What this means is that you should NEVER embed secure credentials in your clients.

Keen IO breaks down its access paths into two modes - writing and reading. Writing, or sending events, requires your Project ID and a Write Key. Reading, or doing analyses, requires your Project ID and a Read Key. If you’re only using one of our clients to add events, don’t include your Read Key. And if you’re only using a client to do analyses, don’t include your Write Key.

The important thing here is that the Master API Key is NEVER required for the most common use cases. You should never embed your Master API Key in a client.

Server Security

Unlike a client, you can actually secure your servers (go you!). This means you’re free to embed your Master API Key in your source code or configuration. One of the easiest ways to make sure your API Key never gets leaked is to proxy all API requests between your clients and Keen IO servers through your own servers. But maintaining a proxy is annoying and can get expensive as you grow (not to mention it’s a potential single point of failure). We have a solution to that.

Protecting Your Data

Let’s say you want to use the Keen IO JavaScript SDK both to collect data from, and give charts to, your users. You’ll have the following security concerns:

  • How do I prevent somebody from sending events to Keen IO?
  • How do I prevent a customer from performing administrative operations in Keen IO?
  • How do I make sure customer A can’t read customer B’s data?

Securing Writes

There’s no way to both allow clients to send data to Keen IO and prevent a malicious user of a client from sending bad data. This is an unfortunate reality. Google Analytics, Flurry, KissMetrics, etc., all have this problem.

The bright side of this is that Keen IO requires a Write Key to write data. And we can disable a write key if it’s being misused in some way. What this means for you is that you have more control over how data is being written to your Keen IO project.

Securing Administrative Operations

At Keen IO, only requests authenticated using your Master API Key can perform administrative operations (things like deleting data, creating new saved queries, etc.). So the simple answer is to NEVER give your Master API Key to anybody and to never expose it in a client. Because sending data to Keen IO doesn’t require your Master API Key, this is usually simple. But what if you also want to let your clients read data?

Securing Queries

Keen IO queries can only be done by authenticated users. A request can be authenticated by two mechanisms:

  1. Your API Key. This is appropriate if your requests are issued from your server. Otherwise you’ll be exposing your API Key, which is bad!

  2. A Scoped Key. This is a special API key that is generated on your server (we generate one for you automatically when you create your project). It applies filters you define to any query that is run while using that Scoped Key. This is helpful if you’re trying to expose data to your users, but you don’t want them to have access to anyone else’s data. The process of generating a Scoped Key is below.

Scoped Keys and Security

Encryption

Keen IO leans on industry standards. What we do is encrypt a payload using AES-256-CBC and send that encrypted payload in place of an API Key. Here’s the general flow:

This process is long and pretty boring. We write it up here so as not to have any secrets and so you can implement it yourself if you want. But this has been added to all our server-side SDKs as a simple convenience method. So use one of those before dealing with it yourself!

  1. Create a Security Options JSON object which includes the filters you wish to apply to your API calls, as well as what operations you want to grant.

    {
        "filters": [{
           "property_name": "account_id",
            "operator": "eq",
            "property_value": 123
      }],
    "allowed_operations": [ "read" ]
    }
    
  2. Serialize the JSON to a string.

  3. Encrypt the stringified JSON using AES-256-CBC. Use your API Key as the AES key. This will also require a cryptographically secure random Initial Value/Initialization Vector (IV). The IV exists to seed the encryption algorithm to make it harder for hackers to crack the cipher. You basically just need to generate 16 random bytes that come from a good random number generator. Make sure to save the IV - you’ll need it later.

    Some details - AES-256 requires a 32-byte key, a 16-byte IV, and that the plaintext to be encrypted is padded to a 32-byte increment. Keen IO supports the industry-standard PKCS7 padding scheme.

  4. Convert your IV to hex and the result of your encryption (the cipher text) to hex as well.

  5. Append the cipher text to your IV. So you’ll end up with a string that logically looks like:

    hexed_iv + hexed_cipher_text

  6. Take that string and use it in place of your API Key.

  7. Keen IO will see this and automatically use your filters in all queries, right alongside the filters defined on those queries themselves. So, for example, your client could issue a general Count query on your “purchases” Event Collection and it would only return the number of purchases done by the current user.

Notes on Scoped Keys

Depending on how you generate it, a Scoped Key can either do writes or reads (or both). It can never do admin operations (like deleting data or listing project metadata). Access is determined by the value you include for the “allowed_operations” key. Its value should be a list of strings. Valid values are “read” and “write”. So you could generate a Scoped Key where “allowed_operations”: [“read”, “write”] and it will support both operations. If you do not include “allowed_operations”, we assume you only want a Read Key.

At the end of the day, the ONLY thing a Scoped Key can do is what you tell it to do. But it can’t delete data and it can’t perform any admin requests. So rest easy knowing that giving your user a Scoped Key is secure.

If you regenerate your API keys, all scoped keys created using the old master key will be invalidated. Therefore, you’ll need to generate all new scoped keys using your newly generated master API key.

When To Generate a Scoped Key

To make this easier for our users, we’ve automatically generated both a Write and a Read Key. They’re listed on your project details page right next to your API Key. Feel free to use these.

If you’re serving analytics to your users, you’ll want to either generate a Scoped Key on every request or you can do it once when a user/account is created in your application. Just keep the created key in your User or Account table and serve it to your clients as appropriate.

Note that AES encryption, while not incredibly CPU-intensive, is still more CPU-intensive than nothing. So if you’re working on something with a lot of traffic, you may want to generate your Scoped Keys only once.

Client Support

Our server-side SDKs (Ruby, Python, Java, Node.js) have built-in methods to make generating a Scoped Key a one-line affair. Our goal is to make this work as transparent as possible. If you’re frustrated by this, we’ve failed. Please let us know so we can make it right for you! Contact us!