Sign-in flows create a session. The Tenant API offers four entry points:
signIn— email + passwordsignInIDP— third-party identity provider (see IdP)signInPasswordless— magic link / OTP (see passwordless)createSessionToken— admin impersonation, no credentials required
All of them rely on the same per-IP rate limiting, captcha, and revealUserExists masking described in anti-abuse. All of them are recorded in the audit log. (since 2.2) Sign-in anomaly detection, when enabled, scores only the password signIn path; the IdP and passwordless flows seed its baseline but are not themselves scored.
Password sign-in
mutation {
signIn(email: "[email protected]", password: "…", expiration: 60) {
ok
result { token }
error { code retryAfter }
}
}
| Arg | Notes |
|---|---|
email, password | Required. |
expiration | Minutes the session token should live. Capped at login.maxTokenExpiration. |
otpToken | TOTP code if 2FA is enabled for the person. |
options.trustForwardedClientInfo | (since 2.2) See proxy trust. |
Errors:
| Code | Cause |
|---|---|
UNKNOWN_EMAIL | No person with that email. Only returned when login.revealUserExists: true. |
INVALID_PASSWORD | Wrong password. Only returned when login.revealLoginMethod: true (since 2.2). |
INVALID_CREDENTIALS | Wrong email or password. Returned when login.revealUserExists: false (masks the email branch) and/or login.revealLoginMethod: false (masks the password/no-password branch). |
PERSON_DISABLED | The person has been disabled. |
EMAIL_NOT_VERIFIED | (since 2.2) The account was created while signup.requireEmailVerification was on and has not yet verified its e-mail. Prompt the user to verify, or resend via requestEmailVerification. See e-mail verification. |
NO_PASSWORD_SET | The person has no password (IDP-only / passwordless-only). Only returned when login.revealLoginMethod: true (since 2.2); otherwise collapsed into INVALID_CREDENTIALS. |
IDP_REQUIRED | (since 2.2) The person is linked to an identity provider with disableLocalAuthentication and must sign in through it. Refused before the password is compared. Only returned when both login.revealUserExists and login.revealLoginMethod are true; otherwise collapsed into INVALID_CREDENTIALS. |
OTP_REQUIRED | The person has 2FA enabled and otpToken was missing — or (since 2.2) anomaly detection forced a step-up for an unusual sign-in. The step-up case can occur even for an account with no standing 2FA and is indistinguishable from the 2FA case at the API; recover it identically by retrying signIn with otpToken set to the emailed code. |
INVALID_OTP_TOKEN | 2FA token rejected. |
RATE_LIMIT_EXCEEDED | Per-IP login rate limit (since 2.2) or per-email exponential backoff hit. retryAfter carries the wait in seconds. |
Signing out
signOut invalidates the current session token. To end every session for the caller (e.g. "log out everywhere"):
mutation { signOut(all: true) { ok } }
signOut requires a session token; it does not work with permanent API keys.
When the session was federated via an OIDC provider that supports RP-initiated logout, signOut also returns a logoutUrl (since 2.2). Redirect the browser there to terminate the session at the IdP as well (OIDC Single Logout); it is null for plain/password sessions and for IdPs without an end_session_endpoint, where only a local logout happens. The logoutUrl is only produced when the IdP session was captured at sign-in — i.e. when session re-validation (configuration.revalidation.enabled) is on for that provider; otherwise it is always null even if the IdP has an end_session_endpoint.
mutation { signOut { ok logoutUrl } }
Admin: create session token
A SUPER_ADMIN (or any role with the PERSON_CREATE_SESSION_KEY permission) can mint a session token for any person without credentials. Useful for impersonation and debugging:
mutation {
createSessionToken(email: "[email protected]", expiration: 120) {
ok
result { token }
error { code }
}
}
Pass either email or personId. Records a create_session_token audit entry.
Login configuration
All login behavior is controlled by the login section of the tenant configuration:
| Field | Effect |
|---|---|
revealUserExists | See anti-abuse — enumeration protection. |
revealLoginMethod | (since 2.2) When false, NO_PASSWORD_SET / INVALID_PASSWORD / IDP_REQUIRED are collapsed into INVALID_CREDENTIALS and signUp omits the recommendedAction hint on EMAIL_ALREADY_EXISTS. Orthogonal to revealUserExists. |
baseBackoff, maxBackoff, attemptWindow | Per-email exponential backoff. Also drives the mail-init throttle for password reset and passwordless init. |
defaultTokenExpiration | Lifetime applied when the client omits expiration. |
maxTokenExpiration | Cap on client-requested expiration. |
anomalyDetection | (since 2.2) Opt-in sign-in anomaly detection for the password path — score thresholds that email the user or force a step-up second factor on an unusual login. |
What the session can do
The session token authorizes subsequent Tenant API calls and Content API calls. The session's effective IP and User-Agent — visible in Identity.sessions and in audit-log entries — depend on whether the api_key has trust-forwarded-info.