What Own Auth writes to Postgres when a user signs up
One call to auth.signUpEmailPassword creates the records needed to identify a user, verify their password, and keep them signed in. Own Auth stores the user, sign-in method, and session in separate Postgres tables instead of putting the complete authentication system in one wide row. Each table can then enforce the constraints and expiry rules for the record it holds.
const { user, session, sessionToken } =
await auth.signUpEmailPassword({
email: "alice@example.com",
password: "her-secret-password",
name: "Alice",
});The returned user and session describe the completed sign-up. The raw sessionToken is the credential sent through the application's chosen secure transport. It is not stored in plaintext. The application does not insert an authentication user, hash a password, or create a session around this call.
The user record
own_auth_users holds the identity shared by every sign-in method. For an email and password sign-up, the row contains the generated user ID, normalized email, optional name, Argon2id password verifier, verification state, account status, timestamps, and authentication metadata. The table is prefixed so it does not collide with an application's existing users table.
Pass the submitted password directly to auth.signUpEmailPassword. Own Auth applies its password policy and hashing. Pre-hashing the password in the route changes the credential, because Own Auth would protect the already transformed string instead of the value the user will enter later. Plaintext passwords and stored verifiers must stay out of logs, traces, analytics, and support output.
The provider account
own_auth_accounts answers a different question: how can this user authenticate? The password sign-up creates an account row whose provider is password, whose provider account ID is the normalized email, and whose user_id references own_auth_users. Magic-link, phone, and supported external providers use the same relationship without duplicating the user profile.
This separation lets one Own Auth user gain another verified sign-in method while keeping one stable user ID. Product tables can reference that ID without caring whether the person arrived through a password, a magic link, or a linked provider. The foreign key also prevents an account row from pointing at a missing user in the package-managed Postgres schema.
The session
A successful sign-up creates a row in own_auth_sessions. It links to the user and records absolute expiry, idle expiry, recent activity, revocation state, and optional request context such as IP address and user agent. Postgres stores only a protected token hash. The raw token returned to the application is shown once and should travel in a Secure HttpOnly cookie or another protected session transport.
Later requests call auth.getCurrentSession with that raw token. Own Auth hashes the supplied token, finds the current database record, and checks expiry, idle timeout, revocation, and whether the user is disabled. Logout and administrative revocation therefore take effect from server state instead of waiting for a self-contained browser token to expire.
Rate limits and audit history
Own Auth checks its shared sign-up rate limit before creating the user. After creation it records a user.signed_up audit event linked to the new user. Framework routes do not need to recreate either behavior.
Application logs should remain smaller than the database history. Record a safe event name and generated user ID after success. Do not log the request body, password, session token, password verifier, or a serialized internal user or session record.
Application profiles stay separate
Authentication data and product profile data do not need the same lifecycle. Own Auth owns email, verification state, credentials, sessions, disablement, and the identifiers used by its authentication methods. An application can keep preferences, onboarding progress, billing attributes, processed avatars, or domain-specific profile fields in its own table keyed by the Own Auth user ID.
CREATE TABLE application_profiles (
own_auth_user_id text PRIMARY KEY
REFERENCES own_auth_users(id) ON DELETE CASCADE,
timezone text,
onboarding_completed_at timestamptz
);Create that application record only when the product needs it. Do not copy password hashes, session state, or provider accounts into it. Application migrations can then change product fields without modifying Own Auth's authentication records.
Inspect a sign-up safely
Check the created records without reading any secret values. Join the user, account, and session tables through their identifiers and select only the fields needed to confirm the sign-up.
SELECT
users.id,
users.email,
accounts.provider,
sessions.created_at AS session_created_at,
sessions.expires_at AS session_expires_at
FROM own_auth_users AS users
JOIN own_auth_accounts AS accounts
ON accounts.user_id = users.id
JOIN own_auth_sessions AS sessions
ON sessions.user_id = users.id
WHERE users.email = 'alice@example.com';A completed password sign-up produces one user identity, one password-provider account, and one active database session. Product code stores the returned user ID where it needs an application reference and sends the session credential through its secure session transport. Own Auth creates and verifies the authentication records.