Visitor sign-in
The people who use a published app are not PhiWebs users. You have a PhiWebs account; they have an account inside your app. The two are separate systems on purpose — the grocer signs in to PhiWebs, the grocer’s customers sign in to the grocer’s app, and neither can see the other’s world.
An app declares whether it needs visitors to sign in at all. An app that
allows anonymous visitors serves anyone with the link; an app that requires
sign-in refuses everyone else with a 401 that also names the door it expects.
Two places a visitor can sign in
| Topology | Who holds the door | Use it when |
|---|---|---|
| Platform | PhiWebs, on your app’s behalf | You want sign-in without running an identity system |
| External | Your own OpenID Connect issuer | You already have one and visitors should use it — Team and Enterprise |
An app picks one. If the app authenticates at its own issuer and something
calls the PhiWebs door anyway, the answer is WRONG_DOOR — with the issuer it
should have gone to instead.
With an external issuer, the visitor’s token is verified against your issuer’s keys on every request. Nothing about their password ever reaches us.
Methods the platform door offers
- Email and password — the visitor registers in your app and is signed in immediately afterwards.
- Google, GitHub, Microsoft — the app sends the visitor to the provider using its own address as the return target, then exchanges what comes back.
Two conditions, and the refusals are different on purpose:
- The app must declare the method. Asking for one it never offered returns
METHOD_UNAVAILABLE, along with the methods it does offer. - The provider must be configured for the deployment. If it is not, the
answer is
PROVIDER_NOT_CONFIGUREDrather than a failure that looks like the visitor’s fault.
These methods are on every plan. There used to be a tier here — email at the bottom, Google and Microsoft above it — and it is gone: the methods the platform operates cost us an OAuth redirect, while email sign-in is the one where we hold the password and send the mail, so charging for the cheap ones and giving away the expensive one priced the platform backwards. A visitor was also the wrong person to refuse; they bought nothing from us and could fix nothing.
What the plan does decide is the other door: pointing your app at your own OIDC/Entra issuer is part of Team and Enterprise — see pricing. Publishing an app that authenticates at an issuer your plan does not include is reported before it ships, not discovered by the first visitor who cannot get in.
The same email is not the same person
A visitor who registers with a password and one who arrives through Google are two different people, even with an identical address. We cannot prove they are the same human, and quietly merging them on a matching email is how account takeover starts.
The endpoints
All paths are relative to your app’s API base, /api/app/{worldId}/{appId}.
| Method | Path | What it does |
|---|---|---|
POST | /register | Create a visitor with email and password, and sign them in |
POST | /login | Sign in with email and password |
POST | /oauth/login | Exchange a provider code (or access token) for a session |
POST | /logout | End the session; safe to call when already signed out |
GET | /session | Who is signed in, or null |
A session token is presented on later requests either as x-app-session or as
Authorization: Bearer ….
Sign-in endpoints are rate limited. A wrong email and a wrong password give the
same answer, INVALID_CREDENTIALS — telling them apart would let anyone
enumerate your customers.
A bad token is always rejected, even on an app that allows anonymous visitors. An expired session must not quietly become “anonymous, then”.
Records belong to one app
Records written through your app are scoped to that app, not to your whole workspace. Two apps in the same workspace never share a collection, even when their record types have the same name.
Some record types are owner-scoped as well: a visitor reads and writes only the records they created. That is what makes a per-customer portal a per-customer portal instead of a shared table with a filter drawn on top of it.
See also
- Publishing your app — the address visitors arrive at
- Account & billing — your own PhiWebs account, which is a different thing entirely