# Service and access token support

> Use Access Tokens and Service Tokens to authenticate requests in Cloud Code modules.

In modules, the `IExecutionContext` interface provides an `AccessToken` and a `ServiceToken`. Use these tokens to authenticate as the calling player or as Cloud Code when you call other UGS services.

| Token type     | Origin                                                                          | Data access                    | Usage                                                                                                                                                                |
| -------------- | ------------------------------------------------------------------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `accessToken`  | Generated by the [Authentication service](/authentication/use-anon-sign-in.md). | Only the authenticated player. | The `AccessToken` is the JWT you use to authenticate a Cloud Code call. You can pass the token on to other UGS services to access data for the authenticated player. |
| `serviceToken` | Generated by Cloud Code.                                                        | Cross-player data access.      | The `ServiceToken` is the token you use to call other UGS services and interact with cross-player data.                                                              |

Use the `AccessToken` to authenticate as the player who called the module endpoint, so the player can only access their own data. Use the `ServiceToken` to authenticate as Cloud Code and access cross-player data. Because an endpoint that uses the `ServiceToken` can reach cross-player data, protect it with [Access Control](./access-control.md) rules to prevent unauthorized access. For more information, refer to [Cross-player data](./cross-player-data.md) and [Authentication](./authentication.md).

## Access token support

