Passkeys
Every sign-in to Stabiso ends with a passkey. You sign in with your Google account, or with your email address and the password Google keeps, and then you confirm with your passkey: your phone, computer or password manager asks for your fingerprint, your face or its PIN. Only then does the session start (ADR-0101).
A stolen password is therefore not enough to sign in, and a fake sign-in page cannot use your passkey either: a passkey only works on the site it was made for. Nobody can switch passkeys off for a company or a person.
Your first passkey
The first time you sign in (after your invitation, or after your passkeys were reset) the sign-in page asks you to create your passkey. Your browser shows its own dialog: choose where to keep it (this device, iCloud Keychain, Google Password Manager or a security key) and confirm. From then on each sign-in asks you to touch it.
A passkey kept by a password manager (iCloud Keychain, Google Password Manager, 1Password and the like) is synced: your other devices get it too. A passkey on a security key, or kept by one device only, is shown as This device only; add a second one so that losing the device does not lock you out.
Your passkeys belong to your address, not to one company: they open every organization you are a user of, its test copies included.
My passkeys
Open My passkeys from your menu at the top right (or type "passkey" in Tell me):
- Add a passkey creates one more, for another device;
- Remove takes away one you no longer have. Your last passkey cannot be removed: add another first.
Both ask you to touch one of your passkeys first, so someone who sits down at your open session cannot add their own.
Steps that ask for a fresh touch
Some steps ask you to touch your passkey again, even though you are signed in, when the last touch was more than five minutes ago: adding or removing a passkey, and resetting someone else's. Steps that move money or change who is paid ask for it too where their guide says so. Your browser shows its passkey dialog, and the step goes ahead once you confirm. An API key, an AI agent and a connected app never can: such a step is always a person's in the web UI.
When the site moves
Stabiso moved from erp.grunte.com to app.stabiso.com on 29 October 2026. A passkey only
works at the address it was made at, so the first time you sign in at the new address:
- Sign in with Google or your password as always.
- Touch your passkey: your browser offers the one you made at the old address.
- Your browser then asks you to create your passkey for the new address. Confirm, and you are signed in. From then on each sign-in asks for the new one.
The old address forwards to the new one. A device whose passkey was kept by one device only (not synced) gets one from My passkeys → Add a passkey once you are signed in. A browser that cannot use the old passkey at the new address (Firefox) needs a reset, as below.
Lost every device
- An administrator of your company resets your passkeys: Settings → Users, your row's menu, Reset passkeys. Your passkeys are removed and your sessions end; your next sign-in creates a new passkey. The administrator touches their own passkey first. Nobody resets their own passkeys this way.
- The platform's operator resets them when you are a user of other organizations as well (an administrator of one company cannot change what opens another), or when there is nobody else to ask, such as a company's only owner. Write to the operator from the address you sign in with.
Every passkey created, removed or reset is a security event of the organization (passkey.add,
passkey.remove, passkey.reset), and a reset is also in the audit trail (user.passkey_reset).
For developers
The web UI drives the steps; an API client does the same with the browser's WebAuthn calls:
POST /v1/auth/googleorPOST /v1/auth/passwordanswersstatus: passkeywithpasskey.setupandpasskey.options(WebAuthn options as JSON; one-time, valid for five minutes).- The browser calls
navigator.credentials.create(setup: true) ornavigator.credentials.getwith those options, and sends the answer (PublicKeyCredential.toJSON()) toPOST /v1/auth/passkey, which sets the session cookie. - A step that needs a fresh touch answers 403
passkey_step_upwithwithin_minutes. AskPOST /v1/auth/step-up/options, have the browser answer, send it toPOST /v1/auth/step-up, and repeat the step. Server code asks for a fresh touch witherp.modules.step_up.require_fresh_passkey(actor, minutes, to=...).
The passkey asks for user verification (userVerification: required) and is bound to the host name
the browser reached (the relying party): a passkey made on app.stabiso.com works there only.
A passkey of the site's former address answers POST /v1/auth/passkey with status: passkey once
more (setup: true): create this address's passkey and send it there too.
Development sign-in (ERP_DEV_LOGIN, never in the cloud) has no passkey step. API keys are not
affected: a script authenticates with its key as before.