Organizations
The organizations plugin adds multi-tenant support to your app. Users can create organizations, invite members, assign roles, and manage teams.
Setup
import { betterAuth } from "better-auth";
import { organization } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [
organization({
allowUserToCreateOrganization: true,
maximumOrganizations: 5, // Per user
roles: {
owner: {
permissions: ["*"], // All permissions
},
admin: {
permissions: ["member:read", "member:invite", "member:remove", "organization:update"],
},
member: {
permissions: ["member:read"],
},
},
}),
],
});Client Setup
import { createAuthClient } from "better-auth/react";
import { organizationClient } from "better-auth/client/plugins";
export const authClient = createAuthClient({
plugins: [organizationClient()],
});Creating an Organization
const { data: org, error } = await authClient.organization.create({
name: "Acme Inc",
slug: "acme",
metadata: {
plan: "pro",
industry: "saas",
},
});
console.log("Created:", org.name); // "Acme Inc"Inviting Members
// Invite by email
const { data: invitation } = await authClient.organization.inviteMember({
organizationId: org.id,
email: "colleague@example.com",
role: "member",
});
// The invited user receives an email with an accept linkAccept an Invitation
const { data } = await authClient.organization.acceptInvitation({
invitationId: "invitation-id",
});Managing Members
List Members
const { data: members } = await authClient.organization.listMembers({
organizationId: org.id,
});
members.forEach((member) => {
console.log(`${member.user.name} — ${member.role}`);
});Update Member Role
await authClient.organization.updateMemberRole({
organizationId: org.id,
memberId: "member-id",
role: "admin",
});Remove a Member
await authClient.organization.removeMember({
organizationId: org.id,
memberId: "member-id",
});Active Organization
Users can be part of multiple organizations. Set the active one:
// Set active organization
await authClient.organization.setActive({
organizationId: org.id,
});
// Get active organization
const { data: activeOrg } = await authClient.useActiveOrganization();Server-Side Usage
Check Organization Membership
const session = await auth.api.getSession({ headers });
const membership = await auth.api.getOrganizationMember({
organizationId: "org-id",
userId: session.user.id,
});
if (!membership) {
throw new Error("Access denied");
}
if (membership.role !== "admin" && membership.role !== "owner") {
throw new Error("Insufficient permissions");
}Database Schema
The plugin adds these tables:
| Table | Description |
|---|---|
organization | Organization details (name, slug, metadata) |
member | User-organization relationship with roles |
invitation | Pending invitations |
Permissions
Define custom permissions per role:
organization({
roles: {
owner: { permissions: ["*"] },
admin: {
permissions: [
"member:read",
"member:invite",
"member:remove",
"project:create",
"project:read",
"project:update",
"project:delete",
"billing:read",
"billing:update",
],
},
viewer: {
permissions: ["member:read", "project:read"],
},
},
});Check permissions:
const hasPermission = await auth.api.hasPermission({
organizationId: "org-id",
userId: session.user.id,
permission: "project:delete",
});