Skip to content

OAuth 2.0

Tip: If other Appfigures users don’t need to log in to your integration, use Personal Access Tokens instead. They take less work to implement than full OAuth 2.0 support.

With OAuth 2.0, your integration can access the API on behalf of you or another Appfigures user without handling passwords.

Most languages and frameworks have OAuth 2.0 packages. If you use one, configure it with your API Client’s client_key (also called client_id) and client_secret, plus the Authorization and Token endpoints below.

  • Client Registration: https://appfigures.com/developers/keys
  • Authorization Endpoint: https://api.appfigures.com/v2/oauth2/authorize
  • Token Endpoint: https://api.appfigures.com/v2/oauth2/access_token
  • Token Revocation Endpoint: https://api.appfigures.com/v2/oauth2/revoke (rfc7009)
  • Token Introspection Endpoint: https://api.appfigures.com/v2/oauth2/tokeninfo (rfc7662)
  • Supported Grant Types: authorization_code only. (rfc6749 4.1)

The following scopes are supported: account:read, account:write, products:read, products:write, public:read, public:write, private:read, private:write

Both the Authorization and Token Endpoints require a redirect_uri. It must match a redirect URL set up in your Appfigures API Client. It MUST be an https URL in production. Query string parameters are supported, but they must match exactly too. To set up redirect URLs, go to My API Keys and select a client to edit.

We don’t normalize the redirect_uri, so the value you send must exactly match a redirect URL in the API Client configuration.

Out of Band Flows: If you must support an out-of-band flow, use urn:ietf:wg:oauth:2.0:oob as the redirect_uri. We’ll show the user a token to paste back into your application.

The access_token from the Token Endpoint doesn’t expire. We don’t issue a refresh_token. You can revoke the access_token with the Token Revocation Endpoint or on your Key Management page.

To authenticate API calls, pass the bearer from the Token Endpoint in the Authorization header: Authorization: Bearer THE_TOKEN. Here’s an example with the token t_1234:

curl -H"Authorization: Bearer t_1234" "https://api.appfigures.com/v2/"

The examples below assume:

  1. The Client ID is client_id_1234 and the Client Secret is client_secret_abcd.
  2. The desired scopes are account:read private:read products:write.
  3. The redirect_uri is https://mydomain.com/oauth_callback.

Each OAuth 2.0 flow needs a randomly generated state. It lets you verify that your client isn’t being tricked into accepting a token for or from an attacker. You can also use it to match the two legs of the flow.

In this example, the state is state_wxyz. Send a request to the Authorization Endpoint with response_type=code, the client_id, the redirect_uri, the desired scope and the generated state.

GET https://api.appfigures.com/v2/oauth2/authorize?response_type=code&client_id=client_id_1234&redirect_uri=https%3A%2F%2Fmydomain.com%2Foauth_callback&scope=account%3Aread%20private%3Aread%20products%3Awrite&state=state_wxyz

Response (to Appfigures, where the user approves the request)

302 Temporary Redirect
Location: (appfigures.com)

Response (after approval, we redirect the user back to your application)

302 Temporary Redirect
Location: https://mydomain.com/oauth_callback?code=code_5678&state=state_wxyz

Error

302 Temporary Redirect
Location: https://mydomain.com/oauth_callback?error=invalid_scope&error_description=scopes%20cannot%20exceed%20scopes%20configured%20in%20api%20client&state=state_wxyz

2. Verifying the Results of the Authorization Request

Section titled “2. Verifying the Results of the Authorization Request”

Once the user approves your application’s request, we redirect them back to your redirect_uri with two added parameters, state and code. You MUST verify that state matches the state you generated in step 1. The URL looks like this: https://mydomain.com/oauth_callback?code=code_5678&state=state_wxyz.

If there’s an error, you’ll get error and error_description parameters instead, as documented in rfc6749 4.1.2.1. If we can’t verify the redirect_uri or client, we show the user a message.

3. Exchanging the Intermediate Code for an access_token

Section titled “3. Exchanging the Intermediate Code for an access_token”

Exchange the code from step 2 for an access_token. You’ll use it to make requests on behalf of the authorizing user. Make an application/x-www-form-urlencoded POST request to the Token Endpoint with grant_type=authorization_code, the code obtained from step 2, and the redirect_uri given in step 1.

The easiest way to authenticate your API client here is to send your client_id and client_secret as the HTTP Basic username and password. You can send client_id and client_secret in the request body instead, but we don’t recommend it.

>> Request
POST https://api.appfigures.com/v2/oauth2/access_token
Authorization: Basic Y2xpZW50X2lkXzEyMzQ6Y2xpZW50X3NlY3JldF9hYmNk
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=code_5678&redirect_uri=https%3A%2F%2Fmydomain.com%2Foauth_callback
<< Sample Success Response
200 OK
Content-Type: application/json
{
"token_type": "bearer",
"access_token": "access_token_rstu",
"scope": "account:read"
}
<< Sample Error Response
400 Bad Request
Content-Type: application/json
{"error": "invalid_request", "error_description": "redirect_uri does not match"}

Use the access_token from the Token Endpoint response to authenticate requests to the API.

>> Request
GET https://api.appfigures.com/v2/
Authorization: Bearer access_token_rstu
<< Response
200 OK
{
"status": "200",
"message": "OK",
"see": "https://docs.appfigures.com/api",
"version": "2.0",
"user": {
"id": 42,
"name": "Test User",
"email": "test@test.com",
"avatar_url": "https://secure.gravatar.com/avatar/dbe9de53f77958ee4ff7e19697a58990?d=mm"
},
. . . snip . . .
}
>> Request
POST https://api.appfigures.com/v2/oauth2/tokeninfo
Authorization: Basic Y2xpZW50X2lkXzEyMzQ6Y2xpZW50X3NlY3JldF9hYmNk
Content-Type: application/x-www-form-urlencoded
token=access_token_rstu
<< Response
200 OK
{
"active": true,
"scope": "account:read",
"client_id": "client_id_1234",
"username": "test@test.com"
}
>> Request
POST https://api.appfigures.com/v2/oauth2/revoke
Authorization: Basic Y2xpZW50X2lkXzEyMzQ6Y2xpZW50X3NlY3JldF9hYmNk
Content-Type: application/x-www-form-urlencoded
token=access_token_rstu
<< Response
200 OK
{}