[Rails] Implementing an API token for post requests 

(Everyday Code – instead of keeping our knowledge in a README.md let’s share it with the internet)

At the BuildIn3D platform we provide clients with API to send certain HTTP POST requests. Questions is – how do we authenticate them.

Here is one of the authentication steps – we implemented our own build_token. When authenticity_token for CSRF is available we also use the authenticity_token. But it is not always available because the authenticity_token depends on the session and the session cookie. But there might not be a session and a cookie in some cases and yet we still need some authentication. Here is how we do it.

Generate a Unique encrypted token on the server side

The server generates a token based on pass params. This could be username or password or other info.

    def to_build_token
      len   = ActiveSupport::MessageEncryptor.key_len
      salt  = Rails.appplicaton.secret_build_token_salt
      key   = ActiveSupport::KeyGenerator.new(Rails.application.secret_key_base).generate_key(salt, len)
      crypt = ActiveSupport::MessageEncryptor.new(key)
      encrypted_data = crypt.encrypt_and_sign(self.build_id)

This will return a new token that has encrypted the build_id.

encrypted_data = crypt.encrypt_and_sign(self.build_id)
# We could easily add more things to encrypt, like user, or some params or anything you need to get back as information from the token when it is later submitted

Given this token we can pass this token to the client. The token could expire after some time.

We would require the client to send us this token on every request from now on. In this way we know that the client has authenticated with our server.

Decryption of the token

What we are trying to extract is the build_id from the token. The token is encrypted so the user can not know the secret information that is the build_id.

def self.build_id_from_token token
  len   = ActiveSupport::MessageEncryptor.key_len
  salt  = Rails.application.secret_salt_for_build_token
  key   = ActiveSupport::KeyGenerator.new(Rails.application.secret_key_base).generate_key(salt, len)
  crypt = ActiveSupport::MessageEncryptor.new(key)

Requiring the param in each post request

When a post request is made we should check that the token is available and it was generated from our server. This is with:

  def create
      build_token = params.require("build_token")
      build_id_from_token = Record.build_id_from_token(build_token)
      .... # other logic that now has the buid_id token

The build token is one of the things we use with the IS at BuildIn3D and FLLCasts.

Polar bear approves of our security.