How to Create a SpacetimeDB Identity: HTTP API and SDK Methods
You can create a SpacetimeDB identity by sending a POST request to the /v1/identity endpoint, or automatically when opening a database connection via the TypeScript or Rust SDK, which returns a 256-bit identifier and a signed JWT token.
SpacetimeDB uses cryptographic identities to authenticate clients and authorize database operations. Whether you are building a multiplayer game or a collaborative application, understanding how to create a SpacetimeDB identity is essential for managing user authentication. The clockworklabs/SpacetimeDB repository provides multiple pathways for identity generation, ranging from direct HTTP API calls to programmatic SDK integration.
Understanding SpacetimeDB Identities
An Identity in SpacetimeDB is a 256-bit opaque identifier represented as a 64-character hexadecimal string. According to the source code in crates/lib/src/identity.rs, this type wraps a u256 value and provides utilities for byte conversion, hex encoding, and claim-based derivation. The identity serves as the foundation for access control within SpacetimeDB modules, allowing the database to verify who is performing each transaction.
Create a SpacetimeDB Identity via the HTTP API
The simplest way to generate a new identity is through the REST API endpoint defined in crates/client-api/src/routes/identity.rs.
Sending the Request
Execute a POST request to /v1/identity:
curl -X POST https://my-spacetimedb-instance.com/v1/identity
Response Format
The server returns a JSON object containing the identity and an authentication token:
{
"identity": "0xc200e5b8a3f1d9a7c5...",
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}
The create_identity handler in crates/client-api/src/routes/identity.rs handles this by calling SpacetimeAuth::alloc, which generates the cryptographic keypair and signs the JWT token for subsequent authenticated requests.
Create a SpacetimeDB Identity Using Client SDKs
For applications requiring persistent WebSocket connections, the SDKs automatically create identities during the connection handshake, eliminating the need for manual HTTP requests.
TypeScript SDK
When using the TypeScript client, the identity is generated and returned in the onConnect callback:
import { DbConnection, Identity } from "spacetimedb";
DbConnection.builder()
.withUri("wss://my-spacetimedb-instance.com")
.withModuleName("my-module")
.onConnect((conn: DbConnection, identity: Identity, token: string) => {
console.log("Connected! Identity:", identity.toHexString());
// Store token for reconnection
})
.build();
Rust Client
The Rust crate spacetimedb-client provides equivalent functionality:
use spacetimedb_client::DbConnectionBuilder;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let conn = DbConnectionBuilder::new()
.with_uri("wss://my-spacetimedb-instance.com")
.with_module_name("my-module")
.on_connect(|_conn, identity, token| {
println!("Connected! Identity: {}", identity);
println!("Auth token: {}", token);
})
.build()
.await?;
Ok(())
}
Derive a Deterministic Identity from OpenID Connect
For scenarios requiring consistent identities across sessions based on external authentication providers, SpacetimeDB supports deterministic identity generation.
The Identity::from_claims method in crates/lib/src/identity.rs derives an identity from an issuer and subject pair:
use spacetimedb_lib::Identity;
let my_identity = Identity::from_claims("https://accounts.google.com", "user@example.com");
println!("Derived identity: {}", my_identity);
This approach ensures that the same OpenID Connect credentials always map to the same SpacetimeDB identity, useful for migrating existing user bases without breaking existing permissions or data ownership.
Implementation Details
Under the hood, identity creation follows a specific cryptographic path implemented in the SpacetimeDB source. When the HTTP endpoint receives a request, it instantiates a temporary SpacetimeAuth context via SpacetimeAuth::alloc. This allocation generates a new 256-bit keypair, creates the Identity object, and produces a signed JWT token for subsequent authenticated requests.
The API documentation in docs/versioned_docs/version-1.12.0/00300-resources/00200-reference/00200-http-api/00200-identity.md specifies that the endpoint requires no authentication headers, as it is designed to bootstrap the authentication process itself.
Summary
- SpacetimeDB identities are 256-bit identifiers represented as 64-character hex strings, implemented in
crates/lib/src/identity.rs. - HTTP API method: Send
POST /v1/identityto receive a new identity and JWT token, handled bycrates/client-api/src/routes/identity.rs. - SDK method: Client libraries automatically generate identities during connection establishment, returning them via
onConnectcallbacks. - Deterministic generation: Use
Identity::from_claimsto derive consistent identities from OpenID Connect issuer/subject pairs.
Frequently Asked Questions
What is the format of a SpacetimeDB identity?
A SpacetimeDB identity is a 256-bit opaque identifier encoded as a 64-character hexadecimal string prefixed with 0x. The underlying implementation in crates/lib/src/identity.rs stores this as a u256 value and provides conversion methods for big-endian and little-endian byte arrays.
Can I reuse a SpacetimeDB identity across different devices?
Yes. Once created, you can persist the JWT token returned by the POST /v1/identity endpoint or SDK onConnect callback. Storing this token allows you to reconnect from any device using the same identity and maintain consistent database access permissions.
How do I create a deterministic identity for existing users?
Use the Identity::from_claims function available in spacetimedb_lib. By passing your OpenID Connect issuer URL and user subject identifier, you can generate the same SpacetimeDB identity consistently, enabling migration of existing user accounts without changing their underlying identifiers.
Is the /v1/identity endpoint protected by authentication?
No. The endpoint is intentionally unauthenticated because its purpose is to generate the credentials used for subsequent authentication. According to the official API reference, it accepts POST requests without headers and returns a fresh identity and token pair.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →