OAuth

Looking for a more general overview of authentication? Check out the Authentication Guide If you’re here to get down and dirty with OAuth (we use 1.0), then you’re in the right place. Also make sure to check out our complete code samples.

URLs and Signature Methods

If you already have experience with OAuth, here’s what you should need to get running with our API.

Consumer Registration URL
https://appfigures.com/developers/keys

Request Token URL
https://api.appfigures.com/v2/oauth/request_token

User Authorization URL
https://api.appfigures.com/v2/oauth/authorize

Access Token URL
https://api.appfigures.com/v2/oauth/access_token

Signature Methods
HMAC-SHA1 or PLAINTEXT

Why use OAuth

In past versions of the API we authenticated using HTTP Authentication. While Basic and Digest modes are both pretty simple and well supported they have one big issue– the user needs to provide his or her credentials to a client directly.

While we know that you take user credentials very seriously, it’s still best to not have to deal with them. OAuth is a system that allows you to authenticate a client without ever seeing the user’s username or password. This is great for everyone. You don’t need to worry about keeping track of user password (a big responsibility) and the user too doesn’t need to worry. The user also has the ability to revoke access to your client remotely, which is great in case of compromised devices and other various misfortunes.

While we still do support HTTP Authentication, it only works if the client and authenticating account are one in the same. That lets you make internal tools more simply, but forces you to use OAuth if you want to make a public facing application.

The Flow

This guide is split into two general sections. The first and most complicated part is obtaining the user’s authorization. Thankfully, this only needs to be once– that is unless a user revokes access. The second part is using that authorization to make requests to protected resources. So to request /products/mine for a user you’ve got to go through the authorization process with that user to have them approve your ability to access that resource. After you have that approval you’re ready to make requests on behalf of that user.

Detour #1: Scopes (Permissions)

It’s good form to minimize the permission that you grant to an application. Scopes allow us to do just that. An API client can request access to just public data or only readonly access to private data. Unfortunately, that’s not something that is canonized in OAuth 1.0, so we’ve added to the spec a bit to get scopes. They can be set up when you create the client credentials and further limited when authorizing. You can read more about scopes here.

Detour #2: A Note on Signatures

OAuth has a couple of different ways to sign signatures. Our API supports HMAC-SHA1 and PLAINTEXT. HMAC-SHA1 signing is pretty complicated compared to PLAINTEXT, but is resistant to replay and forged requests through unsecured transport channels. Since our API only allows you to use HTTPS, we’ll use PLAINTEXT in this example because it’s far simpler and the transport channel itself secures the client’s interaction.

Getting a user’s authorization

Okay, with that out of the way let’s talk about the things that need to happen to make OAuth work:

  1. Obtain a Request Token
  2. Send the user to us so that we can verify their identity and ask them nicely to grant authorization
  3. Exchange the Request Token for an Access Token

When you create an api client in your account you’re given two tokens: a Client Key and Client Secret. You use these to obtain an Request Token and Secret. These are temporary and signify that you are initiating authorization. You then send the user to Appfigures to approve the Request Token, and then trade it in for an Access Token and secret that prove the user’s authorization.

To actually make an authorized request we need 4 things: the Client Key, Client Secret, Access Token, and Access Secret. We have the first two when we create the app. We trade a Request Token/Secret pair for an Access Token/Secret pair after the user authorizes the app.

Obtain request token

The first step in the authentication process is to use your client_key and client_secret to obtain a set of intermediate tokens (oauth_token, oauth_token_secret). Once you get these you can prove that you know both the client key and secret and have expressed intent to initiate an OAuth flow.

Here you can also set a scope to restrict the permissions that your application has. This is done with the X-OAuth-Scope header. It’s totally optional, without giving it your resulting Request Token will inherit the scope that your application was set up with. This feature can only be used to further restrict the permissions of an application, not expand them beyond what was originally selected when creating the application.

https://api.appfigures.com/v2/oauth/request_token is the resource that provides these intermediate Request Token and Secret called oauth_token and oauth_secret respectively. You make a request to it with the following parameters:

  • oauth_consumer_key » your client_key
  • oauth_callback » where the user should be directed in the next phase (or the string ‘oob’ if you want the user to enter the token manually)
  • oauth_signature_method » in this case ‘PLAINTEXT’, could be ‘HMAC-SHA1’
  • oauth_signature » your client_secret and an ampersand (if your client_secret is “dogbert” oauth_signature would be ‘dogbert&’)

