Exact.OAuth (exact_online v0.1.0)

Copy Markdown View Source

The OAuth2 authorization code flow for Exact Online.

Register an app in the Exact App Center to get a client id, a client secret and a redirect URI. The flow is:

opts = [
  client_id: client_id,
  client_secret: client_secret,
  redirect_uri: "https://example.com/oauth/callback",
  region: :nl
]

# 1. Send the user to this URL.
Exact.OAuth.authorize_url(opts)

# 2. Exchange the `code` query parameter from the callback.
{:ok, token} = Exact.OAuth.exchange_code(code, opts)

# 3. Later, when the access token has expired.
{:ok, token} = Exact.OAuth.refresh(token.refresh_token, opts)

Store the token after every step. Refresh tokens rotate, see Exact.Token. Exact Online does not use scopes: the app's permissions are configured in the App Center.

Summary

Functions

Builds the URL to send the user to.

Exchanges an authorization code for a token.

Exchanges a refresh token for a new token.

Functions

authorize_url(opts)

@spec authorize_url(keyword()) :: String.t()

Builds the URL to send the user to.

Options:

  • :client_id - required
  • :redirect_uri - required, must match the App Center registration
  • :region - defaults to :nl, see Exact.Region
  • :base_url - overrides :region
  • :state - opaque value returned on the callback, use it against CSRF
  • :force_login - true forces a fresh login screen, defaults to false

exchange_code(code, opts)

@spec exchange_code(String.t(), keyword()) ::
  {:ok, Exact.Token.t()} | {:error, Exact.Error.t()}

Exchanges an authorization code for a token.

Takes the same options as authorize_url/1 plus :client_secret.

refresh(refresh_token, opts)

@spec refresh(String.t(), keyword()) ::
  {:ok, Exact.Token.t()} | {:error, Exact.Error.t()}

Exchanges a refresh token for a new token.

The returned token carries a new refresh token; the one passed in is no longer valid. Persist the result before doing anything else with it.