Logto Mock Social 连接器实战解析:面向集成测试的模拟社交登录实现与版本演进
2026/9/14 14:26:54 网站建设 项目流程

Logto Mock Social 连接器实战解析:面向集成测试的模拟社交登录实现与版本演进

【免费下载链接】logto🧑‍🚀 Authentication and authorization infrastructure for SaaS and AI apps, built on OIDC and OAuth 2.1 with multi-tenancy, SSO, and RBAC.项目地址: https://gitcode.com/GitHub_Trending/lo/logto

@logto/connector-mock-social是 Logto 开源项目中专为集成测试设计的模拟社交登录连接器(官方 README 明确标注 "For integration tests only")。本文以该包的 CHANGELOG 为骨架,结合 源码实现、类型定义、集成测试用例 等仓库证据,系统讲解其工作原理、配置方式、能力演进脉络,以及在 Logto 集成测试体系中的实际用法,帮助读者理解 Logto 社交连接器(Social Connector)的标准接口契约与测试驱动设计思路。

连接器定位:为什么需要"模拟社交登录"

在 Logto 的架构中,社交登录(Social Sign-in)通过连接器(Connector)接入第三方身份提供商(如 Google、GitHub、微信等)。真实连接器需要真实的 OAuth 授权端点、Client 凭证与用户账号,无法在 CI 环境中稳定复现。为此,Logto 在 packages/connectors/connector-mock-social 中实现了一个完全模拟的社交连接器

  • 授权地址指向一个约定的模拟域名http://mock-social/(见 index.ts);
  • 不需要真实的第三方服务,即可完成"重定向 → 回调 → 换取用户信息"的完整社交登录链路;
  • 被 packages/integration-tests 下大量 API 级与端到端测试复用,用于验证社交登录、身份绑定、多身份管理等业务逻辑。

从连接器元数据看,它声明的idmock-social-connectortargetmock-social、平台类型为ConnectorPlatform.Universal(全平台通用),并支持 Token 存储(isTokenStorageSupported: true),详细声明见 constant.ts。

配置模型:clientId 与 clientSecret

该连接器的配置结构非常精简,由 types.ts 中的mockSocialConfigGuard(基于 zod)定义:

export const mockSocialConfigGuard = z.object({ clientId: z.string(), clientSecret: z.string(), });
  • clientId:模拟应用的客户端标识,必填;
  • clientSecret:模拟应用的客户端密钥,必填。

配套的配置模板 docs/config-template.json 给出了占位示例:

{ "clientId": "<client-id>", "clientSecret": "<client-secret>" }

在集成测试中,实际写入的值被定义为常量(见 connectors-mock.ts):

export const mockSocialConnectorId = 'mock-social-connector'; export const mockSocialConnectorTarget = 'mock-social'; export const mockSocialConnectorConfig = { clientId: 'client_id_value', clientSecret: 'client_secret_value', }; export const mockSocialConnectorNewConfig = { clientId: 'client_id_value_new', clientSecret: 'client_secret_value_new', };

mockSocialConnectorNewConfig用于测试"更新连接器配置"的场景。连接器通过configGuard在运行时对管理员下发的配置做校验,不合法配置会在写入阶段即被拒绝——这是 Logto 所有连接器共用的配置校验机制。

核心实现:四个关键接口的源码级拆解

createMockSocialConnector(index.ts)返回一个符合SocialConnector契约的对象,包含metadatatypeconfigGuard以及三个核心方法。这些方法签名均来自 connector-kit 的社交连接器类型定义,理解它们即可理解整个社交连接器抽象。

1. getAuthorizationUri:生成授权地址

