JWT Authentication

GeckoForm uses JSON Web Tokens for API authentication.


Preparation

Create an API user

It is best practice to create a dedicated user for accessing the API. This isn't essential but brings a number of benefits.

  • Security - using a specific user group allows you to limit the permissions the API users have.
    This is similar to not giving admin access to a user who doesn't need it. Note: You can further limit the permissions for each API token you create.
  • Transparency - by using a dedicated API user any data modifications will be attributed to the API user.
    This can be useful in the event that any unexpected changes are made.
  • Reliability - by using a dedicated API user you protect them from a number of scenarios where access may be interrupted.
    This can include if the user leaves the team or their permissions are changed/removed.

To create a dedicated API user:

  1. Create an 'API Users' user group and give it only the permissions your application will need.
  2. Create a new user in this group using a strong password.
  3. Keep a note of this password in a secure location such as a password manager.

Storing the token

Because JWTs are short-lived you will need to refresh them periodically. This will require your implementation to store the replacement token after each refresh.

You may choose to use a service, such as AWS Secrets Manager, which can automatically rotate secrets.

 

Getting a JWT

Managing API Tokens

These steps assume you are logged in as the dedicated API user.

You can see your existing sessions and create API tokens from your Security Preferences: View Active Sessions.
Or when logged in to GeckoForm from the the user menu select "Security Preferences" then "Active Sessions".

Creating a new token

  1. Select "Create New API Token"
  2. Give your new token a descriptive name so you can identify it in the future
  3. Select the profile that you wish to generate API access for and continue to the next step
  4. Select the permissions your new token will need.
    You should only grant the necessary permissions for the task your API token will be carrying out.
    Note: Selecting permissions the user doesn't have will have no effect.
  5. Now that you have created your API Token you can copy the Access, ID, and Refresh tokens for use in your application.
    You should store these securely and treat them like your password.

Decoding Your JWTs

You can examine the contents of a JWT manually using jwt.io.

Javascript example
const accessToken = 'eyJ0eXAiOi...SJVshYBNjP25g'
const expiresAt = JSON.parse(atob(accessToken.split('.')[1])).exp;

You may want to use a third party package to make decoding your tokens super simple. We recommend jwt-decode.

import jwt_decode from "jwt-decode";

const accessToken = 'eyJ0eXAiOi...SJVshYBNjP25g';
const decodedAccessToken = jwt_decode(accessToken);

 

Accessing the API

The JWT comes in three parts: ID, Access, and Refresh.

To access the GeckoForm API resources you must use the Access token.

The API region is included in your Access Token. To get your GeckoForm account's region simply decode your Access Token and use the value from the region property.

Once you have determined your region you can use one of the following API urls:

eu use - https://api-eu.geckoform.com
us-e use - https://api-us-e.geckoform.com

Pass your encoded Access Token to the API using the Authorization header, prefixed with Bearer. For example:

cURL example
curl '{regionUrl}/forms?per_page=15' \
    -H 'Accept: application/json' \
    -H 'Authorization: Bearer eyJ0eXAiOi...SJVshYBNjP25g' # Access Token
Javascript example
import jwt_decode from "jwt-decode";

const accessToken = 'eyJ0eXAiOi...SJVshYBNjP25g';
const region = jwt_decode(accessToken).region;
const regionUrl = `https://api-${region}.geckoform.com`;
fetch(`${regionUrl}/forms?per_page=15`, {
    headers: {
        'Authorization': `Bearer ${accessToken}` # Access Token
    }
});

 

Refreshing your JWT

JWT are valid for a fixed amount of time (generally 1 day for API tokens). After this time a new JWT must be obtained using the Refresh token. The Refresh token will also expire (generally after 30 days for API tokens).

When the JWT is refreshed all three parts will be regenerated with new expiry times. If the token is not refreshed before the refresh token expires it will be revoked. The tokens can be refreshed at any time before the refresh token expires (you can continue to use the original Access token until it expires). You should refresh your token early to ensure uninterrupted API access.

🚨 Important

When you use the refresh token you MUST update all three parts of your JWT with the replacement token.

You can only use a refresh token once. If you do not store the new JWT your application will stop working once your original token expires. If this happens you can copy the latest tokens from the API users Active Sessions

Check if a refresh is due

The payload of each token contains an 'expires at' field called exp. This contains a unix timestamp of the last second when the token is valid.

The ID, Access, and Refresh can all have different expiry times. In most cases the Refresh token is valid far longer than the ID or Access tokens.

To refresh your tokens you need to use a separate API url to interact with the GeckoAuth service: https://account-api.geckoengage.com

 

Example refresh request

cURL example
curl 'https://account-api.geckoengage.com/tokens/refresh' \
    -H 'Accept: application/json' \
    -H 'Authorization: Bearer eyJ0eXAiOi...SJVshYBNjP25g' # Refresh Token
Javascript example
fetch('https://account-api.geckoengage.com/tokens/refresh', {
    headers: {
        'Authorization': 'Bearer eyJ0eXAiOi...SJVshYBNjP25g' # Refresh Token
    }
});

Example response

You will receive replacement ID, Access, and Refresh tokens.

{
    "AccessToken": "eyJhbGciOiJS...gpMsaKDEtbA",
    "IdToken": "eyJhbGciOiJSUz...7TzOGG5MuG5pniIpiV3C7920",
    "RefreshToken": "eyJhbGciOiJSUzI...b6XGfNerz1i4O7PDpCxyh9oWxFCk",
    "ExpiresIn": 1617638510,
    "TokenType": null
}