Pratham Majithia
Pratham Majithia

Reputation: 15

How to handle the Invalid Grant error in a ruby service?

I'm working on a Rails application integrated with the NetDocuments API, where multiple users access a single service account. The API uses single-use refresh tokens to obtain new access tokens. According to the NetDocuments documentation, a refresh token expires as soon as it's used, and a new refresh token is provided in the response. I keep getting an invalid grant error once every few months: unexpected token at 'Invalid grant'

The challenge arises because the application has multiple threads or processes that may try to refresh the token simultaneously, leading to race conditions and invalid grant errors.

Here is my current refresh token logic:

def self.netdocuments_credential
  credential = Credential.find_by(kind: 'netdocuments')

  if credential.present? && Time.now > credential.expires_at
    resp = Faraday.post("#{API_BASE_URL[get_data_region]}/v1#{TOKEN_PATH}") do |req|
      authorization_string = Base64.encode64("#{CLIENT_ID[get_data_region]}:#{CLIENT_SECRET[get_data_region]}").gsub(/\n/, '')
      req.headers['Authorization'] = "Basic " + authorization_string
      req.body = { grant_type: "refresh_token", refresh_token: credential.refresh_token }
    end

    begin
      response_body = JSON.parse(resp.body)
      access_token = response_body["access_token"]
      refresh_token = response_body["refresh_token"]
      credential.update!(
        token: access_token,
        refresh_token: refresh_token,
        expires_at: Time.now + 3600
      )
    rescue JSON::ParserError => e
      credential.destroy
      Rails.logger.error "Failed to parse response from NetDocuments: #{e.message}"
      raise StandardError, "NetDocuments: Please login again."
    end
  end

  credential
end

The application uses one central credential, with multiple users using the same Service Account. My Questions: 1.) How can I handle token management to ensure that the refresh token is only used once, even in a multi-threaded or multi-process environment? 2.) I think I might be making a mistake with how I am refreshing the token. I am manually setting a 1 hour expiry when I should be only refreshing when the access token fails. Is that why this could be causing an invalid grant error?

I tried handling the error and deleting the credential, but I want a more graceful logic to make sure this does not happen often and I am confident in its working.

Upvotes: 0

Views: 43

Answers (0)

Related Questions