Auth / Connect your own sign-in
Connect your own sign-in
Onelo Auth is the default sign-in. An app that already signs its users in with Supabase, Clerk, Firebase or another OpenID Connect issuer connects that sign-in instead and keeps its users: nobody signs up again and nothing is imported. Your provider keeps signing people in, your app hands Onelo the provider's token, and Onelo answers with an ordinary Onelo session that every module reads.
What an own sign-in is, and when to choose it
Every app has one Sign-in Mode. It is either Onelo Auth, where Onelo signs your users in, or your app's own sign-in, where Onelo trusts the tokens of one issuer you name.
| Your app today | Choose | Why |
|---|---|---|
| Has no sign-in yet | Onelo Auth | Password, magic link and social sign-in with Google, GitHub and Apple work together on one app and are already configured. There is no provider to set up and none of the limits on this page apply. |
| Already signs users in through a provider or its own OpenID Connect issuer | Own sign-in | Users keep their accounts and their way of signing in. You add one setting and a few lines of code. |
| Signs users in with something that issues no OpenID Connect token | Onelo Auth, or put an OpenID Connect issuer in front | Onelo can only verify a signed token from an issuer that publishes its keys. See Limits today. |
Own sign-in is available on every Onelo plan, Free included. Users who arrive this way count toward your monthly active users like any other user.
What Onelo needs from your sign-in
How you sign people in is your business: password, social sign-in, a one-time code, anything. Onelo never sees that step. It receives one thing, a signed token from your issuer, and reads everything it needs from inside it. The e-mail travels inside that token, not beside it: there is no separate field in which your app tells Onelo who the user is.
| The token carries | Claim | What Onelo does with it |
|---|---|---|
| The issuer | iss | Must equal the issuer saved for the app, exactly. |
| The user’s stable subject | sub | Together with the issuer it IS the user in Onelo. Required. |
| The audience | aud | Checked when the app’s configuration names an audience: Firebase (the project ID) and a generic issuer. When authorized parties are saved, azp is checked the same way. |
| Issue time and expiry | iat, exp | Both required, at most one hour apart. An expired token is refused. |
| E-mail, optional | email | Copied to the Onelo user. Without it the user gets a placeholder address. |
| Whether the e-mail is verified, optional | email_verified | Only the value true marks the address verified. |
| Whether the user is anonymous, optional | is_anonymous | Read only with the e-mail confirmation setting: an anonymous user’s address never counts as verified. |
Three conditions make a sign-in connectable, whatever it is built with:
- One issuer. Every way of signing in ends in a token from the same issuer. An app trusts exactly one.
- Published public keys. The token is signed with an asymmetric key (RS256 or ES256), and Onelo can fetch the matching public key from the issuer's discovery document.
- The same subject for the same person. Somebody who signs in with a password one day and through a social provider the next must get the same
sub. With two different subjects Onelo sees two people, and when both tokens carry the same e-mail it refuses the second withemail_in_use.
Clerk and Firebase meet the first two as they come. Supabase meets the first, and the second once the project signs with an asymmetric key (see its section below). The third depends on how accounts are linked at your provider, so check that there. A home-built sign-in has to take care of all three itself.
How own sign-in works
- Your app sends the provider's token to Onelo. Onelo checks its signature against the keys the issuer publishes, checks that it was issued for your project, and answers with an Onelo session.
- A user is identified by the issuer and the user id inside the token (its
sub), never by e-mail. The first exchange creates the user in Onelo; later ones find the same user. - The Onelo session lasts 30 minutes and has no refresh token. After about 80% of that time the SDK asks your function for a fresh provider token and exchanges again, so the user never sees it lapse.
- A user removed at your provider gets no new token, so their Onelo session ends within 30 minutes. A ban in Onelo applies at once.
- Onelo never receives your provider's secrets. Setup takes public values only, and the SDK sends only the user's token.
Turn on own sign-in: dashboard and MCP
In the dashboard. The setting is the Sign-in Mode section on the app's Auth screen.
Choose “My app's own sign-in”, pick the provider, fill in its public value and save.
When you save, Onelo fetches the issuer's OpenID Connect discovery document and its signing keys. The save is refused when the issuer does not answer, answers for a different issuer, or publishes no RS256 or ES256 signing key. Nothing is stored until that check passes.
| Provider | What Onelo asks for | Example |
|---|---|---|
| Supabase | Project reference or project URL | https://abcdefghijklmnopqrst.supabase.co |
| Clerk | Frontend API URL; optionally the authorized parties (the origins allowed in azp) | https://your-app.clerk.accounts.dev |
| Firebase | Project ID | my-app-1a2b3 |
| Other OpenID Connect issuer | Issuer URL and audience (the token’s aud claim); optionally the authorized parties | https://auth.example.com |
sign_in_mode_locked. To move the users, press Ask Onelo to migrate my users on the locked Sign-in Mode card (Dashboard → your app → Auth): Onelo receives the request and gets in touch to plan the move. Choose the mode before you launch. The one exception is Onelo's own staging environment, where the switch stays open for testing: users there are not moved and cannot sign in until the app is switched back.A platform app of an Umbrella app has no Sign-in Mode of its own. Its users sign in at the Umbrella app, so set the mode there.
Through the MCP. An AI agent connected to the Onelo MCP server does the same thing in two calls.
auth.get_guideleads the setup. When it asks whether the app takes Onelo Auth, the answer for an app with its own sign-in isexisting. The guide then asks for the provider and says where each value is.auth.set_sign_in_modesaves it:modeisexternal,presetissupabase,clerk,firebaseoroidc, followed by that provider's public values (project,issuer,project_id,audience,authorized_parties).- The change always waits for your approval in the Onelo panel. The agent's first call comes back with
confirmation_requiredand an approval id; after you approve, the agent repeats the call with that id.
Only public values are needed, read from your app's code or config. Never give Onelo or an agent a provider secret or service key: nothing here uses one.
Supabase: step by step
- Find the project URL your app already passes to the Supabase client, for example
https://abcdefghijklmnopqrst.supabase.co. The 20-character project reference alone works too, and so does a custom domain. - In the Supabase dashboard open the JWT signing keys settings and make sure the project signs with an asymmetric key. A project still on the legacy shared secret uses “Migrate JWT secret” and then “Rotate keys”.
- Save the Sign-in Mode in Onelo with the Supabase provider and that project value.
- Add the Supabase block below to your app.
// `supabase` is your existing Supabase client, `onelo` the instance above.
// The project must sign its tokens with an asymmetric key (ES256 or RS256);
// the legacy shared-secret (HS256) tokens are refused.
// getSession() refreshes the Supabase session when needed. null = signed out.
const supabaseToken = async () =>
(await supabase.auth.getSession()).data.session?.access_token ?? null
// Fires once on start (INITIAL_SESSION), then on every sign-in and sign-out.
let supabaseUser: string | null | undefined
supabase.auth.onAuthStateChange((_event, session) => {
const user = session?.user.id ?? null
if (user === supabaseUser) return // a token refresh, not another user
supabaseUser = user
// Outside the callback: Supabase calls must not run inside it.
setTimeout(() => {
onelo.auth.useExternalToken(supabaseToken).catch((e) => console.error('[Onelo]', e))
}, 0)
})Clerk: step by step
- Find your instance's Frontend API URL. It looks like
https://your-app.clerk.accounts.devin development andhttps://clerk.your-domain.comin production. It is theissof every Clerk session token. - In the Clerk Dashboard open the Sessions page. Under “Customize session token”, add
emailandemail_verifiedin the Claims editor and save. - Save the Sign-in Mode in Onelo with the Clerk provider and the Frontend API URL. Optionally list the authorized parties: the origins of your app, such as
https://app.example.com. When the list is set, a token whoseazpis not on it is refused. - Add the Clerk block below to your app.
// `clerk` is your loaded Clerk instance (window.Clerk, or useClerk() in
// React), `onelo` the instance above.
// getToken() answers from Clerk's cache and fetches a new token when the
// one-minute token has expired. null = signed out.
const clerkToken = async () => (await clerk.session?.getToken()) ?? null
// Fires once on start, then whenever the Clerk session changes.
let clerkUser: string | null | undefined
clerk.addListener(({ session }) => {
if (session === undefined) return // Clerk is still loading
const user = session?.user?.id ?? null
if (user === clerkUser) return
clerkUser = user
onelo.auth.useExternalToken(clerkToken).catch((e) => console.error('[Onelo]', e))
})
// Clerk's session token carries no e-mail by default. To give Onelo the
// address, add `email` and `email_verified` to the session token in the Clerk
// dashboard (Sessions → Customize session token).Firebase: step by step
- Find the Firebase project ID: Project settings → General in the Firebase console, or
projectIdin your app's Firebase config. It looks likemy-app-1a2b3. - Save the Sign-in Mode in Onelo with the Firebase provider and that project ID.
- Add the Firebase block below to your app.
import { getAuth, onAuthStateChanged } from 'firebase/auth'
// `onelo` is the instance above.
const firebaseAuth = getAuth()
// getIdToken() returns the current ID token and refreshes one that expires
// within five minutes. No current user = signed out.
const firebaseToken = async () => (await firebaseAuth.currentUser?.getIdToken()) ?? null
// Fires once on start, then on every sign-in and sign-out.
onAuthStateChanged(firebaseAuth, () => {
onelo.auth.useExternalToken(firebaseToken).catch((e) => console.error('[Onelo]', e))
})Another OpenID Connect issuer
Any other issuer connects through the same door, with the issuer URL and the audience. What it has to do:
- Publish a discovery document at
<issuer>/.well-known/openid-configurationwhoseissuerequals the URL you enter, character for character, and which names a key set (jwks_uri). - Sign with RS256 or ES256, and give every signing key a key id (
kid). - Put in each token:
issequal to the issuer,audcontaining the audience you entered, a non-emptysub, and bothiatandexp, at most one hour apart. - Be reachable over HTTPS on a public address, on the default port, without redirects.
To give Onelo the user's address, include the standard email and email_verified claims. There is no ready-made block for a generic issuer: hand useExternalToken a function that returns your issuer's current token, the way the provider blocks above do.
Wire your app: web (JavaScript) and Node.js
Install and initialize the JavaScript SDK in the browser and, when you have a server, the Node.js SDK there. These are the same install panels as on the Auth page.
Install
npm install github:onelo-tools/onelo-jsInitialize
import { Onelo } from '@onelo/js'
// Initialize once (e.g. in a module-level singleton)
const onelo = new Onelo({
publishableKey: 'onelo_pk_live_YOUR_KEY',
apiUrl: 'https://api.onelo.tools',
})Usage
// Sign in. This is your app's FIRST screen for a visitor with no session:
// call it where you would otherwise redirect to /login — NOT from a "Sign in"
// button. It renders INSIDE your own window (no popup, no extra step) and
// auto-routes to waitlist / paywall-store when those are enabled for your app.
//
// Once the app is live, your site's origin must be in Allowed Domains
// (dashboard → app → Security). While the app is not live nothing is enforced,
// whatever that list holds — localhost and a staging host just work. After
// "Go live" only origins on the list work, exact match: add every one you serve
// from (www, staging subdomain) before you switch.
const session = await onelo.loadAuthView()
// Escape hatch — a top-level popup window instead of the in-page view. Only for
// origins you genuinely cannot add (a preview host with a rotating hostname, an
// embedder whose CSP you don't control). Browsers can block popups, so never
// reach for this just to skip the Allowed Domains step.
// const session = await onelo.loadAuthView({ mode: 'popup' })
// Read the current session + react to changes. null = signed out: your own
// signOut(), a remote revoke, a declined consent gate, or a session that ENDED
// (expired, or its refresh token was replaced — e.g. another device). None of
// these throws — getSession() just answers null. A gated app goes straight back
// to sign-in; this ONE handler covers every case:
const current = await onelo.auth.getSession()
const unsub = onelo.auth.onAuthStateChange((s) => {
if (!s) void onelo.loadAuthView()
})
// ── Paywall hard-gate (apps that sell access) ───────────────
// loadAuthView() (above) never lets an unentitled user through: it resolves with
// a session ONLY once they are allowed in, and null otherwise. Which screen it
// shows them first depends on your Access Gate — the store, or Onelo's "No
// active plan" — but the RESULT is the same either way, which is exactly why you
// gate on the result and never on "sign-in happened". (Unlike Electron you don't
// manage a window — your framework re-renders on state — but this is the same
// entitlement the SDK enforces server-side on every call.)
// ONE call: "signed in AND allowed in". It folds the session check and the
// entitlement check together, so there is nothing to assemble by hand — and a
// gate you assemble by hand is a gate you can assemble wrongly. (The composed
// form this replaces omitted the session check, so a signed-out visitor to a
// NON-paywalled app passed it.) Requires @onelo/js 0.42.0+.
if (await onelo.auth.isAllowedIn()) {
// → render your app
} else {
// Not entitled. WHAT the user was just shown depends on your Access Gate
// (Paywall → Store → Access Gate), so do not assume a store:
// "Show the store" — they saw the store and closed it without buying.
// "Sign in only" — there is no in-app store at all; they saw Onelo's
// "No active plan" screen. Sending them to a store here
// would point at something that does not exist.
// Either way: keep your locked screen. loadAuthView() re-opens whichever
// surface is correct for your settings, so call that rather than a store.
}
// Sign out (also revokes the session server-side).
//
// This clears the session and fires onAuthStateChange(null) — and that is ALL
// it does. It does NOT open the sign-in screen for you, because whether a
// signed-out visitor should see a login box, a marketing page or a guest mode
// is your app's decision, not ours. In a gated app the onAuthStateChange
// handler above re-opens sign-in — for this AND for a session that ended.
await onelo.auth.signOut()
// ── Magic link ──────────────────────────────────────────────
// Nothing to wire when you use loadAuthView(): the hosted page offers the link,
// and the tab opened from the email hands the sign-in back to the tab you
// started in, which then continues as normal. The email tab shows a short
// "you can close this" message instead of a second copy of your app.
//
// Building your own sign-in UI instead? sendMagicLink needs a return URL on the
// web — the email always opens a NEW tab, so without one there is nowhere to
// come back to. It must be an absolute URL on an origin in your Allowed Domains
// (a bare path is refused); the SDK finishes the sign-in when the browser lands
// back there. This one check does not wait for "Go live": as soon as the list
// has an entry, the return URL has to be on it.
// await onelo.auth.sendMagicLink(email, "https://yourapp.com/signed-in")
// ── Legal-consent gate (Terms / Privacy updates) ────────────
// When you publish a version with "Require in-app acceptance" ON in the
// dashboard (works for BOTH Terms of Service AND Privacy Policy), signed-in
// users get a BLOCKING full-screen gate they must accept — or Sign out — before
// continuing. Auto-presents on sign-in and the moment you publish (over SSE).
// "Notify only" versions never block. Nothing to wire — it's on by default.
//
// Return to sign-in on ANY sign-out (the gate's Sign out, a session revoke, or
// an ended session): the onAuthStateChange handler above already does it.
//
// Custom UI instead of the built-in gate (new Onelo({ autoPresentConsentGate: false })):
// onelo.consent.onConsentRequired(() => { /* re-read + render your own banner */ })
// const pending = await onelo.consent.requiredConsents()
// await onelo.consent.acceptConsent(pending[0].versionId)Install
npm install github:onelo-tools/onelo-nodeInitialize
import { Onelo } from '@onelo/node'
import { requireUser } from '@onelo/node/express'
// Authenticate with your SERVER SECRET key (onelo_sk_live_…) — NOT a
// publishable key. Read it from the environment; never hard-code a secret.
const onelo = new Onelo({
secretKey: process.env.ONELO_SECRET_KEY!, // onelo_sk_live_… (NEVER commit)
apiUrl: 'https://api.onelo.tools',
})Usage
// The frontend sends the user's ACCESS TOKEN (returned by the Onelo SDK after
// sign-in — NOT your secret key) as: Authorization: Bearer <token>.
// requireUser verifies it and attaches req.oneloUser. When the App's Sign-in
// Mode is an external provider (Supabase, Clerk, Firebase…), requireUser also
// accepts that provider's token, so the frontend keeps sending what it sends.
app.get('/me', requireUser(onelo), (req, res) => {
// requireUser guarantees req.oneloUser is set here — assert non-null.
res.json({ id: req.oneloUser!.id, email: req.oneloUser!.email })
})
// Post-verify gates + SSE support (all optional):
// requireUser(onelo, { acceptQueryToken: true }) // allow ?token= for EventSource/SSE
// requireUser(onelo, { identifyMonitor: false }) // opt out of auto monitor.setUser (on by default when a monitor scope is active)
// optionalUser(onelo) // sets req.oneloUser = null instead of 401 (a 503 outage still surfaces)
// ── Other frameworks — one adapter import, same onelo client ──
// Next.js → import { withUser } from '@onelo/node/next'
// export const GET = withUser(onelo, async (req, user) =>
// Response.json({ id: user.id }))
// Fastify → import { requireUser } from '@onelo/node/fastify'
// fastify.get('/me', { preHandler: requireUser(onelo) },
// async (req) => ({ id: req.oneloUser!.id }))
// Hono → import { requireUser } from '@onelo/node/hono'
// app.use('/me', requireUser(onelo))
// app.get('/me', (c) => c.json({ id: c.get('oneloUser').id }))
// Any other (Koa, Nest, raw http, WebSocket, queue worker):
// import { verifyToken } from '@onelo/node'
// const user = await verifyToken(onelo, token) // throws typed errors
//
// Error → status: OneloAuthInvalidToken / missing → 401 · OneloAuthForbidden /
// failed gate → 403 · OneloAuthRateLimited (429) / OneloAuthUnavailable (5xx) → 503.In the browser, add the block for your provider from the sections above. Each one hands onelo.auth.useExternalToken(getToken) a function that returns the provider's current token, or nothing when no user is signed in there. Then read the Onelo session as usual:
// From here every module works as with Onelo Auth.
const session = await onelo.auth.getSession() // null = signed out at the provider
onelo.auth.onAuthStateChange((s) => {
console.log(s ? `signed in as ${s.user.email}` : 'signed out')
})
if (await onelo.auth.isAllowedIn()) showApp()- When your function returns no token, the Onelo session ends and
onAuthStateChangereports signed out. - Onelo sign-in screens are never shown in this mode:
loadAuthView()only returns the current session. - On the server,
requireUserandverifyTokenfrom the Node.js SDK accept the provider's token as well as an Onelo session token. Your frontend keeps sending theAuthorization: Bearerheader it sends today; the SDK exchanges the token at Onelo with your secret key and hands you the Onelo user.
A server without tokens: the server assertion
If your backend signs users in with its own server sessions and has no issuer token to hand over, your server can say who the user is instead. Create an identity key on the API Keys page (Identity keys). It can only assert which user is signed in, can be limited to your server's IP addresses, and is not a Secret Key. Two keys can be active at once, so you can rotate without downtime. The Node.js SDK refuses to run this call in a browser.
import { assertIdentity } from '@onelo/node'
// On YOUR server, after your own sign-in has identified the user.
// The identity key (onelo_ik_live_…) comes from the dashboard: API Keys →
// Identity keys. It can only say who is signed in; it is not a Secret Key.
// Read it from the environment; never send it to a browser.
const { user, session } = await assertIdentity({
apiUrl: 'https://api.onelo.tools',
identityKey: process.env.ONELO_IDENTITY_KEY!,
externalId: account.id, // your own id for this user
email: account.email, // optional
emailVerified: account.emailVerified === true,
})
// session.accessToken is an ordinary Onelo session (30 minutes, no refresh):
// hand it to your frontend, or use user.id with the other Onelo modules.
// Refusals throw typed errors with .code — invalid_identity_key,
// ip_not_allowed, sign_in_mode_onelo, banned, rate_limited …What changes for your app
- Onelo's own sign-in is closed for the app. The hosted sign-in and sign-up pages, password sign-in and password reset, magic link, Onelo's social sign-in with Google, GitHub and Apple, and account creation in the hosted store all answer
sign_in_mode_external. Users come in through your sign-in only. - Every other module works with the same user. The exchange returns an ordinary Onelo session, and Paywall, Features, Consent and the rest read that session the way they read one from Onelo Auth.
- Bans and plan limits apply unchanged. A banned user is refused at the exchange, and the monthly active user limit of your plan counts these users.
Limits today
- Web (JavaScript) and Node.js only. Electron, Python and the mobile SDKs (Swift, Android, Flutter, React Native) still use Onelo Auth and cannot connect an own sign-in yet.
- Social sign-in through your provider works unchanged. When Google, Apple or GitHub sign-in runs through the provider you connected, Onelo receives that provider's token, the same as after a password sign-in. There is nothing extra to configure.
- One app trusts one issuer. If you wired several social providers directly, with no provider in between, you have several issuers (Google and Apple are two), and an app accepts one. The way through is your own backend issuing one OpenID Connect token after any of them.
- The issuer must speak OpenID Connect with asymmetric keys. A sign-in that issues no OpenID Connect token, a home-made sign-in on session cookies, or tokens signed with a shared secret (HS256) cannot be connected: saving the Sign-in Mode is refused. What you need is a published discovery document and RS256 or ES256 signing keys.
- Onelo Auth has none of these limits. Password, magic link and Google, GitHub and Apple sign-in work together on one app, already configured. That is the reason to choose Onelo Auth when the app has no provider yet.
- Onelo's social sign-in is closed in this mode, together with the rest of Onelo Auth. The two cannot be mixed on one app.
- Users are not imported or moved. Switching an app that already has users is locked, as described above.
E-mail rules for these apps
- The address is copied from the token's
emailclaim on every exchange, so a change at your provider reaches Onelo at the next sign-in or renewal. - It counts as verified only when the token says
email_verified: true. Bulk mail from Onelo goes only to addresses your provider marked verified. - A token with no e-mail creates the user with a placeholder address that is not a real mailbox.
- Accounts are never linked by e-mail. Two identities with the same address are two different people to Onelo, and the second one is refused (see
email_in_usebelow).
Troubleshooting: refusal codes
Every refusal carries a code. In the browser the SDK's error message names it; in Node.js it is on the error's code property. When a save is refused, the MCP answers with the code and the message; the dashboard shows the message.
When saving the Sign-in Mode
| Code | What it means |
|---|---|
sign_in_mode_locked | The app already has users, so the mode can no longer be changed here. Press Ask Onelo to migrate my users on the app’s Auth page in the dashboard. |
parent_owned_setting | This is a platform app of an Umbrella app. Set the Sign-in Mode on the Umbrella app. |
invalid_preset | The provider is not one of the four presets listed under “Turn on own sign-in”. |
invalid_project | The project value is neither a 20-character project reference nor a project URL starting with https://. |
invalid_project_id | Firebase: the value does not look like a project ID. |
invalid_issuer | Clerk or a generic issuer: the issuer URL is missing. |
invalid_audience | A generic issuer needs the audience its tokens carry in aud. |
invalid_authorized_parties | Authorized parties must be a list of at most 10 origins such as https://app.example.com. |
issuer_not_https | The issuer must start with https://. |
issuer_invalid_url | The issuer is not a usable URL: it is malformed, or carries a user name, password or fragment. |
issuer_port_not_allowed | The issuer must not name a port. |
issuer_query_not_allowed | The issuer must not carry a query string. |
issuer_private_address | The issuer resolves to a private or internal address. It has to be reachable from the public internet. |
issuer_unreachable | Onelo could not reach the issuer, its host was not found, or it answered with an error status. Check the URL for a typo. |
issuer_redirect | The issuer answered with a redirect. Onelo does not follow redirects; enter the final address. |
issuer_timeout | The issuer took too long to answer. |
issuer_response_too_large | The discovery document or key set is larger than 256 KB. |
issuer_invalid_document | The discovery document or key set is not valid JSON, or names no key set. |
issuer_mismatch | The discovery document names a different issuer. Enter the issuer exactly as it appears there, including or excluding the trailing slash. |
issuer_symmetric_key | The issuer publishes a symmetric or private key. Only asymmetric signing keys are accepted. |
issuer_no_signing_keys | The issuer publishes no RS256 or ES256 key. If it signs with a shared secret (HS256), switch it to asymmetric signing keys first. |
issuer_key_without_kid | A signing key of the issuer has no key id (kid). |
When a user signs in
| Code | What it means |
|---|---|
sign_in_mode_onelo | The app is on Onelo Auth, so it does not accept a provider’s token. Set the Sign-in Mode before calling useExternalToken(). |
sign_in_mode_external | The app uses its own sign-in, so Onelo Auth is not available for it. Something is still calling an Onelo sign-in screen or endpoint. |
token_malformed | What was sent is not a signed JWT. Check that your function returns the provider’s token and not a user object or an opaque session id. |
token_alg_not_allowed | The token is signed with something other than RS256 or ES256, typically HS256 from a shared secret. |
token_kid_missing | The token’s header names no signing key (kid). |
token_key_unknown | The token is signed with a key the issuer does not publish. Often a token from another project or instance. |
token_signature_invalid | The signature does not match the issuer’s key. |
token_issuer_mismatch | The token comes from a different issuer than the one saved: another project, a development instance instead of production, or a mistyped Firebase project ID. |
token_audience_mismatch | The token was issued for a different project or audience. |
token_authorized_party_mismatch | The token’s azp is not one of the authorized parties saved for the app. Add the origin your app runs on. |
token_expired | The token has expired. The JavaScript SDK asks your function for a fresh one and retries. |
token_not_yet_valid | The token is dated in the future, usually a clock a little off. The JavaScript SDK retries. |
token_lifetime_too_long | The token is valid for more than one hour, or lacks iat or exp. Shorten the token lifetime at the issuer. |
token_subject_missing | The token names no user (sub). |
email_in_use | Another user of this app already has this e-mail. See below. |
banned | The user is banned in Onelo. |
account_deleted | The user’s Onelo account was deleted. |
issuer_unavailable | Onelo could not read the issuer’s signing keys just now. Temporary: the SDK keeps the session and retries. |
rate_limited | Too many exchanges in a minute from one address, for one user or for the app. Temporary. |
new_user_cap_reached | The app created too many new users in the last hour. Temporary: existing users are not affected. |
go_live_required | The app is still a draft and has reached its draft user limit, so no new user can be created. Go live to add more users. |
plan_limit_exceeded | The monthly active user limit of your Onelo plan is reached. |
no_plan_available | The app sells access and signs out users whose access has ended, and this user has no active plan. |