title: Does this (small) snippet of code correctly prevent API KEY timing attacks? (RoR)
body: <p>I am implementing API KEY authentication/authorization for an API project I am creating. I am making use of the <code>authenticate_or_request_with_http_token</code> method call and guarding against timing attacks. I read about timing attacks for the first time and I've tried to implement that safe guard in my <code>ApplicationController</code>. I believe I have the mechanism done correctly but would like confirmation. Here is the snippet of code.</p>
  <pre><code>before_action :authenticate_request
  
  def authenticate_request
    authenticate_or_request_with_http_token do |token, options|
      api_key = ApiKey.find_by(access_token: token)
      secret_key = ApiKey.find(api_key.id).secret_key
      api_key.present? &amp;&amp; (api_key.active != false) &amp;&amp; secure_compare_with_hashing(api_key.secret_key, secret_key)
    end
  end
  
  def secure_compare_with_hashing(key1, key2)
    ActiveSupport::SecurityUtils.secure_compare(key1, key2)
  end
  </code></pre>
  <p>Basically, I am 1). Finding the Api key by the token submitted in the header, 2). I am then finding using the id of the api_key to retrieve the secret key. 3). I am comparing the secret key of both values for time constant comparison.</p>
  <p>If I am not mistaken, I believe that this should satisfy the successful mitigation of timing attacks. Am I correct in this?</p>
  <p>====== update ======</p>
  <p>For context, I am using this resource to address the timing error <a href="https://devblast.com/r/master-ruby-web-apis/clients-authentication#cid5" rel="nofollow noreferrer">Timing Attack Prevention</a>. Here is a small paragraph quote from the online book.</p>
  <blockquote>
  <p>The way we implemented the API key is vulnerable to timing attacks. That’s why many web APIs come with an access key and a secret key. The access key can be used to find the record in the database before doing a secure comparison of the secret keys.</p>
  </blockquote>
  <blockquote>
  <p>In order to check whether or not an API key is valid in a safe way, we need to retrieve the database record without using the actual token. Indeed, doing a SQL query like ApiKey.where(key: 'abc') is vulnerable to timing attacks.</p>
  </blockquote>
  <blockquote>
  <p>To avoid this, we can ask the client to provide us with another way to find the record, for example by sending the key id. We would end up with receiving api_key=1:abc instead of api_key=abc, where 1 is a API key id.</p>
  </blockquote>
  <blockquote>
  <p>For a real-world application, we should have created a new field to save an access key instead of using the id.</p>
  </blockquote>
  <p>Here is the code that I am trying to adapt.</p>
  <pre><code>module Authentication
    include ActiveSupport::SecurityUtils
    # Hidden Code
  
    included # Hidden Code
  
    private
  
    def validate_auth_scheme # Hidden Code
    def unauthorized! # Hidden Code
    def authorization_request # Hidden Code
  
    def credentials
      @credentials ||= Hash[authorization_request.scan(/(\w+)[:=] ?&quot;?([\w|:]+)&quot;?/)]
    end
  
    def api_key
      @api_key ||= compute_api_key
    end
  
    def compute_api_key
      return nil if credentials['api_key'].blank?
  
      id, key = credentials['api_key'].split(':')
      api_key = id &amp;&amp; key &amp;&amp; ApiKey.activated.find_by(id: id)
  
      return api_key if api_key &amp;&amp; secure_compare_with_hashing(api_key.key, key)
    end
  
    def secure_compare_with_hashing(a, b)
      secure_compare(Digest::SHA1.hexdigest(a), Digest::SHA1.hexdigest(b))
    end
  
  end
  </code></pre>
  <p>Does my code not properly follow this procedure? Ignoring the problm case where my code doesn't return the key, does the comparison of the secret_key make sense?</p>
  <p>For example,</p>
  <pre><code>api_key = ApiKey.find_by(access_token: token) #Timing attack :(
  </code></pre>
  <p>I get the secret key using the api_key that I found.</p>
  <pre><code>secret_key = ApiKey.find(api_key.id).secret_key
  </code></pre>
  <p>Timing attack circumvented.</p>
  <pre><code>secure_compare_with_hashing(api_key.secret_key, secret_key)
  </code></pre>