These parameters are required, but can be passed to the request_token resource in a variety of ways: as GET parameters, as the data in a form-urlencoded POST, or in the Authorization header of a POST or GET.

Here are the cURL commands to do it in all three ways. For this example the client_key is ‘mykey’ and the client_secret is ‘dogbert’.

    # In the Authorization header
    curl -XPOST 'https://api.appfigures.com/v2/oauth/request_token'\
        -H'Authorization: OAuth oauth_signature_method=PLAINTEXT,
                                oauth_consumer_key=mykey,
                                oauth_callback=oob,
                                oauth_signature=dogbert&'
\
       -H'X-OAuth-Scope: account:read, private:read'
     
   
   
    # In the querystring -- this must be all on one line for you
    curl -XGET 'https://api.appfigures.com/v2/oauth/request_token?
        oauth_signature_method=PLAINTEXT&
        oauth_consumer_key=mykey&
        oauth_callback=oob&
        oauth_signature=dogbert%26'
\
       -H'X-OAuth-Scope: account:read, private:read'
   
    # In the request body with a POST
    curl -XPOST 'https://api.appfigures.com/v2/oauth/request_token' \
        -d'oauth_signature_method=PLAINTEXT' \
        -d'oauth_consumer_key=mykey' \
        -d'oauth_callback=oob' \
        -d'oauth_signature=dogbert%26' \
        -H'X-OAuth-Scope: account:read, private:read'
   
   
    # all three ways return the same result:
    oauth_callback_confirmed=true&oauth_token=myotoken&oauth_token_secret=catbert

Note how the ‘&’ is percent-encoded in the latter two methods. All values that are not letters, numbers, ‘‘, ‘.’, ‘‘, or ‘~’ should be encoded.

Send the user to Appfigures to grant permission

Now that you have a set of oauth_token and oauth_token_secret you can send the user to Appfigures with them to prompt the user to approve your request. This part is pretty easy, just direct the user to https://api.appfigures.com/v2/oauth/authorize?oauth_token=myotoken, where TOKEN is whatever you were given for oauth_token above.

Note: Is the user is already logged into their Appfigures account we’ll automatically send them to the authorization page. If you want your app to force the user to login again append force_login=true to the querystring of your request. This will force the user to enter their credentials in order to approve the app (without logging them out of their Appfigures account).

Receive authorization

Remember oauth_callback from step 1 (Obtain request token)? Well, now it comes into play. When the user approves your request, she is redirected back to whatever you specified in this field. If the callback was given as oob (out-of-band) that means that the user will not be redirected, but rather shown a page with the oauth_verifier that she’ll need to give to your application. How you negotiate that is up to you.

There are two querystring parameters appended to the callback: oauth_token, and oauth_verifier. So if you set your oauth_callback to be http://coolapp.com/oauth_callback and the oauth_verifier is ‘certified’ and the oauth_token is ‘myotoken’, then the user will be redirected to http://coolapp.com/oauth_callback?oauth_token=myotoken&oauth_verifier=certified

Now that you have an oauth_verifier you are ready to exchange the Request Token and Secret that came from oauth_token and oauth_token_secret into an Access Token/Secret pair.

https://api.appfigures.com/v2/oauth/access_token is the resource that provides the final Access Token and Secret called oauth_token and oauth_secret respectively. You make a request to it with the following parameters:

  • oauth_consumer_key » your client_key. In this case: ‘mykey’
  • oauth_token » your Request Token. In this case: ‘myotoken’
  • oauth_verifier » your oauth_verifier. In this case ‘certified’
  • oauth_signature_method » in this case ‘PLAINTEXT’, could be ‘HMAC-SHA1’
  • oauth_signature » your client_secret and Request Secret separated by an ampersand. In this case ‘dogbert&catbert’
    # cURL using the Authorization header scheme
     curl -XGET https://api.appfigures.com/v2/oauth/access_token' \
        -H'
