API Authentication

The Vanilo REST API can only be accessed after authentication.

The authentication subsystem is an implementation of the Bearer Token specification which is a subset of the OAuth 2.0 standard.

Authorization Workflow

  1. Authenticate the user: Receive tokens.
  2. Call your API: Use the retrieved Access Token to call your API.
  3. Refresh Tokens: Use a Refresh Token to request new tokens when the existing ones expire.

Authentication

To begin the flow, you need to have a user of type API and their username and password.

The users of the REST API are stored in the same list of users where the "admin" users are.

The consumers of the REST API are not human but applications, thus only users of type api are allowed to authenticate against the REST API.

Login

Use the /api/1.0/auth/login endpoint to authenticate the user and receive tokens.

You need to pass the following parameters to the login endpoint:

  • client_id - The email address of the API user
  • client_secret - The password of the API user

The request data must be POST and sent with application/x-www-form-urlencoded encoding.

If all goes well, you'll receive an HTTP 200 response with a payload containing access_token, refresh_token, expires_in, and token_type values:

{
  "access_token": "eyJhbGciOiJIVCJ9.eyJixjM0NTY3ODkwIioNSiW0jxTyT5TyCjIxOTI3MjJ9.kOkTVr4rPq5wiv2WgbBqUQ",
  "token_type": "Bearer",
  "expires_in": 9000,
  "refresh_token": "eyJhbR5cCI6IkXV9.ezdWIiOzNSwiaWF0IjoxNTYyMTg5MOjE1NjU5MsdDMsw.lFlaJqxPP4xX-c3wWACjvO"
}

The returned access token can be used for calling the API.

Calling The API

The access and refresh tokens are JWT encoded credentials.

To use the token to call the api you have to pass it as the Authorization HTTP header in your request:

Authorization: Bearer eyJhbGciOiJIVCJ9.eyJixjM0NTY3ODkwIioNSiW0jxTyT5TyCjIxOTI3MjJ9.kOkTVr4rPq5wiv2WgbBqUQ

Refreshing Tokens

Access tokens have a limited lifetime, specified in seconds in the expires_in field of the login response.

When the Access Token expires you'll receive an HTTP 401 response with the message:

{
    "message": "Expired token. Use the refresh token to get a new one"
}

Using the Refresh Token, you can get a new access token. Make a POST request to the /1.0/auth/token endpoint with the following parameter:

  • refresh_token - The refresh token you've received in the initial login request.

The request data must be sent with application/x-www-form-urlencoded encoding.

If all goes well, you'll receive an HTTP 200 response with the same content as at login:

{
  "access_token": "eyJhbGciOiJIVCJ9.eyJixjM0NTY3ODkwIioNSiW0jxTyT5TyCjIxOTI3MjJ9.kOkTVr4rPq5wiv2WgbBqUQ",
  "token_type": "Bearer",
  "expires_in": 9000,
  "refresh_token": "eyJhbR5cCI6IkXV9.ezdWIiOzNSwiaWF0IjoxNTYyMTg5MOjE1NjU5MsdDMsw.lFlaJqxPP4xX-c3wWACjvO"
}

It's bad practice calling the endpoint to get a new Access Token every time you call an API. Auth endpoints are rate limited that will restrict the amount of requests allowed.

Refresh tokens must be stored securely since they allow a user to remain authenticated for a very long period (1 year unless differently configured).

Refresh tokens have an extended lifecycle, 1 year by default. Once a refresh token expires you'll get an HTTP 401 response when invoking the token endpoint. In this case you need to invoke the login endpoint again to obtain a new access and refresh token.

Configuration

The lifetime of tokens (in seconds) can be configured.

Access Token Lifetime

Configuration entry api.auth.access_token.ttl: defaults to 90000 (sec), ie. 25 hours. To use a custom value, set a different value in config/api.json:

{
  "auth": {
    "access_token": {
      "ttl": 604800 
    }
  }
}

Refresh Token Lifetime

Configuration entry api.auth.refresh_token.ttl: defaults to 31708800 (sec), ie. 367 days. To use a custom value, set a different value in config/api.json:

{
  "auth": {
    "refresh_token": {
      "ttl": 63417600 
    }
  }
}

JWT Token Signature

The tokens are being cryptographically signed and verified. The signing key is being read from the api.auth.token_signature configuration. It has a default setting that can be changed in the config/api.json file:

To use a custom signing key, set some long, random sequence of
characters that only the server knows.

! Changing the API signing key will invalidate every existing API token.

config/api.json:

{
  "auth": {
    "token_signature": "D!3@a83cMtLKzI=B19bKlJWLvJCyf/FUg|5H3e+CjE0cvIAXlcjdsCOjknQgrk"
  }
}