Login & Registration
How a basic app signs users up, signs them in and out, using the
@rw3iss/auth-client SDK directly (no UI components). All session
state — tokens, refresh scheduling, cross-tab sync — is owned by the
client core; you just call the modules.
Reference: AuthModule ·
AccountModule ·
AuthClient
Instantiate the client
One client per app, created once at boot. appCode is your app’s code
in the auth-server’s app registry —
it scopes every issued token.
import { createAuthClient } from '@rw3iss/auth-client';
const client = createAuthClient({ apiBaseUrl: 'https://auth.ryanweiss.net/api/v1', appCode: 'my-app',});
// Wait for the boot check (validates any cached session).await client.ready();Register a new account
const result = await client.auth.register({ email: 'new@example.com', password: 'Str0ngPass!', firstName: 'New', lastName: 'User', // appCode defaults to the client's configured app code.});
console.log(result.user.id, result.verification_email_sent);The server applies the app’s registration policy (allowed email domains / auth methods), places the user in the app’s default pool, and fires any configured webhooks.
Tip: render an accurate form before submit by reading the public policy — no token required:
const policy = await client.auth.getRegistrationPolicy();// policy.allowed_email_domains, policy.allowed_auth_methods, …Log in
const res = await client.auth.login({ email: 'new@example.com', password: 'Str0ngPass!', rememberMe: true, // 30d refresh token instead of 7d});
if (res.requires_2fa) { // Account has TOTP active — re-submit with the code. const code = await promptUserForTotp(); await client.auth.login({ email, password, twoFactorCode: code });}
client.auth.isAuthenticated(); // trueclient.auth.getCurrentUser(); // decoded from the access tokenawait client.auth.whoami(); // server-authoritative /auth/meAfter login the SDK persists the token pair, schedules refresh ahead of expiry, and broadcasts the session to other tabs. Subscribe to lifecycle events instead of polling:
client.on('logged_out', () => router.push('/login'));client.on('session_expired', () => router.push('/login'));client.on('token_refreshed', () => {/* metrics, etc. */});Log out
await client.auth.logout(); // revoke THIS session's refresh tokenawait client.auth.logoutAll(); // revoke EVERY session (all devices) + // bump the server token-version so // outstanding access tokens die immediatelyAccount self-service
Everything the signed-in user does to their own account lives on
client.account:
// Password reset (anonymous — server is silent on unknown emails)await client.account.requestPasswordReset('new@example.com');await client.account.resetPassword(tokenFromEmail, 'NewStr0ngPass!');
// Change password while signed inawait client.account.changePassword('Str0ngPass!', 'NewStr0ngPass!');
// Email verificationawait client.account.verifyEmail(tokenFromEmail);await client.account.resendVerificationEmail('new@example.com');
// Two-factor (TOTP)const { provisioningUri, secret } = await client.account.setupTwoFactor();// render provisioningUri as a QR code, then:await client.account.enableTwoFactor(firstCodeFromApp);See also
- Quickstart — full boot pattern + framework adapters.
- How it works → User registration & login — what the server does on each call.
- SSO and magic-link entry points:
AuthModule.startSso,AuthModule.requestMagicLink.