Skip to content

Instantly share code, notes, and snippets.

@AntonNguyen
Last active July 22, 2016 05:38
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AntonNguyen/5583949 to your computer and use it in GitHub Desktop.
Save AntonNguyen/5583949 to your computer and use it in GitHub Desktop.

The OAuth Dance with FreshBooks

Terminology

  • User - The FreshBooks account, whose information we are trying to access via OAuth
  • Consumer - The FreshBooks account, who we authorize to access the user's information
  • Consumer key - The consumer's subdomain, consumer_key.freshbooks.com
  • Consumer Secret - The consumer's secret, that we will use to make OAuth requests.
  • Request Token - A value used by the consumer to obtain authorization and an access token from the user.
  • Access Token - A value used by the consumer to access the user's information.
  • Access Token Secret - A secret used by the consumer to establish ownership of a given Token.
  • Callback URL - URL you want the user to be redirected to, after the user authorization step.
  • Nonce - A nonce is a random string, uniquely generated for each request.
  • Timestamp - The current number of seconds since January 1, 1970 00:00:00 GMT.

Before you start

Gain OAuth access for your consumer account

  1. On your FreshBooks account, go to "My Account", then "FreshBooks API".
  2. Enable OAuth under the "OAuth Developer Access" section:
  3. Fill out the authorization form:
  4. Once you've gained access, you'll see your Consumer Secret.

Find a FreshBooks account, whose information you'll be accessing

This can be any FreshBooks account, even the consumer account.

The 4-Step OAuth Dance

Obtaining an OAuth Request Token

  1. Make sure the following parameters are set on the Authorization header:
  • OAuth realm=""
  • oauth_version="1.0"
  • oauth_consumer_key="<CONSUMER_SUBDOMAIN>"
  • oauth_timestamp="<TIMESTAMP>"
  • oauth_nonce="<NONCE>"
  • oauth_signature_method="PLAINTEXT"
  • oauth_signature="<CONSUMER SECRET>%2526"
  • oauth_callback="<CALLBACK URL>"
  1. Make a POST to the following URL: https://<USER SUBDOMAIN>.freshbooks.com/oauth/oauth_request.php
  2. You'll receive a response from the server with both an oauth_token and an oauth_token_secret. Make sure you store those two values somewhere.

Obtaining User Authorization

  1. The user has to now authorize the consumer to access their data, so the user has to open up the following url in a browser: https://<USER SUBDOMAIN>.freshbooks.com/oauth/oauth_authorize.php?oauth_token=<oauth_token>
  2. If the oauth_token is valid, the user will be asked to sign in and allow access.
  3. You'll receive a verifier, which you should store.
  • If a <CALLBACK_URL> was defined, the user will be redirected to the URL with the verifier as a query string: <CALLBACK_URL?verifier=<VERIFIER_VALUE>
  • If a <CALLBACK_URL> was not defined, the <VERIFIER_VALUE> will be displayed on the page.

Obtaining an OAuth Access Token

  1. You'll be making another post now, to get your Access tokens. Make sure you swap out the right values on the Authorization header:
  • OAuth realm=""
  • oauth_version="1.0"
  • oauth_consumer_key="<CONSUMER_SUBDOMAIN>"
  • oauth_timestamp="<TIMESTAMP>"
  • oauth_nonce="<NONCE>"
  • oauth_signature_method="PLAINTEXT"
  • oauth_signature="<CONSUMER SECRET>%2526"
  • oauth_token="<OAUTH_TOKEN>"
  • oauth_verifier="<VERIFIER_VALUE>"
  1. Make a POST to the following URL: https://<USER SUBDOMAIN>.freshbooks.com/oauth/oauth_access.php
  2. You'll finally receive a response from the server with newoauth_token and an oauth_token_secret values. Make sure you store those two values somewhere.

Accessing User Data

  1. You're now able to make API calls with OAuth! Make sure you swap out the right values in the Authorization header:
  • OAuth realm=""
  • oauth_version="1.0"
  • oauth_consumer_key="<CONSUMER_SUBDOMAIN>"
  • oauth_timestamp="<TIMESTAMP>"
  • oauth_nonce="<NONCE>"
  • oauth_signature_method="PLAINTEXT"
  • oauth_signature="<CONSUMER_SECRET>%2526<OAUTH_TOKEN_SECRET>"
  • oauth_token="<OAUTH_TOKEN>"
  1. Make a POST to the following URL: https://<USER SUBDOMAIN>.freshbooks.com/api/2.1/xml-in

OAuth Dance Example

Here's an example using purely curl commands. Today's consumer will be darthvader.freshbooks.com, who will be trying to access rebels.freshbooks.com's data.

Obtaining an OAuth Request Token

  1. Preparing our authorization header
  • oauth_consumer_key: darthvader
  • oauth_timestamp: 1368630669
  • oauth_nonce: UU7gRl0HDdt
  • oauth_signature: G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526
  1. Posting to https://rebels.freshbooks.com/oauth/oauth_request.php with the following values in our Authorization header:
