Member Authentication
Add registration, login, page protection, and password reset to your published site.
Overview
Site members are the end-users of your published website — completely separate from CMS admin users. Each workspace maintains its own member base (multi-tenant), and authentication uses secure httpOnly cookies so tokens are never accessible via JavaScript.
Enabling Member Auth
Go to Settings → Member Authentication in the admin panel and toggle Enable Member Auth. Once enabled, configure the following options:
| Setting | Description |
|---|---|
allowRegistration | Allow new members to self-register |
requireEmailVerification | Block login until email is verified |
loginUrl | Path to your login page (default: /login) |
registerUrl | Path to your registration page |
afterLoginUrl | Redirect destination after successful login |
afterLogoutUrl | Redirect destination after logout |
Building Auth Pages
Create dedicated pages and blocks for the auth flow. Recommended pages: /login, /register, /forgot-password, /reset-password, and /verify-email.
Login Block
const result = await context.auth.login(email, password);
if (result.success) {
window.location.href = redirectUrl;
} else {
showError(result.message);
}Register Block
const result = await context.auth.register(email, password, {
firstName: "Jane",
lastName: "Doe"
});
// Show "check your email" on successLogout
await context.auth.logout();
window.location.href = "/";Forgot Password Block
await context.graphql(`
mutation($wid: ID!, $email: String!) {
siteMemberRequestPasswordReset(
workspaceId: $wid, email: $email
) { success message }
}
`, { wid: context.workspace.id, email });Reset Password Block
Read ?token= from URL:
const token = new URLSearchParams(location.search).get("token");
await context.graphql(`
mutation($token: String!, $pw: String!) {
siteMemberResetPassword(token: $token, newPassword: $pw) {
success message
}
}
`, { token, pw: newPassword });Verify Email Block
const token = new URLSearchParams(location.search).get("token");
await context.graphql(`
mutation($token: String!) {
siteMemberVerifyEmail(token: $token) { success message }
}
`, { token });Auth Context in Blocks
context.auth is available in any block when member auth is enabled. Functions are client-side only.
| Property / Method | Type | Description |
|---|---|---|
context.auth.isAuthenticated | boolean | Whether current visitor is logged in |
context.auth.member | object | { id, email, role, isVerified, profile } |
context.auth.login(email, pw) | Promise | Returns { success, message } |
context.auth.register(email, pw, profile?) | Promise | Returns { success, message } |
context.auth.logout() | Promise | Clears session cookie |
Conditional Rendering
if (context.auth.isAuthenticated) {
const { displayName } = context.auth.member.profile;
// show member content
} else {
// show login prompt
}Page Protection
Protect pages server-side via access control settings. Unauthenticated users redirect to loginUrl before any HTML is sent.
| Setting | Description |
|---|---|
requireAuth: true | Redirect unauthenticated visitors |
allowedRoles: ["premium"] | Restrict to specific roles |
Member Roles
Default roles: Guest, Member (default on registration), Premium. Custom roles configurable per workspace.
Member Profile
firstName,lastName,displayNameavatarUrl,phonecustomFields— workspace-defined extra fields
Password Requirements
- Min 8 characters, one uppercase, one lowercase, one number
Email Verification Flow
- Register → status pending, verification email sent
- Click link →
/verify-email?token=xxx→ status active - If
requireEmailVerification: true, login blocked until verified
Password Reset Flow
- Forgot password form → reset email sent
- Click link →
/reset-password?token=xxx→ new password - Token expires after 1 hour
Session
JWT in httpOnly cookie, 7-day expiry. Auto-forwarded on all block GraphQL requests. No manual token management needed.
Tips
- Create all 5 auth pages:
/login,/register,/forgot-password,/reset-password,/verify-email - Protected pages redirect to
/loginby default (configurable per page) context.authfunctions are client-side only- Use
context.auth.isAuthenticatedto show/hide content conditionally - All member data is workspace-scoped (multi-tenant safe)