OAuth V2#

While the official OAuth V2 spec offers lots of options, the flow we respect matches GitHub's and Facebook's implementation of the authorization_code flow.

A complete OAuth V2 example is available on our Formstack example page. Check that out for more detail in a real world example!

Initial Setup#

First, you'll need to select OAuth V2 or OAuth V2 (w/refresh) as your auth type, and then provide the following parameters:

OAuth parameters

We'll automatically create the required access_token and refresh_token (optional) auth fields for you. They look something like this in the developer interface - the access_token field is required at minimum:

Hint: Does your app need to change the URL based on the user's subdomain or domain? Simply add another authentication field (right alongside access_token from the above screenshot) that has the key like subdomain and then use it like https://{{subdomain}}.yourwebsite.com/api/token in all your URLs.

1. Redirecting the User to Your App#

We'll redirect the user to an authorize_url (provided by you), along with a query string which contains a redirect_uri (provided by us), scope (optional, provided by you) and client_id (provided by you).

302 <authorize_url>?client_id=<client_id>&scope=<scope>&redirect_uri=https://zapier.com/dashboard/auth/oauth/return/AppIDAPI/

2. Redirecting the User Back to Zapier#

After the user clicks allow, you should redirect the user to the redirect_uri along with a code parameter in the query string.

Note: Don't hardcode the redirect_uri on your side, as it will change as you deploy new versions of your app. If your app goes public, we'll assign you a permanent ID, but some users may be using older versions even after that point.

302 <redirect_uri>?code=<code>

We use that code to make a POST to the access_token_url (provided by you) along with the code, matching redirect_uri (provided by us), client_id (provided by you), and client_secret (provided by you) as a form encoded request.

POST <access_token_url> \
    -H Accept: application/json \
    -d 'client_id=<client_id>&
        client_secret=<client_secret>&
        code=<code>&
        grant_type=authorization_code&
        redirect_uri=https://zapier.com/dashboard/auth/oauth/return/AppIDAPI/'

Zapier will try two ways to get the token: POST with data in querystring, if that returns a 4xx, we will retry a POST with the data in the form-encoded body. You can always override this behavior with the Scripting though!

While we ask for a JSON response, the response can be JSON, XML or query string encoded as where the value you return is access_token. For example, any of the below are valid responses:

With Content-Type: application/json:

{
  "access_token": "1234567890abcdef",
  "refresh_token": "1234567890abcdef" // optional
}

With Content-Type: application/xml:

<AnyRootElem>
  <access_token>1234567890abcdef</access_token>
  <refresh_token>1234567890abcdef</refresh_token> <!-- optional -->
</AnyRootElem>

With Content-Type: text/plain:

access_token=1234567890abcdef&refresh_token=1234567890abcdef

We automatically pull and store access_token and refresh_token from the JSON, XML, or query string data, but if you want to pull and store more fields, you can set them up in your auth setup under Extra Requested Fields:

3. Authorizing Requests to Your App#

By default, we append the access_token to the querystring for all requests, as well as in an Authorization header, however, you can use scripting to modify request parameters as you see fit (IE: place the access_token in a special header). This is called the bearer token type.

An example of the default with access_token_placement set to header:

GET https://api.example.com/v2/tickets.json \
    -H Authorization: Bearer 1234567890abcdef

And now with access_token_placement set to querystring:

GET https://api.example.com/v2/tickets.json?access_token=1234567890abcdef

4. Refreshing Tokens (optional)#

Optionally, if your app supports refresh tokens, we natively support that.

You'll need to select OAuth V2 (w/refresh) and provide us the refresh_token_url in addition to the previous requirements. When we encounter a 401 status code, we'll attempt to refresh like so:

POST <refresh_token_url> \
    -H Accept: application/json \
    -d 'client_id=<client_id>&
        client_secret=<client_secret>&
        grant_type=refresh_token&
        refresh_token=<refresh_token>'

We will only attempt to refresh an access token when we encounter a 401 status code from your API.

If your API does not signal expired tokens with a 401, use scripting to manually set the status code header to 401 upon conditions of your choosing. Or, you can raise a RefreshTokenException in your post_XXXX function call to kick off a new refresh.

The resulting access_token will be updated in our system and the previous, failed call will be attempted once more.

We prefer and advocate one of two patterns around expiring refresh tokens:

  1. Never expire refresh tokens except on password changes or user revocation.
  2. In the last 10% window of a refresh token's life (IE: last 9 days of a 90 day lifetime), give a brand new refresh_token along with the normal access_token refresh.

We fully support each pattern. While option 1 is definitely more common, option 2 works very nicely and has the effect of eventually cleaning up unused oauth tokens.

If you cannot adhere to one of the above patterns and you app requires manual refresh of tokens on a regular basis, you should check for this condition and notify users via scripting. With throw new ExpiredAuthException('Your reason.');, the current call is interrupted, the zap is turned off (to prevent more calls with expired auth), and a predefined email is sent out informing the user to refresh the credentials.

Some Examples#

We highly recommend looking at each of GitHub's, Facebook's and Podio's (with refresh tokens) authentication documentation for some great examples of how OAuth V2 can be implemented. Our system is designed to match their industry standard implementation pattern.

A complete OAuth V2 example is available on our Formstack example page. Check that out for more detail in a real world example!

↑ Was this documentation useful? Yes No
Get Help