Authentication in Spooky is built directly into the sql schema, making it robust, typesafe, and dynamic. Because access control is defined at the database layer, your rules are consistently enforced regardless of how the data is accessed.
Schema Configuration
You define authentication using DEFINE ACCESS. This allows you to specify exactly how users sign up and sign in, and what permissions they have.
sql
-- Define access scope for accountsDEFINE ACCESS account ON DATABASE TYPE RECORDSIGNUP ( CREATE user SET username = $username, password = crypto::argon2::generate($password))SIGNIN ( SELECT * FROM user WHERE username = $username AND crypto::argon2::compare(password, $password))DURATION FOR TOKEN 15m, FOR SESSION 30d;-- Permissions use the $auth variable to check the current userDEFINE TABLE user SCHEMAFULLPERMISSIONSFOR update, delete WHERE id = $auth.idFOR select, create WHERE true;
Client-Side Authentication
Spooky provides a strongly-typed authentication service on the client. It integrates seamlessly with the schema definitions.
Sign In
TypeScript
import { db } from './db';// The second argument is typesafe based on your SIGNIN definitionawait db.auth.signIn('account', {username: 'spooky_user',password: 'secure_password'});
Sign Up
TypeScript
import { db } from './db';await db.auth.signUp('account', {username: 'new_user',password: 'secure_password'});
Sign Out
TypeScript
await db.auth.signOut();
Reacting to Auth State
You can subscribe to authentication state changes to update your UI dynamically. The callback receives the user ID when authenticated, or null when signed out.