Convex 工作OS AuthKit 系统
此组件是将 WorkOS AuthKit 认证与您的 Convex 项目整合的正式方式 .
特征 :
- 将用户数据从 WorkOS 同步到您的 Convex 数据库 可靠且持久 .
- 响应带有 Convex 函数的事件 .
- 将组件添加到现有应用程序时回填已存在的 WorkOS 用户 .
见 实例 用于演示如何将此组件纳入您的应用程序.
打开 a GitHub 问题 与 任何反馈或错误.
先决条件
跟着 Convex 工作OS AuthKit 引导 与WorkOS AuthKit一起建立一个工作项目.
然后遵循下面的步骤来设置用户数据同步和事件处理.
配置网点
用户数据同步需要在您的 WorkOS 项目中配置webhooks .
在 WorkOS 工程中从左侧栏选择 Webhooks, 并创建新 以下设置的 webhook :
- 端点 URL数字 :
https://<your-convex-deployment>.convex.site/workos/webhook - 活动数字 :
user.created, (中文(简体) ),user.updated, (中文(简体) ),user.deleted

复制 Webhook 密钥并将其添加到您的环境变量中
WORKOS_WEBHOOK_SECRET。 。 。 .

npx convex env set WORKOS_WEBHOOK_SECRET=<your-webhook-secret>
安装
第一,添加 @convex-dev/workos-authkit 到您的 Convex 项目 :
npm install @convex-dev/workos-authkit
然后在您内部安装组件 convex/convex.config.ts 文件 :
// convex/convex.config.ts
import workOSAuthKit from "@convex-dev/workos-authkit/convex.config";
import { defineApp } from "convex/server";
const app = defineApp();
app.use(workOSAuthKit);
export default app;
在您内部创建 Convex AuthKit 客户端 convex/ 文件夹,并指向
至已安装组件:
// convex/auth.ts
import { AuthKit } from "@convex-dev/workos-authkit";
import { components } from "./_generated/api";
import type { DataModel } from "./_generated/dataModel";
export const authKit = new AuthKit<DataModel>(components.workOSAuthKit);
最后,在 convex/http.ts数字 :
import { httpRouter } from "convex/server";
import { authKit } from "./auth";
const http = httpRouter();
authKit.registerRoutes(http);
export default http;
自定义域
如果你已经配置了 自定义 WorkOS 认证 API 域,通过它作为 apiHostname 当构建 AuthKit 客户端时。 它将 WorkOS SDK 通过您的域名并更新 JWT 发行器和 JWKS URL 以匹配 .
// convex/auth.ts
export const authKit = new AuthKit<DataModel>(components.workOSAuthKit, {
apiHostname: "auth.example.com",
});
使用量
WorkOS中的用户创建/更新/删除会自动被同步 组件.
使用 getAuthUser 获取当前认证用户的组件方法
对象 :
export const getCurrentUser = query({
args: {},
handler: async (ctx, _args) => {
const user = await authKit.getAuthUser(ctx);
return user;
},
});
活动
AuthKit 组件可以配置用于处理来自 WorkOS 的事件. 这是 用于在 WorkOS 中创建、更新或删除用户时运行代码, 或针对任何其他提供的事件.
默认情况下,该组件将处理以下事件:
user.createduser.updateduser.deleted
这个 user.deleted 当组件从未存储用户时, 处理器也会运行, for
例如WorkOS在创建前发送删除. event.data 那时
已发送的 webhook 有效载荷,所以 id 虽然它被打成
一个完整的用户。 当组件存储了用户时,其字段会填补任何空白.
如果您的应用程序没有用户记录, 请务必返回而不是丢弃 .
扔出失败的 Webhook 并滚回组件的删除记录,
这样 user.created 在 WorkOS 重试之前到达的
组件和您的应用程序.
// convex/auth.ts
import { AuthKit, type AuthFunctions } from "@convex-dev/workos-authkit";
import { components, internal } from "./_generated/api";
import type { DataModel } from "./_generated/dataModel";
// Get a typed object of internal Convex functions exported by this file
const authFunctions: AuthFunctions = internal.auth;
const authKit = new AuthKit<DataModel>(components.workOSAuthKit, {
authFunctions,
});
// create `authKitEvent` as a named export
export const { authKitEvent } = authKit.events({
"user.created": async (ctx, event) => {
// ctx is a mutation context and event.data is typed
await ctx.db.insert("todoLists", {
name: `${event.data.firstName}'s Todo List`,
userId: event.data.id,
});
},
});
其他事件类型
该组件可以处理任意WorkOS事件类型. WorkOS文件提供a 完整 事件列表。处理额外事件 类型,请在 webhook 配置 添加一个 处理者.
// convex/auth.ts
import { AuthKit, type AuthFunctions } from "@convex-dev/workos-authkit";
import { components, internal } from "./_generated/api";
import type { DataModel } from "./_generated/dataModel";
const authFunctions: AuthFunctions = internal.auth;
const authKit = new AuthKit<DataModel>(components.workOSAuthKit, {
authFunctions,
});
export const { authKitEvent } = authKit.events({
"session.created": async (ctx, event) => {
// do something with the session data
},
"session.revoked": async (ctx, event) => {
// do something with the session data
},
});
用户数据
大多数应用程序需要控制其用户计划,并能直接查询 与用户表相对。 AuthKit 组件拥有自己的用户表和用户 数据来自WorkOS. 您可以将此视为用户的认证元数据, 但是 您可能想要通过您的应用程序中的额外数据来扩展此功能 .
常见的模式是创建自己的用户表,其中参考 authKit 用户表,使用用户事件进行任何必要的同步.
// convex/auth.ts
import { AuthKit, type AuthFunctions } from "@convex-dev/workos-authkit";
import { components, internal } from "./_generated/api";
import type { DataModel } from "./_generated/dataModel";
const authFunctions: AuthFunctions = internal.auth;
const authKit = new AuthKit<DataModel>(components.workOSAuthKit, {
authFunctions,
});
export const { authKitEvent } = authKit.events({
"user.created": async (ctx, event) => {
await ctx.db.insert("users", {
authId: event.data.id,
email: event.data.email,
name: `${event.data.firstName} ${event.data.lastName}`,
});
},
"user.updated": async (ctx, event) => {
const user = await ctx.db
.query("users")
.withIndex("authId", (q) => q.eq("authId", event.data.id))
.unique();
if (!user) {
console.warn(`User not found: ${event.data.id}`);
return;
}
await ctx.db.patch(user._id, {
email: event.data.email,
name: `${event.data.firstName} ${event.data.lastName}`,
});
},
"user.deleted": async (ctx, event) => {
const user = await ctx.db
.query("users")
.withIndex("authId", (q) => q.eq("authId", event.data.id))
.unique();
if (!user) {
console.warn(`User not found: ${event.data.id}`);
return;
}
await ctx.db.delete(user._id);
},
// Handle any event type
"session.created": async (ctx, event) => {
console.log("onCreateSession", event);
},
});
回填现有用户
如果您正在将此组件添加到一个已经在 WorkOS 有用户的应用程序中, 您
可以将它们回填入组件的用户表。 后面的填充物也会起火
user.created 事件处理器,所以你的应用程序自己的表格也会有人.
从您的认证文件导出回填工具 :
// convex/auth.ts
export const { backfillUsers } = authKit.utils();
然后从CLI或Convex仪表板触发:
npx convex run auth:backfillUsers
回填处理用户最老-最先. 这是天分 - 如果中断,只是 它会跳过已经同步的用户 .
行动
AuthKit 组件可以配置用于处理来自 WorkOS 的动作. 行动 允许您根据自己的逻辑屏蔽用户注册或认证. 更多信息,请访问 工作操作系统 文档。 。 。 .
配置
- 在工作OS仪表板中配置动作 .
- 设置您动作的终点 URL
https://<your-convex-deployment>.convex.site/workos/action - 从仪表盘上复制动作签名秘诀,放入您
环境变量为
WORKOS_ACTION_SECRET。 。 。 .

使用量
动作处理器使用 actions authKit 组件上的方法.
AuthKit 动作必须返回允许或否认该动作的响应有效载荷,
因此向动作处理器提供了响应对象 allow 财务报告和审定财务报表 deny
方法。 。 .
// convex/auth.ts
import { AuthKit, type AuthFunctions } from "@convex-dev/workos-authkit";
import { components, internal } from "./_generated/api";
import type { DataModel } from "./_generated/dataModel";
const authFunctions: AuthFunctions = internal.auth;
const authKit = new AuthKit<DataModel>(components.workOSAuthKit, {
authFunctions,
});
export const { authKitAction } = authKit.actions({
authentication: async (_ctx, _action, response) => {
return response.allow();
},
userRegistration: async (_ctx, action, response) => {
if (action.userData.email.endsWith("@gmail.com")) {
return response.deny("Gmail accounts are not allowed");
}
return response.allow();
},
});