# Identity and authentication (https://docs.open-e2ee.dev/relay/identity.md)



Relay authorizes each request from verified credentials. A user ID, device ID, provider subject, organization, project, or environment sent by a client is never authority by itself.

Reviewed: 2026-10-19.

## Sandbox first [#sandbox-first]

Device-owned identity is the shortest path to the first Sandbox message. The device proves possession of an account key. Sandbox credentials cannot cross into Production.

In a Sandbox environment, `hostedRelaySandboxIdentity(storage)` from the SDK creates the `getIdentityAssertion` callback. The callback signs a device-owned assertion with an Ed25519 key that it keeps in `storage`, and the Relay binds the account to that key. Pass the same store as `adapters.storage`:

```ts
import {
  createHostedSignalProtocolClient,
  hostedRelaySandboxIdentity,
} from '@open-e2ee/signal-protocol-sdk';

const signal = await createHostedSignalProtocolClient({
  adapters: { storage },
  hosted: {
    relayUrl,
    getIdentityAssertion: hostedRelaySandboxIdentity(storage),
  },
});
```

The helper works only in a Sandbox environment. It signs only device registration, and it rejects a request for a production environment, recovery, provider migration, or recent or step-up assurance. A device that loses its store loses its Sandbox account, so an in-memory store creates a new Sandbox test account on each run. Another device of the account joins through device linking, not with a copy of the key.

Production supports device-owned accounts and application-bound accounts. Device-owned identity does not bind a Relay account to your application login. Protect its persistent account key. Provider sign-in cannot recover that key after its loss.

The `hostedRelaySandboxIdentity(storage)` helper remains Sandbox-only. Do not use it with a Production connection.

Use application-bound identity for your application member accounts. In production, the callback comes from the identity integration of your application. It returns a short-lived assertion for the signed-in member. Configure that verifier before member-device registration. [Custom-token setup](https://docs.open-e2ee.dev/relay/custom-token.md) defines that contract.

## Configuration and readiness [#configuration-and-readiness]

Open the project settings and select **Identity in Production**. The custom-token path accepts public P-256 signing keys and ES256 assertions. The external ES256 option requires the same Relay-specific claims. It does not accept arbitrary OIDC session tokens.

Clerk and Firebase setup remains unavailable until its SDK and provider acceptance checks pass. Do not substitute their ordinary tokens for the custom-token contract.

The settings form can select a different profile only while the environment has no account history. A reserved registration counts as use. An in-use change requires account migration. Deleting a device does not make that environment unused.

Each status proves a separate fact:

| Status                       | Evidence                                                                                            |
| ---------------------------- | --------------------------------------------------------------------------------------------------- |
| Production enabled           | The environment has an activated Relay plan.                                                        |
| Identity configuration saved | Relay stores the selected verifier policy.                                                          |
| Test assertion valid         | A sample signature and registration claims match the draft verifier. The check stores no assertion. |
| Device registered            | Relay accepted an identity assertion and device proof.                                              |
| First exchange acknowledged  | A recipient device acknowledged a stored message.                                                   |

A card, a saved profile, or a sample assertion does not prove application integration. A registration does not prove that your backend checks every member correctly. Verify the member mapping and access-control behavior in your application.

## Provider migration [#provider-migration]

A provider change is an authenticated account transition, not a new account. Relay binds the old and new verified subjects to one canonical account and one recovery generation. The migration cannot adopt another account, reuse an expired assertion, or keep two active provider authorities after completion.

The initial settings form cannot migrate an account. It refuses a change to an in-use identity profile.

## What identity does not do [#what-identity-does-not-do]

Authentication does not move private keys to Relay. Device identity keys, sessions, ratchets, safety-number state, and recovery secrets stay under the SDK's device-side storage contract. Relay stores public key material and the routing metadata required to deliver ciphertext.
