Applications
Registering and configuring applications — the consuming apps of
the auth platform — via client.apps. Every route here is
system_admin only; sign in with an admin account first.
Reference: AppsModule ·
AppRecord ·
App registration guide
Instantiate + sign in as admin
import { createAuthClient } from '@rw3iss/auth-client';
const client = createAuthClient({ apiBaseUrl: 'https://auth.ryanweiss.net/api/v1', appCode: 'auth-client-demo', // an app the admin can log in to});await client.ready();await client.auth.login({ email: 'admin@ryanweiss.net', password: '…' });Register an app (basic / default config)
The minimal app: a code, a name, redirect URLs. Users live in the
shared default pool, any email domain may register, first login
self-grants access:
const app = await client.apps.create({ code: 'my-app', name: 'My App', allowed_redirect_urls: ['https://my-app.example.com/auth/callback'], auto_grant_on_signup: true,});console.log(app.id, app.status); // 'active'Register an app with its OWN user pool
Pools segregate identity — email is unique per pool. Give the app a dedicated default pool so its registrants are isolated from the shared platform users:
await client.apps.create({ code: 'partner-portal', name: 'Partner Portal', allowed_redirect_urls: ['https://partners.example.com/auth/callback'], auto_grant_on_signup: true, registration_namespace: 'partner-portal', // new users' home pool read_namespaces: [], // nobody else may log in});Register an app on the EXISTING default pool, recognizing siblings
New users land in default; existing users from the claimleo and
wristleo pools may also log in (and new registrants get tagged into
those pools):
await client.apps.create({ code: 'claimleo', name: 'ClaimLeo', allowed_redirect_urls: ['https://claims.example.com/auth/callback'], registration_namespace: 'default', // home pool for new users read_namespaces: ['claimleo', 'wristleo'], // other pools (login)});Full pool semantics: User pools.
Modify an app’s config
client.apps.update(appId, body) is a PATCH — send only what changes.
Everything except the immutable code is editable:
// Registration policy: restrict domains + methods, set a default orgawait client.apps.update(app.id, { allowed_email_domains: ['ryanweiss.net'], allowed_auth_methods: ['password', 'google'], default_organization_id: orgId, // '' clears});
// Frontend URL — where account emails (verify/reset/invite) link to.// Mind the blast radius: a wrong value strands those flows.await client.apps.update(app.id, { frontend_url: 'https://my-app.example.com' });
// Webhooks — POSTed on every new-user registration through this app.// hooks.slack.com URLs automatically get Slack {"text"} format.await client.apps.update(app.id, { webhooks: [{ name: 'Slack #signups', url: 'https://hooks.slack.com/services/T…/B…/x…', events: ['user.registered'], enabled: true, }],});
// Disable logins without deleting the appawait client.apps.update(app.id, { status: 'disabled' });Webhook payload + delivery semantics: App registration → Webhooks.
List / inspect / delete
const apps = await client.apps.list(); // every registered appconst one = await client.apps.get(app.id); // single rowawait client.apps.delete(app.id); // soft-delete (audit kept)See also
- Users — granting users access to an app.
- User pools catalog —
client.pools.list()for type-ahead pool pickers.