Skip to content

Users & Roles

Users represent identities in Seamless Auth and carry the global role data your application uses for authorization.

Organizations add membership roles and scopes for tenant-style access, but they do not replace the global user record.


User
-> global roles
-> credentials
-> sessions
-> organization memberships

FieldDescription
idUnique user ID
emailUnique email
phoneUnique phone
rolesArray of global roles
revokedWhether authentication is disabled
emailVerifiedEmail verification status
phoneVerifiedPhone verification status
verifiedFully verified status
challengeIn-progress auth challenge
challengeContextContext for the in-progress auth challenge
lastLoginLast successful login

Related records hold passkeys, OAuth identities, TOTP credentials, sessions, organization memberships, and auth events.


Global roles are stored directly on the user record.

Example:

["user", "admin:read"]

That makes role checks explicit in both frontend and backend code.

System config shapes role behavior through:

  • default_roles
  • available_roles

Those values control which roles new users receive by default and which roles are allowed in the system.


Admin access now supports scoped roles.

Granted roleSatisfies
adminadmin, admin:read, admin:write
admin:writeadmin:write, admin:read
admin:readadmin:read only

The legacy admin role remains broad for backwards compatibility. Use admin:read and admin:write for new admin-facing route checks when you want clearer least-privilege behavior.


Seamless Auth gives you identity, global roles, session context, and membership data. Your application still decides how to enforce access.

That can look like:

  • UI checks with hasScopedRole('admin:read')
  • backend middleware such as requireRole('admin:write')
  • product-specific role combinations in your own application code
  • organization membership checks for tenant-specific actions

Example:

const { hasScopedRole } = useAuth()
if (hasScopedRole('admin:read')) {
return <AdminLink />
}

On the backend:

app.post('/settings', requireAuth({ cookieSecret }), requireRole('admin:write'), updateSettings)

Organization membership records connect users to organizations.

Each membership has:

  • organizationId
  • userId
  • roles
  • scopes

Use global roles for system-wide permissions. Use membership roles and scopes when the decision is specific to one organization.


Users move through a verification lifecycle:

Unverified -> Email verified -> Phone verified -> Fully verified

The exact path depends on the auth flow your app enables.


A user can have:

  • WebAuthn credentials/passkeys
  • OAuth identities
  • TOTP credentials

Passkeys are stored in credentials. OAuth links are stored in oauth_identities. TOTP enrollment state is stored in totp_credentials with encrypted secrets.


If a user is revoked:

  • they should no longer be able to authenticate
  • existing sessions should be treated as invalidated

Revocation distinguishes an identity record that still exists from one that is still allowed to participate in auth flows.


Admins are normal users with admin, admin:read, or admin:write roles.

That simplicity matters because it keeps authorization explicit across:

  • admin dashboard access
  • backend route protection
  • operator actions