An access token is a [JWT](https://jwt.io/) that the [Authentication service](/authentication/use-anon-sign-in.md) generates. You can use the access token to authenticate players.

When an authenticated player calls a Cloud Code module, they pass their access token to the module as the `AccessToken` property of the `IExecutionContext` interface.

You can use access tokens with the Cloud Code C# Game SDKs. To use access tokens with other UGS APIs, you need to pass the token as a bearer token in the Authentication header.

### Supported services

To check which services support access tokens, refer to the table below:

| Provider                  | Supported services                                                                                                              |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Cloud Code C# Client SDKs | All Cloud Code C# Client SDKs support the same access tokens as their corresponding service APIs.                               |
| UGS Client APIs           | All UGS services that support the Authentication service.                                                                       |
| Cloud Code C# Admin SDKs  | Not supported. Use [Service Account authentication](./authentication.md#cloud-code-admin-api-\(basic-authentication\)) instead. |
| UGS Admin APIs            | Not supported. Use [Service Account authentication](./authentication.md#cloud-code-admin-api-\(basic-authentication\)) instead. |

> **Note:**
>
> Most UGS services are onboarded with the Authentication service and support access tokens.

### Use tokens with Cloud Code C# Client SDKs

To use the `AccessToken` with the Cloud Code C# Client SDKs, you need to pass the token from the `IExecutionContext` interface.

The example below increments the currency balance for the player that calls the module:

```csharp
[CloudCodeFunction("IncrementBalance")]
public async Task<ApiResponse<CurrencyBalanceResponse>> IncrementPlayerBalance(IGameApiClient gameApiClient, IExecutionContext ctx, string currencyId)
{
    ...
    try
    {
    // Increment the balance of the currency for the player calling the module
    var res =  await gameApiClient.EconomyCurrencies.IncrementPlayerCurrencyBalanceAsync(ctx, ctx.AccessToken,
            ctx.ProjectId, ctx.PlayerId, currencyId, new CurrencyModifyBalanceRequest(currencyId, 10));

    _logger.LogInformation("Incremented currency {currencyId} balance by {amount}", currencyId, 10);
    return res;

    }
    catch (ApiException e)
    {
        _logger.LogError("Failed to increment {currencyId} balance for the player. Error: {error}", currencyId, e.Message);
        throw new Exception($"Failed to increment {currencyId} balance for playerId {ctx.PlayerId}. Error: {e.Message}");
    }
}

```

### Use with UGS Client APIs

To use the `AccessToken` with the UGS Client APIs, pass the token as a bearer token in the Authentication header.

> **Note:**
>
> If the service you want to call provides a Cloud Code C# SDK, you can use the SDK instead of calling the service API directly. For a list of available SDKs, refer to [Available libraries](../reference/available-libraries) page.

```csharp
public class Relationships
{
    private readonly RestClient _httpClient;

    public Relationships()
    {
        _httpClient = new RestClient("https://social.services.api.unity.com/v1/relationships");
    }

    public async Task<List<RelationshipsApiResponse?>> GetRelationships(IExecutionContext context)
    {
        var request = new RestRequest()
        {
            // Pass the access token as a bearer token in the header
            Authenticator = new JwtAuthenticator(context.AccessToken)
        };

        ....
    }

}
```

## Service token support

A service token is a [JWT](https://jwt.io/) that Cloud Code generates. You can use service tokens to authenticate services as Cloud Code. This is a service account token that's gone through the [Token Exchange](./authentication.md#cloud-code-client-api-\(bearer-authentication\)) process.

You can use the service token with the Cloud Code C# Client SDKs. To use it with other APIs, you need to pass it as a bearer token in the Authentication header.

### Supported services

For a list of services that support service tokens, refer to the table below:

| Provider                  | Supported services                                                                                                                                                                                                   |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Cloud Code C# Client SDKs | Refer to [Available libraries](../reference/available-libraries) for a list of available SDKs.                                                                                                                       |
| UGS Client APIs           | [Cloud Save][Cloud Save Client API], [Economy][Economy Client API], [Leaderboards][Leaderboards Client API], [Lobby][Lobby Client API], [Player Names][Player Names Client API], [Matchmaker][Matchmaker Client API] |
| Cloud Code C# Admin SDKs  | Not supported. Use [Service Account authentication](./authentication.md#cloud-code-admin-api-\(basic-authentication\)) instead.                                                                                      |
| UGS Admin APIs            | Not supported. Use [Service Account authentication](./authentication.md#cloud-code-admin-api-\(basic-authentication\)) instead.                                                                                      |

> **Note:**
>
> Dedicated reference documentation for the Cloud Code C# Client SDKs isn't available yet. In the meantime, refer to the [JavaScript documentation](../../scripts/how-to-guides/unity-services-integration), which follows a similar structure. Your IDE's autocomplete and IntelliSense features can also help you explore the available methods.

[Cloud Save Client API]: https://services.docs.unity.com/cloud-save/v1/

[Economy Client API]: https://services.docs.unity.com/economy/v2/

[Leaderboards Client API]: https://services.docs.unity.com/leaderboards/v1/

[Lobby Client API]: https://services.docs.unity.com/lobby/v1/

[Player Names Client API]: https://services.docs.unity.com/player-names/v1/

[Matchmaker Client API]: https://services.docs.unity.com/matchmaker/v2/

### Use tokens with Cloud Code C# Client SDKs

To use a `ServiceToken` with the Cloud Code C# Client SDKs, pass the token from the `IExecutionContext` interface.

The example below takes in a player ID and increments the balance of a currency for that player:

```csharp
[CloudCodeFunction("IncrementBalance")]
public async Task<ApiResponse<CurrencyBalanceResponse>> IncrementPlayerBalance(IGameApiClient gameApiClient, IExecutionContext ctx, string currencyId, string playerId)
{
    ...
    try
    {
    // Increment the balance of the currency for the player ID passed in, authenticated as Cloud Code
    var res =  await gameApiClient.EconomyCurrencies.IncrementPlayerCurrencyBalanceAsync(ctx, ctx.ServiceToken,
            ctx.ProjectId, playerId, currencyId, new CurrencyModifyBalanceRequest(currencyId, 10));

    _logger.LogInformation("Incremented currency {currencyId} balance by {amount}", currencyId, 10);
    return res;

    }
    catch (ApiException e)
    {
        _logger.LogError("Failed to increment {currencyId} balance for the player. Error: {error}", currencyId, e.Message);
        throw new Exception($"Failed to increment {currencyId} balance for playerId {ctx.PlayerId}. Error: {e.Message}");
    }
}
```

### Use tokens with UGS Client APIs

To use a `ServiceToken` with the UGS Client APIs, pass the token as a bearer token in the Authentication header.

> **Note:**
>
> If the service you call provides a Cloud Code C# SDK, you can use the SDK instead of calling the service API directly. For a list of available SDKs, refer to the [Available libraries](../reference/available-libraries) page.

For example, if you define an interface for Cloud Save API, you can use the `ServiceToken` to authenticate and interact with cross-player data.
The example below takes in a player ID and returns all the data stored for that player:

```csharp
using System.Net;
using Unity.Services.CloudCode.Core;
using Newtonsoft.Json;
using RestSharp;
using RestSharp.Authenticators;

namespace ExampleModule;

public interface ICloudSaveData
{
    public Task<CloudSaveResponse?> GetData(IExecutionContext context, string playerId);
}

public class CloudSaveResponse
{
    public CloudSaveItem[] Results { get; set; }
}

public class CloudSaveItem
{
    public string Key { get; set; }
    public object Value { get; set; }
}

public class CloudSaveData : ICloudSaveData
{
    private readonly RestClient _httpClient;

    public async Task<CloudSaveResponse?> GetData(IExecutionContext context, string playerId)
    {
        var request = new RestRequest($"v1/data/projects/{context.ProjectId}/players/{playerId}/items")
        {
            // Authenticate as Cloud Code to interact with cross-player data
            Authenticator = new JwtAuthenticator(context.ServiceToken)
        };

           // Pass through the analytics user id and Unity installation id to the service.
        if (context.AnalyticsUserId != null)
            request = request.AddHeader("analytics-user-id", context.AnalyticsUserId);
        if (context.UnityInstallationId != null)
            request = request.AddHeader("unity-installation-id", context.UnityInstallationId);

        RestResponse response = await _httpClient.ExecuteGetAsync(request);
        if (response.Content == null)
            throw new Exception("Failed to load data from Cloud Save: Content was null");

        if (response.StatusCode != HttpStatusCode.OK)
            throw new Exception("Failed to load data from Cloud Save: " + response.Content);

        return JsonConvert.DeserializeObject<CloudSaveResponse>(response.Content);
    }
}
```
