Sign in with Google
Instead of asking your users for a name and seed phrase, you can let them sign in with their Google account. PrefsDB gives each user their own key, the same one every time they sign in, on any device.
- No PrefsDB account for you or your users. You only need a Google client ID, the one you'd use for "Sign in with Google" anyway.
- Your app, your sign-in screen. Google's consent screen shows your app's name, not PrefsDB's.
- No email to confirm. Google has already confirmed the address, so the key works right away.
- Nothing to remember or lose. There's no seed phrase; signing in again finds the same data.
Ready-made buttons
Sign-in Buttons adds this provider's button, and any of the others, to your page with a few lines, and takes care of the one-time codes and popups shown below. You still need the setup in step 1.
How it works
There's no seed phrase in this flow. Instead:
- Your page asks PrefsDB for a one-time code (
PrefsDB.idTokenNonce()). - Your page shows Google's "Sign in with Google" button, set up with your Google client ID and that code.
- The user signs in on Google's own screens. Google hands your page a signed proof of who they are, which includes the code.
- Your page passes that proof to
PrefsDB.getkeyWithIdToken()in place ofgetkey(name, seed). PrefsDB checks it with Google's keys and gives you the user's key.
From there it's an ordinary PrefsDB object: db.key("theme").write("dark") and everything else work as usual.
1. Get a Google client ID
If your app already has "Sign in with Google", use its client ID and skip this step.
- Open the Google Cloud console and create or pick a project.
- Set up the OAuth consent screen (on newer accounts, Google Auth Platform → Branding): your app's name, a support email and your logo. This is what your users see when they sign in.
- Go to APIs & Services → Credentials → Create credentials → OAuth client ID (or Google Auth Platform → Clients → Create client), and choose Web application.
- Under Authorized JavaScript origins, add the address your app runs at, such as
https://app.example.com. Add each address you serve the app from: staging, a second domain, and so on. - Save, and copy the Client ID. It looks like
1234567890-abc123.apps.googleusercontent.com. It isn't a secret; it goes in your page.
You don't need a client secret or a redirect address for this.
Your page must be served over https, or from http://localhost while you develop (add that address to the client's Authorized JavaScript origins too). PrefsDB refuses to sign in from a plain http page anywhere else.
2. Add the button to your page
<script src="https://accounts.google.com/gsi/client" async></script>
<script src="https://prefsdb.com/prefsdb.v1.min.js"></script>
<div id="signin"></div>
<script>
const GOOGLE_CLIENT_ID = "1234567890-abc123.apps.googleusercontent.com";
// Google's button, set up with a fresh one-time code from PrefsDB.
async function showSignIn() {
const nonce = await PrefsDB.idTokenNonce();
google.accounts.id.initialize({
client_id: GOOGLE_CLIENT_ID,
nonce,
callback: signedIn,
});
google.accounts.id.renderButton(document.getElementById("signin"), { theme: "outline", size: "large" });
}
// Google calls this when the user has signed in.
async function signedIn({ credential }) {
try {
const db = await PrefsDB.getkeyWithIdToken(credential, { name: "settings" });
document.getElementById("signin").hidden = true;
await db.key("theme").write("dark");
console.log(await db.key("theme").read());
} catch (err) {
console.error("Sign-in failed:", err.error, err.message);
showSignIn(); // a new code, so the user can try again
}
}
window.addEventListener("load", showSignIn);
</script>
# 1. A one-time code, to pass to Google as the nonce
curl -s https://prefsdb.com/api/v1/getkey/nonce/
# -> {"status":"success","success":true,"nonce":"<NONCE>","expires":1792420000,...}
# 2. The user signs in with Google in a browser. Google returns an
# ID token containing <NONCE>; that can't be done with curl.
# 3. Trade the ID token for the user's key (in the request body, never the URL)
curl -s -c cookies.txt https://prefsdb.com/api/v1/getkey/ \
--data-urlencode "id_token=$ID_TOKEN" \
--data-urlencode "provider=google" \
--data-urlencode "name=settings"
# -> {"status":"success","success":true,"token":"<KEY>","message":"New key generated.",...}
A few things to know:
- Each code works once, within 10 minutes. The example gets a new one whenever a sign-in fails, so the user can just click again. If your page stays open a long time before people sign in, call
showSignIn()again every few minutes. namepicks one of several keys for the same user, as withgetkey(). Leave it out and it's"default".- The same options as
getkey()work here too:offline,offlineTtl,sessionTtl,optimistic,encryptionandthrowOnError.namespaceandappcreddon't apply. - Signing in again on any device, or after clearing the browser, returns the same key and data.
- Keep the rest of your code as it is. After sign-in,
dbworks exactly like one fromgetkey(). To change the key itself, calldb.rotate()with no arguments.
Signing out
When your user signs out, call await db.logout(). It deletes what the key kept in this browser (cached values and changes not sent yet), so the next person on a shared computer can't see them. Then forget your db object. With the sign-in buttons, call signin.signOut() instead, which does the same. See Signing out.
Which users get which key
A key belongs to one Google account in your app: your Google client ID and the name you pass. Another app using PrefsDB gives the same person a different key, so apps never see each other's data.
Letting users see their data
db.reviewUrl() is a page where your users sign in with Google again to see their data, download it all, or upgrade their storage. Unlike the rest of the sign-in, this page shows PrefsDB's name, since it's where PrefsDB talks to them directly. It also works if your app is no longer around.
Storage
A signed-in user's free storage is shared across every app they use with PrefsDB. See Storage space, and use db.onStorage() to warn users before they run out.
Encrypting data in the browser
Client-side encryption works with signed-in users too, but it still needs its own key or passphrase. Don't make one from anything in the Google sign-in, such as the user's ID or email: PrefsDB sees those, so data encrypted with them wouldn't be private from PrefsDB.
If something goes wrong
| What you see | What to do |
|---|---|
IDTOKEN_INVALID |
The sign-in couldn't be checked, or it was too old. Ask the user to sign in again (with a new idTokenNonce()). |
IDTOKEN_REPLAYED |
That sign-in was already used. Get a new nonce and sign in again. |
IDTOKEN_EMAIL_UNVERIFIED |
The Google account's email address isn't confirmed. |
IDTOKEN_KEYS_UNAVAILABLE |
Sign-in is briefly unavailable. Try again shortly. |
More in Error Codes.