How to give one user multiple roles
Create one user with auth.signUpEmailPassword, then attach every role that person needs to the returned user ID. A second sign-up with the same normalized email is rejected. Global roles belong in application tables, tenant roles belong on organisation memberships, and both must be checked by the server before protected work is performed.
Keep one user ID
auth.signUpEmailPassword creates the user and returns its ID. Use that ID in every application role, organisation membership, and product record for the person. Later, auth.getCurrentSession resolves the same user before the application loads those authorization records.
Creating another user record for a new role splits password recovery, linked providers, sessions, and audit events across duplicate identities. Updating the roles attached to one user avoids that ambiguity and keeps every sign-in method tied to the same person.
Choose where the role applies
Before storing a role, decide where it grants access. A global role applies across the product. An organisation role applies only inside one tenant. Access to one record can be stored directly against that record without granting a broader role.
- Use an application-managed global role for platform-wide administration or support access.
- Use an Own Auth organisation membership when access depends on the selected tenant.
- Use an application table when a user owns, shares, purchases, or is assigned a specific record.
The same user can appear in all three places. A global role does not add the user to every organisation. An organisation role does not grant access in another tenant. Access to one record does not authorize other records of the same type.
Store global roles in application tables
Store product-wide roles in an application-owned table keyed by the user ID returned by Own Auth. One row per role supports several roles without adding application authorization fields to own_auth_users.
CREATE TABLE application_role_assignments (
user_id text NOT NULL
REFERENCES own_auth_users(id) ON DELETE CASCADE,
role text NOT NULL,
granted_at timestamptz NOT NULL DEFAULT now(),
granted_by_user_id text REFERENCES own_auth_users(id),
PRIMARY KEY (user_id, role)
);Only privileged server operations should insert or delete these rows. Profile updates must never grant roles. Record who changed each role, and query the current assignments during sensitive requests so removal takes effect immediately.
Store tenant roles on organisation memberships
One user can belong to several organisations, with one role stored on each membership. The built-in owner, admin, and member roles cover organisation management. Custom roles can add the exact tenant permissions the product needs.
import {
createOwnAuth,
defineOwnAuthAuthorization,
} from "own-auth";
const authorization = defineOwnAuthAuthorization({
permissions: ["records:read", "records:write"],
roles: {
reviewer: ["view_members", "records:read"],
editor: [
"view_members",
"records:read",
"records:write",
],
},
});
export const auth = createOwnAuth({
tokenPepper: process.env.OWN_AUTH_TOKEN_PEPPER,
authorization,
});Define custom roles once in application configuration. Own Auth stores the selected role on each membership and checks its configured permissions. Every Own Auth instance using the database must load the same definition. Reassign affected members before removing a role.
Check access on the server
Resolve the user from the session and check the required permission on the server. Never accept a user ID, role, or organisation membership supplied by the browser as proof of access.
const current = await auth.requireCurrentSession(sessionToken);
await auth.requirePermission(
organisationId,
current.user.id,
"records:write",
);
const record = await records.findForOrganisation({
recordId,
organisationId,
});auth.requirePermission confirms an active membership with records:write. The repository query also requires the same organisation ID, preventing an authorized user from changing recordId to reach another tenant's data.
Change roles without creating users
Granting new access means adding a global role, changing an organisation membership role, or creating a record-level permission. None of those operations requires another user, password, provider account, or session.
Keep the user ID stable. Store each role where its scope is enforced, and read that authorization data on protected requests. One person can then hold every required role while using one set of credentials and sessions.