Add sign-in to your app
Prompt:
Let people sign in to my app with Google, GitHub, or a code sent to their email.
Also works:
- "Only let people I invite use this for now. Everyone else should see a short coming-soon page."
- "Lock the app down to the beta group until launch."
- "Nobody gets in without an invite yet, and search engines shouldn't see it."
- "Some of my users don't have Google. Let them sign in with their email address."
- "Let our staff sign in with their work accounts."
What your tool does
- Reads the application's manifest. Where its
servicesarray declares no accounts service, it adds{"kind": "accounts"}and submits the manifest as Author the manifest and the platform'sadd-serviceskill state. The submission creates an end-user realm for each environment the application has: production's alone on an application with one environment. - Calls
read_realmwith the application's identifier for each environment, to learn the realm's current sign-in methods, creation policy, and limits. - Calls
configure_realmwith the sign-in methods you chose, once for production, and once more withenvironment: "development"where the application has a development environment, because each call reaches one realm. The manifest'srealmmember can set the sign-in methods, the creation mode, and theentraandapplemembers for each realm the application has at once instead (Author the manifest). - For a work-account route, asks you for the tenant identifier, the client identifier, and the name the client secret is stored under. It passes the name in
entra, never the value. Where the secret is not stored yet, it sends you to Store a secret first. - For invitation-only sign-up, sets the manifest's
audienceto{"kind": "invited"}and submits it, or keeps apublicaudience and callsconfigure_realmwithcreation: "invited"(step 6). Where a realm's sign-in methods includeentra, it first removes that route withconfigure_realm. - Writes the sign-in and sign-out links into the application and, where the backend needs to know who is signed in, the session check (step 8).
- For a private beta with a notice page, writes the notice page into the application (step 9), and the optional header check where you want your own tools to read the pages (step 10).
- Deploys the change as Deploy an application states, so sign-in is live on the hostname your users open. The deploy reaches production on an application with one environment; with two, it reaches development, and a promote then moves the change to production.
- For invitation-only sign-up, calls
issue_invitationwith the application's identifier and each person'semail, and prints eachurl. The platform emails nothing for an application's users, so you deliver the URL yourself. - Asks you which sign-in methods to offer and whether sign-up is open or invitation-only, where the prompt does not say. It asks for the addresses to invite where the prompt names none.
- Reports every value it configured and every invitation URL. It asks for no browser approval, because every call here takes effect when it is made.
What you need
- Which ways to sign in you want to offer: Google, GitHub, passkeys, a code emailed to the person, or a company work account.
- Whether anyone may sign up, or only people you invite.
- For invitation-only sign-up, the email addresses of the people you want to invite, and a way to send each person their invitation link yourself.
- For a private beta, the wording of the notice page shown to everyone else, in whichever language you choose.
- For work-account sign-in, the tenant identifier (a GUID) and the client identifier of the app registration in that company's tenant. You will also need the client secret value from that app registration. Step 5 names the redirect URI the registration lists.
Before your AI starts
This section is for your AI tool: what it checks and gathers before it begins. You don't need to do these steps yourself.
- A connected, signed-in tool (Connect your tool).
- A deployed application with a backend (Deploy an application), and its manifest (Author the manifest). Step 1 adds the accounts service if the manifest lacks it.
- The application's identifier, which
list_applicationsreturns. - For work-account sign-in, the client secret stored by name at the application's scope, in the environment the realm belongs to (Store a secret).
- For a session check in the backend, the Account package at version 0.9.0 or later (Account).
Steps
1. Turn on sign-in for the application
Declare {"kind": "accounts"} in the manifest's services array and submit the manifest. The application then gets one end-user realm for each environment it has. A realm is the application's own set of users, with their sign-ins, passkeys, and invitations. Each realm is kept apart from any other environment's realm, from other applications, and from the platform's own accounts, so your users need no Turn Zero account.
A new application has one environment, production, so it has one realm, production's. Your testers sign in there beside your live users, also while the backend runs on your machine. Turning on a development environment gives it a realm of its own (Manage versions and environments).
A new realm offers the sign-in methods google, github, email, and passkey, and open sign-up. Under an invited audience it is invitation-only instead. Manage end users states what happens to a realm when its environment or its application is deleted.
A development realm has at most ten end users on every plan. A sign-in that would create an eleventh is refused 403 development_realm_full. An existing user can always sign in.
2. Where your users sign in
- The sign-in pages are on the application's own hostnames, under the path
/__account/. Your application's own routes cannot use that path. - The sign-in page is
/__account/signin. It shows the sign-in methods the realm offers. - A link to
/__account/start/<method>, such as/__account/start/google, starts that provider's sign-in at once, without the sign-in page. A "Continue with Google" button on your own page can link there. The method must be one the realm offers ofgoogle,github,apple, andentra, or the link returns 400route_not_enabled. - After an ordinary sign-in, the browser returns to
/on the same hostname. - On an application with one environment, users and testers sign in at the production hostname,
<label>.ai.host, also during a local run. The development hostname offers no sign-in, and returns 404realm_not_declaredunder/__account/. - Where the application has a development environment, its hostname,
<label>-dev.ai.host, signs users in to the development realm, even before the first development deploy. - While an environment is halted, its hostname returns 503
environment_haltedon/__account/too, so sign-in waits until the environment is resumed. GET /__account/mereturns the signed-in user, andPOST /__account/signoutsigns the user out.
3. Choose the sign-in methods
Call configure_realm with the application's identifier and sign_in_methods, the complete list of sign-in methods to offer. The list replaces the current one, and the change takes effect at once, with no redeploy. configure_realm reaches production when environment is left out. Where the application has a development realm, configuring both realms takes a second call with environment: "development".
| Sign-in method | How the person signs in |
|---|---|
google |
With a Google account. |
github |
With a GitHub account. |
passkey |
With a passkey kept on a device or in a password manager, a faster way to sign in by emailed code. Named only beside email. |
email |
With a six-digit code emailed to their address (step 4). |
entra |
With a Microsoft work account of one company (step 5). |
The rules for sign-in methods:
- An empty list turns sign-in off.
- A passkey is a faster way to sign in by emailed code, so
passkeyis accepted only besideemail.configure_realmandcreate_environmentrefuse a list namingpasskeywithoutemailaspasskey_not_sole_route.submit_manifestrefuses it asmanifest_invalid, naming that rule. - Where a realm offers both, a user with no passkey is offered one after each sign-in by emailed code, and never after a Google or GitHub sign-in. A user who declines is offered one again after thirty days. Leaving
passkeyout ofsign_in_methodsturns that offer off, and passkey sign-in with it. - To remove
emailfrom a list namingpasskey, removepasskeywith it. The realm keeps its users' passkeys, unused, until both routes return. - A realm whose stored list names
passkeywithoutemailserves no passkey route, and thedetailofread_realmsays so. - Only a user who signs in by emailed code can register a passkey. Manage end users shows how your page tells which users can.
- A passkey works only on the hostname it was registered on, so a development passkey works only on the development hostname. Manage end users covers passkeys after a rename.
4. Turn on the emailed code
A new realm offers the emailed-code route. Where a realm's sign_in_methods leave it out, call configure_realm with sign_in_methods including email, for example ["google", "github", "email"]. The application's sign-in page then shows an address form after the provider buttons.
The user enters an address and receives a six-digit code. They type it on the same page, in the same browser, within ten minutes. The message contains no link. Under invitation-only sign-up, a code is sent only where the address belongs to a user of the realm or matches the invitation that browser opened. The page looks the same either way, so it does not reveal which addresses are known.
A user who signs in by code with an address their Google or GitHub identity already verified reaches the same user, with the new route added. list_end_users shows the routes each user has.
The code comes from donotreply@turnzero.ai, display name Turn Zero. Its subject is "Your sign-in code for" followed by the hostname label. The hostname label is the application's label for production and <label>-dev for development; after a rename it is the new label. The message is fixed text: the code, its ten-minute validity, a line for anyone who did not ask, and a line saying never to share the code. It contains nothing a user typed and is not tracked.
The limits on emailed codes:
| Limit | Value | Refusal | Can you raise it? |
|---|---|---|---|
| Codes sent to one address per hour | limits.code_sends_per_hour, 5 by default |
signin_code_rate_limited |
Yes, up to 30 |
| Wrong entries for one address per hour | 10 | signin_code_rate_limited |
No |
| Codes sent by one realm per hour | Set by the application's plan: 30 on Free, 300 on Standard, 1,000 on Pro | signin_code_rate_limited |
No; it follows the plan |
| Codes sent across the platform per hour | The platform's mail quota less 10; 90 at the default quota | signin_code_rate_limited |
No |
| Emailed-code starts from one source address per hour, across every realm | A sixth of the platform-wide limit; 15 at the default quota | signin_rate_limited |
No |
A code start also counts toward the realm's signin_starts_per_hour limit, which does not change that share. A passkey sign-in counts one start toward signin_starts_per_hour, as a code start does. A workforce realm never offers the route, and configure_realm refuses email there.
The development realm offers the route too and sends real mail under the same limits, because your own sign-in on the development hostname needs it. Where the development realm's sign_in_methods leave it out, turning it on takes the second call with environment: "development".
5. Work accounts
A work account is a person's Microsoft Entra account at one company. To offer it, call configure_realm with entra:
tenant, the company's tenant identifier, a GUID;client_id, the client identifier of the app registration in that tenant;client_secret_name, the name the client secret is stored under at this application's scope.
In the app registration, add the address in callbacks.entra as a web redirect URI, exactly as returned. read_realm and configure_realm both return it once the manifest declares the accounts service, even before the route is set up. On the production platform it is https://turnzero.ai/auth/entra/callback. It is never your application's hostname, and both environments of every application use it.
In the app registration's Token configuration, add the optional claims email and xms_edov to the ID token. A work-account user's address is the email claim the tenant sends. It is verified only where the token also carries xms_edov as true, meaning the address's domain owner is verified, and unverified otherwise. The address comes marked source: "tenant", and a route that needs a verified address reads verified first.
A verified work address is one account's address. At its first sign-in, a person whose address another sign-in method already holds is asked to link, not given a second account. A work account whose verified address another account already holds can sign in with that address unverified. That happens on a realm without the emailed code, and where the other account holds the address through a work account alone. A code sent to an address that only a work account holds verified asks the person to sign in with that work account to link.
Supplying entra prepares the work-account settings; name entra in sign_in_methods to turn the route on. Configuring moves the secret into the realm vault, where it stays under that name, and you rotate it by name as before. A name an upstream of this application already uses is refused. Manage end users lists every member of the entra setting.
The manifest's realm member can name the same entra member for each realm the application has at once, where a client secret not stored yet is accepted (Author the manifest).
The entra route cannot be used with invitation-only sign-up, whether the realm's creation or the invited audience makes it so. To allow only one company's staff, declare the workforce audience with that tenant (step 6). A workforce audience allows only the entra route of its declared tenant. The audience decides who may reach the app, and the realm's entra route, set up with the same tenant, is what signs them in, so declare both.
6. Choose who may sign up
Two settings set who may become a user and who may reach the pages. The realm's creation is open or invited. Under open, anyone who signs in becomes a user, and no invitation is needed. Under invited, a first sign-in without an invitation creates no user and is refused unrecognized_invitation.
The manifest's audience sets who may reach the application. The platform checks it before it forwards a request.
publicneeds no end-user sign-in.invitedneeds an end-user session and accepts new users only by invitation.workforceallows only signed-in users of the declared Microsoft Entra tenant.
Under invited and workforce, a request without an end-user session is refused, on every path but /__account/ and the paths the audience lists as session-free. A visitor who opens a page is sent to the sign-in page, and any other request is refused 401 authentication_required.
A payment provider's webhook, or any other service's callback, has no session. To receive one under those two audiences, list its path in the audience's session_free_paths, for example {"kind": "invited", "session_free_paths": ["/webhooks/stripe"]}. The platform lets every request to a listed path through without checking who sent it. So the route at each listed path checks the provider's signature itself and refuses a request without a valid one.
The list has at most ten paths. Each starts with /, is not / alone, contains no spaces and no .., and is outside /__account/ and /__router/. A listed path also covers every path below it: /webhooks/stripe covers /webhooks/stripe/events, but not /webhooks/stripe-test. A public audience lists none, because it lets every request through already. A path that breaks a rule is refused manifest_invalid at its own place in the list.
A request whose path contains a dot segment, .., or an encoded dot, slash, backslash, or percent sign is never read as a listed path and is gated as usual.
The manifest's health path is gated like every other path. The platform's own deploy check still reaches it, and a request from outside without a session is refused unless the list names the path. Choosing the health path says what listing it opens.
The invited audience makes every realm of the application invitation-only, whatever their creation setting. configure_realm then refuses creation: "open", and read_realm still shows the configured value, with a detail saying creation is invitation-only because of the audience. To allow sign-ins without an invitation, change the audience to public and resubmit the manifest. A manifest declaring invited while a realm's sign-in methods include entra is refused declared_audience_contradicts_route; remove the route with configure_realm first.
Pick one of three set-ups:
| You want | Audience | Creation |
|---|---|---|
| Anyone may sign up | public |
open, the new realm's default |
Only invited people, every page behind sign-in except the webhook paths you list in session_free_paths |
invited |
Invitation-only by the audience |
| Only invited people, with a notice page of your own | public |
invited, set on each realm with configure_realm |
One manifest covers every environment the application has, so the audience applies to each. Where the application has a development environment, anyone who knows its hostname can reach it and its data under a public audience. The platform does not publish that hostname, and every response on it includes X-Robots-Tag: noindex, nofollow. Treat development test data as public under a public audience, or declare an invited audience while the application is in development.
7. Invite people
Under invitation-only sign-up, issue_invitation invites each person. Call it with the application's identifier and the person's email, and with environment: "development" for the development realm. It returns an invitation with its id, email, single-use url, and expires_at, 14 days away by default. The platform does not email it, so you deliver the URL yourself.
Opening the URL opens the application's sign-in page with the realm's sign-in methods. The page shows nothing of the invitation, so a spent or expired URL looks the same. The person signs in with a route that verifies the invited address. list_invitations shows the invitation as standing, then redeemed after the person signs in. Manage end users covers listing, revoking, and suspending.
8. Check who is signed in
Give your pages a link to /__account/signin, or to one provider's /__account/start/<method> (step 2), and a sign-out control that posts to /__account/signout. GET /__account/me returns the signed-in user to a page as JSON. It returns 401 without a live session, and 403 user_suspended for a suspended user.
| Member | What it contains |
|---|---|
user.id |
The user's opaque identifier, the same one your backend's verification returns. |
user.realm |
The realm the user belongs to. |
user.addresses |
The user's verified addresses, each as email and verified. A user who signed in only with a work account also has the tenant's address, marked "source": "tenant", verified or not. |
user.routes |
The providers linked to the user: google, github, apple, entra, or email. A passkey is not listed. |
user.standing |
active. |
session.expires |
When the session ends. |
A page that shows who is signed in can read the address here, with no route of your own.
Where the backend needs to know who sent a request, it verifies the session on each request. A signed-in user's browser has the cookie __Host-turnzero_cloud_realm on the application's hostname, and the Account package's verification client checks it. Manage end users shows how to build the client, and Verifying an end user explains the token and the keys.
For invitation-only sign-up under a public audience, verify the session on every page request, so sign-in is required on every page. Send a visitor without a session to the notice page of step 9, or to the sign-in page. With invitation-only sign-up, every signed-in user was invited. Under the invited audience, the platform already sends a visitor without a session to the sign-in page.
9. A private beta: a notice page of your own
A private beta with a notice page takes three pieces your application already controls, and an optional fourth. The platform has no single switch for it. Each piece is a few lines of your own code, and the notice's words, language, and design stay yours:
- Invitation-only sign-up under a
publicaudience (step 6). - Sign-in required on every page (step 8).
- A notice page for everyone else, this step.
- Optionally, a request header for your own tools (step 10).
The notice page needs the public audience. Under the invited audience, the platform sends a visitor without a session to the sign-in page before any code of yours runs, so the visitor never sees the notice page.
For a visitor without a session, serve a static page of your own. While the beta lasts, keep search engines out:
- give the page
<meta name="robots" content="noindex">; - send it with the response header
X-Robots-Tag: noindex, nofollow; - respond to
/robots.txtwithUser-agent: *andDisallow: /.
The page is a file of your application, so its words and language are yours. Give it a link to the sign-in page for the people you invited.
10. Optional: a request header for your own tools
Your own tools may need to read the pages during the beta, such as a coding agent with a shell or a check script. For them, accept one request header, for example X-Show-Page. Serve the page to any request that includes the header, with any value. Send the same noindex headers, and Vary: X-Show-Page.
A person in a browser cannot set a request header, and a crawler sends none, so both still see the notice. A shell reads a page with curl -H "X-Show-Page: 1" <url>.
The header is a convenience, not security: anyone who learns its name can read the pages. That is the same protection a beta notice gives. Never let the header open a page that shows a user's data; keep such pages behind sign-in.
The platform's own documentation site uses the same pattern while the site is private, as its home page describes.
Expected result
configure_realm returns a realm object with the realm identifier, the sign_in_methods, the creation policy, the three limits, invitation_days, session_days, and the entra settings where they are set. It also returns callbacks, the platform's addresses that the entra and apple registrations list (step 5 for entra; Manage end users for apple). Its detail says the realm uses the configuration from now on and that deploying code changes none of it. read_realm returns the same members, with counts of users and sessions and the secrets names. Under a public audience with invitation-only sign-up, both show creation: "invited" and the methods you kept.
The detail also names each change the call made that affects sign-in, and the response's page is the address of this page. Each of those changes means:
- With no route enabled, no one can sign in (step 3). Under the
invitedaudience, sign-up stays invitation-only (step 6). - A new
session_daysapplies to sessions opened from then on. A browser session keeps the expiry it was opened with, and a native app's session takes the new length at its next refresh. session_cap_daysis the most days a native app's session can run from its creation, checked at each refresh.- Each declared native client holds no secret, and sign-in accepts only the redirect URIs it declares, exactly, except that a loopback URI may use any port (Sign in from a native app).
- Where a raised
minimum_versionrefuses versions seen in the last day, the response also containswarnings, which names those versions for each client (Keep installed clients compatible). - The work-account settings (
entra) or the Sign in with Apple settings (apple) are saved, and that route is offered oncesign_in_methodsnames it (step 5; Manage end users for Sign in with Apple). The platform reads the client secret or the signing key by its name only to sign a user in, and no response ever contains it.
Under the invited audience, submit_manifest responds with the realms confirmed. read_realm shows the configured creation value, with a detail saying creation is invitation-only because of the audience.
issue_invitation returns the invitation's id, email, single-use url, and expires_at, and its detail says nothing was emailed. After the person uses the URL, list_end_users lists them with standing: "active" and the route they used, and list_invitations shows the row as redeemed.
On the deployed hostname:
- the sign-in page shows the sign-in methods you enabled;
- under open sign-up, a person who signs in becomes a user;
- under invitation-only sign-up, a person who opens an invitation URL signs in and reaches the pages;
- a sign-in without an invitation creates no user and is refused
unrecognized_invitation; - under the
invitedaudience, a visitor without a session is sent to the sign-in page; - under a
publicaudience with a notice page, a visitor without a session receives your notice page with the noindex header, and/robots.txtdisallows every path; - a request from a shell with the optional header receives the page, and a browser without a session still receives the notice.
Refusals
A refusal changes nothing on the platform. The status is the one the HTTP route returns, and the Model Context Protocol (MCP) tool returns the same name. The rows from development_realm_full on are returned on the application's hostname, to the person signing in or to the request. The manifest submission's refusals are listed under Author the manifest, and the deploy's and the promote's under Deploy an application. Refusals lists every refusal the platform returns.
Where the manifest's realm member sets the credential, custody_entry_missing, custody_entry_unmovable, and name_bound_to_setting come from submit_manifest or create_environment instead. There the manifest stays recorded, and the remedy is the value stored again, a new name in the manifest, or the binding removed.
| Refusal | Status | Cause | Remedy |
|---|---|---|---|
invalid_request |
400 | A member is missing or malformed, such as an unknown route or creation value, entra.tenant not a GUID, or a limit out of range. issue_invitation named no valid email. The detail identifies the member. |
Correct the named member and call again. |
passkey_not_sole_route |
400 | configure_realm, or the manifest's realm member through it, named passkey without email. A passkey is a faster way to sign in by emailed code, not a route on its own. |
Name email beside passkey, or leave passkey out. To remove email from a list naming passkey, remove passkey with it; the realm's passkeys stay unused until both return. |
no_such_application |
404 | configure_realm, read_realm, or issue_invitation named an application the account does not own. |
Use the identifier list_applications returns. |
realm_not_declared |
404 | The manifest declares no accounts service, so there is no realm to configure or invite into. The development hostname of an application with one environment returns it under /__account/ too. |
Add {"kind": "accounts"} to the manifest's services, call submit_manifest, then call again. For the development hostname, sign in at the production hostname. |
environment_not_created |
409 | configure_realm, read_realm, or issue_invitation named development on an application with one environment, which has no development realm. |
Leave environment out to reach the production realm, or turn development on with create_environment. |
grant_required |
403 | configure_realm or issue_invitation was called without application. |
Name your application in the call. |
token_scope_refused |
403 | A token bound to one application named another application, or left out application. |
Name the token's application, or use your signed-in session or a token for the whole account. |
app_credential_not_admitted |
403 | The call ran under an application's platform credential, which only read_account accepts. |
Use your signed-in session or a minted token. |
account_suspended |
403 | Your account is suspended, so actions that need your identity are refused. | Wait for platform staff to reinstate the account, then sign in again. |
invited_realm_refuses_work_account |
409 | configure_realm combined invitation-only creation, by creation: "invited" or by the invited audience, with the entra route. |
Leave entra out of sign_in_methods. Where the realm's own creation makes it invitation-only, set creation: "open" under a public audience. |
creation_contradicts_audience |
409 | configure_realm named creation: "open" under the invited audience. |
Leave creation out or name invited. To allow sign-ins without an invitation, change the audience to public and resubmit the manifest. |
declared_audience_contradicts_route |
409 | submit_manifest declared the invited audience while a realm's sign-in methods include entra. |
Remove entra from that realm's sign_in_methods with configure_realm, then submit the manifest again. |
declared_tenant_contradicts_route |
409 | The workforce audience gives a different tenant from the work-account route of one of the application's realms, and the refusal's environment names which. |
Declare that route's tenant, or call configure_realm for the named environment with the audience's tenant. |
route_set_contradicts_audience |
409 | Under a workforce audience, configure_realm named a route such as email, or an entra.tenant other than the declared one. |
Name entra alone with the declared tenant, or change the audience and resubmit the manifest. |
custody_entry_missing |
409 | configure_realm named a client secret that is not stored at the application's scope in the realm's environment. |
Store it with store_secret, as Store a secret describes, naming the application and environment, then call configure_realm again. |
platform_minted_name |
409 | configure_realm named a credential the platform minted, credential-<application id>, database-<application id>, or issue-tracking-<application id>, as the client secret. |
Store the client secret under your own name with store_secret, as Store a secret describes, and name that. |
name_bound_to_upstream |
409 | configure_realm named a secret that an upstream of this application uses. |
Store the secret under another name at the application's scope, and name that. |
name_bound_to_push |
409 | configure_realm named a secret that a push configuration of this application uses as a provider credential. |
Store the secret under another name at the application's scope, and name that. |
name_bound_to_setting |
409 | configure_realm named a secret that a setting binds: the manifest's settings, the running copy of either environment, or a deploy, promote, or redeploy in flight to one. The detail names the setting and where it is bound. |
Store the secret under another name at the application's scope, and name that. A running copy keeps its binding until that environment's next deploy or promote of a manifest without it, and an action in flight keeps it until the action ends. |
realm_vault_unregistered |
409 | The platform has no realm vault set up for the application's hosting cell. | Report it to platform staff; nothing on your side fixes it. |
custody_entry_unmovable |
409 | The realm vault already contains the secret's name, live or soft-deleted, at another version. | Store the value under a new name with store_secret, as Store a secret describes, and name that. |
manifest_owned_field |
409 | configure_realm would change a field the manifest's realm member names. The detail names each field. |
Change the member in the manifest and resubmit it with submit_manifest. |
development_realm_full |
403 | A sign-in would create an eleventh user in a development realm. | Delete a development user with delete_end_user and environment: "development". Production has no such limit. |
realm_creation_ceiling |
403 | A sign-in would create more users than limits.creation_ceiling, 1,000 by default. |
Raise limits.creation_ceiling with configure_realm, or delete users. |
unrecognized_invitation |
403 | Under invitation-only sign-up, a first sign-in came without a valid invitation for that address. | Issue a new invitation for the address the person signs in with, and deliver its URL. |
signin_rate_limited |
429 | A source address passed signin_starts_per_hour, or its share of emailed-code starts in the hour across the platform. Or the address's passkey autofill requests on an application's sign-in page passed 120 in the hour, a window of its own that counts no sign-in start. The detail gives the share's number. |
Wait for the hour to pass. Raise the first limit with limits.signin_starts_per_hour; the share cannot be raised. |
signin_code_rate_limited |
429 | An emailed-code start passed one of the four code limits in step 4. | Wait for the hour to pass. Only limits.code_sends_per_hour can be raised. |
email_domain_undeliverable |
400 | An emailed-code start was for an address whose domain publishes no mail server, so no code could reach it. A reauthentication, which sends to the verified address, is refused the same way. | The person corrects a typo in the address and starts again. Where the start posted no address, they sign in with another route. |
environment_halted |
503 | The environment is halted, so its sign-in pages wait too. | Resume it with resume_environment. |
authentication_required |
401 | Under an invited or workforce audience, a request other than a page visit came without an end-user session, to a path the audience does not list as session-free. Your tool's own call gets it when no credential matched an account. |
The person signs in at /__account/signin first. For your tool's call, sign in again through your tool. |
Related
- Manage end users invites, lists, suspends, and deletes users, lists every realm setting, and verifies a session from the backend.
- Verifying an end user explains the session token and the keys your backend verifies against.
- Account is the package whose verification client the backend uses.
- Sign in from a native app signs in the users of a mobile app through the same realm.
- The manifest explains the audience kinds, and Author the manifest declares them.
- Store a secret stores the work-account client secret by name.
- Deploy an application deploys and promotes the change.
- Glossary defines realm, end user, and sign-in method.
- configure_realm, read_realm, issue_invitation, and list_invitations in the generated reference give each action's arguments, result, and refusals.