@baukit/自动节点
@baukit/auth-node 是用于CLI和MCP客户端的节点24 OIDC设备流程包. 它处理发现,RFC 8628投票,S256 PKCE,刷新回转,以及一个本地配置缓存. 它没有运行时间依赖.
软件包不打印指令或打开浏览器. 为这些行动提供回调.
设备流程客户端
import { DeviceFlowClient } from '@baukit/auth-node/device-flow';
const auth = new DeviceFlowClient(
{
issuer: process.env['OIDC_ISSUER'] ?? '',
clientId: process.env['OIDC_CLIENT_ID'] ?? '',
scopes: ['openid', 'profile', 'offline_access'],
audience: 'notes-api',
cache: {
namespace: 'notes-mcp',
},
},
{
environmentToken: () => process.env['NOTES_API_TOKEN'],
},
);
await auth.login({
presentation: {
showVerification: ({ verificationUri, userCode }) => {
process.stderr.write(`Open ${verificationUri}\nEnter ${userCode}\n`);
},
showStatus: (status) => {
process.stderr.write(`Login status: ${status}\n`);
},
openBrowser: (url) => openProductBrowser(url),
},
});
const token = await auth.accessToken();
accessToken() 先检查注入环境的源头。 然后读取所选缓存配置文件并刷新已近过期的符号 。 刷新过程中共享一个承诺并持有相邻 .lock 正在读取和替换缓存.
refreshLeewaySeconds 默认为 60 秒; 刷新窗口是该值中较小的部分, 半个符号寿命, 以 expiresAt - issuedAt。 。 。 .
通过一个 AbortSignal 改为 login, (中文(简体) ), accessToken,或 logout。发现和符号请求有一个15秒的默认超时。 登录总超时10分钟. 两种限制都是可以确定的.
终点政策
配置的发行者必须匹配发现元数据 。 将已知发行人别名放入 endpointPolicy.issuerAllowlist。Token 和设备端点必须共享发行者的来源和路径。 将提供者的有记录的端点来源输入 endpointOriginAllowlist 当它使用单独的来源.
所有发售者,设备,符号,和校验URL都需要HTTPS. 地方发展可以确定 allowLoopbackHttp: true; 仅允许 localhost, (中文(简体) ), 127.0.0.0/8,以及 ::1。 。 。 .
发现和象征体默认限制在64 KiB. 出错包含一个稳定的代码,一个允许上市的消息,一个可选的HTTP状态,没有提供者机构. 客户端不登录.
API 来源
parseApiOrigin(value, { allowLoopbackHttp, label }) 检查已配置的 API 基础 URL, 如 MCP 服务器 PRODUCT_API_URL,与终点政策相同的计划规则。 它会修剪白空间,接受一个后行斜线,然后返回 url.origin。 。 。 .
import { parseApiOrigin } from '@baukit/auth-node';
const apiUrl = parseApiOrigin(process.env['PRODUCT_API_URL'] ?? 'http://localhost:8080', {
allowLoopbackHttp: process.env['NODE_ENV'] !== 'production',
label: 'PRODUCT_API_URL',
});
它会扔 ApiOriginError页:1 TypeError,带有 reason 联 合 国 invalid_url, (中文(简体) ), insecure_scheme,或 not_an_origin。证书、路径、查询或碎片计数为: not_an_origin。 。 。 . allowLoopbackHttp 默认为虚假。 消息将标签和被打破的规则命名,永远不表示值,因此可以安全地日志.
Keycloak 测试助手
@baukit/auth-node/keycloak-testing 设置用户对可支配开发的 Keycloak 进行端到端测试. 它运行在节点24,使用全球 fetch,不需要 Playwright 依赖.
副航道舰只作为无害环境管理, 就像每一个Baukit包。 节点 24 从普通JS 装入 require(esm),所以普通JS测试项目不需要动态 import()模式 "module": "node20" 或者说 "nodenext"; 下节 "node16" 它报告TS1479的进口,因为 node16 描述无法打开的节点释放 require 无害环境管理.
import {
allowKeycloakWebOrigin,
createKeycloakTestUser,
keycloakStack,
signInWithKeycloak,
} from '@baukit/auth-node/keycloak-testing';
const stack = keycloakStack({
url: 'http://localhost:8081',
realm: 'notes',
webClientId: 'notes-web',
});
await allowKeycloakWebOrigin(stack, 'http://localhost:5183');
const user = await createKeycloakTestUser(stack);
await page.getByRole('button', { name: 'Sign in' }).click();
await signInWithKeycloak(page, user, stack);
keycloakStack(defaults, environment = process.env) 返回产品的默认值,除非 E2E_KEYCLOAK_URL, (中文(简体) ), E2E_KEYCLOAK_REALM, (中文(简体) ), E2E_KEYCLOAK_ADMIN_USERNAME, (中文(简体) ), E2E_KEYCLOAK_ADMIN_PASSWORD,或 E2E_KEYCLOAK_WEB_CLIENT_ID 已经设定。 管理员证书默认为 admin 财务报告和审定财务报表 admin,然后从 URL 中删除尾条.
createKeycloakTestUser(stack, user?, options?) 进入主域 admin-cli 并创建经验证、启用的用户,并设置永久密码。 无 user,用户名为 e2e-<uuid> 并且密码是随机的,所以并行的测试永远不会共享一个身份. 过 username, (中文(简体) ), email,或 password 当王国通过电子邮件签名时。 它回来了 { username, password, email, subject }· ; subject 是 Keycloak 用户代号,它成为 sub 索赔.
revokeKeycloakUserSessions(stack, subject) 结束用户的每次会话, 因此应用程序的下一个刷新失败 . allowKeycloakWebOrigin(stack, origin) 添加 <origin>/* 到网络客户端的重定向 URI 及其 post.logout.redirect.uris 属性,以及 origin 到它的网络起源。 它保留了客户端的其他属性,当三个都在场时则无所作为. 保存的日志后列表 + 已经重用重定向的 URI, 所以帮助者将它放过 . signInWithKeycloak(page, user, stack, { timeoutMs }) 等待页面出现在 Keycloak 来源上,填写 #username 财务报告和审定财务报表 #password,单击 #kc-login;这些ID不会随登录地块而改变. page 是 Playwright 的任何对象 waitForURL 财务报告和审定财务报表 locator,例如 Page 或登机弹出.
每个管理员的电话都要接 { fetch, timeoutMs }; 超时默认为 DEFAULT_KEYCLOAK_REQUEST_TIMEOUT_MS (30秒) (英语). 失败投出 Error 来命名步骤和 HTTP 状态, 并且从不包含响应机构或管理员密码。 创建的用户和添加的起源留在了域中,因此将帮助者只指向一个发展域.
缓存合同
JSON 缓存将命名的配置文件保存在一个命名空间下. defaultTokenCachePath(namespace) 决定: $XDG_CONFIG_HOME/<namespace>/tokens.json,或 ~/.config/<namespace>/tokens.json 何时 XDG_CONFIG_HOME 未设定.
配置文件记录 issuedAt 财务报告和审定财务报表 expiresAt ; 没有配置文件 issuedAt 失败 cache_corrupt。 。 。 .
在 POSIX 系统中,缓存文件必须具有模式 0600 而其直接目录必须具有模式 0700。现有的不安全权限失败 cache_permission。缓存拒绝同源路径组件。 写作使用新的临时文件,同步,并在解剖上重新命名,所以在重命名之前,一个写作失败离开旧文件完好无损. Windows跳过POSIX模式检查并依赖于主机ACLs.
对不能共享证书的账户使用单独的命名空间或配置文件 . logout() 删除选中的配置文件并保留其他配置文件.
仅显示索赔
displayClaims() 财务报告和审定财务报表 decodeDisplayOnlyClaims() 解码 JWT 字段的小型许可列表,而不检查签名 。 仅对像 a 这样的标签使用结果 whoami 显示。 永远不要用它来授权,存储分区,审计身份,或者分析身份.
从产品本地认证迁移
将本地发现、设备投票、刷新和缓存功能替换为一个 DeviceFlowClient在应用程序中保留这些产品投入:
- 环境变量名称和默认值;
- 发行人、客户身份、范围、受众;
- CLI 文本和浏览器启动行为;
- API 基址和无记名接线;以及
- 缓存命名空间、路径和配置文件选择 .