How to Obtain an OIDC ID Token for SpacetimeDB Using Next.js and Auth0
Hello! Since the first SpacetimeDB video came out, I’ve become a huge fan of this technology and am very grateful to Clockwork for releasing the database. From day one, I’ve been experimenting with SpacetimeDB in my projects. I followed the guide to build a simple chat, and then I decided to use SpacetimeDB in one of my own projects: Overvoted — a everyday clicker-and-voting. The project started as a fun idea, but I realized it was a great way to test the database and learn how to use it for my future ideas. The Authentication Challenge in SpacetimeDB The Spacetime documentation focuses mostly on usage scenarios; how to build a chat or a small Agar.io-style game; but these examples don’t cover authentication and authorization in depth. For MMORPG use cases (which is where SpacetimeDB really shines), robust auth is critical. SpacetimeDB doesn’t provide any built-in authorization mechanisms, and for authentication it expects an ID Token issued by an OpenID Connect–compliant provider. In practice, that means we developers must implement our own auth flow and obtain a token from a third-party OIDC provider. For my project, I chose Auth0 and I’m using Next.js on the frontend. Note that our application is essentially a single-page app (SPA), not an MPA or server-rendered app. I haven’t yet tackled the server-side auth scenario. Prerequisites A running SpacetimeDB instance with your module code and database logic already set up An Auth0 account with a configured Single Page Application A frontend client (I’m using Next.js, but any SPA framework will work) Step 1: Set Up Your SpacetimeDB Client and Module Follow the official quickstarts for your language of choice: TypeScript client C# module Rust module Key Concepts to Understand Before implementing the flow, keep these points in mind: Token and Identity: The token you provide to SpacetimeDB lets it assign and persist a client identity. In simple terms: the same user token always yields the same SpacetimeDB identity. That’s the core of how connections remain stable. ID Token Only: SpacetimeDB specifically requires the ID Token (not an Access Token or any other token) issued by an OIDC provider. Provider Compatibility: Not every auth provider fully implements OIDC. Always verify OIDC compatibility for your chosen provider. Auth0 is fully OIDC-compliant. Auth Services: An authentication aggregator like Auth0 can support multiple identity providers (Google, Twitter, etc.). You could also integrate a provider like Google directly, but using an aggregator often offers more flexibility for your users. SPA Implementation For React/Next.js apps, I recommend using react-oidc-context. For other TypeScript frameworks, oidc-client-ts works well. OIDC Configuration for Auth0 export const oidcConfig = { authority: "https://dev-aaaaAAAAAAAaaaa.us.auth0.com", // Your Auth0 OIDC issuer URL in app it will be Domain client_id: "AAaaaAAAAaaaaaAAAAaAa", // Your Auth0 Client ID redirect_uri: "http://localhost:3001/callback", // Redirect URI to receive the tokens post_logout_redirect_uri: "http://localhost:3001", // Where to go after logout response_type: "code", // Use Authorization Code Flow scope: "openid email profile", // OIDC scopes (openid required) }; Simplified Provider Setup in Next.js import { AuthProvider } from 'react-oidc-context'; export function Providers({ children }) { return {children}; } Connecting to SpacetimeDB with the ID Token import { useAuth } from 'react-oidc-context'; import { useEffect, useState } from 'react'; import { DbConnection } from '@module-bingings'; // generated module bindings function SpacetimeConnector() { const auth = useAuth(); const [identity, setIdentity] = useState(null); useEffect(() => { if (auth.isAuthenticated && auth.user.id_token) { const conn = DbConnection.builder() .withUri('spacetime://my-project.spacetimedb.net') .withModuleName('my_module') .withToken(auth.user.id_token) .onConnect((conn, identity) => { console.log(`Connected with identity: ${identity}`); setIdentity(identity); }) .build(); return () => conn.close(); } }, [auth.isAuthenticated, auth.user]); return ( {identity && Your SpacetimeDB Identity: {identity}} ); } Temporary Tokens and Verifying Your Setup SpacetimeDB Temporary Tokens The onConnect callback’s third argument is a temporary SpacetimeDB token if you didn’t supply an ID Token via .withToken(). SpacetimeDB issues this token itself. If you require external auth, you can safely ignore the temporary token. Temporary tokens are useful when you don’t have an external auth system but still want session persistence: // Without external auth (using the temporary

