Skip to content

Advisory auth vs the backend gate

Authentication appears in the SDK as a deliberately small surface: the session snapshot, the session.changed event, and two helpers, getRoles() and hasRole(role). That is the whole of it. There is no “check this permission” call, because there is nothing in the SDK that could enforce one.

The app uses hasRole to decide what to show; the backend enforces on every request and returns 403 if not allowed.

platform.session is a snapshot of the current user — whether they are authenticated, who they are, and an advisory list of roles. session.changed fires when that snapshot changes (a sign-in, a sign-out, a role grant). hasRole is a convenience over the snapshot’s roles.

You use all of this for exactly one thing: deciding what to render. Show the “view invoices” button when hasRole("invoices:read"); hide it otherwise.

It does not give you a way to authorize an action, and that omission is the design. The session cookie, the introspection the platform performs against it, and the role enforcement that gates each request all live below the SDK, in infrastructure your app never touches through the client. From inside your app, they are invisible — and that is correct, because:

  • The backend is the single source of truth. Authorization is checked where the data lives, on every request, against the live session — not against a snapshot the client happened to receive.
  • A client-side check is not a security boundary. Anything the SDK hands your iframe, a user can read and change. A role boolean flipped in devtools reveals a button; it does not grant access. The backend serving that button’s data still returns a 403.

hasRole decides whether to show a control. The backend decides whether the action behind it is allowed. Never let the first stand in for the second.

If you treat the advisory roles as enforcement, you have not built a permission system — you have built a UI hint that looks like one. Build the affordance with hasRole (how-to); let the backend be the gate.