Authentication
Zero uses a JWT-based flow to authenticate connections to zero-cache.
Frontend
During login:
- Your API server creates a
JWT
and sends it to your client. - Your client constructs a
Zero
instance with this token by passing it to theauth
option.
const zero = new Zero({
...,
auth: token, // your JWT
userID, // this must match the `sub` field from `token`
});
Server
For zero-cache
to be able to verify the JWT, one of the following environment variables needs to be set:
ZERO_AUTH_SECRET
- If your API server uses a symmetric key (secret) to create JWTs then this is that same key.ZERO_AUTH_JWK
- If your API server uses a private key to create JWTs then this is the corresponding public key, in JWK format.ZERO_AUTH_JWKS_URL
- Many auth providers host the public keys used to verify the JWTs they create at a public URL. If you use a provider that does this, or you publish your own keys publicly, set this to that URL.
Refresh
The auth
parameter to Zero can also be a function:
const zero = new Zero({
...,
auth: async () => {
const token = await fetchNewToken();
return token;
},
userID,
});
In this case, Zero will call this function to get a new JWT if verification fails.
Client-Side Data Storage
Zero stores client-side data in IndexedDB
by default, but this is customizable with the kvStore
parameter:
const zero = new Zero({
// Store data in React Native's SQLite database
// See https://github.com/Braden1996/react-native-replicache
kvStore: createReplicacheReactNativeOPSQLiteKVStore,
});
const zero = new Zero({
// Store data in memory, it disappears on refresh
kvStore: 'mem',
});
Because multiple users can share the same browser, Zero requires that you provide a userID
parameter on construction:
const zero = new Zero({
...,
userID: "user-123",
});
Zero stores each user's data in a different IndexedDB instance. This allows users to quickly switch between multiple users and accounts without resyncing.
If your application is unauthenticated, or if you don't need fast user switching, you can just set userID
to a constant like anon
or guest
:
const zero = new Zero({
...,
userID: "anon",
});
Alternately, if you have more than one set of Zero data per-user (i.e., for different apps in the same domain), you can additonally use the storageKey
parameter:
const zero = new Zero({
...,
userID: "user-123",
storageKey: "my-app",
});
If specified, storageKey
is concatenated along with userID
and other internal Zero information to form a unique IndexedDB database name.

Zero's IndexedDB databases are prefixed with 'rep' or 'replicache' because ... well because we haven't fixed this yet.
Logging Out
When a user logs out, you should consider what should happen to the synced data.
If you do nothing, the synced data will be left on the device. The next login will be a little faster because Zero doesn't have to resync that dta from scratch. But also, the data will be left on the device indefinitely which could be undesirable for privacy and security.
If you instead want to clear data on logout, Zero provides the dropAllDatabases
function:
import {dropAllDatabases} from '@rocicorp/zero';
// Returns an object with:
// - The names of the successfully dropped databases
// - Any errors encountered while dropping
const {dropped, errors} = await dropAllDatabases();
Permissions
Any data placed into your JWT (claims) can be used by permission rules on the backend.
const isAdminRule = (decodedJWT, {cmp}) => cmp(decodedJWT.role, '=', 'admin');
See the permissions section for more details.
Examples
See zbugs or hello-zero.