> ## 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.

# Custom Identity Provider

> Learn how to use custom identity to build cross-platform chats for your applications.

**Custom Identity Provider** was created for those who build more advanced integrations that handle user sessions. It allows you to match customer identities in Text with those stored in your service. As a result, your customers will never lose chats they had with your support. What is more, if you also use Text on other platforms (for example, in mobile applications), customer conversations will sync, making the communication even more seamless and natural.

From the technical perspective, *custom identity* is an ID assigned to each customer by our API. Based on that ID, we can match customer data and chat history with a specific person using our services. *Custom identity* is not customer metadata such as name or email. If you would like to pass one of those, you are probably looking for [updating session variables](/api/chat-widget-js-api/methods#update-session-variables).

The Custom Identity Provider routes all of your widget traffic through the [Customer Chat API](/api/customer-chat/). All requests from such implementation count toward your API usage and fall under the standard [API pricing](/getting-started/api-pricing).

## Setup

Custom Identity Provider is essentially a singleton function.

```js theme={null}
// Custom Identity Provider
function () {
    return {
        getToken: ...,
        getFreshToken: ...,
        hasToken: ...,
        invalidate: ...
    }
}
```

You can define it as a part of the [LiveChatWidget object](https://platform.text.com/docs/extending-chat-widget/javascript-api/#getting-started) from the tracking code used to install the Chat Widget on your website or from any other place with access to the `window.__lc` object (in case of more advanced applications). However, **it has to be provided before widget initialization**.

```js theme={null}
window.__lc.custom_identity_provider = function () {
    return {
        getToken: ...,
        getFreshToken: ...,
        hasToken: ...,
        invalidate: ...
    }
}
```

You can also use it with [Customer SDK](https://platform.text.com/docs/extending-chat-widget/customer-sdk#using-the-api) if you build your own chat widget implementation. Pass it through the optional `identityProvider` parameter of the configuration object.

```js theme={null}
const customerSDK = CustomerSDK.init({
    licenseId: LICENSE_ID,
    clientId: CLIENT_ID,
    identityProvider: function () {
        return {
            getToken: ...,
            getFreshToken: ...,
            hasToken: ...,
            invalidate: ...
        }
    }
})
```

## Methods

In order to make Custom Identity Provider work, you'll have to properly implement and provide a set of following methods:

* `getToken` - resolving [Chat Widget token](#chat-widget-token). If you want to cache the token, this should return the cached token instead of a fresh request to `https://accounts.livechat.com/customer/token` endpoint.
* `getFreshToken` - resolving [Chat Widget token](#chat-widget-token). This should always make a call for a fresh token from `https://accounts.livechat.com/customer/token` endpoint.
* `hasToken` - resolving boolean. It determines whether a token has been acquired.
* `invalidate` - resolving nothing. When called, it should remove the current token. There is no need to do anything else as a new token will be requested by `getFreshToken` afterward.

All of the above will have to be returned in a function assigned to `window.__lc.custom_identity_provider`.

## Chat Widget token

The authorization token to resolve in functions should contain the following properties:

| Parameter      | Description                                                                       |
| -------------- | --------------------------------------------------------------------------------- |
| `accessToken`  | A token you can use to call the Text APIs on behalf of the user (customer).       |
| `entityId`     | The ID of the customer.                                                           |
| `expiresIn`    | A number in **milliseconds** specifying how long the `accessToken` will be valid. |
| `tokenType`    | Value: `Bearer`.                                                                  |
| `creationDate` | Unix timestamp specifying the time of creation of the token.                      |
| `licenseId`    | Text license ID.                                                                  |

### How to acquire it?

In order to get a Chat Widget token, you need to implement a function that calls the `https://accounts.livechat.com/customer/token` endpoint. To do so, you can follow [customer authorization flows](/authentication/customer-tokens) or have a look at our [example](https://github.com/livechat/identity-provider-example/blob/master/lib/get-customer-token.ts) that uses cookies.

The first time you execute this logic, the connection between our `customer_id` (`entity_id`) and the identity from your service doesn't exist yet. Start by creating a new custom identity. Next time you execute this logic, you'll be able to provide `entity_id`, and therefore, you will only need to refresh the token.

**Mind the fact that the data returned from the endpoint is not 1:1 with the token shape described above.** You'll have to make the following adjustments to your token before passing it further:

* Rename all the keys from `snake_case` to `camelCase`
* Add the `creationDate` and `licenseId` fields.
* Multiply `expiresIn` by 1000. It's because we expect `expiresIn` to be expressed in milliseconds while the endpoint operates in seconds.

## Examples

Here are our suggested implementations of Custom Identity Provider. The `fetchTextToken()` method is used in the examples to acquire the [Chat Widget token](#chat-widget-token).

### Without caching

If you don't need to cache the token, the fetching logic shall occur on every refresh of your application page. In such a case, the implementation can be very simple – we only have to ensure the handling of the `getToken` promise, and resolve other promises.

```js theme={null}
window.__lc.custom_identity_provider = () => {
  const fetchTextToken = () => {
    // fetch a token from the Text Accounts API here
  };

  let tokenPromise = null;
  const fetchToken = () => {
    tokenPromise = fetchTextToken().then((response) => {
      tokenPromise = null;
      return response;
    });
    return tokenPromise;
  };

  return {
    getToken: () => tokenPromise || fetchToken(),
    getFreshToken: () => tokenPromise || fetchToken(),
    hasToken: () => Promise.resolve(false),
    invalidate: () => Promise.resolve(),
  };
};
```

### With caching

If you care about the number of requests being made in your application, you can unleash the full potential of the Custom Identity Provider.

```js theme={null}
window.__lc.custom_identity_provider = () => {
  const fetchTextToken = () => {
    // fetch a token from the Text Accounts API here
  };

  const cacheKey = "YOUR_CACHE_KEY";
  let tokenPromise = null;
  let cachedToken = null;

  const isExpired = ({ creationDate, expiresIn }) =>
    Date.now() >= creationDate + expiresIn;

  const token = window.sessionStorage.getItem(cacheKey);
  if (token) {
    cachedToken = JSON.parse(token);
  }

  const getToken = () => {
    if (tokenPromise) {
      return tokenPromise;
    }

    if (cachedToken && !isExpired(cachedToken)) {
      return Promise.resolve(cachedToken);
    }

    return getFreshToken();
  };

  const getFreshToken = () => {
    tokenPromise = fetchTextToken().then(
      (token) => {
        tokenPromise = null;
        window.sessionStorage.setItem(cacheKey, JSON.stringify(token));
        cachedToken = token;
        return token;
      },
      (error) => {
        throw error;
      },
    );
    return tokenPromise;
  };

  const hasToken = () => Promise.resolve(!!cachedToken);

  const invalidate = () => {
    cachedToken = null;
    window.sessionStorage.removeItem(cacheKey);
  };

  return {
    getToken,
    getFreshToken,
    hasToken,
    invalidate,
  };
};
```

### Tutorial

See our [tutorial](https://platform.text.com/resource-center/updates/livechat-custom-identity-provider-setup-tutorial) for a full walkthrough of setting up a Custom Identity Provider.

### Repository

See the [example application](https://github.com/livechat/identity-provider-example/) presenting the usage of the Custom Identity Provider mechanism.
