> For the complete documentation index, see [llms.txt](https://docs.convai.com/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convai.com/api-docs/plugins-and-integrations/convai-unity-sdk/authentication/custom-token-provider.md).

# Write a custom token provider

Register a custom credential provider so your backend issues short-lived Convai auth tokens automatically for each connection.

Implement `IConvaiAuthTokenProvider` when your project already has a backend or login layer that can mint a Convai auth token, and you want the SDK to call it automatically for every connection. Use this page when your project is in Auth Token mode and you want token resolution to happen without touching connection code at each call site.

### Prerequisites

* The project's `ConvaiSettings` asset has `AuthMode` set to `AuthToken`. See [Configure Auth Token mode](/api-docs/plugins-and-integrations/convai-unity-sdk/authentication/configure-auth-token-mode.md).
* A backend endpoint or SDK that returns a short-lived Convai auth token (an `apiAuthToken`) for the signed-in player.

### Implement the interface

`IConvaiAuthTokenProvider` has a single method:

```csharp
public interface IConvaiAuthTokenProvider
{
    Task<AuthTokenResult> GetTokenAsync(CancellationToken cancellationToken);
}
```

The SDK calls `GetTokenAsync` once for every new room connection attempt. Return `AuthTokenResult.Succeeded(token, expiresAtUtc)` on success, or `AuthTokenResult.Failed(errorMessage)` when the token cannot be resolved. `expiresAtUtc` is optional.

{% code title="Assets/Scripts/MyAuthTokenProvider.cs" %}

```csharp
using System;
using System.Threading;
using System.Threading.Tasks;
using Convai.Runtime.Core.Configuration;

public sealed class MyAuthTokenProvider : IConvaiAuthTokenProvider
{
    public async Task<AuthTokenResult> GetTokenAsync(CancellationToken cancellationToken)
    {
        try
        {
            string token = await MyBackend.RequestConvaiTokenAsync(cancellationToken);
            return string.IsNullOrWhiteSpace(token)
                ? AuthTokenResult.Failed("My backend returned an empty token.")
                : AuthTokenResult.Succeeded(token);
        }
        catch (Exception exception)
        {
            return AuthTokenResult.Failed($"My backend request failed ({exception.GetType().Name}).");
        }
    }
}
```

{% endcode %}

{% hint style="warning" %}
`IConvaiAuthTokenProvider` implementations must not log or persist the returned token. Treat it as a short-lived secret scoped to a single connection attempt.
{% endhint %}

### Register the provider before connecting

Register the provider with `ConvaiAuthTokenProviderRegistry` before the first connection attempt, typically from an early `Awake`:

```csharp
using Convai.Runtime.Core.Configuration;
using UnityEngine;

public sealed class AuthBootstrap : MonoBehaviour
{
    private MyAuthTokenProvider _provider;

    private void Awake()
    {
        _provider = new MyAuthTokenProvider();
        ConvaiAuthTokenProviderRegistry.Register(_provider);
    }

    private void OnDestroy()
    {
        ConvaiAuthTokenProviderRegistry.Unregister(_provider);
    }
}
```

`ConvaiAuthTokenProviderRegistry.Register` replaces whichever provider is currently registered. `Unregister(provider)` removes it only if it is still the active registration; `Unregister()` with no argument and `Clear()` both remove whichever provider is active.

{% hint style="warning" %}
`ConvaiAuthTokenProviderRegistry` is a static, process-local registration that resets automatically on `RuntimeInitializeLoadType.SubsystemRegistration`. This runs on every domain reload and every entry into Play mode, so a provider registered once does not survive it — register the provider again each time your bootstrap script runs, rather than assuming a one-time call is enough.
{% endhint %}

### Use a delegate for a simple case

For a provider that only needs a single async lookup, wrap a lambda in `DelegateAuthTokenProvider` instead of writing a full class:

```csharp
using Convai.Runtime.Core.Configuration;

ConvaiAuthTokenProviderRegistry.Register(
    new DelegateAuthTokenProvider(async cancellationToken =>
        await MyBackend.RequestConvaiTokenAsync(cancellationToken)));
```

`DelegateAuthTokenProvider` wraps a `Func<CancellationToken, Task<string>>`. It fails with `AuthTokenResult.Failed` if the delegate returns `null`, an empty task, or an empty string, so your delegate only needs to return the token string or throw.

### Verify the setup

Enter Play mode and connect a character. If the provider resolves correctly, the connection proceeds with no auth-related error. If it fails, the connection surfaces the message from `AuthTokenResult.Failed` through the normal connection error path.

### Next steps

{% content-ref url="/pages/kIlJ7N9lKJysoIrmsbqK" %}
[Connect with an existing auth token](/api-docs/plugins-and-integrations/convai-unity-sdk/authentication/connect-with-auth-token.md)
{% endcontent-ref %}

{% content-ref url="/pages/hU1HhBYKZDoChhsoNKJN" %}
[Authentication scripting reference](/api-docs/plugins-and-integrations/convai-unity-sdk/authentication/scripting-reference.md)
{% endcontent-ref %}

{% content-ref url="/pages/KS7LOFRhjJV0jNeUBAo9" %}
[Troubleshoot authentication](/api-docs/plugins-and-integrations/convai-unity-sdk/authentication/troubleshooting.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.convai.com/api-docs/plugins-and-integrations/convai-unity-sdk/authentication/custom-token-provider.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
