Sign-in Buttons
Add "Sign in with Google", "Sign in with Apple", "Sign in with Microsoft" and "Sign in with GitHub" buttons to your page with a few lines. Each user who signs in gets their own key, the same one every time, on any device.
The buttons are each provider's own: Google's and Apple's are drawn by Google's and Apple's scripts, and the Microsoft and GitHub buttons follow those companies' design rules. The add-on also takes care of the fiddly parts of sign-in: loading each provider's script, the one-time codes, and getting popups past the browser's popup blocker.
You can start from the ready-made sign-in page instead.
Before you start
Set up each provider you want, as described on its own page. GitHub needs no setup.
| Provider | What you need | Setup |
|---|---|---|
| A client ID | Sign in with Google | |
| Apple | A Services ID, and one of its Return URLs | Sign in with Apple |
| Microsoft | An Application (client) ID, and a return page on your site | Sign in with Microsoft |
| GitHub | Nothing | Sign in with GitHub |
For Microsoft, the return page is an empty page on your site that Microsoft's sign-in window comes back to. Use signin-done.html and register its address as a Single-page application redirect URI.
Your page must be served over https, or from http://localhost while you develop (except for Apple, which needs a real https address).
Add the buttons
<div id="signin"></div>
<script src="https://prefsdb.com/prefsdb.v1.min.js"></script>
<script src="https://prefsdb.com/prefsdb.signin.v1.min.js"></script>
<script>
const signin = PrefsDB.signIn({
name: "settings",
google: { clientId: "1234567890-abc.apps.googleusercontent.com" },
apple: { clientId: "com.example.web", redirectUri: "https://app.example.com/" },
microsoft: { clientId: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
redirectUri: "https://app.example.com/signin-done.html" },
github: true,
onSignIn: async (db, { provider }) => {
// db is ready to use, like the result of getkey()
await db.key("theme").write("dark");
console.log("Signed in with", provider, await db.key("theme").read());
},
onError: (err) => {
if (err.error !== "POPUP_CLOSED") console.error(err.error, err.message);
},
});
signin.mount("#signin");
</script>
Leave out the providers you don't use. The buttons appear one under the other, in the order Google, Apple, Microsoft, GitHub (change it with order).
The add-on loads each provider's script only when that provider is in your list.
Start from a template
signin-template.html is a complete sign-in page: a card with the buttons, a "Signing in…" message, friendly error messages, a "Last used" label on the button the user picked last time, and a signed-in view with a link to the user's data and a sign-out button. It follows the light or dark setting of the user's device.
- Download signin-template.html, and signin-done.html if you use Microsoft.
- Fill in
CONFIGat the top of the script: your IDs, and delete the providers you don't use. - Put the files on your site.
- Replace
showApp()with your app.
Options
| Option | What it does |
|---|---|
google |
{ clientId }. Add oneTap: true to also show Google's One Tap prompt, and button to change Google's button (Google's renderButton options, such as { shape: "pill" }). |
apple |
{ clientId, redirectUri }: your Services ID and one of its Return URLs. Optional: locale (such as "fr_FR", for the button's language), scope (default "email"; "" to not ask for an email address), button (Apple's button settings, such as { type: "continue" }). |
microsoft |
{ clientId, redirectUri }: your Application (client) ID and your return page. Optional: authority (default "https://login.microsoftonline.com/common"; it must match the account types your registration allows, see Which accounts can sign in), button ({ theme: "dark" }, { label: "…" }), msalUrl (your own copy of Microsoft's MSAL.js). |
github |
true, or { button: { theme, label } }. |
name |
Which of the user's keys to use, as with getkey(). Default "default". |
offline, offlineTtl, sessionTtl, optimistic, encryption, timeout, throwOnError, remember |
The same as for getkey(). With remember, PrefsDB.resume(name) gets the key back after a reload (see Staying Signed In). |
theme |
"light" (default) or "dark": the background the buttons sit on. |
width |
Button width in pixels, default 280. Google's button is 200–400 wide and Apple's 130–375. |
order |
Which buttons mount() shows, in order, such as ["apple", "google"]. A provider you leave out can still use your own button. |
onSignIn(db, { provider, previousProvider }) |
Called with a ready-to-use PrefsDB object after a sign-in. previousProvider is set when this browser last signed in with a different provider, which means a different key. |
onError(err) |
Called when a sign-in doesn't work. See below. |
onStart({ provider }) |
Called when a sign-in begins, for showing "Signing in…". |
The object PrefsDB.signIn() returns also has:
mount(element)puts the buttons into an element (or a selector such as"#signin").signOut()signs the user out: it callsdb.logout()on the PrefsDB object the last sign-in gave you, which deletes what that key kept in this browser (cached values and changes not sent yet), and keeps Google from signing the user straight back in. Call it (andawaitit) when your user signs out.signOut({ keepLocal: true })keeps the browser's copy. See Signing out.destroy()removes the buttons.lastProvider()returns the provider this browser signed in with last time.
Using your own button
Microsoft and GitHub have no official ready-made button, so you can use your own element for them:
Google and Apple sign in only through their own buttons, so use mount() for them.
If something goes wrong
onError gets an object like { error, message, provider }, the same for every provider:
error |
What it means |
|---|---|
POPUP_CLOSED |
The user closed the sign-in window. Usually nothing to show. |
POPUP_BLOCKED |
The browser blocked the sign-in window. Ask the user to allow pop-ups for your site. |
NOT_READY |
The user clicked before sign-in was ready, for example while offline. Trying again usually works. |
SCRIPT_LOAD_FAILED |
A provider's script couldn't be loaded (offline, a blocker, or your site's Content-Security-Policy). That provider's button is left out. |
SIGNIN_FAILED |
The provider reported a problem; message has its details. |
IDTOKEN_INVALID, … |
PrefsDB's own errors, as listed in Error Codes. |
Good to know
- Each way in is a separate key. The same person signing in with Google one day and GitHub the next (or with a seed and email) gets two different keys, each with its own data. They aren't linked. Tell your users which one to use, and use the hint the add-on gives you: when this browser last signed in with a different provider,
onSignIngets it aspreviousProvider, so you can say "You signed in with GitHub last time. This is a different account." The button they used last is also marked "Last used". - One set of buttons per page. Google's and Apple's scripts each keep one setup per page. To change the buttons, call
destroy()and create new ones. - Content-Security-Policy. If your site sends one, allow the scripts the add-on loads:
https://prefsdb.comand, for the providers you use,https://accounts.google.com/gsi/client,https://appleid.cdn-apple.comandhttps://cdn.jsdelivr.net(Microsoft's MSAL.js). Google also needshttps://accounts.google.com/gsi/underframe-srcandconnect-srcandhttps://accounts.google.com/gsi/styleunderstyle-src; Microsoft needshttps://login.microsoftonline.comunderconnect-src. Apple's button is drawn with inline styles, so with Applestyle-srcalso needs'unsafe-inline'. - Already using MSAL.js? If your page has loaded it already, the add-on uses that copy.
- Pop-ups. Sign-in windows open straight from the click, which browsers allow. A page that sends
Cross-Origin-Opener-Policy: same-origincuts the window off from the page; usesame-origin-allow-popups.