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
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 mail | requestSigninLink(email): no password at all. The link works once, and expires |
| Password reset | requestPasswordReset(email) mails a link; confirmPasswordReset(token, password) sets the new one |
| Other providers | Google, 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 codes | Six 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.
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 PASSWORDmakes one.