Overview

Orgs, clients, tenants, users and pages, and how they compose.

Everything in LoginWith belongs to one org. Inside it, clients are the apps that receive tokens, tenants are the groups users act in, users are the people, and pages are where they sign in.

Org

An org is the administrative boundary, and the issuer. It has a slug (acme), and its OAuth endpoints and signing keys live at https://acme.loginwith.dev/ — the iss of every token it mints. Every other resource below belongs to exactly one org.

People who administer an org are its members, as owner or member.

Client

A client is an OAuth client registered in the org — the client_id your app identifies itself with, and the aud of every token minted for it. On the API a client has an id (cli_…), a name, a logo, redirect_uris, and confidential:

  • Public (confidential: false) — a browser app or SPA. It holds no secret and runs the authorization code flow with PKCE.
  • Confidential (confidential: true) — a backend. It holds a client_secret, shown once when created or rotated, and may restrict where it can be used from with an ip_allowlist. It can run client_credentials as itself, back a login as a backend-for-frontend, or promote a public client’s tokens.

Every client gets the authorization code flow — response_type=code. There is no implicit flow.

Many apps end up with two clients: a public one for the browser and a confidential one for their backend.

Tenant

A tenant is a group within the org — the team or workspace your users act in. Tokens carry the active one as tnt: "tnt_…". A user who can enter several picks one at sign-in, and can switch later without signing in again.

Who may enter is the tenant’s mode:

ModeWho gets in
publicAnyone who signs in
domainUsers whose email domain is on the tenant’s list
workspaceUsers whose provider account belongs to an allowed workspace — a Google Workspace domain, for instance
closedOnly users added or invited

Inside a tenant, members hold a role (owner, admin, member, or invited) and can carry labels — named groups your app can gate on, returned by /users/me.

User

A user is a person who has signed in, with an id usr_… — the sub of their tokens. A user belongs to one org: the same person signing in to two orgs is two separate users. Within the org, they can be a member of many tenants.

The profile (email, name, picture) is not in the token; read it from GET /users/me.

Page

A page is a hosted login page, at {slug}.loginwith.page or on one of your custom domains. Each page signs users in to one client, and chooses its sign-in methods: password, magic link, and any of the SSO providers. It wears a kit — a set of branding (logo, colors, favicon) that several pages can share.

How they fit together

flowchart TD
  Org[Org: acme<br/>https://acme.loginwith.dev/]
  SPA[Client: public SPA]
  Srv[Client: confidential backend]
  Page[Page: acme.loginwith.page]
  Default[Tenant: acme]
  EU[Tenant: acme-eu]
  U1((user))
  U2((user))

  Org --> SPA
  Org --> Srv
  Org --> Page
  Page -. signs in to .-> SPA
  Org --> Default
  Org --> EU
  Default --> U1
  EU --> U1
  EU --> U2

A user token answers four questions at once: which org (iss), for which client (aud), in which tenant (tnt), as which user (sub). See Tokens for the rest.