bknd-setup-auth
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSetup Authentication
身份验证配置
Initialize and configure the Bknd authentication system with strategies, JWT, cookies, and roles.
初始化并配置Bknd身份验证系统,包含策略、JWT、Cookie和角色设置。
Prerequisites
前置条件
- Bknd project initialized
- Code-first configuration (auth config is code-only)
- For OAuth: provider credentials (client ID, client secret)
- 已初始化Bknd项目
- 代码优先配置(身份验证配置仅支持代码方式)
- 若使用OAuth:需准备服务商凭证(客户端ID、客户端密钥)
When to Use UI Mode
何时使用UI模式
- Viewing current auth configuration
- Toggling strategies on/off
- Testing auth endpoints via admin panel
UI steps: Admin Panel > Auth > Settings
Note: Full auth configuration requires code mode. UI only shows/toggles existing settings.
- 查看当前身份验证配置
- 开启/关闭验证策略
- 通过管理面板测试身份验证端点
UI操作步骤: 管理面板 > 身份验证 > 设置
注意: 完整的身份验证配置需要使用代码模式,UI仅能查看或切换已有的设置。
When to Use Code Mode
何时使用代码模式
- Initial authentication setup
- Configuring JWT secrets and expiry
- Setting up password hashing
- Defining roles and permissions
- Production security hardening
- 身份验证初始设置
- 配置JWT密钥和过期时间
- 设置密码哈希规则
- 定义角色与权限
- 生产环境安全加固
Code Approach
代码配置方法
Step 1: Enable Auth with Minimal Config
步骤1:通过最简配置启用身份验证
Start with basic password authentication:
typescript
import { serve } from "bknd/adapter/bun";
import { em, entity, text } from "bknd";
const schema = em({
posts: entity("posts", { title: text().required() }),
});
serve({
connection: { url: "file:data.db" },
config: {
data: schema.toJSON(),
auth: {
enabled: true,
},
},
});This enables:
- Password strategy (default)
- Auto-created entity
users - JWT-based sessions
- endpoints
/api/auth/*
从基础密码身份验证开始:
typescript
import { serve } from "bknd/adapter/bun";
import { em, entity, text } from "bknd";
const schema = em({
posts: entity("posts", { title: text().required() }),
});
serve({
connection: { url: "file:data.db" },
config: {
data: schema.toJSON(),
auth: {
enabled: true,
},
},
});此配置将启用:
- 密码验证策略(默认)
- 自动创建实体
users - 基于JWT的会话管理
- 系列端点
/api/auth/*
Step 2: Configure JWT Settings
步骤2:配置JWT设置
JWT tokens authenticate API requests. Configure for security:
typescript
{
auth: {
enabled: true,
jwt: {
secret: process.env.JWT_SECRET, // Required in production
alg: "HS256", // Algorithm: HS256, HS384, HS512
expires: 604800, // Expiry in seconds (7 days)
issuer: "my-app", // Optional issuer claim
fields: ["id", "email", "role"], // Fields included in token
},
},
}JWT options:
| Option | Type | Default | Description |
|---|---|---|---|
| string | | Signing secret (256-bit minimum for production) |
| string | | Algorithm: HS256, HS384, HS512 |
| number | - | Token expiry in seconds |
| string | - | Token issuer claim (iss) |
| string[] | | User fields in payload |
JWT令牌用于验证API请求,需从安全角度进行配置:
typescript
{
auth: {
enabled: true,
jwt: {
secret: process.env.JWT_SECRET, // 生产环境必填
alg: "HS256", // 加密算法:HS256、HS384、HS512
expires: 604800, // 过期时间(秒),此处为7天
issuer: "my-app", // 可选的签发者声明
fields: ["id", "email", "role"], // 令牌中包含的用户字段
},
},
}JWT选项说明:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| 字符串 | | 签名密钥(生产环境至少256位) |
| 字符串 | | 加密算法:HS256、HS384、HS512 |
| 数字 | - | 令牌过期时间(秒) |
| 字符串 | - | 令牌签发者声明(iss) |
| 字符串数组 | | 令牌载荷中包含的用户字段 |
Step 3: Configure Cookie Settings
步骤3:配置Cookie设置
Auth cookies store JWT tokens for browser sessions:
typescript
{
auth: {
enabled: true,
jwt: { secret: process.env.JWT_SECRET },
cookie: {
secure: true, // HTTPS only (set false for local dev)
httpOnly: true, // Block JavaScript access
sameSite: "lax", // CSRF protection: "strict" | "lax" | "none"
expires: 604800, // Cookie expiry in seconds (7 days)
path: "/", // Cookie path scope
renew: true, // Auto-extend on requests
pathSuccess: "/", // Redirect after login
pathLoggedOut: "/", // Redirect after logout
},
},
}Cookie options:
| Option | Type | Default | Description |
|---|---|---|---|
| boolean | | HTTPS-only flag |
| boolean | | Block JS access |
| string | | CSRF protection |
| number | | Expiry in seconds |
| boolean | | Auto-extend expiry |
| string | | Post-login redirect |
| string | | Post-logout redirect |
身份验证Cookie用于在浏览器会话中存储JWT令牌:
typescript
{
auth: {
enabled: true,
jwt: { secret: process.env.JWT_SECRET },
cookie: {
secure: true, // 仅HTTPS环境启用(本地开发设为false)
httpOnly: true, // 禁止JavaScript访问
sameSite: "lax", // CSRF防护:"strict" | "lax" | "none"
expires: 604800, // Cookie过期时间(秒),此处为7天
path: "/", // Cookie作用路径
renew: true, // 请求时自动延长过期时间
pathSuccess: "/", // 登录成功后重定向路径
pathLoggedOut: "/", // 登出后重定向路径
},
},
}Cookie选项说明:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| 布尔值 | | 仅HTTPS环境生效标志 |
| 布尔值 | | 禁止JavaScript访问 |
| 字符串 | | CSRF防护设置 |
| 数字 | | 过期时间(秒) |
| 布尔值 | | 自动延长过期时间 |
| 字符串 | | 登录成功后重定向路径 |
| 字符串 | | 登出后重定向路径 |
Step 4: Configure Password Strategy
步骤4:配置密码策略
Set up password hashing and requirements:
typescript
{
auth: {
enabled: true,
jwt: { secret: process.env.JWT_SECRET },
strategies: {
password: {
type: "password",
enabled: true,
config: {
hashing: "bcrypt", // "plain" | "sha256" | "bcrypt"
rounds: 4, // bcrypt rounds (1-10)
minLength: 8, // Minimum password length
},
},
},
},
}Hashing options:
| Option | Security | Performance | Use Case |
|---|---|---|---|
| None | Fastest | Development only, never production |
| Good | Fast | Default, suitable for most cases |
| Best | Slower | Recommended for production |
设置密码哈希规则和复杂度要求:
typescript
{
auth: {
enabled: true,
jwt: { secret: process.env.JWT_SECRET },
strategies: {
password: {
type: "password",
enabled: true,
config: {
hashing: "bcrypt", // 哈希算法:"plain" | "sha256" | "bcrypt"
rounds: 4, // bcrypt加密轮次(1-10)
minLength: 8, // 密码最小长度
},
},
},
},
}哈希选项对比:
| 选项 | 安全性 | 性能 | 使用场景 |
|---|---|---|---|
| 无 | 最快 | 仅用于开发环境,绝对禁止在生产环境使用 |
| 良好 | 较快 | 默认选项,适用于大多数场景 |
| 最高 | 较慢 | 生产环境推荐使用 |
Step 5: Define Roles
步骤5:定义角色
Configure roles for authorization:
typescript
{
auth: {
enabled: true,
jwt: { secret: process.env.JWT_SECRET },
roles: {
admin: {
implicit_allow: true, // Can do everything
},
editor: {
implicit_allow: false,
permissions: [
{ permission: "data.posts.read", effect: "allow" },
{ permission: "data.posts.create", effect: "allow" },
{ permission: "data.posts.update", effect: "allow" },
],
},
user: {
implicit_allow: false,
is_default: true, // Default role for new registrations
permissions: [
{ permission: "data.posts.read", effect: "allow" },
],
},
},
default_role_register: "user", // Role assigned on registration
},
}配置用于授权的角色:
typescript
{
auth: {
enabled: true,
jwt: { secret: process.env.JWT_SECRET },
roles: {
admin: {
implicit_allow: true, // 拥有全部权限
},
editor: {
implicit_allow: false,
permissions: [
{ permission: "data.posts.read", effect: "allow" },
{ permission: "data.posts.create", effect: "allow" },
{ permission: "data.posts.update", effect: "allow" },
],
},
user: {
implicit_allow: false,
is_default: true, // 新注册用户的默认角色
permissions: [
{ permission: "data.posts.read", effect: "allow" },
],
},
},
default_role_register: "user", // 注册时分配的默认角色
},
}Step 6: Configure Registration
步骤6:配置注册功能
Control user self-registration:
typescript
{
auth: {
enabled: true,
allow_register: true, // Enable/disable registration
default_role_register: "user", // Role for new users
entity_name: "users", // User entity name (default: "users")
basepath: "/api/auth", // Auth API base path
},
}控制用户自助注册的相关设置:
typescript
{
auth: {
enabled: true,
allow_register: true, // 启用/禁用注册功能
default_role_register: "user", // 新用户的默认角色
entity_name: "users", // 用户实体名称(默认:"users")
basepath: "/api/auth", // 身份验证API的基础路径
},
}Full Production Example
完整生产环境示例
Complete auth setup with security best practices:
typescript
import { serve, type BunBkndConfig } from "bknd/adapter/bun";
import { em, entity, text, date } from "bknd";
const schema = em({
users: entity("users", {
email: text().required().unique(),
name: text(),
avatar: text(),
created_at: date({ default_value: "now" }),
}),
posts: entity("posts", {
title: text().required(),
content: text(),
}),
});
type Database = (typeof schema)["DB"];
declare module "bknd" {
interface DB extends Database {}
}
const config: BunBkndConfig = {
connection: { url: process.env.DB_URL || "file:data.db" },
config: {
data: schema.toJSON(),
auth: {
enabled: true,
basepath: "/api/auth",
entity_name: "users",
allow_register: true,
default_role_register: "user",
// JWT configuration
jwt: {
secret: process.env.JWT_SECRET!,
alg: "HS256",
expires: 604800, // 7 days
issuer: "my-app",
fields: ["id", "email", "role"],
},
// Cookie configuration
cookie: {
secure: process.env.NODE_ENV === "production",
httpOnly: true,
sameSite: "lax",
expires: 604800,
renew: true,
pathSuccess: "/dashboard",
pathLoggedOut: "/login",
},
// Password strategy
strategies: {
password: {
type: "password",
enabled: true,
config: {
hashing: "bcrypt",
rounds: 4,
minLength: 8,
},
},
},
// Roles
roles: {
admin: {
implicit_allow: true,
},
editor: {
implicit_allow: false,
permissions: [
{ permission: "data.posts.read", effect: "allow" },
{ permission: "data.posts.create", effect: "allow" },
{ permission: "data.posts.update", effect: "allow" },
{ permission: "data.posts.delete", effect: "allow" },
],
},
user: {
implicit_allow: false,
is_default: true,
permissions: [
{ permission: "data.posts.read", effect: "allow" },
],
},
},
},
},
options: {
seed: async (ctx) => {
// Create initial admin on first run
const adminExists = await ctx.em.repo("users").findOne({
where: { email: { $eq: "admin@example.com" } },
});
if (!adminExists) {
await ctx.app.module.auth.createUser({
email: "admin@example.com",
password: process.env.ADMIN_PASSWORD || "changeme123",
role: "admin",
});
console.log("Admin user created");
}
},
},
};
serve(config);遵循安全最佳实践的完整身份验证配置:
typescript
import { serve, type BunBkndConfig } from "bknd/adapter/bun";
import { em, entity, text, date } from "bknd";
const schema = em({
users: entity("users", {
email: text().required().unique(),
name: text(),
avatar: text(),
created_at: date({ default_value: "now" }),
}),
posts: entity("posts", {
title: text().required(),
content: text(),
}),
});
type Database = (typeof schema)["DB"];
declare module "bknd" {
interface DB extends Database {}
}
const config: BunBkndConfig = {
connection: { url: process.env.DB_URL || "file:data.db" },
config: {
data: schema.toJSON(),
auth: {
enabled: true,
basepath: "/api/auth",
entity_name: "users",
allow_register: true,
default_role_register: "user",
// JWT配置
jwt: {
secret: process.env.JWT_SECRET!,
alg: "HS256",
expires: 604800, // 7天
issuer: "my-app",
fields: ["id", "email", "role"],
},
// Cookie配置
cookie: {
secure: process.env.NODE_ENV === "production",
httpOnly: true,
sameSite: "lax",
expires: 604800,
renew: true,
pathSuccess: "/dashboard",
pathLoggedOut: "/login",
},
// 密码策略
strategies: {
password: {
type: "password",
enabled: true,
config: {
hashing: "bcrypt",
rounds: 4,
minLength: 8,
},
},
},
// 角色配置
roles: {
admin: {
implicit_allow: true,
},
editor: {
implicit_allow: false,
permissions: [
{ permission: "data.posts.read", effect: "allow" },
{ permission: "data.posts.create", effect: "allow" },
{ permission: "data.posts.update", effect: "allow" },
{ permission: "data.posts.delete", effect: "allow" },
],
},
user: {
implicit_allow: false,
is_default: true,
permissions: [
{ permission: "data.posts.read", effect: "allow" },
],
},
},
},
},
options: {
seed: async (ctx) => {
// 首次运行时创建初始管理员
const adminExists = await ctx.em.repo("users").findOne({
where: { email: { $eq: "admin@example.com" } },
});
if (!adminExists) {
await ctx.app.module.auth.createUser({
email: "admin@example.com",
password: process.env.ADMIN_PASSWORD || "changeme123",
role: "admin",
});
console.log("Admin user created");
}
},
},
};
serve(config);Auth Endpoints
身份验证端点
After setup, these endpoints are available:
| Method | Path | Description |
|---|---|---|
| POST | | Login with email/password |
| POST | | Register new user |
| GET | | Get current user |
| POST | | Log out (clear cookie) |
| GET | | List enabled strategies |
配置完成后,将启用以下端点:
| 请求方法 | 路径 | 说明 |
|---|---|---|
| POST | | 使用邮箱/密码登录 |
| POST | | 注册新用户 |
| GET | | 获取当前用户信息 |
| POST | | 登出(清除Cookie) |
| GET | | 查看已启用的验证策略 |
Environment Variables
环境变量
Recommended env vars for auth:
bash
undefined推荐用于身份验证的环境变量:
bash
undefined.env
.env
JWT_SECRET=your-256-bit-secret-minimum-32-characters-long
ADMIN_PASSWORD=secure-initial-admin-password
Generate a secure secret:
```bashJWT_SECRET=your-256-bit-secret-minimum-32-characters-long
ADMIN_PASSWORD=secure-initial-admin-password
生成安全密钥的命令:
```bashGenerate 64-character random string
生成64位随机字符串
openssl rand -hex 32
undefinedopenssl rand -hex 32
undefinedDevelopment vs Production
开发环境 vs 生产环境
| Setting | Development | Production |
|---|---|---|
| Can use placeholder | Required, strong secret |
| | |
| | |
| | Consider |
Dev config shortcut:
typescript
const isDev = process.env.NODE_ENV !== "production";
{
auth: {
enabled: true,
jwt: {
secret: isDev ? "dev-secret-not-for-production" : process.env.JWT_SECRET!,
expires: isDev ? 86400 * 30 : 604800, // 30 days dev, 7 days prod
},
cookie: {
secure: !isDev,
},
strategies: {
password: {
type: "password",
config: {
hashing: isDev ? "sha256" : "bcrypt",
},
},
},
},
}| 设置项 | 开发环境 | 生产环境 |
|---|---|---|
| 可使用占位符 | 必填,需使用高强度密钥 |
| | |
| | |
| | 若为封闭系统,建议设为 |
开发环境配置快捷方式:
typescript
const isDev = process.env.NODE_ENV !== "production";
{
auth: {
enabled: true,
jwt: {
secret: isDev ? "dev-secret-not-for-production" : process.env.JWT_SECRET!,
expires: isDev ? 86400 * 30 : 604800, // 开发环境30天,生产环境7天
},
cookie: {
secure: !isDev,
},
strategies: {
password: {
type: "password",
config: {
hashing: isDev ? "sha256" : "bcrypt",
},
},
},
},
}Common Pitfalls
常见问题
Missing JWT Secret in Production
生产环境缺失JWT密钥
Problem: error
Cannot sign JWT without secretFix: Set JWT secret via environment variable:
typescript
{
auth: {
jwt: {
secret: process.env.JWT_SECRET, // Never hardcode in production
},
},
}问题: 出现错误
Cannot sign JWT without secret解决方法: 通过环境变量设置JWT密钥:
typescript
{
auth: {
jwt: {
secret: process.env.JWT_SECRET, // 生产环境绝对禁止硬编码
},
},
}Cookie Not Set (HTTPS Issues)
Cookie未成功设置(HTTPS问题)
Problem: Auth cookie not set in browser
Fix: Set for local development:
secure: falsetypescript
{
auth: {
cookie: {
secure: process.env.NODE_ENV === "production", // false for localhost
},
},
}问题: 浏览器中未设置身份验证Cookie
解决方法: 本地开发时将设为:
securefalsetypescript
{
auth: {
cookie: {
secure: process.env.NODE_ENV === "production", // 本地环境设为false
},
},
}Role Not Found
角色未找到
Problem: when creating users
Role "admin" not foundFix: Define roles before referencing them:
typescript
{
auth: {
roles: {
admin: { implicit_allow: true }, // Define first
user: { implicit_allow: false },
},
default_role_register: "user", // Now can reference
},
}问题: 创建用户时出现错误
Role "admin" not found解决方法: 先定义角色再引用:
typescript
{
auth: {
roles: {
admin: { implicit_allow: true }, // 先定义角色
user: { implicit_allow: false },
},
default_role_register: "user", // 再进行引用
},
}Registration Disabled
注册功能被禁用
Problem: error
Registration not allowedFix: Enable registration:
typescript
{
auth: {
allow_register: true, // Default is true, but check if explicitly disabled
},
}问题: 出现错误
Registration not allowed解决方法: 启用注册功能:
typescript
{
auth: {
allow_register: true, // 默认值为true,但需检查是否被显式禁用
},
}Weak Password Hashing
密码哈希强度不足
Problem: Using or in production
plainsha256Fix: Use bcrypt for production:
typescript
{
auth: {
strategies: {
password: {
config: {
hashing: "bcrypt",
rounds: 4, // Balance security and performance
},
},
},
},
}问题: 生产环境中使用或哈希算法
plainsha256解决方法: 生产环境使用bcrypt:
typescript
{
auth: {
strategies: {
password: {
config: {
hashing: "bcrypt",
rounds: 4, // 平衡安全性与性能
},
},
},
},
}Verification
验证方法
After setup, verify auth works:
1. Check enabled strategies:
bash
curl http://localhost:7654/api/auth/strategies2. Register a test user:
bash
curl -X POST http://localhost:7654/api/auth/password/register \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com", "password": "password123"}'3. Login:
bash
curl -X POST http://localhost:7654/api/auth/password/login \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com", "password": "password123"}'4. Check current user (with token):
bash
curl http://localhost:7654/api/auth/me \
-H "Authorization: Bearer <token-from-login>"配置完成后,验证身份验证功能是否正常:
1. 检查已启用的策略:
bash
curl http://localhost:7654/api/auth/strategies2. 注册测试用户:
bash
curl -X POST http://localhost:7654/api/auth/password/register \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com", "password": "password123"}'3. 登录:
bash
curl -X POST http://localhost:7654/api/auth/password/login \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com", "password": "password123"}'4. 查看当前用户信息(需携带令牌):
bash
curl http://localhost:7654/api/auth/me \
-H "Authorization: Bearer <token-from-login>"Security Checklist
安全检查清单
Before deploying to production:
- Set strong (256-bit minimum)
jwt.secret - Use for password strategy
hashing: "bcrypt" - Set (HTTPS only)
cookie.secure: true - Set (default)
cookie.httpOnly: true - Set or
cookie.sameSite: "lax""strict" - Configure (don't leave unlimited)
jwt.expires - Review setting
allow_register - Create admin user via seed (not via public registration)
- Store secrets in environment variables
部署到生产环境前需完成以下检查:
- 设置高强度(至少256位)
jwt.secret - 密码策略使用
hashing: "bcrypt" - 设置(仅HTTPS环境)
cookie.secure: true - 确保(默认值)
cookie.httpOnly: true - 设置或
cookie.sameSite: "lax""strict" - 配置(禁止设置为永不过期)
jwt.expires - 检查设置
allow_register - 通过种子脚本创建管理员用户(而非公开注册)
- 将密钥存储在环境变量中
DOs and DON'Ts
注意事项
DO:
- Use environment variables for secrets
- Use bcrypt hashing in production
- Set JWT expiry times
- Define roles before assigning them
- Test auth flow after configuration changes
DON'T:
- Hardcode JWT secrets in code
- Use hashing in production
plain - Skip setting in production
cookie.secure - Leave registration open if not needed
- Forget to create initial admin user
建议:
- 使用环境变量存储密钥
- 生产环境使用bcrypt哈希算法
- 设置JWT过期时间
- 先定义角色再进行分配
- 配置变更后测试身份验证流程
禁止:
- 在代码中硬编码JWT密钥
- 生产环境使用哈希算法
plain - 生产环境跳过设置
cookie.secure - 不需要公开注册时仍保持开启状态
- 忘记创建初始管理员用户
Related Skills
相关技能
- bknd-create-user - Create user accounts programmatically
- bknd-login-flow - Implement login/logout functionality
- bknd-registration - Set up user registration flows
- bknd-oauth-setup - Configure OAuth providers (Google, GitHub)
- bknd-create-role - Define roles for authorization
- bknd-session-handling - Manage user sessions
- bknd-create-user - 以编程方式创建用户账号
- bknd-login-flow - 实现登录/登出功能
- bknd-registration - 设置用户注册流程
- bknd-oauth-setup - 配置OAuth服务商(Google、GitHub等)
- bknd-create-role - 定义用于授权的角色
- bknd-session-handling - 管理用户会话