Hello! Since the first SpacetimeDB video came out, I’ve become a huge fan of this technology and am very grateful to Clockwork for releasing the database. From day one, I’ve been experimenting with SpacetimeDB in my projects. I followed the guide to build a simple chat, and then I decided to use SpacetimeDB in one of my own projects: Overvoted — a everyday clicker-and-voting. The project started as a fun idea, but I realized it was a great way to test the database and learn how to use it for my future ideas.
The Authentication Challenge in SpacetimeDB
The Spacetime documentation focuses mostly on usage scenarios; how to build a chat or a small Agar.io-style game; but these examples don’t cover authentication and authorization in depth. For MMORPG use cases (which is where SpacetimeDB really shines), robust auth is critical. SpacetimeDB doesn’t provide any built-in authorization mechanisms, and for authentication it expects an ID Token issued by an OpenID Connect–compliant provider. In practice, that means we developers must implement our own auth flow and obtain a token from a third-party OIDC provider.
For my project, I chose Auth0 and I’m using Next.js on the frontend. Note that our application is essentially a single-page app (SPA), not an MPA or server-rendered app. I haven’t yet tackled the server-side auth scenario.
Prerequisites
- A running SpacetimeDB instance with your module code and database logic already set up
- An Auth0 account with a configured Single Page Application
- A frontend client (I’m using Next.js, but any SPA framework will work)
Step 1: Set Up Your SpacetimeDB Client and Module
Follow the official quickstarts for your language of choice:
Key Concepts to Understand
Before implementing the flow, keep these points in mind:
Token and Identity: The token you provide to SpacetimeDB lets it assign and persist a client identity. In simple terms: the same user token always yields the same SpacetimeDB identity. That’s the core of how connections remain stable.
ID Token Only: SpacetimeDB specifically requires the ID Token (not an Access Token or any other token) issued by an OIDC provider.
Provider Compatibility: Not every auth provider fully implements OIDC. Always verify OIDC compatibility for your chosen provider. Auth0 is fully OIDC-compliant.
Auth Services: An authentication aggregator like Auth0 can support multiple identity providers (Google, Twitter, etc.). You could also integrate a provider like Google directly, but using an aggregator often offers more flexibility for your users.
SPA Implementation
For React/Next.js apps, I recommend using react-oidc-context. For other TypeScript frameworks, oidc-client-ts works well.
OIDC Configuration for Auth0
export const oidcConfig = {
authority: "https://dev-aaaaAAAAAAAaaaa.us.auth0.com", // Your Auth0 OIDC issuer URL in app it will be Domain
client_id: "AAaaaAAAAaaaaaAAAAaAa", // Your Auth0 Client ID
redirect_uri: "http://localhost:3001/callback", // Redirect URI to receive the tokens
post_logout_redirect_uri: "http://localhost:3001", // Where to go after logout
response_type: "code", // Use Authorization Code Flow
scope: "openid email profile", // OIDC scopes (openid required)
};
Simplified Provider Setup in Next.js
import { AuthProvider } from 'react-oidc-context';
export function Providers({ children }) {
return <AuthProvider {...oidcConfig}>{children}</AuthProvider>;
}
Connecting to SpacetimeDB with the ID Token
import { useAuth } from 'react-oidc-context';
import { useEffect, useState } from 'react';
import { DbConnection } from '@module-bingings'; // generated module bindings
function SpacetimeConnector() {
const auth = useAuth();
const [identity, setIdentity] = useState(null);
useEffect(() => {
if (auth.isAuthenticated && auth.user.id_token) {
const conn = DbConnection.builder()
.withUri('spacetime://my-project.spacetimedb.net')
.withModuleName('my_module')
.withToken(auth.user.id_token)
.onConnect((conn, identity) => {
console.log(`Connected with identity: ${identity}`);
setIdentity(identity);
})
.build();
return () => conn.close();
}
}, [auth.isAuthenticated, auth.user]);
return (
<div>
{identity && <p>Your SpacetimeDB Identity: {identity}</p>}
</div>
);
}
Temporary Tokens and Verifying Your Setup
SpacetimeDB Temporary Tokens
The onConnect
callback’s third argument is a temporary SpacetimeDB token if you didn’t supply an ID Token via .withToken()
. SpacetimeDB issues this token itself. If you require external auth, you can safely ignore the temporary token.
Temporary tokens are useful when you don’t have an external auth system but still want session persistence:
// Without external auth (using the temporary SpacetimeDB token)
.onConnect((conn, identity, tempToken) => {
console.log(`Connected with identity: ${identity}`);
localStorage.setItem('spacetime_temp_token', tempToken);
})
// With OIDC ID Token
.onConnect((conn, identity, _tempToken) => {
console.log(`Connected with identity: ${identity}`);
// We ignore the temporary token when using an OIDC ID Token
})
How to Verify Your Configuration
Ensure the same authenticated user always receives the same SpacetimeDB identity:
- Log in to your app.
- Connect to SpacetimeDB and note the returned identity.
- Refresh the page or open the app in a different browser.
- Log in as the same user.
- Check that the identity remains unchanged.
.onConnect((conn, identity, tempToken) => {
console.log(`Connected with identity: ${identity}`);
// This identity should be stable for a single user
})
If identities differ for the same user, check:
- You’re sending an OIDC ID Token (not an Access Token).
- Your OIDC provider settings are correct.
- You’re persisting and reusing the token properly.
Conclusion
I had very limited experience with authentication and authorization systems, and OIDC was entirely new to me. Initially, integrating it felt overwhelming and I wasn’t sure what I was doing. Having worked through the steps now, I can see that it’s actually quite approachable.
Big thanks to Lethalchip (Chip) for his GitHub example (spacetimedb-cookbook/oidc-test). Note: although his example is generally correct, he mistakenly uses an Access Token rather than an ID Token, which broke identity stability in my tests.
I hope this guide helps you integrate SpacetimeDB into your projects with a reliable OIDC authentication system via Auth0 or other OIDC complaint provider.