Features Apograph CMS on GitHub

Identity plugin

Authentication, authorization, and the identity providers a deployment can reach.

Documents 0.5.2 Updated Edit this page Report a problem

On this page

The foundational plugin. It answers who is this person? and what are they allowed to do?, and it enforces both app-wide: an AuthGuard is registered as the global APP_GUARD, so every route requires a valid session unless it is marked @Public().

Apograph is invite-only by design. There is no public registration; the only route into an account is an admin’s invite, or — since 0.4.0 — a first sign-in through an identity provider a deployment has configured.

Install

npm install @apograph/identity-server @apograph/identity-admin

Add an identity provider package only if you want single sign-on:

ProviderPackageSpeaks
OpenID Connectidentity-provider-oidcOkta, Auth0, Keycloak, Google, Entra ID…
GitHubidentity-provider-githubOAuth2, no identity token
SAML 2.0identity-provider-samlA POST binding and XML signatures
Scriptedidentity-provider-fakeNothing — offline and deterministic
npm install @apograph/identity-provider-oidc

To reach a directory none of them speaks, see writing an SSO provider.

Register

// apps/server/src/plugins.ts
import { IdentityPlugin } from '@apograph/identity-server';

IdentityPlugin(config.plugins.identity);

With providers, the second argument carries the constructed adapters:

IdentityPlugin(config.plugins.identity, {
    sso: {
        providers: [{ name: 'google', provider: createGoogleProvider({ /* … */ }) }]
    }
});
// apps/admin/src/plugins.ts
import { IdentityPlugin } from '@apograph/identity-admin';

IdentityPlugin();

The admin half goes first in the admin list. It is the one plugin contributing public routes — the sign-in and accept-invite screens — which have to render outside the gated layout the shell wraps everything else in.

What it owns

Workspaces, users, roles, permissions, memberships, sessions and tokens are its tables, and it ships their migrations. It also seeds the three system roles — admin, contributor, viewer — idempotently on boot, and protects them from deletion.

Environment

Sessions and tokens

VariableDefaultWhat it does
ALLOWED_ORIGINSthe dev admin originComma-separated origins allowed to make state-changing calls
SESSION_TTL_SECONDS604800 (7 days)How long a session stays valid
INVITE_TTL_SECONDS604800 (7 days)Invite link lifetime
RESET_TTL_SECONDS3600 (1 hour)Password-reset link lifetime
LOGIN_RATE_LIMIT10Login attempts per window
LOGIN_RATE_LIMIT_TTL_SECONDS60The window

Root administrator

VariableDefaultWhat it does
APOGRAPH_ROOT_ADMIN_EMAILunsetWith an email set, an admin is provisioned on boot
APOGRAPH_ROOT_ADMIN_PASSWORDunsetIts first password
APOGRAPH_ROOT_ADMIN_NAMEunsetIts display name

Provisioning is idempotent and non-destructive: an existing account with that address is left exactly as it is. This is how you get your first login.

Single sign-on

VariableDefaultWhat it does
SSO_PUBLIC_BASE_URLfirst allowed originThe origin browsers reach the API on. Builds the redirect_uri
SSO_REQUEST_TTL_SECONDS600How long one sign-in attempt stays live
SSO_PROVISION_DOMAINSunset — offComma-separated email domains that may be provisioned just in time
SSO_PROVISION_ROLEviewerRole a provisioned account gets
SSO_ALLOW_PASSWORD_LOGINtrueSet false to turn passwords off. The root admin is always exempt
SSO_SESSION_TTL_SECONDSunsetA shorter session lifetime for SSO sessions alone

Per-provider variables — SSO_OIDC_*, SSO_GITHUB_*, SSO_SAML_* — are on the single sign-on page, along with what a sign-in is and is not allowed to do to an account.

Providers and a strict cookie do not mix

The plugin refuses to boot with SSO providers registered and session.cookieSameSite: 'strict'. A strict cookie is not sent on the provider’s cross-site redirect back, so every sign-in would fail with a generic error and nothing in the response would say why.

HTTP surface

Sign-in, sign-out and the redemption halves of the invite and reset flows live here, under /api/auth. Issuing invites and resets belongs to the users plugin; identity owns the tokens table and the redemption.

The full route list is in the endpoint reference, and the permission keys the guards check are in the permission reference.

What is not here

No email is sent

Inviting somebody returns the raw invite token once, for an admin to turn into a link and deliver themselves. The same is true of a password reset. There is no mail transport in Apograph and no configuration for one.