Authorization

RBAC that knows where it applies

Role-based access control, with the parts multi-tenant SaaS actually needs: roles bundle scopes, and grants apply them to one resource at a time

Auth/Roles and permissions · production

Roles and permissions

Roles bundle scopes, and a grant applies one inside a context.

4 roles · 92 grantsNew role

Scopes granted by admin

projects:read
projects:write
members:invite
members:remove
billing:read
billing:write
keys:rotate
logs:read

await nulvless.auth.verify({
  resource: "proj_16tbwq34",
  roles: ["admin"],
})

The model

The model

Four pieces that compose, instead of a permissions table you maintain by hand

Auth/Access token claims

Access token claims

What your services read straight out of the token.

2 custom claims · signed with RS256New claim
{
  "sub": "usr_4c81f0a2",
  "iss": "https://acme.nulvless.co",
  "email": "[email protected]",
  "roles": ["owner"],
  "scopes": ["projects:write", "members:invite"],
  "org": "org_2f19ac",
  "plan": "premium"
}
custom · orgcustom · plan

Claims are computed per token, so a role change lands on the next token minted — not on your next deploy

Scopes

The smallest unit: a single thing that may be done

Roles

A named bundle of scopes you can change without touching users

Contexts

Organization, project or any resource of yours — the "where" a role applies

Grants

A user holding a role in a context, with an audit trail behind it

Scopes

The capability your code checks, so a renamed role breaks nothing

Checking it

Checking it

One call, at the edge, with the answer already next to the session that asked

  • verify()

    Resource plus roles in, a typed decision out — no policy engine to run

  • Access-token claims

    Put roles, scopes and your own claims into the token your services already read

  • Server-side checks

    A service key and forwarded user headers for work your backend does

  • Deny by default

    Nothing is reachable until a grant says it is

Explorer

One trail across auth, functions, notifications and system events.

Run
select ts, email, reason, ip from auth_events
where event = "signin" and ok = false
tsemailreasonip
12:04:11[email protected]bad_password31.22.8.4
12:03:52[email protected]user_banned77.14.2.90
12:02:19[email protected]mfa_required81.3.44.7
11:59:03[email protected]bad_password31.22.8.4

Grant changes are queryable like anything else, which is usually what an auditor is actually asking for

Handing it over

Handing it over

The invitation and membership flows every B2B product ends up building twice

Invitation lifecycle

created
email sent, no account required yet
accepted
grant issued inside the target context
expired
after the window you set
revoked
tokens carrying it stop passing

Invitations

Invite by email into a context and a role, before an account exists

Ownership transfer

Move the owner grant without a support ticket

Delegation

Let an admin grant only what they themselves hold

Revocation

Pull a grant and the tokens carrying it stop passing

Invite into a context, not into the app

Grants are issued against an organization, a project or a resource — so the same person can be an owner in one place and a reader in another.

authorization.ts
import { createServerClient, forwardUserHeaders } from "@nulvless/nulvless-js";

const nulvless = createServerClient(url, "sk-…");

const { data, error } = await nulvless.auth.grants.invite(
  { email: "[email protected]", context: "org", roles: ["admin"] },
  { headers: forwardUserHeaders(req) },
);

One platform, from your first user

Focus on your product. We handle identity infrastructure

What you would have built

Six areas, every one of them a project of its own.

  • Authenticationpasswords, providers, MFA, sessions
  • AuthorizationRBAC, scopes, per-resource grants
  • OAuth serverOIDC discovery, JWKS, PKCE
  • Edge functionsDeno runtime, deploys, rollback
  • Notificationstemplates, providers, delivery logs
  • Observabilitymonitoring, audit trail, query
Roughly9 engineer-months · $135,000You start at$0