Users and Organizations
After a user authenticates, your application needs a way to represent who they are and which customer account they belong to. Seal models this with two core entities: Organization and Organization User.
An Organization represents one of your customers — a company, team, or workspace. An Organization User represents an individual person who can sign in and interact with your application. Users connect to organizations through memberships, and a single user can belong to multiple organizations.
Flexible sign-in options for organizations
Section titled “Flexible sign-in options for organizations”Each organization can enforce its own authentication policies. Seal supports multiple authentication methods that can be configured per organization:
- Password — traditional email and password sign-in
- Magic link — passwordless sign-in via email verification code
- Enterprise SSO — SAML or OIDC connections with identity providers like Okta, Google Workspace, or Microsoft Entra ID
- Social login — sign in with Google or Microsoft
- Passkey — WebAuthn-based passwordless authentication
Organizations control which methods are available through domain policies. For example, one organization might require enterprise SSO for all users with a matching email domain, while another allows password and magic link authentication.
Seal handles authentication policy enforcement at the organization level. When a user signs in, Seal checks whether their email domain matches an organization with SSO enabled and routes them to the correct identity provider automatically. See the authentication flow page for details on how home realm discovery works.
User record deduplication
Section titled “User record deduplication”- Two users cannot share the same email address within an environment. The email field on an organization user has a unique constraint scoped to the environment.
- When a user authenticates with a new method (for example, signing in with Google after previously using a password), Seal links the new identity to the existing user record rather than creating a duplicate account.
How users join and leave organizations
Section titled “How users join and leave organizations”Users become members of an organization through several paths:
- Invitations — an existing member invites a new user by email address. The invitation includes a role assignment and an expiration time.
- Domain-based routing — when a user signs in with an email domain that matches an organization’s verified domain, Seal can route them to that organization automatically.
- Just-in-time provisioning — when SSO is enabled for an organization, Seal creates user accounts on first login without requiring pre-provisioning.
- Multi-organization membership — a single user can belong to multiple organizations. Each membership is tracked independently with its own status.
Invitation-based role assignment
Section titled “Invitation-based role assignment”When inviting a user to an organization, the inviter specifies a role. Seal stores this role on the invitation record and applies it when the invitee accepts.
The invitation model tracks:
| Field | Description |
|---|---|
email_address | Email address of the person being invited |
role | Role to assign when the invitation is accepted |
organization_id | The organization the user is being invited to |
inviter_id | The user who sent the invitation |
expires_at | When the invitation expires |
is_used | Whether the invitation has been accepted |
Organization memberships
Section titled “Organization memberships”The membership record links a user to an organization. Each membership is a separate record in the organization_membership table, allowing a user to belong to multiple organizations.
A membership contains the following fields:
| Field | Description |
|---|---|
id | Unique membership identifier (prefixed with org_mem) |
organization_id | The organization the user belongs to |
organization_user_id | The user who holds the membership |
status | Membership status (active) |
created_at | When the membership was created |
A user with memberships in two organizations looks like this:
{ "id": "org_usr_1234567890", "email": "jane@example.com", "first_name": "Jane", "last_name": "Doe", "organizations": [ { "id": "org_abc123", "name": "Acme Corp" }, { "id": "org_def456", "name": "Globex Inc" } ]}The unique constraint on (organization_id, organization_user_id) ensures a user cannot hold duplicate memberships in the same organization.
Access tokens
Section titled “Access tokens”When authentication completes, Seal issues a JWT access token. The token contains claims that identify the user and their organization context:
| Claim | Description |
|---|---|
sub | The organization user ID |
sid | Session ID |
organization | Organization ID (present when the user selected an organization) |
iat | Token issue time |
exp | Token expiration time |
The token response also includes user and organization details alongside the JWT:
{ "access_token": "eyJhbGciOiJSUz...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "dGhpcyBpcyBh...", "user": { "id": "org_usr_1234567890", "first_name": "Jane", "last_name": "Doe", "email": "jane@example.com" }, "organization": { "id": "org_abc123", "name": "Acme Corp" }}Organization policies
Section titled “Organization policies”Each organization can configure authentication policies that control how users interact with it:
| Policy | Description |
|---|---|
require_sso_for_domain_members | Require SSO for users whose email matches a verified organization domain |
require_sso_for_guests | Require SSO for users who do not match an organization domain |
require_mfa_for_non_sso | Require multi-factor authentication for users who sign in without SSO |
These policies are evaluated during the authentication flow. For example, if require_sso_for_domain_members is enabled and a user with a matching email domain attempts to sign in with a password, Seal redirects them to the organization’s SSO identity provider.
Migrating from a one-to-one model
Section titled “Migrating from a one-to-one model”In a one-to-one model, each user belongs to exactly one organization. Applications like Slack and QuickBooks use this pattern — a user creates a separate account for each workspace or company.
If your application currently uses this model, Seal’s membership system can represent it directly. Each user has a single membership record. To adopt multi-organization support later, you add additional membership records without changing the user or organization structures.
Migrating from a one-to-many model
Section titled “Migrating from a one-to-many model”In a one-to-many model, a user has a single profile shared across multiple organizations. Applications like Notion and Figma use this pattern — one login provides access to all workspaces.
If your application already tracks organization membership in its own database, add the Seal organization_user_id to your existing membership table. This links your internal records to Seal’s user identity without replacing your membership logic.
| Aspect | One-to-one | One-to-many |
|---|---|---|
| User belongs to | One organization | Multiple organizations |
| Email address | Can be reused across orgs (separate accounts) | One account per email |
| Authentication | Per-organization credentials | Single sign-in, organization selection |
| Example apps | Slack, QuickBooks | Notion, Figma |
| Seal approach | Single membership per user | Multiple memberships per user |
Next steps
Section titled “Next steps”- Authentication flow — understand how Seal routes users through sign-in based on their organization’s policies
- Organizations — manage organizations, domains, and SSO connections
- Enterprise SSO — set up SAML or OIDC connections for your customers