Authentication & accounts

Your app's end-users sign up and log in through the /account service. A successful login returns a session; the client sends it back on every request (the SDK handles this automatically via a cookie, or you pass the secret in X-Appwrite-Session).

Sign up & log in

curl
# Create an account
curl -X POST "https://base.finiteskills.com/v1/account" -H "X-Appwrite-Project: <YOUR_PROJECT_ID>" \
  -H "Content-Type: application/json" \
  -d '{"userId":"unique()","email":"user@example.com","password":"password123","name":"Jane"}'

# Create a session (log in)
curl -X POST "https://base.finiteskills.com/v1/account/sessions/email" -H "X-Appwrite-Project: <YOUR_PROJECT_ID>" \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"password123"}'

Read the current account with GET /account, list sessions, and log out with DELETE /account/sessions/current.

Login methods

  • Email + passwordPOST /account/sessions/email.
  • AnonymousPOST /account/sessions/anonymous; later upgrade with PATCH /account/email to attach an email + password.
  • Magic linkPOST /account/tokens/magic-url emails a link; complete with POST /account/sessions/token.
  • Email OTPPOST /account/tokens/email sends a 6-digit code.
  • Phone OTPPOST /account/tokens/phone (requires an SMS gateway to be configured for the deployment).
  • OAuth / OIDCGET /account/sessions/oauth2/{provider} for Google, GitHub, or a generic OIDC provider your project admin configures.

Password policy

Passwords must be at least the deployment's minimum length (8 by default). When the breached-password check is enabled, the password is additionally screened against the Have-I-Been-Pwned corpus using k-anonymity — only the first five characters of its SHA-1 leave the process, and a match returns 400 password_policy_violation. OTP-based logins cap wrong attempts: after the limit a token is burned and a fresh code must be requested.

Two-factor (TOTP)

A signed-in user can enable authenticator-app 2FA:

Flow
POST /account/mfa/totp        -> { secret, uri }   (show the uri as a QR code)
PUT  /account/mfa/totp        -> { recoveryCodes } (verify a 6-digit code to enable)
# Afterwards, email login also requires an `otp` field:
POST /account/sessions/email  { email, password, otp }

Passkeys (WebAuthn)

Register a passkey for a signed-in user (a second factor / device credential), or let a user log in with a passkey and no password at all. Each ceremony is two calls — start returns the WebAuthn options and challenge, finish verifies the authenticator's response:

Register a passkey (signed-in user)
POST /account/mfa/webauthn/register/start   -> { options }   # pass to navigator.credentials.create()
POST /account/mfa/webauthn/register/finish  { response }     # verify + store the credential
Passwordless login
POST /account/webauthn/login/start   { email }    -> { options }  # navigator.credentials.get()
POST /account/webauthn/login/finish  { email, response }          # verifies + returns a session

SAML single sign-on

A project admin registers a SAML identity provider; your app then starts login by redirecting the browser to the SP endpoint, and the IdP posts its assertion back to the Assertion Consumer Service (ACS), which mints a session just like OAuth:

SAML SP flow
GET  /account/sessions/saml/{provider}       # 302 -> the IdP login page
POST /account/sessions/saml/{provider}/acs   # IdP posts the assertion here -> session

Email verification & password reset

POST /account/verifications/email sends a verification link; POST /account/recovery starts a password reset. When the deployment has email configured, the link is emailed; otherwise the token is returned in the response for your app to deliver.

JWTs for your own backend

POST /account/jwt returns a short-lived JWT the client can forward to your backend, which passes it to FiniteBase as X-Appwrite-JWT to act as that user. The token carries custom claims — email, emailVerification, teams and roles — on top of the project and user ids.

Signing algorithm
# Default: HS256, symmetric, verifiable only by the engine.
POST /account/jwt                 -> { jwt }

# RS256: asymmetric, signed with the project RSA key (carries a `kid`).
POST /account/jwt  { "alg": "RS256" }  -> { jwt }

An RS256 token can be verified offline by your own backend against the project's public keys — no round-trip to FiniteBase. Fetch the JSON Web Key Set (which includes the project header but needs no session) and the OIDC discovery document:

Offline verification
GET /keys                   # JWKS: the project RSA public key(s), keyed by `kid`
GET /openid-configuration   # OIDC discovery: issuer + jwks_uri