$ curl -k -H 'Authorization: OAuth realm="",oauth_version="1.0",oauth_consumer_key="darthvader",oauth_timestamp="1368630669",oauth_nonce="UU7gRl0HDdt",oauth_signature_method="PLAINTEXT",oauth_signature="G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526",oauth_callback=""' -X POST https://rebels.freshbooks.com/oauth/oauth_request.php
  1. Which gives us the following response:
oauth_token=ezRLfnwqT4euejh3eFZr5w5UsGmcTqp2&oauth_token_secret=SSF4aRtvFEEX9wBWqebrfpskufHrLtU7V&oauth_callback_confirmed=true

Obtaining User Authorization

  1. Using the obtained oauth_token, I open up the following URL in my browser: https://rebels.freshbooks.com/oauth_oauth_authorize.php?oauth_token=ezRLfnwqT4euejh3eFZr5w5UsGmcTqp2

  2. Since I didn't provide a callback_url, the verifier was right on the page for me: fsVZcfYq8vv7pJzKfzk96cswXuGBpKiRu

Obtaining an OAuth Access Token

  1. Preparing our authorization header
  • oauth_consumer_key: darthvader
  • oauth_token: ezRLfnwqT4euejh3eFZr5w5UsGmcTqp2
  • oauth_timestamp: 1368630857
  • oauth_nonce: bDu0qrocMxD
  • oauth_signature: G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526
  • oauth_verifier: fsVZcfYq8vv7pJzKfzk96cswXuGBpKiRu
  1. Posting to https://rebels.freshbooks.com/oauth/oauth_access.php
$ curl -k -H 'Authorization: OAuth realm="",oauth_version="1.0",oauth_consumer_key="darthvader",oauth_token="ezRLfnwqT4euejh3eFZr5w5UsGmcTqp2",oauth_timestamp="1368630857",oauth_nonce="bDu0qrocMxD",oauth_signature_method="PLAINTEXT",oauth_signature="G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526",oauth_verifier="fsVZcfYq8vv7pJzKfzk96cswXuGBpKiRu"' -X POST https://rebels.freshbooks.com/oauth/oauth_access.php
  1. Which gives us the following response:
oauth_token=KsT3w4xPpYLd3dTEsRDv7RvvBGy8X36Mv&oauth_token_secret=MnfWWC4ZHiuEe52v7feuBH9FdfRce9rxC

Accessing User Data

  1. Preparing our authorization header
  • oauth_consumer_key: darthvader
  • oauth_token: KsT3w4xPpYLd3dTEsRDv7RvvBGy8X36Mv
  • oauth_timestamp: 1368631017
  • oauth_nonce: ddtCiqS5nlZ
  • oauth_signature: G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526MnfWWC4ZHiuEe52v7feuBH9FdfRce9rxC
  1. Making a post to https://rebels.freshbooks.com/api/2.1/xml-in:
$ curl -k -H 'Authorization: OAuth realm="",oauth_version="1.0",oauth_consumer_key="darthvader",oauth_token="KsT3w4xPpYLd3dTEsRDv7RvvBGy8X36Mv",oauth_timestamp="1368631017",oauth_nonce="ddtCiqS5nlZ",oauth_signature_method="PLAINTEXT",oauth_signature="G6A9YrCrdizGDdtyWU9FgrAP795KL5baj%2526MnfWWC4ZHiuEe52v7feuBH9FdfRce9rxC"' -X POST https://rebels.freshbooks.com/api/2.1/xml-in -d '<request method="invoice.list" />'
  1. Which gives us the following response:
<?xml version="1.0" encoding="utf-8"?>
<response xmlns="http://www.freshbooks.com/api/" status="ok">
  <invoices page="1" per_page="25" pages="1" total="1">
    <invoice>
      <invoice_id>00000248946</invoice_id>
      <organization>Princess Leia</organization>
      <first_name>Leia</first_name>
      <last_name>Organa</last_name>
      <lines>
        <line>
          <line_id>1</line_id>
          <name>Death Star Plans</name>
          <unit_cost>10000000000000000.00</unit_cost>
          <quantity>1</quantity>
          <amount>10000000000000000.00</amount>
          <type>Item</type>
        </line>
      </lines>
    </invoice>
  </invoices>
</response>
@AlfredomZ
Copy link

Hi Anton

I find your article more interesting.

My questions are:
1.) Under the Find a FreshBooks account(above), when I created my Account and I have setup an Accountant and Staff (under People Tab), Do they qualify as a FreshBook Account?

I think I have the same case for Robert J you'd answered from this link: https://groups.google.com/forum/#!topic/freshbooks-api/SOFTZJSb9DM

2.) I was able to successfully simulate all your steps except for the last one: Accessing User Data
I am using google's postman as a debugger... I'm trying to pull the client's list (...e.g.) I am getting
an (20010) Authentication failed error.

Your answer is very much appreciated.
Thank you

Regards;
Alfred

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment