Skip to content

Authentication

Zatabase uses JWT (JSON Web Token) authentication with separate access and refresh tokens. The auth system supports multi-tenancy with organization scoping, environment isolation (live/sandbox), and optional OAuth integration with external identity providers.

Create the initial admin user for your organization:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/signup \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "SecurePass123!"
}' | jq

Response:

{
"access_token": "eyJhbGciOi...",
"refresh_token": "eyJhbGciOi...",
"access_expires_at": 1709300000,
"refresh_expires_at": 1709900000,
"environment": {
"id": "live",
"name": "Live"
}
}

Passwords are hashed with Argon2 using secure random salts and constant-time verification to prevent timing attacks.

Exchange credentials for tokens:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "SecurePass123!",
"environment": "live"
}' | jq

The environment field is optional and defaults to the last-used environment. You can specify "live", "sandbox", or any custom environment name.

Include the access token in the Authorization header:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/sql \
-H "Authorization: Bearer eyJhbGciOi..." \
-H "Content-Type: application/json" \
-d '{"query": "SELECT * FROM users"}'

Access tokens have a short lifetime (default: 15 minutes). Use the refresh token to get new tokens before expiry:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "eyJhbGciOi..."
}' | jq

Response:

{
"access_token": "eyJhbGciOi...(new)...",
"refresh_token": "eyJhbGciOi...(new)...",
"access_expires_at": 1709301000,
"refresh_expires_at": 1709901000
}

Refresh tokens have a longer lifetime (default: 7 days). Both tokens are rotated on each refresh.

Revoke the current session:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/logout \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "eyJhbGciOi..."
}'

Zatabase supports multiple environments per organization for data isolation. Switch environments without re-authenticating:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/switch \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "eyJhbGciOi...",
"environment": "sandbox"
}' | jq

This returns new tokens scoped to the target environment. All subsequent requests use that environment’s data.

List available environments:

Terminal window
curl -s https://your-project.zatabase.io/v1/environments \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

The /v1/whoami endpoint returns the current session details:

Terminal window
curl -s https://your-project.zatabase.io/v1/whoami \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

Response includes user ID, organization ID, environment, roles, and labels.

For local development and testing, Zatabase supports HMAC-signed development tokens that bypass the normal authentication flow. Configure via environment variables:

Terminal window
# Set development token configuration
export ZAUTH_DEV_ORG_ID=1
export ZAUTH_DEV_SECRET="my-dev-secret"
# Start the server
zatabase

On startup, Zatabase prints a development token to the console:

INFO Dev token: zatabase_dev_<hmac_signature>

Use this token as a Bearer token in the Authorization header. Dev tokens are tied to the configured org ID and grant full access.

Production safety: Zatabase detects production environments by checking for environment variables like PRODUCTION=true, NODE_ENV=production, railway/fly.io/render indicators, and similar patterns. Dev tokens are automatically blocked in production even if ZAUTH_DEV_SECRET is set.

Environment VariableDefaultDescription
ZJWT_SECRET(random)HMAC key for signing access tokens
ZJWT_REFRESH_SECRET(random)HMAC key for signing refresh tokens
ZJWT_ACCESS_TTL_SECS900 (15 min)Access token lifetime in seconds
ZJWT_REFRESH_TTL_SECS604800 (7 days)Refresh token lifetime in seconds
ZAUTH_DEV_ORG_ID(none)Organization ID for development tokens
ZAUTH_DEV_SECRET(none)HMAC secret for development tokens

Zatabase supports OAuth authentication with multiple providers for single sign-on (SSO):

ProviderStatusFeatures
GoogleSupportedDomain restrictions, org mapping
GitHubSupportedOrganization and team sync
DiscordSupportedServer integration
AppleSupportedPrivacy-focused data handling
Terminal window
# Google OAuth
export GOOGLE_CLIENT_ID="your-client-id"
export GOOGLE_CLIENT_SECRET="your-client-secret"
# GitHub OAuth
export GITHUB_CLIENT_ID="your-client-id"
export GITHUB_CLIENT_SECRET="your-client-secret"
# Redirect base URL
export OAUTH_REDIRECT_BASE_URL="https://zatabase.io"

Users can link multiple OAuth accounts to a single Zatabase account for unified access across identity providers. The system handles email conflict resolution and provides secure unlinking with audit trails.

Zatabase supports multiple 2FA methods to secure user accounts. The 2FA system is org-scoped, so organizations can enforce their own policies. All 2FA endpoints require an authenticated session.

Get the current 2FA configuration for your account:

Terminal window
curl -s https://your-project.zatabase.io/v1/auth/2fa/status \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

Response:

{
"enabled": true,
"required": false,
"enabled_methods": ["totp"],
"default_method": "totp",
"phone_verified": false,
"backup_codes_remaining": 8
}

Set up time-based one-time passwords with any TOTP-compatible authenticator app (Google Authenticator, Authy, 1Password, etc.).

Step 1: Generate setup

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/2fa/totp/setup \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"issuer": "Zatabase",
"account_name": "[email protected]"
}' | jq

Response:

{
"secret_id": "01HQXYZ...",
"secret": "JBSWY3DPEHPK3PXP",
"qr_code_url": "otpauth://totp/Zatabase:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=Zatabase",
"qr_code_png": "<base64-encoded PNG>"
}

Scan the QR code (or enter the secret manually) in your authenticator app.

Step 2: Verify and activate

Enter the 6-digit code from your authenticator to confirm setup:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/2fa/totp/verify \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"secret_id": "01HQXYZ...",
"code": "482910"
}' | jq

Response:

{
"success": true,
"backup_codes": [
"a1b2c3d4e5",
"f6g7h8i9j0",
"..."
]
}

Save the backup codes in a secure location. They cannot be retrieved again.

