---
id: "customers/authentication-backend"
title: "Verify access tokens on your backend"
description: "This article shows you how to use the RevenueCat access token to protect the calls between your app and your backend. By the end, your backend will reject requests without a valid access token and will know which Customer sent each request."
permalink: "/docs/customers/authentication-backend"
slug: "authentication-backend"
version: "current"
original_source: "docs/customers/authentication-backend.mdx"
---

> **AI agents:** This is the Markdown version of a RevenueCat documentation page. For the complete documentation index, see [llms.txt](https://www.revenuecat.com/docs/llms.txt).

This article shows you how to use the RevenueCat access token to protect the calls between your app and your backend. By the end, your backend will reject requests without a valid access token and will know which Customer sent each request.

:::info[Private beta]

Authentication is in private beta, and backend support is basic during the beta. Support for custom resource servers and scopes will follow. [Tell us about your use case](https://revenuecateventfeedback.typeform.com/to/bzxYhAjZ) to get early access.

:::

## Prerequisites

- [Authentication in your app](https://www.revenuecat.com/docs/customers/authentication-ios), so that your app holds a RevenueCat access token for the Customer
- Your app sends the access token to your backend with each request, for example in an `Authorization` header
- Your RevenueCat Project ID, from **Project Settings → General** in the RevenueCat dashboard. See [Project settings](https://www.revenuecat.com/docs/projects/overview#general-settings).

## Choose how to verify the token

The access token is a JSON Web Token (JWT) that RevenueCat signs with the keys of your project. Your backend can verify it in one of two ways.

| Approach                                                              | Use it when                                                                                               |
| --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| [Verify the token on your backend](#verify-the-token-on-your-backend) | You want no runtime dependency on RevenueCat and the lowest latency. The token expires after three hours. |
| [Call the RevenueCat API](#call-the-revenuecat-api)                   | You also want the Customer's information from RevenueCat with each request.                               |

## Verify the token on your backend

Verify the token with an established JWT library for your language. Don't write your own verification logic. A library handles the edge cases that cause security bugs. For a list of libraries, see [jwt.io](https://www.jwt.io/).

### Check the claims and the signature

Your backend must check four things before it trusts a token:

| Check      | Claim | Expected value                                      |
| ---------- | ----- | --------------------------------------------------- |
| Issuer     | `iss` | `https://api.revenuecat.com/auth/{YOUR_PROJECT_ID}` |
| Audience   | `aud` | `https://api.revenuecat.com/auth/{YOUR_PROJECT_ID}` |
| Expiration | `exp` | A time later than the current time, in UTC          |
| Signature  | —     | Signed by one of the public keys of your project    |

RevenueCat publishes the public keys of your project at its [JWKS endpoint](https://www.revenuecat.com/api-v1#tag/customers/operation/get-project-jwks):

```text
https://api.revenuecat.com/auth/{YOUR_PROJECT_ID}/.well-known/jwks.json
```

To verify the signature:

1. Read the key ID from the `kid` header of the access token.
2. Get the public keys of your project from the JWKS endpoint.
3. Find the key with the same key ID. If no key matches, reject the token.
4. Verify the signature with that key.

Cache the response from the JWKS endpoint, so that your backend doesn't fetch the keys for every request.

### Read the Customer from the token

After the token passes every check, read these two claims to identify the Customer:

| Claim            | Value                                                               |
| ---------------- | ------------------------------------------------------------------- |
| `sub`            | The RevenueCat Customer ID                                          |
| `rc.app_user_id` | The [App User ID](https://www.revenuecat.com/docs/customers/identifying-customers) of the Customer |

Both claims identify the same Customer, but they hold different values.

## Call the RevenueCat API

Call [`GET /v1/customer`](https://www.revenuecat.com/api-v1#tag/customers/operation/get-authenticated-customer) with the access token in the `Authorization` header, using the `Bearer` scheme. The response contains the [Customer Info](https://www.revenuecat.com/api-v1#tag/customer_info_model) of the Customer, and a `user` object that lists the identities the Customer signed in with.

```http
GET /v1/customer HTTP/1.1
Host: api.revenuecat.com
Authorization: Bearer <ACCESS_TOKEN>
Accept: application/json
```

Replace `<ACCESS_TOKEN>` with the access token that your app sent. The access token is the only credential for this call. Don't send your public SDK key or your secret API key.

The endpoint reads the Customer from the access token, so the response is always for the Customer of that token. One access token gives access to one Customer.

Cache the response for 30 seconds. The cache saves latency on each request and reduces the load on RevenueCat.

## Limitations

- The access token has no custom audiences or scopes during the beta. Every token for a project has the same issuer and audience.

## Next steps

- [Add authentication to your iOS app](https://www.revenuecat.com/docs/customers/authentication-ios) to get the access token that your backend verifies
- [Authentication](https://www.revenuecat.com/docs/customers/customer-authentication) for how the identity provider, the method, and the access token fit together
