JavaScript: Authentication
Sign app users up and in with email and password, magic links, email codes, SMS codes and social providers; manage sessions, MFA, users and roles with @sovaria/sdk.
sovaria.auth signs app users — the people who use your app — in and out of your project. The client keeps the session, sends it with every request, refreshes it before it expires and, in browsers, keeps it across reloads. Your policies and row-level security then decide what each user can do.
import { createClient } from '@sovaria/sdk'
const sovaria = createClient('https://<project-ref>.sovaria.in', '<anon-key>')
// Fires once right away with the current session, then on every sign-in, refresh and sign-out.
const stop = sovaria.auth.onAuthStateChange((event, session) => {
console.log(event, session?.user?.email)
})
await sovaria.auth.signUp('ada@example.com', 'Correct-Horse-9!', 'Ada')
await sovaria.auth.signIn('ada@example.com', 'Correct-Horse-9!')
console.log(sovaria.auth.getSession()?.user)
await sovaria.auth.signOut()
stop()sovaria.auth
sovaria.auth.onAuthStateChange
Listen for sign-in, token refresh and sign-out.
sovaria.auth.onAuthStateChange(
callback: (event: AuthChangeEvent, session: SovariaSession | null) => void,
): () => voidFires once right away with the current session (INITIAL_SESSION). Returns a function that stops listening.
Parameters
callback(event: AuthChangeEvent, session: SovariaSession | null) => voidrequired- Called with the event (
INITIAL_SESSION,SIGNED_IN,TOKEN_REFRESHED,SIGNED_OUT) and the session (ornull).
- Returns
() => void— A function that stops listening.
sovaria.auth.getSession
The signed-in app user's session, or null.
sovaria.auth.getSession(): SovariaSession | null- Returns
SovariaSession | null— The current session object, ornullwhen nobody is signed in. Synchronous — no network call.
sovaria.auth.signOut
Sign the app user out (revokes the refresh token) and fall back to the anon key.
sovaria.auth.signOut(): Promise<void>- Returns
Promise<void>— Resolves when the refresh token is revoked; the client then acts as an anonymous visitor (anon key).
sovaria.auth.signUp
Create an app user and sign them in.
sovaria.auth.signUp(email: string, password: string, name?: string = ''): Promise<JsonObject>When the project requires email confirmation, the result has email_verification_required: true and no session until the user confirms.
Parameters
emailstringrequired- The user's email address.
passwordstringrequired- Must meet the project's password rules (Authentication → Settings).
namestringoptionaldefault''- Display name stored on the user.
- Returns
Promise<JsonObject>— The new user and a session — oremail_verification_required: trueand no session when the project requires email confirmation first.
- Fails with
403 SIGNUP_DISABLEDwhen new sign-ups are turned off for the project.
const result = await sovaria.auth.signUp('ada@example.com', 'Correct-Horse-9!', 'Ada')
if (result.email_verification_required) {
showMessage('Check your inbox to confirm your email.')
}sovaria.auth.signIn
Sign an app user in with email and password (same as projectLogin).
sovaria.auth.signIn(email: string, password: string): Promise<JsonObject>Parameters
emailstringrequired- The user's email address.
passwordstringrequired- Their password.
- Returns
Promise<JsonObject>— The session; afterwards every request from this client runs as the user.
- If the user has MFA turned on, finish with
auth.verifyMfa(code).
try {
await sovaria.auth.signIn(email, password)
} catch (err) {
if (err.statusCode === 401) showError('Wrong email or password')
else throw err
}sovaria.auth.register
Create an app user (no session).
sovaria.auth.register(email: string, password: string, name: string): Promise<JsonObject>Most apps want signUp(), which also signs them in.
Parameters
emailstringrequiredpasswordstringrequirednamestringrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/register
- Most apps want
signUp, which also signs the user in.
sovaria.auth.login
Login.
sovaria.auth.login(email: string, password: string): Promise<JsonObject>Parameters
emailstringrequiredpasswordstringrequired
- Returns
Promise<JsonObject>
sovaria.auth.consoleLogin
Strict console login — rejects every project-scoped credential.
sovaria.auth.consoleLogin(email: string, password: string): Promise<JsonObject>Parameters
emailstringrequiredpasswordstringrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/console/login
- For scripts acting as a team member (managing the project). Never use it for app users.
sovaria.auth.loginConsole
Alias for consoleLogin() matching lane terminology in docs.
sovaria.auth.loginConsole(email: string, password: string): Promise<JsonObject>Parameters
emailstringrequiredpasswordstringrequired
- Returns
Promise<JsonObject>
sovaria.auth.projectLogin
Strict project login — requires X-Sovaria-Org-ID + X-Sovaria-Project-ID.
sovaria.auth.projectLogin(email: string, password: string): Promise<JsonObject>Parameters
emailstringrequiredpasswordstringrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/project/login
sovaria.auth.loginProduct
Alias for projectLogin() matching lane terminology in docs.
sovaria.auth.loginProduct(email: string, password: string): Promise<JsonObject>Parameters
emailstringrequiredpasswordstringrequired
- Returns
Promise<JsonObject>
sovaria.auth.refresh
Refresh.
sovaria.auth.refresh(refreshToken: string): Promise<JsonObject>Parameters
refreshTokenstringrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/refresh
sovaria.auth.logout
Logout.
sovaria.auth.logout(refreshToken?: string): Promise<JsonObject>Parameters
refreshTokenstringoptional
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/logout
sovaria.auth.me
Me.
sovaria.auth.me(): Promise<JsonObject>- Returns
Promise<JsonObject>— The signed-in user's profile (id, email, roles, metadata).- HTTP
GET /api/v1/auth/me
sovaria.auth.verifyMfa
Verify mfa.
sovaria.auth.verifyMfa(code: string, method?: 'totp' | 'phone' = 'totp'): Promise<JsonObject>Parameters
codestringrequired- The 6-digit code from the authenticator app (or SMS).
method'totp' | 'phone'optionaldefault'totp'totpfor an authenticator app,phonefor SMS.
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/mfa/verify
sovaria.auth.sendMagicLink
Send a one-time login link by email.
sovaria.auth.sendMagicLink(
email: string,
opts?: { orgId?: string; projectId?: string; redirectTo?: string } = {},
): Promise<JsonObject>Returns 200 even for unknown emails.
Parameters
emailstringrequired- Where to send the link.
opts{ orgId?: string; projectId?: string; redirectTo?: string }optionaldefault{}redirectTo: the page of your app the link opens (must be an allowed redirect URL);orgId/projectIdonly when the client has no project scope.
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/magic-link/send
- Always succeeds, whether or not the address has an account, so it can't be used to discover users.
await sovaria.auth.sendMagicLink('ada@example.com', { redirectTo: 'https://app.example.com/auth/callback' })sovaria.auth.resetPasswordForEmail
Email a password-reset link.
sovaria.auth.resetPasswordForEmail(
email: string,
opts?: { orgId?: string; projectId?: string; redirectTo?: string } = {},
): Promise<JsonObject>Returns 200 even for unknown emails.
Parameters
emailstringrequired- The account's email.
opts{ orgId?: string; projectId?: string; redirectTo?: string }optionaldefault{}redirectTo: your page that sets the new password.
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/password-reset/send
await sovaria.auth.resetPasswordForEmail(email, { redirectTo: 'https://app.example.com/reset' })sovaria.auth.confirmPasswordReset
Set a new password with the token from a reset link (type=recovery).
sovaria.auth.confirmPasswordReset(token: string, newPassword: string): Promise<JsonObject>Parameters
tokenstringrequired- The
tokenfrom the reset link. newPasswordstringrequired- The new password (same rules as sign-up).
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/password-reset/confirm
sovaria.auth.handleEmailLink
Handle the link an auth email opened (?token=…&type=… on your Site URL).
sovaria.auth.handleEmailLink(
url?: string,
): Promise<{ type: string; error: string; description: string | undefined; session?: undefined; result?: undefined; token?: undefined; } | { type: string; session: JsonObject; error?: undefined; description?: undefined; result?: undefined; token?: undefined; } | { type: string; result: JsonObject; error?: undefined; description?: undefined; session?: undefined; token?: undefined; } | { type: string; token: string; error?: undefined; description?: undefined; session?: undefined; result?: undefined; } | null>Magic links sign the user in; email confirmations are confirmed; for recovery the token is returned so you can show a "new password" form and call confirmPasswordReset. Returns null when the URL isn't an auth link.
Parameters
urlstringoptional- The URL to read; defaults to the current page.
- Returns
Promise<{ type: string; error: string; description: string | undefined; session?: undefined; result?: undefined; token?: undefined; } | { type: string; session: JsonObject; error?: undefined; description?: undefined; result?: undefined; token?: undefined; } | { type: string; result: JsonObject; error?: undefined; description?: undefined; session?: undefined; token?: undefined; } | { type: string; token: string; error?: undefined; description?: undefined; session?: undefined; result?: undefined; } | null>—{ type, error, … }—typeis what the link did (sign-in, email verification, password recovery, email change).- HTTP
POST /api/v1/auth/email-change/confirm
// On the page your auth emails link to (your Site URL or redirectTo):
const { type, error } = await sovaria.auth.handleEmailLink()
if (error) showError(error)
else if (type === 'recovery') router.push('/set-new-password')
else router.push('/')sovaria.auth.signInWithProvider
"Sign in with Google / GitHub / …" (providers connected in Authentication › Sign in / Providers).
sovaria.auth.signInWithProvider(
providerId: string,
opts?: { redirectTo?: string; projectId?: string } = {},
): Promise<{ url: string; }>Sends the browser to the provider; it comes back to redirectTo (or your Site URL) with ?code=…&type=sso, which handleEmailLink() / exchangeCodeForSession() turn into a session. A PKCE verifier is kept in sessionStorage so only this browser can redeem the code.
Parameters
providerIdstringrequired- A provider enabled under Authentication → Providers, e.g.
googleorgithub. opts{ redirectTo?: string; projectId?: string }optionaldefault{}redirectTo: where the provider sends the user back.
- Returns
Promise<{ url: string; }>—{ url }— the browser is sent there; after consent the user returns toredirectTowith acode.- HTTP
GET /api/v1/auth/sso/{…}/authorize
await sovaria.auth.signInWithProvider('github', { redirectTo: 'https://app.example.com/auth/callback' })
// on /auth/callback:
const code = new URL(location.href).searchParams.get('code')
if (code) await sovaria.auth.exchangeCodeForSession(code)sovaria.auth.exchangeCodeForSession
Exchange the one-time code from a provider sign-in redirect for a session.
sovaria.auth.exchangeCodeForSession(code: string, codeVerifier?: string): Promise<JsonObject>Parameters
codestringrequired- The
codequery parameter from the redirect. codeVerifierstringoptional- Only if you started the flow yourself; the SDK keeps it otherwise.
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/sso/exchange
sovaria.auth.listProviders
Enabled social / enterprise providers for your sign-in screen.
sovaria.auth.listProviders(projectId?: string): Promise<JsonValue>Parameters
projectIdstringoptional
- Returns
Promise<JsonValue>— The providers you enabled, to render sign-in buttons.- HTTP
GET /api/v1/auth/sso/providers
sovaria.auth.getPublicConfig
Public sign-in config for a project: enabled providers, password rules, MFA factors, passkeys.
sovaria.auth.getPublicConfig(projectId?: string): Promise<JsonObject>Parameters
projectIdstringoptional
- Returns
Promise<JsonObject>— Whether sign-up is open, enabled providers, password rules, MFA and passkey settings — everything a sign-in screen needs, without a session.- HTTP
GET /api/v1/auth/public-config{…}
sovaria.auth.verifyMagicLink
Exchange a magic-link token for an access + refresh token pair.
sovaria.auth.verifyMagicLink(token: string): Promise<JsonObject>Parameters
tokenstringrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/magic-link/verify
sovaria.auth.verifyEmailCode
Sign in with the 6-digit code from the sign-in email (the same email carries the magic link).
sovaria.auth.verifyEmailCode(
email: string,
code: string,
opts?: { orgId?: string; projectId?: string } = {},
): Promise<JsonObject>Uses the client scope's org/project unless given.
Parameters
emailstringrequired- The address the code was sent to.
codestringrequired- The 6-digit code from the email.
opts{ orgId?: string; projectId?: string }optionaldefault{}
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/magic-link/verify-code
await sovaria.auth.verifyEmailCode('ada@example.com', '123456')sovaria.auth.sendOtp
Send an SMS OTP code for phone-based login.
sovaria.auth.sendOtp(
phone: string,
opts?: { orgId?: string; projectId?: string; envId?: string } = {},
): Promise<JsonObject>Parameters
phonestringrequired- E.164 number, e.g.
+15551234567. opts{ orgId?: string; projectId?: string; envId?: string }optionaldefault{}
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/otp/send
- Needs an SMS provider configured for the project.
sovaria.auth.verifyOtp
Verify an SMS OTP code and establish a session.
sovaria.auth.verifyOtp(
phone: string,
code: string,
opts?: { orgId?: string; projectId?: string; envId?: string; password?: string } = {},
): Promise<JsonObject>Passwordless by default — pass password when argon2_salt is present to populate the session KEK without a follow-up password login.
Parameters
phonestringrequired- The number the code was sent to.
codestringrequired- The code from the SMS.
opts{ orgId?: string; projectId?: string; envId?: string; password?: string }optionaldefault{}
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/otp/verify
sovaria.auth.oauthHandoff
Exchange an OAuth handoff token for a session (console OAuth callback).
sovaria.auth.oauthHandoff(token: string, password?: string): Promise<JsonObject>Passwordless: session KEK is not derived unless password is supplied.
Parameters
tokenstringrequiredpasswordstringoptional
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/oauth/handoff
sovaria.auth.listConsoleProductUsers
Console-operator listing of product users across accessible projects.
sovaria.auth.listConsoleProductUsers(): Promise<JsonValue>Path: GET /api/v1/auth/product-users (console lane).
- Returns
Promise<JsonValue>- HTTP
GET /api/v1/auth/product-users
sovaria.auth.sendVerificationEmail
Trigger a verification email for the authenticated user.
sovaria.auth.sendVerificationEmail(): Promise<JsonObject>- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/verify-email/send
sovaria.auth.confirmVerificationEmail
Confirm an email-verification token.
sovaria.auth.confirmVerificationEmail(token: string): Promise<JsonObject>Parameters
tokenstringrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/verify-email/confirm
sovaria.auth.listUsers
List users.
sovaria.auth.listUsers(): Promise<JsonValue>- Returns
Promise<JsonValue>
- Needs the service role key or a project admin session; never call it from a browser.
sovaria.auth.deleteUser
Delete user.
sovaria.auth.deleteUser(userId: string): Promise<JsonObject>Parameters
userIdstringrequired
- Returns
Promise<JsonObject>- HTTP
DELETE /api/v1/auth/product-users/{…}
sovaria.auth.banUser
Ban user.
sovaria.auth.banUser(userId: string): Promise<JsonObject>Parameters
userIdstringrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/product-users/{…}/ban
App users (admin)
sovaria.auth.productUsers.list
Every product user: follows all pages.
sovaria.auth.productUsers.list(): Promise<JsonObject[]>Use listPage() for big projects.
- Returns
Promise<JsonObject[]>
sovaria.auth.productUsers.listPage
One page of product users, newest first.
sovaria.auth.productUsers.listPage(
params?: { limit?: number; cursor?: string | null; search?: string; status?: 'active' | 'banned' } = {},
): Promise<ProductUsersPage>search matches part of an email or an exact id.
Parameters
params{ limit?: number; cursor?: string | null; search?: string; status?: 'active' | 'banned' }optionaldefault{}limit(page size),cursor(from the previous page),search(part of an email or name).
- Returns
Promise<ProductUsersPage>
let cursor = null
do {
const page = await sovaria.auth.productUsers.listPage({ limit: 100, cursor })
page.users.forEach((u) => console.log(u.email))
cursor = page.nextCursor
} while (cursor)sovaria.auth.productUsers.delete
Delete.
sovaria.auth.productUsers.delete(userId: string): Promise<JsonObject>Parameters
userIdstringrequired
- Returns
Promise<JsonObject>
sovaria.auth.productUsers.ban
Ban.
sovaria.auth.productUsers.ban(userId: string): Promise<JsonObject>Parameters
userIdstringrequired
- Returns
Promise<JsonObject>
sovaria.auth.productUsers.roles
Roles.
sovaria.auth.productUsers.roles(userId: string): Promise<JsonObject>Parameters
userIdstringrequired
- Returns
Promise<JsonObject>
sovaria.auth.productUsers.setRoles
Set roles.
sovaria.auth.productUsers.setRoles(userId: string, roles: string[]): Promise<JsonObject>Parameters
userIdstringrequired- The app user's id.
rolesstring[]required- App roles to give the user, e.g.
["librarian"]. Policies refer to them asapp:<role>.
- Returns
Promise<JsonObject>
await sovaria.auth.productUsers.setRoles(userId, ['librarian'])sovaria.auth.productUsers.create
Create.
sovaria.auth.productUsers.create(
payload: { email: string; password: string; name?: string; roles?: string[] },
): Promise<JsonObject>Parameters
payload{ email: string; password: string; name?: string; roles?: string[] }requiredemail,password, optionalnameandroles.
- Returns
Promise<JsonObject>
Sessions
sovaria.auth.sessions.list
List.
sovaria.auth.sessions.list(): Promise<JsonValue>- Returns
Promise<JsonValue>- HTTP
GET /api/v1/auth/sessions
sovaria.auth.sessions.revoke
Revoke.
sovaria.auth.sessions.revoke(sessionId: string): Promise<JsonObject>Parameters
sessionIdstringrequired
- Returns
Promise<JsonObject>- HTTP
DELETE /api/v1/auth/sessions/{…}
sovaria.auth.sessions.revokeOthers
Revoke others.
sovaria.auth.sessions.revokeOthers(): Promise<JsonObject>- Returns
Promise<JsonObject>— Signs the user out everywhere except this device.- HTTP
POST /api/v1/auth/sessions/revoke-others
sovaria.auth.sessions.getConfig
Get config.
sovaria.auth.sessions.getConfig(): Promise<JsonObject>- Returns
Promise<JsonObject>- HTTP
GET /api/v1/auth/sessions/config
sovaria.auth.sessions.setConfig
Set config.
sovaria.auth.sessions.setConfig(body: JsonObject): Promise<JsonObject>Parameters
bodyJsonObjectrequired
- Returns
Promise<JsonObject>- HTTP
PUT /api/v1/auth/sessions/config
Multi-factor authentication
sovaria.auth.mfa.status
Status.
sovaria.auth.mfa.status(): Promise<JsonObject>- Returns
Promise<JsonObject>- HTTP
GET /api/v1/auth/mfa/status
sovaria.auth.mfa.enroll
Enroll.
sovaria.auth.mfa.enroll(): Promise<JsonObject>- Returns
Promise<JsonObject>— A secret andotpauth://URL to show as a QR code; confirm withauth.verifyMfa.- HTTP
POST /api/v1/auth/mfa/enroll
sovaria.auth.mfa.disable
Disable.
sovaria.auth.mfa.disable(totpCode: string): Promise<JsonObject>Parameters
totpCodestringrequired
- Returns
Promise<JsonObject>- HTTP
DELETE /api/v1/auth/mfa
Provider settings
sovaria.auth.providersConfig.get
Get.
sovaria.auth.providersConfig.get(): Promise<JsonObject>- Returns
Promise<JsonObject>- HTTP
GET /api/v1/auth/providers/config
sovaria.auth.providersConfig.set
Set.
sovaria.auth.providersConfig.set(body: JsonObject): Promise<JsonObject>Parameters
bodyJsonObjectrequired
- Returns
Promise<JsonObject>- HTTP
PUT /api/v1/auth/providers/config
Auth event hooks
sovaria.auth.eventHooks.list
List.
sovaria.auth.eventHooks.list(): Promise<JsonValue>- Returns
Promise<JsonValue>- HTTP
GET /api/v1/auth/event-hooks
sovaria.auth.eventHooks.create
Create.
sovaria.auth.eventHooks.create(
payload: { name: string url: string events: string[] secret?: string enabled?: boolean projectId?: string },
): Promise<JsonObject>Parameters
payload{ name: string url: string events: string[] secret?: string enabled?: boolean projectId?: string }required
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/event-hooks
sovaria.auth.eventHooks.delete
Delete.
sovaria.auth.eventHooks.delete(hookId: string): Promise<JsonObject>Parameters
hookIdstringrequired
- Returns
Promise<JsonObject>- HTTP
DELETE /api/v1/auth/event-hooks/{…}
Console members
sovaria.auth.consoleMembers.list
List.
sovaria.auth.consoleMembers.list(): Promise<JsonValue>- Returns
Promise<JsonValue>- HTTP
GET /api/v1/org/{…}/members
sovaria.auth.consoleMembers.delete
Delete.
sovaria.auth.consoleMembers.delete(userId: string): Promise<JsonObject>Parameters
userIdstringrequired
- Returns
Promise<JsonObject>- HTTP
DELETE /api/v1/org/{…}/member/{…}
sovaria.auth.consoleMembers.ban
Ban.
sovaria.auth.consoleMembers.ban(userId: string): Promise<JsonObject>Parameters
userIdstringrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/auth/product-users/{…}/ban
GitHub connection (console)
sovaria.auth.github.connectionState
Connection state.
sovaria.auth.github.connectionState(): Promise<JsonObject>- Returns
Promise<JsonObject>- HTTP
GET /api/v1/auth/github/connection-state
sovaria.auth.github.disconnect
Disconnect.
sovaria.auth.github.disconnect(): Promise<JsonObject>- Returns
Promise<JsonObject>- HTTP
DELETE /api/v1/auth/github/connection-state