WebAuthn / FIDO2 (Hardware Keys and Biometrics)

Section titled “WebAuthn / FIDO2 (Hardware Keys and Biometrics)”

Zatabase supports WebAuthn/FIDO2 for hardware security keys (YubiKey, Titan), platform authenticators (Touch ID, Windows Hello), and passkeys.

Step 1: Start registration

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/2fa/webauthn/register \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"rp_origin": "https://zatabase.io",
"rp_id": "zatabase.io",
"rp_name": "My Zatabase Instance",
"user_email": "[email protected]",
"display_name": "Admin"
}' | jq

Response:

{
"creation_options": { "...WebAuthn PublicKeyCredentialCreationOptions..." },
"session_data": { "session_id": "01HQXYZ..." }
}

Pass creation_options to the browser’s navigator.credentials.create() API.

Step 2: Complete registration

Send the credential from the browser back to Zatabase:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/2fa/webauthn/register/finish \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"session_id": "01HQXYZ...",
"credential": { "...RegisterPublicKeyCredential from browser..." },
"credential_name": "My YubiKey"
}' | jq

Response:

{
"credential_id": "01HQXYZ...",
"name": "My YubiKey",
"created_at": 1709300000
}

Registration states expire after 5 minutes for security.

Set up SMS-based 2FA:

Terminal window
# Initiate SMS setup
curl -s -X POST https://your-project.zatabase.io/v1/auth/2fa/sms/setup \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"phone_number": "+15551234567"}' | jq
# Verify with the code received
curl -s -X POST https://your-project.zatabase.io/v1/auth/2fa/sms/verify \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"verification_id": "01HQXYZ...",
"code": "482910"
}' | jq

When 2FA is enabled, login may require a second factor. Create and verify a challenge:

Terminal window
# Create a challenge (optionally specify method: totp, sms, email, webauthn, backup_code)
curl -s https://your-project.zatabase.io/v1/auth/2fa/challenge?method=totp \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
# Verify the challenge
curl -s -X POST https://your-project.zatabase.io/v1/auth/2fa/challenge/{challenge_id}/verify \
-H "Content-Type: application/json" \
-d '{"code": "482910"}' | jq

Backup codes are generated when you first enable TOTP. You can regenerate them at any time (this invalidates all previous codes):

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/2fa/backup-codes \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

If you lose access to all 2FA methods, initiate account recovery:

Terminal window
curl -s -X POST https://your-project.zatabase.io/v1/auth/recovery/initiate \
-H "Content-Type: application/json" \
-d '{
"org_id": 1,
"email": "[email protected]",
"method": "email"
}' | jq
# Verify the recovery token received via email
curl -s -X POST https://your-project.zatabase.io/v1/auth/recovery/verify \
-H "Content-Type: application/json" \
-d '{
"recovery_id": "01HQXYZ...",
"token": "abc123..."
}' | jq

Recovery methods: email, sms, security_questions.

Disable a specific method:

Terminal window
curl -s -X DELETE https://your-project.zatabase.io/v1/auth/2fa/method/totp \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

Valid method names: totp, sms, email, webauthn, backup_codes.

Manage devices that bypass 2FA challenges:

Terminal window
# List trusted devices
curl -s https://your-project.zatabase.io/v1/auth/2fa/trusted-devices \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
# Remove a trusted device
curl -s -X DELETE https://your-project.zatabase.io/v1/auth/2fa/trusted-devices/{device_id} \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq

Administrators can enforce 2FA requirements across the organization:

Terminal window
# Get current policy
curl -s https://your-project.zatabase.io/v1/auth/2fa/policy \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
# Update policy (admin only)
curl -s -X PUT https://your-project.zatabase.io/v1/auth/2fa/policy \
-H "Authorization: Bearer $ZATABASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"required": true,
"allowed_methods": ["totp", "webauthn"],
"grace_period_days": 7
}' | jq
# Check your compliance status
curl -s https://your-project.zatabase.io/v1/auth/2fa/compliance \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq
MethodPathDescription
GET/v1/auth/2fa/statusGet 2FA status for current user
POST/v1/auth/2fa/totp/setupGenerate TOTP setup (QR code + secret)
POST/v1/auth/2fa/totp/verifyVerify TOTP code and activate
POST/v1/auth/2fa/sms/setupInitiate SMS 2FA setup
POST/v1/auth/2fa/sms/verifyVerify SMS code and activate
POST/v1/auth/2fa/webauthn/registerStart WebAuthn registration
POST/v1/auth/2fa/webauthn/register/finishComplete WebAuthn registration
GET/v1/auth/2fa/challengeCreate a 2FA challenge
POST/v1/auth/2fa/challenge/:id/verifyVerify a 2FA challenge
DELETE/v1/auth/2fa/method/:methodDisable a 2FA method
POST/v1/auth/2fa/backup-codesGenerate new backup codes
GET/v1/auth/2fa/trusted-devicesList trusted devices
DELETE/v1/auth/2fa/trusted-devices/:idRemove a trusted device
GET/v1/auth/2fa/policyGet organization 2FA policy
PUT/v1/auth/2fa/policyUpdate organization 2FA policy (admin)
GET/v1/auth/2fa/complianceCheck 2FA compliance status
POST/v1/auth/recovery/initiateStart account recovery
POST/v1/auth/recovery/verifyVerify recovery token

Zatabase uses role-based access control (RBAC) with org-scoped permissions. See Architecture for details on the permission model. Key built-in roles:

  • admin: Full CRUD access to all resource types
  • operator: Read/write access to data resources, read-only for system configuration
  • reader: Read-only access to data resources

Check effective permissions:

Terminal window
curl -s https://your-project.zatabase.io/v1/permissions/effective \
-H "Authorization: Bearer $ZATABASE_TOKEN" | jq