Sign-in and users

People are a collection like any other, with sign-in built in. There is no auth service to add: accounts, sessions and permissions live in the same binary as the data they protect.

Signing in

app.ts
const users = sluurp.collection("users");
await users.authWithPassword(email, password);

sluurp.authStore.record;   // who is signed in
sluurp.logout();

A sign-in answers a token that lasts 14 days; authRefresh() swaps it for a fresh one. Passwords are at least 8 characters and stored as Argon2 hashes.

A link by mailrequestSigninLink(email): no password at all. The link works once, and expires
Password resetrequestPasswordReset(email) mails a link; confirmPasswordReset(token, password) sets the new one
Other providersGoogle, GitHub, Microsoft, GitLab, or any OpenID Connect provider, set up in the admin UI under Sign-in. location.href = users.oauthUrl("google"), and captureOAuthToken(sluurp) on the page it comes back to
Two-factor codesSix digits from an authenticator app, after the first factor. Five wrong tries and the attempt is over

There are no recovery codes: someone who loses their phone asks an administrator, who turns the second factor off from their record and signs them out everywhere.

Who may join

A setting on the app, enforced by the server:

  • invite, the default: only with an invitation.
  • open: anyone may sign up, under the collection’s create rule.
  • closed: nobody, for accounts that come from a directory.

An invitation is filled in twice. Whoever invites decides the fields that are theirs to decide, such as the organisation and the role, and the sign-up can’t change them. The person joining fills in the rest: their name, a password.

app.ts
await users.invite("parent@example.com", {
  fields: { org: school.id, roles: ["parent"] },
  collect: ["first_name", "last_name"],
});

Roles

A person’s roles is a list that rules can ask about: @request.auth.roles ~ "teacher". It matches whole roles only, so “admin” never matches “superadmin”.

For administrators

  • Impersonate someone from their record in the admin UI, to see the app as they do.
  • Sign out everywhere: revoking a person’s tokens ends every session they have, at once.
  • Superusers are separate from the app’s people: sluurp superuser EMAIL PASSWORD makes one.