Authentication
Lucent provides a complete authentication system with JWT support.
Setup
Enable authentication in your configuration:
// lucent.config.ts
export default defineConfig({
auth: {
jwtSecret: process.env.JWT_SECRET,
jwtExpiry: "7d",
},
collections: {
users: defineCollection({
/* ... */
}),
},
});
User Collection
Your users collection must include specific fields:
export const users = defineCollection({
name: "users",
fields: {
email: { type: "email", required: true, unique: true },
password: { type: "string", required: true, hidden: true },
name: { type: "string" },
role: { type: "select", options: ["admin", "user"], default: "user" },
// Auth fields
verified: { type: "boolean", default: false },
verificationToken: { type: "string", hidden: true },
resetToken: { type: "string", hidden: true },
resetExpiry: { type: "datetime", hidden: true },
},
});
Authentication Methods
Email/Password
// Register
const user = await lucent.auth.register({
email: "user@example.com",
password: "securepassword123",
name: "John Doe",
});
// Login
const { user, token } = await lucent.auth.login({
email: "user@example.com",
password: "securepassword123",
});
// Logout (invalidates the current refresh token)
await lucent.auth.logout(token);
// Logout from ALL devices (invalidates every refresh token for this user)
// POST /api/:collection/logout-all
await fetch("/api/users/logout-all", {
method: "POST",
headers: { Authorization: `Bearer ${accessToken}` },
});
API Keys
API keys provide a simple, non-rotating credential for programmatic access.
They support optional scopes (read, write, admin) that can be used in your access functions to restrict what the key may do.
Managing API keys
// Create a key (POST /api/:collection/api-keys)
const res = await fetch("/api/users/api-keys", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
name: "CI deployment key",
scopes: ["read", "write"], // optional — omit to grant all operations
// expiresAt: "2026-01-01T00:00:00Z", // optional ISO-8601 expiry
}),
});
const { apiKey } = await res.json();
// apiKey.key is only shown once — store it securely
// List your keys (GET /api/:collection/api-keys)
const { apiKeys } = await fetch("/api/users/api-keys", {
headers: { Authorization: `Bearer ${accessToken}` },
}).then((r) => r.json());
// Revoke a key (DELETE /api/:collection/api-keys/:id)
await fetch(`/api/users/api-keys/${apiKey.id}`, {
method: "DELETE",
headers: { Authorization: `Bearer ${accessToken}` },
});
Enforcing scopes in access functions
The scopes array is available on the AuthUser object for requests authenticated with an API key:
export const Posts = defineCollection({
slug: "posts",
access: {
// Only keys with the "write" scope (or regular users) may create posts
create: ({ user }) => {
if (!user) return false;
if (user.scopes) return user.scopes.includes("write") || user.scopes.includes("admin");
return true; // regular JWT / session user, no scope restriction
},
},
fields: [
/* ... */
],
});
Using the Token
Include the token in API requests:
fetch("/api/posts", {
headers: {
Authorization: `Bearer ${token}`,
},
});
Password Requirements
auth: {
password: {
minLength: 8,
requireUppercase: true,
requireNumbers: true,
requireSymbols: true
}
}
Email Verification
// Send verification email
await lucent.auth.sendVerificationEmail(userId);
// Verify email
await lucent.auth.verifyEmail(token);
Password Reset
// Request password reset
await lucent.auth.requestPasswordReset(email);
// Reset password
await lucent.auth.resetPassword(token, newPassword);