const getAuthorizationUri: GetAuthorizationUri = async ( { state, redirectUri, connectorId, scope }, setSession ) => { await setSession({ state, redirectUri, connectorId }); // ... const queryParams = new URLSearchParams({ state, redirect_uri: redirectUri, scope: scope ?? defaultScope, }); return `${mockSocialAuthDomain}?${queryParams.toString()}`; };
  • 调用setSessionstateredirectUriconnectorId写入连接器会话,用于回调阶段校验;
  • 生成http://mock-social/?state=...&redirect_uri=...&scope=...形式的授权地址;
  • scope 处理:优先使用调用方传入的scope,未传入时回退到默认值defaultScope = 'email profile'(源码中为硬编码常量)。这正是 CHANGELOG 1.5.0 版本引入的能力(详见下文"能力演进"章节)。

2. getUserInfo:从回调数据解析用户信息

const mockSocialDataGuard = z.object({ code: z.string(), userId: z.optional(z.string()), email: z.string().optional(), phone: z.string().optional(), name: z.string().optional(), avatar: z.string().optional(), });

回调数据要求必须包含code,并支持可选的userIdemailphonenameavatargetUserInfo依次完成:

  1. mockSocialDataGuard校验回调数据,校验失败抛出ConnectorError(ConnectorErrorCodes.InvalidResponse)
  2. 调用validateConnectorSession确认连接器会话存在(防 CSRF 的基础手段);
  3. 返回规范化用户信息,其中用户 ID 优先取回调中的userId,否则生成mock-social-sub-${randomUUID()}形式的随机 ID;
  4. 将原始回调数据原样放入rawData字段——这是 1.2.0 版本引入的"返回并存储原始数据"能力(见下文)。

validateConnectorSessionNotImplemented错误做了宽容处理(连接器会话能力未实现时忽略异常),保证向后兼容。

3. getTokenResponseAndUserInfo:Token 存储模式下的组合取数

const getTokenResponseAndUserInfo: GetTokenResponseAndUserInfo = async (data, getSession) => { const result = mockSocialDataGuard .extend({ tokenResponse: tokenResponseGuard.optional() }) .safeParse(data); // ... return { userInfo: { id: userId ?? `mock-social-sub-${randomUUID()}`, ...rest, rawData: jsonGuard.parse(data) }, tokenResponse }; };

当连接器启用 Token 存储(元数据中isTokenStorageSupported: true)时,Logto 会调用该方法一次性获取 Token 响应与用户信息。它复用了mockSocialDataGuard并额外接受可选的tokenResponse字段(结构由 connector-kit 的 tokenResponseGuard 定义,支持id_tokenaccess_tokenrefresh_tokenexpires_inscopetoken_type)。

SocialConnector类型还定义了可选的getAccessTokenByRefreshTokenvalidateSamlAssertion,Mock 连接器未实现它们——这类能力均为可选实现,体现了连接器接口的渐进式设计。

能力演进:从 CHANGELOG 还原技术脉络

该连接器的 CHANGELOG 记录了从 1.0.1 到 1.5.6 的全部版本。除去纯依赖升级(Patch Changes),共有 4 次带实质性变更的 Minor 版本,逐条解析如下。

1.5.0:getAuthorizationUri 支持自定义 scope

feat: support custom scope in thegetAuthorizationUrimethod. This change allows thegetAuthorizationUrimethod in the social connectors to accept an extrascopeparameter, enabling more flexible authorization requests. If the scope is provided, it will be used in the authorization request; otherwise, the default scope configured in the connector settings will be used.

对应 connector-kit 的类型定义中,GetAuthorizationUri的 payload 增加了可选字段scope?: string。Mock 连接器的实现即上文所示:scope: scope ?? defaultScope

需要说明的是:按 CHANGELOG 描述,未传 scope 时应使用"连接器设置中的默认 scope",而 Mock 连接器源码将其实现为硬编码常量'email profile'。这也符合其"测试专用"定位——真实连接器(如 Google)则会将scope作为可配置项写入configGuard(connector-kit 中 Google 连接器的配置即含scope: z.string().optional())。

1.2.0:返回并存储社交连接器原始数据

return and store social connector raw data

该变更对应getUserInfo/getTokenResponseAndUserInfo返回对象中的rawData字段(通过jsonGuard.parse(data)序列化)。SocialUserInfo类型(见 social.ts)定义了rawData?: Json,使 Logto 能够在规范化的id/email/phone/name/avatar之外,保留身份提供方返回的原始 JSON,便于审计与排障。

1.3.0:切换 tsup 构建

use tsup for building. We've updated some of the packages to usetsupfor building. This will make the build process faster, and should not affect the functionality of the packages.

这是 Logto monorepo 中一批包的工程化升级:将构建工具统一为 tsup。从 package.json 可以看到该包目前的构建脚本为"build": "tsup"、开发模式为"dev": "tsup --watch",产物输出到lib/index.jsmain/module/exports均指向该文件),包类型为 ESM("type": "module")。

1.1.0 / 1.4.0:Node 引擎版本要求

  • 1.1.0:use Node 20 LTS for engine requirement,同时将 TypeScript 升级至 5.3.3(commit9089dbf84)。CHANGELOG 特别注明:由于 Logto 通过 Docker 镜像分发,此项不构成用户侧破坏性变更;
  • 1.4.0:bump node version to ^22.14.0,将 Node 版本要求提升至 22.14+。

当前 package.json 的engines字段为"node": "^22.14.0",与 1.4.0 的变更保持一致。1.3.1 的"bump dependencies for security update"则属于依赖安全更新。

依赖演进:与 connector-kit 的耦合关系

该连接器是 connector-kit 最忠实的"消费者"之一,两者几乎同步发版。将 CHANGELOG 中所有版本整理如下:

连接器版本变更类型connector-kit 版本实质变更
1.5.6Patch5.1.1依赖升级
1.5.5Patch5.1.0依赖升级
1.5.4Patch5.0.1依赖升级
1.5.3Patch5.0.0依赖升级
1.5.2Patch4.7.0依赖升级
1.5.1Patch4.6.0依赖升级
1.5.0Minor4.4.0getAuthorizationUri支持自定义 scope
1.4.0Minor4.3.0Node 版本升至 ^22.14.0
1.3.1Patch4.1.1依赖安全更新
1.3.0Minor改用 tsup 构建
1.2.1Patch4.0.0依赖升级
1.2.0Minor3.0.0返回并存储社交连接器原始数据
1.1.0Minor2.1.0Node 20 LTS 引擎要求、TypeScript 5.3.3
1.0.1Patch2.0.0依赖升级

可以看出:getAuthorizationUri签名变更(1.5.0)与rawData能力(1.2.0)均需要 connector-kit 同步提供类型与 Guard 支持,因此这两次 Minor 版本同时伴随着 connector-kit 的 Minor 升级(4.4.0 与 3.0.0)。源码层面,index.ts 从@logto/connector-kit导入的ConnectorErrorConnectorErrorCodesConnectorTypejsonGuardtokenResponseGuard等正是这些接口契约的具体载体。

实战用法:集成测试中的完整链路

Mock 连接器在 packages/integration-tests 中被系统化使用,链路如下:

  1. 测试准备:helpers/connector.ts 中的setSocialConnector()通过管理 API 创建连接器实例:
export const setSocialConnector = async (api?: KyInstance) => postConnector( { connectorId: mockSocialConnectorId, config: mockSocialConnectorConfig, syncProfile: true, }, api );
  1. 场景覆盖mockSocialConnectorId被广泛引用在账户中心(Account Center)与体验 API(Experience API)测试中,例如 account/social.test.ts、account/social.delete-identity.test.ts、experience-api/interaction.test.ts 等,覆盖社交登录、身份绑定(linkSocialIdentity)、身份替换、身份删除、仅社交登录标识符等场景。

  2. 配置更新测试mockSocialConnectorNewConfig用于验证"更新连接器配置"后新配置生效(如切换clientId),这依赖configGuard对新旧配置的持续校验。

此外,包内还附带一个占位测试 src/index.test.ts(仅it('makes ci happy')),真正的行为验证交给集成测试层完成——这再次印证其"仅服务于集成测试"的定位。

工程与发布细节

从 package.json 可进一步了解该包工程化约定:

  • 脚本:check(tsc 类型检查)、build/dev(tsup 构建)、test(vitest)、lint(eslint)与prepublishOnly(发布前自动构建);
  • 依赖:@logto/connector-kit(workspace 协议)、got(HTTP 客户端)、snakecase-keyszod(校验);
  • 发布文件:libdocslogo.svg
  • 许可协议:MPL-2.0。

开发调试时可在仓库根目录执行pnpm --filter @logto/connector-mock-social dev进入 tsup watch 模式,pnpm --filter @logto/connector-mock-social test运行包内测试。

小结

从 CHANGELOG 到源码,@logto/connector-mock-social展示了 Logto 连接器体系的两条核心设计原则:

  1. 契约先行:连接器能力全部收敛在 connector-kit 的类型与 Guard 中(GetAuthorizationUriGetUserInfoGetTokenResponseAndUserInfo等),Mock 实现只需按契约填实现,即可无缝接入 Logto 核心;
  2. 测试驱动:用一个零依赖外部服务的模拟连接器,把社交登录的完整链路(授权地址生成、回调校验、用户信息解析、Token 存储)搬进 CI,从而在不依赖真实 OAuth 提供商的前提下保障业务逻辑的正确性。

对于希望为 Logto 贡献新社交连接器或深入理解其抽象层的开发者,从阅读该 Mock 连接器源码入手,是性价比最高的起点:它体量小、无外部依赖,却完整覆盖了社交连接器的全部标准接口。

【免费下载链接】logto🧑‍🚀 Authentication and authorization infrastructure for SaaS and AI apps, built on OIDC and OAuth 2.1 with multi-tenancy, SSO, and RBAC.项目地址: https://gitcode.com/GitHub_Trending/lo/logto

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询