API Authentication for Ruby

Hey there!

I am developing an integration on my Ruby On Rails app to Fireblocks, following the information here. However I would like to know if anyone have alternatives like APIs for Ruby, or some starting point?

I have checked this project on github, but it’s very old and not compatible with the latest version of the API.

Anyone has any hints of how to start on authentication in Ruby?

Thanks!

Hey @juliomonteiro !

A good starting point can be reviewing how the official SDKs create the JWT object. You can find the implementation in Python here and in JavaScript here. I’m also seeing that the 3rd-party Ruby project implements the JWT creation in the token.rb file.

Just out of curiosity, is there a reason you would prefer to build a Ruby integration rather than use the official SDKs? Thanks!

Hey there, thanks for the references @yoji!

I found another source that may help, using openapi-generator.tech, and generating ruby code, but I am still strugling with JWT generation.

I would love to use something else, but my legacy tokenization app is built on RoR. There is an internal company project for porting it to another language in the future, but its quite huge, so it will take a while, when we have priority for switching.

For now, my only option is to stick to Ruby, or maybe build a nodejs middleware.

Thanks again!
Julio

Hello there!

So, I still having issues connecting, after trying many alternatives, I switched to the basic approach:

Here’s my call to the API:

def create_fireblocks_account
      Thread.new do
        url = URI("#{FIREBLOCKS_API_URL}/vault/accounts")

        https = Net::HTTP.new(url.host, url.port)
        https.use_ssl = true

        account_id = "#{@user.id}-#{@deposit.asset_id}"

        data = {
          name: account_id,
          customerRefId: @user_id,
        }

        token = JwtService.call(url, data)

        request = Net::HTTP::Post.new(url)
        request['X-API-Key'] = FIREBLOCKS_API_KEY,
        request["Authorization"] = "Bearer #{token}"
        request["Content-Type"] = "application/json"

        print (request.to_json + "\n")
        print ("===== JSON DATA for #{account_id}-#{@deposit.id}\n")
        print(data)

        request.body = data.to_json

        response = https.request(request)
        puts response.read_body
        # Check the response
        if response.code == '200'
          result = JSON.parse(response.body)
          print("==== Request sucessfull #{result}\n")
        else
          print("==== Request failed with code: #{response.code} #{response}\n")
        end
      end

    end

My class JwTService, is basically a clone of the token.rb link @yoji pointed out:

class JwtService
  class << self
    def call(body, uri)
      new(body, uri).call
    end
  end

  attr_accessor :body, :uri

  def initialize(body, uri)
    @body = body
    @uri = uri
  end

  def request_uri
    URI("#{FIREBLOCKS_API_URL}#{path}")
  end

  def created_at
    Time.now.to_i
  end

  def expire_at
    Time.now.to_i + 55
  end

  def call
    JWT.encode jwt_headers, rsa_private, 'RS256', type: 'JWT'
  end

  def body_hash
    Digest::SHA256.hexdigest(body.to_json)
  end

  def decode_token
    JWT.decode token, rsa_private.public_key, true, algorithm: 'RS256'
  end

  def jwt_headers
    {
      uri: @uri,
      nonce: nonce,
      iat: created_at,
      exp: expire_at,
      sub: FIREBLOCKS_API_KEY,
      bodyHash: body_hash
    }
  end

  def nonce
    "#{Time.now.to_i}#{Time.now.nsec}".to_i
  end

  def rsa_private
    OpenSSL::PKey::RSA.new(File.read(FIREBLOCKS_PRIVATE_KEY))
  end
end

The error I get is: { "message": "Unauthorized: Error getting User certificate: Your key is too long", "code": -7}

The Authentication header becomes: "authorization":["Bearer <1034 characters>"]

Any hints?

Thanks!

Hey @juliomonteiro,

This was brought to my attention by Ricardo.
I added some examples for GET and POST requests here:

Let me know if it solves the issue.

2 Likes

Thank you very much!

Just finished adding that to my code, and I was having an issue, but after I regenerated the secret and api key, it worked.

Thanks!!