Skip to main content

Sign-in

Sign-in flows create a session. The Tenant API offers four entry points:

  • signIn — email + password
  • signInIDP — 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.

Password sign-in

mutation {
signIn(email: "[email protected]", password: "…", expiration: 60) {
ok
result { token }
error { code retryAfter }
}
}
ArgNotes
email, passwordRequired.
expirationMinutes the session token should live. Capped at login.maxTokenExpiration.
otpTokenTOTP code if 2FA is enabled for the person.
options.trustForwardedClientInfo(since 2.2) See proxy trust.

Errors:

CodeCause
UNKNOWN_EMAILNo person with that email. Only returned when login.revealUserExists: true.
INVALID_PASSWORDWrong password. Only returned when login.revealLoginMethod: true (since 2.2).
INVALID_CREDENTIALSWrong email or password. Returned when login.revealUserExists: false (masks the email branch) and/or login.revealLoginMethod: false (masks the password/no-password branch).
PERSON_DISABLEDThe person has been disabled.
NO_PASSWORD_SETThe person has no password (IDP-only / passwordless-only). Only returned when login.revealLoginMethod: true (since 2.2); otherwise collapsed into INVALID_CREDENTIALS.
OTP_REQUIREDThe person has 2FA enabled and otpToken was missing.
INVALID_OTP_TOKEN2FA token rejected.
RATE_LIMIT_EXCEEDEDPer-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.

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:

FieldEffect
revealUserExistsSee anti-abuse — enumeration protection.
revealLoginMethod(since 2.2) When false, NO_PASSWORD_SET / INVALID_PASSWORD are collapsed into INVALID_CREDENTIALS and signUp omits the recommendedAction hint on EMAIL_ALREADY_EXISTS. Orthogonal to revealUserExists.
baseBackoff, maxBackoff, attemptWindowPer-email exponential backoff. Also drives the mail-init throttle for password reset and passwordless init.
defaultTokenExpirationLifetime applied when the client omits expiration.
maxTokenExpirationCap on client-requested expiration.

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.