> ## Documentation Index
> Fetch the complete documentation index at: https://www.text.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Accounts SDK

> The Accounts SDK is a JavaScript tool for implementing Sign in with Text authorization in your app.

The **Accounts SDK** (`@livechat/accounts-sdk`) is a JavaScript library that lets you implement the **Sign in with Text** flow — the easiest way to get access to basic information in Text accounts.

The **Sign in with Text** flow lets you:

* Get access to the Text account user's email, account ID, or organization ID.
* Receive an `access_token` that can be used to perform API calls.
* Receive a `code` using the PKCE extension, which could be then used to obtain the account's `refresh_token` and `access_token`.

### User flow

Users start the flow by clicking the **Sign in with Text** button. If a user is not signed in, they'll be asked to do that.

Then, the user must give the app access to the specified parts of their Text account. Finally, the app receives an `access_token` that allows it to perform different API calls, limited to what the user agreed to in the prompt.

## How to start

### Step 1: Create a new app

Go to [Settings → API access → OAuth clients](https://www.text.com/app/settings/integrations/api-access/oauth-clients) and create a new OAuth client. You will receive a new `client_id` to use in the next steps.

The **Redirect URI** field must match the URL of the website that has the **Sign in with Text** button installed. The button will not work with any other URL addresses.

### Step 2: Include the SDK library

Install the SDK from NPM:

```bash theme={null}
npm install --save @livechat/accounts-sdk@^2.0.0
```

```js theme={null}
import AccountsSDK from "@livechat/accounts-sdk";
```

### Step 3: Prepare button container

Prepare the login button, which will invoke the authorization flow when a user clicks it.

```html theme={null}
<div id="login-button" style="background: url(.../livechat_sign_in.png)"></div>
```

```js theme={null}
// javascript
const instance = new AccountsSDK({
  client_id: "<your_app_client_id>",
  redirect_uri: "<your_app_redirect_uri>",
});

document.getElementById("login-button").onclick = (e) => {
  if (e && e.preventDefault) {
    e.preventDefault();
  }

  instance
    .popup()
    .authorize()
    .then((authorizeData) => {
      const transaction = instance.verify(authorizeData);
      if (transaction != null) {
        // authorization success
        // authorizeData contains `accessToken` or `code`
        // transaction contains state and optional code_verifier (code + PKCE)
        console.log("User access token: " + transaction.accessToken);
        document.getElementById("login-button").style.display = "none";
      } else {
        console.log("Redirect state doesn't match the previous one");
      }
    })
    .catch((e) => {
      console.error("Failed to authorize user", e);
    });
};
```

<Tip>
  Use `prompt: "consent"` to force the app to ask you for access to certain
  resources.
</Tip>

## Accounts SDK reference

Following classes and methods are available in the Accounts SDK:

| Class                         | Methods                                                                                               |
| ----------------------------- | ----------------------------------------------------------------------------------------------------- |
| [`AccountsSDK`](#accountssdk) | [`popup()`](#popup) [`redirect()`](#redirect) [`authorizeURL()`](#authorizeurl) [`verify()`](#verify) |
| [`Popup`](#popup-1)           | [`authorize()`](#authorize)                                                                           |
| [`Redirect`](#redirect-1)     | [`authorize()`](#authorize-1) [`authorizeData()`](#authorizedata)                                     |

### AccountsSDK

The main instance of the SDK used to authorize users in Text Accounts.

```js theme={null}
const instance = new AccountsSDK({
  client_id: "<your_app_client_id>",
});
```

The constructor accepts an `options` object with the following properties:

| Property        | Required | Data type | Description                                                                                                                                                                    |
| --------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `client_id`     | yes      | `string`  | Application **Client Id** (available in Text under **Settings → API access → OAuth clients**)                                                                                  |
| `prompt`        | no       | `string`  | Use `consent` to force the consent prompt in a popup and the redirect flows. Default: `''`                                                                                     |
| `response_type` | no       | `string`  | OAuth response type. Possible values: `token` or `code`. Default: `token`                                                                                                      |
| `popup_flow`    | no       | `string`  | `auto` – close the popup automatically if the user is already logged in; `manual` - always show the popup that requires the user to provide their credentials; default: `auto` |
| `state`         | no       | `string`  | OAuth state parameter. Use it for better security.                                                                                                                             |
| `verify_state`  | no       | `bool`    | Check if `state` matches after the redirect; default: `true`                                                                                                                   |
| `scope`         | no       | `string`  | The scopes your application will request from the user; if not provided, then all application scopes will be requested. Comma-separated string, default: `null`                |
| `redirect_uri`  | yes      | `string`  | OAuth redirect URI; default: the current location                                                                                                                              |
| `email_hint`    | no       | `bool`    | Fill in email in forms                                                                                                                                                         |
| `server_url`    | no       | `string`  | Authorization server URL                                                                                                                                                       |
| `tracking`      | no       | `object`  | Object with tracking query string params                                                                                                                                       |
| `transaction`   | no       | `object`  | An object with options for the transaction manager                                                                                                                             |
| `pkce`          | no       | `object`  | An object with the PKCE configuration                                                                                                                                          |

The `transaction` object consists of the following parameters:

| Property              | Required | Data type | Description                                                  |
| --------------------- | -------- | --------- | ------------------------------------------------------------ |
| `namespace`           | no       | `string`  | Transaction key prefix; default: `'com.livechat.accounts'`   |
| `key_length`          | no       | `string`  | Transaction random state length; default: `32`               |
| `force_local_storage` | no       | `bool`    | Try to use localStorage instead of cookies; default: `false` |

In the `pkce` object, define the following configuration properties:

| Property                | Required | Data type | Description                                                                                         |
| ----------------------- | -------- | --------- | --------------------------------------------------------------------------------------------------- |
| `enabled`               | yes      | `bool`    | Enable OAuth 2.1 PKCE extension; default: `true`                                                    |
| `code_verifier`         | no       | `string`  | Override the auto-generated code verifier.                                                          |
| `code_verifier_length`  | no       | `integer` | Define the length of the code verifier. It should be between 43 and 128 characters; default: `128`. |
| `code_challange_method` | no       | `string`  | Define the code challenge method. Possible values: `S256` or `plain`; default: `S256`               |

#### popup

Returns a `Popup` object instance built on top of `sdk`.

| Parameter | Data type | Description                                                     |
| --------- | --------- | --------------------------------------------------------------- |
| `options` | `object`  | An object with the same parameters as provided in `AccountsSDK` |

```js theme={null}
const popup = instance.popup({
  client_id: "<your_app_client_id>",
});
```

#### redirect

Returns a `Redirect` object instance built on top of `sdk`.

| Parameter | Data type | Description                                                     |
| --------- | --------- | --------------------------------------------------------------- |
| `options` | `object`  | An object with the same parameters as provided in `AccountsSDK` |

```js theme={null}
const redirect = instance.redirect({
  client_id: "<your_app_client_id>",
});
```

#### authorizeURL

Creates an authorization URL for the given flow and parameters.

| Parameter | Data type | Description                                                     |
| --------- | --------- | --------------------------------------------------------------- |
| `options` | `object`  | An object with the same parameters as provided in `AccountsSDK` |
| `flow`    | `string`  | `code` or `token`. `code` can only be used with the `PKCE` flow |

```js theme={null}
const authURL = instance.authorizeURL(
  {
    client_id: "<your_app_client_id>",
  },
  "token",
);
```

#### verify

Verifies if the `state` parameter from the redirect matched the one provided upon initialization. If it does, the method returns `Transaction`. Otherwise, it returns `null`.

| Parameter       | Data type | Description                     |
| --------------- | --------- | ------------------------------- |
| `authorizeData` | `object`  | Data returned from the redirect |

```js theme={null}
const transactionData = instance.verify(authorizeData);
if (transactionData) {
  console.log("Verified correctly");
} else {
  console.log("Url/state mismatch");
}
```

### Popup

A class responsible for acquiring the user authorization data through a popup window.

| Parameter | Data type | Description                                                     |
| --------- | --------- | --------------------------------------------------------------- |
| `options` | `object`  | An object with the same parameters as provided in `AccountsSDK` |
| `sdk`     | `object`  | An `sdk` instance                                               |

```js theme={null}
const instance = new AccountsSDK({
  client_id: "<your_app_client_id>",
});

const popup = new Popup(instance, instance.options);
```

A popup object instance can also be created via `sdk`:

```js theme={null}
const popup = instance.popup();
```

#### authorize

Returns a promise that resolves with the user authorization data or an error.

```js theme={null}
popup
  .authorize()
  .then((authorizeData) => {
    console.log("authorize data acquired: " + authorizeData);
  })
  .catch((e) => {
    console.error("Failed to acquire authorization data: " + e);
  });
```

The <a href="https://github.com/livechat/sample-app-popup-auth" target="_blank">Sample app with the popup flow</a> has a fully implemented authorization flow.

### Redirect

A class responsible for acquiring the user authorization data through the `redirect` method.

| Parameter | Data type | Description                                                     |
| --------- | --------- | --------------------------------------------------------------- |
| `options` | `object`  | An object with the same parameters as provided in `AccountsSDK` |
| `sdk`     | `object`  | An `sdk` instance                                               |

```js theme={null}
const instance = new AccountsSDK({
  client_id: "<your_app_client_id>",
});

const redirect = new Redirect(instance, instance.options);
```

A redirect object instance can also be created via `sdk`:

```js theme={null}
const redirect = instance.redirect();
```

#### authorize

Starts the redirect authorization flow.

```js theme={null}
redirect.authorize();
```

#### authorizeData

Checks if a user was redirected to the current origin with the authorization data. Returns a promise that resolves with the user authorization data or an error.

```js theme={null}
redirect
  .authorizeData()
  .then((authorizeData) => {
    console.log("Authorization data acquired: " + authorizeData);
  })
  .catch((e) => {
    console.error("Failed to acquire authorization data: " + e);
    redirect.authorize(); // Try to redirect user to authorization once more
  });
```

The <a href="https://github.com/livechat/sample-app-redirect-auth" target="_blank">Sample app with the redirect flow</a> has a fully implemented authorization flow.

## PKCE support

To acquire both `access_token` and `refresh_token` in a frontend application, use the <a href="https://www.oauth.com/oauth2-servers/oauth-native-apps/pkce/" rel="noopener nofollow" target="_blank">PKCE Extension</a>, which prevents the usage of a hijacked redirect by malicious apps.

1. Start by enabling PKCE. Provide `AccountsSDK` instance with PKCE options:

```js theme={null}
const instance = new AccountsSDK({
  client_id: "<your_app_client_id>",
  redirect_uri: "<your_app_redirect_uri>",
  response_type: "code",
  pkce: {
    enabled: true,
  },
});
```

2. Then, using the `redirect` flow, you're able to receive the `code` authorization data:

```js theme={null}
instance
  .redirect()
  .authorizeData()
  .then((authorizeData) => {
    const transactionData = instance.verify(authorizeData);
    if (transactionData === null) {
      console.log("Failed to verify authorization data");
      return;
    }
    fetch(instance.options.server_url + "/v2/token", {
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      method: "POST",
      body: JSON.stringify({
        grant_type: "authorization_code",
        code: authorizeData.code,
        client_id: transactionData.client_id,
        redirect_uri: transactionData.redirect_uri,
        code_verifier: transactionData.code_verifier,
      }),
    })
      .then((res) => {
        res.json();
      })
      .then((data) => {
        console.log("User tokens: " + data);
      })
      .catch((e) => {
        console.log("Failed to exchange code: " + e);
      });
  })
  .catch((e) => {
    const wasRedirected = sessionStorage.getItem("lc_accounts");
    if (wasRedirected === "yes") {
      console.error("Couldn't authorize user: " + e);
      return;
    }
    sessionStorage.setItem("lc_accounts", "yes");
    instance.redirect().authorize(); // Initiate authorization redirect flow
  });
```

## Response format

All `authorize` methods return the user authorization data on success, or an error on failure.

### Success

| Field             | Returned                        | Description                                                      |
| ----------------- | ------------------------------- | ---------------------------------------------------------------- |
| `access_token`    | only for `response_type: token` | Used for authorizing Text API calls.                             |
| `code`            | only for `response_type: code`  | Must be exchanged for `access_token` and `refresh_token`         |
| `scope`           | for both response types         | An array of scopes that `access_token` has.                      |
| `expires_in`      | for both response types         | Defines for how long `access_token` will be valid.               |
| `account_id`      | only for `response_type: code`  | Text Accounts user ID                                            |
| `organization_id` | only for `response_type: code`  | Text Accounts organization ID to which the account is logged in. |
| `client_id`       | only for `response_type: code`  | `client_id` that you passed in the `init` method.                |

### Error

If the authorization process fails, the promise will be rejected with an error:

```js theme={null}
{
  "oauth_exception": "<exception_name>",
  "identity_exception": "<exception_name>",
  "description": "<exception_description>"
}
```

#### identity\_exception

Possible values:

* `unauthorized` – The resource owner identity is unknown or the consent is missing.

#### oauth\_exception

Possible values:

* `invalid_request` – The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.
* `unauthorized_client` – The client is not authorized to request a token using this method.
* `access_denied` – The resource owner or authorization server denied the request.
* `unsupported_response_type` – The authorization server doesn't support acquiring a token using this method.
