BexioApiClient (bexio_api_client v1.0.0)
base functionality like refreshing the access token.
The API Documentation for Bexio can be found under https://docs.bexio.com.
Fields or arguments with date time reference expect them in the time zone Europe/Zurich.
requirements
Requirements:
- Http Client: ** Req: the api client depends on Req.
refresh-tokens
Refresh tokens
Bexio does not currently rotate refresh tokens — the same refresh token keeps
working — and the access token refresher does not manage rotation. Token
responses expose the refresh_token through access_token/3 anyway, so if
Bexio ever enables rotation (a Keycloak realm option), host applications can
persist the new token from the map and pass it to new/3 themselves.
Hammering the token endpoint with failing refreshes can get the OAuth client
blacklisted by Bexio (per IP), which is why failed refreshes are backed off
instead of retried.
Link to this section Summary
Functions
Fetches a token response from the Bexio (Keycloak) token endpoint.
Creates a new client using the never ending all powerful API Token.
Creates a new client using the client id, client secret and refresh token. Be aware that getting this information is part of the OpenID flow which is not in the scope of this library.
Removes all expired access tokens from the ETS table.
Link to this section Functions
access_token(refresh_token, client_id, client_secret)
@spec access_token(String.t(), String.t(), String.t()) :: {:ok, %{ :access_token => String.t(), :expires_in => integer(), optional(:refresh_token) => String.t() | nil, optional(:id_token) => String.t() | nil, optional(:scope) => String.t() | nil, optional(:token_type) => String.t() | nil }} | {:error, {:unexpected_response, integer(), any()}} | {:error, {:request_failed, any()}}
Fetches a token response from the Bexio (Keycloak) token endpoint.
arguments
Arguments:
refresh_token-> the refresh token we need the access token forclient_id-> the client id of our application that also got the refresh tokenclient_secret-> the client secret of our application
response
Response
On success, the full token map is returned, including the refresh_token the
response contains (Bexio currently keeps refresh tokens stable — the same
token comes back).
{:ok, %{access_token: "", expires_in: 3600, id_token: nil, refresh_token: nil, scope: nil, token_type: nil}}Every non-success response (including 2xx with an unexpected body) returns the
status and body and logs the full Req.Response, so failures can be
classified afterwards:
{:error, {:unexpected_response, 403, %{"reason" => "blacklisted", "status" => "blocked"}}}Transport failures return:
{:error, {:request_failed, exception}}This function never retries on its own; retry policy belongs to
BexioApiClient.Req.AccessTokenRefresher.
new(api_token)
@spec new(String.t()) :: Req.Request.t()
Creates a new client using the never ending all powerful API Token.
new(client_id, client_secret, refresh_token, opts \\ [])
@spec new(String.t(), String.t(), String.t(), keyword()) :: Req.Request.t()
Creates a new client using the client id, client secret and refresh token. Be aware that getting this information is part of the OpenID flow which is not in the scope of this library.
Additional opts are passed to BexioApiClient.Req.AccessTokenRefresher.attach/2,
e.g. on_refresh_gave_up: {module, function, args}.
remove_expired_access_tokens()
Removes all expired access tokens from the ETS table.