Authorization: OAuth oauth_signature_method=PLAINTEXT,
                                oauth_verifier=certified,
                                oauth_consumer_key=mykey,
                                oauth_token=myotoken,
                                oauth_signature=dogbert&catbert'
   
    # returns
    oauth_token=accesstoken&oauth_token_secret=accesssecret

The Access Token and Secret are returned by this resource much like the Request Token and Key. Now you have all 4 things you need to make a request:

  1. consumer_key (mykey — your Client Key)
  2. consumer_secret (dogbert — your Client Secret)
  3. oauth_token (accesstoken — the Access Token you just were given by /oauth/access_token)
  4. oauth_secret (accesssecret — the Access Key)

Making a request

Say you want your app to get a list of the authenticated user’s products. You’ve already gone through the above process and have all 4 pieces of information you need to make a request: a Client Key, a Client Secret, an Access Token and an Access Secret.

Those 4 pieces of information are given in every request in the Authorization header much like the above uses of the Authorization header.

  • oauth_consumer_key » your client_key. In this case: ‘mykey’
  • oauth_token » your Access Token. In this case: ‘accesstoken’
  • oauth_signature_method » in this case ‘PLAINTEXT’, could be ‘HMAC-SHA1’
  • oauth_signature » your client_secret and Access Secret separated by an ampersand. In this case ‘dogbert&accesssecret’

Then they are all put into an Authorization header like so:

    Authorization:  OAuth oauth_signature_method=PLAINTEXT,
                          oauth_consumer_key=mykey,
                          oauth_token=accesstoken,
                          oauth_signature=dogbert&accesskey

So a request to get a user’s products would look like

    GET https://api.appfigures.com/v2/products/mine HTTP/1.1
    Authorization: OAuth oauth_signature_method=PLAINTEXT,
                         oauth_consumer_key=mykey,
                         oauth_token=accesstoken,
                         oauth_signature=dogbert&accesskey

Or with cURL

     curl -XGET 'https://api.appfigures.com/v2/products/mine' \
        -H'Authorization: OAuth oauth_signature_method=PLAINTEXT,
                                oauth_consumer_key=mykey,
                                oauth_token=accesstoken,
                                oauth_signature=dogbert&accesskey'
  • Mikhail

    Hi there,

    Is there a way to programmatically disconnect an OAuth client? Use case: a user removes the Appfigures connection in our app and we’d like to remove it from that user’s https://appfigures.com/account/api list.

    • https://appfigures.com/ Alex Quick

      Hi Mikhail,

      Unfortunately we don’t have anything like that at the moment. That’s a very good idea though. I’ll see where it can be fit into the development schedule.

      Alex

  • http://joeshaw.org Joe Shaw

    Is there any expiration of access tokens currently? I’d like to provide my app with the access token without needing to add in the whole OAuth authentication flow to it.

  • Dominik Deobald

    I tried to use the HMAC-SHA1 signing method through an preexisting oAuth library and totally failed – it always told me that the signature was wrong. I ended up with PLAINTEXT. Could you give one example request with a working signature so that we can check our libraries against that?

    • alexquick

      Hi Dominik,

      Here are some requests and signatures: https://gist.github.com/alexquick/c5d0b88f1f00c35d1a75

      What client are you using? One issue that once bit me is that we don’t handle duplicate slashes in URLs very well (“https://api.appfigures.com/v2//products/mine”, for example). They are removed before we even get to start calculating the signature, so the signatures won’t match.

      • Dominik Deobald

        I use the PHPoAuthLib library (https://github.com/Lusitanian/PHPoAuthLib), but had to add the PLAINTEXT signature method myself.

        I don’t think there were any double slashes in the URL, but I’ll recheck on friday.

  • http://www.mikebrittain.com/ mikebrittain

    The access token code sample is out of date. Should be:

    
    
     curl -XGET 'https://api.appfigures.com/v2/oauth/access_token'
        -H'Authorization: OAuth oauth_signature_method=PLAINTEXT,
                                oauth_verifier=certified,
                                oauth_consumer_key=mykey,
                                oauth_token=myotoken,
                                oauth_signature=dogbert&catbert'

    • alexquick

      Good catch, thanks!

  • Will Townsend

    Is there a way to get the users email address with this method? It’s needed to get the information about the user with the api/users/{email} call. Or is there an API call that will return user information if the client is logged in via oAuth?