FaableAuth REST API的客户端——来自服务器的管理,会话和登录流出自浏览器或CLI.
程序上通过FaableAuth REST API管理FaableAuth的用户,团队,连接和客户端——并用正确的策略从浏览器或CLI中调用租户会话和登录端点.
⚠️ 它能跑的地方取决于证书,而不是包裹. 这个 SDK本身对浏览器没有节点唯一的依赖和捆绑. 什麽 您决不能将任何不可信运行时间运送到浏览器中
client_secret或一个 API 密钥 - 赠款管理范围 租户。 用户自己的无记名符号或浏览器的会话 cookie 这些是很好的客户端.
| 战略 | 证书 | 赠款 | 何处 |
|---|---|---|---|
authClientCredentials | client_id + 键 client_secret | 客户端管理 API 范围( 它允许列表; 无默认) | 只有服务器 |
authApikey | API 密钥 (单位:千美元)fak_…(中文(简体) ) | 关键词的管理范围 | 只有服务器 |
authBearer | 呼叫者已经持有的标志 | 不管那个标志的 范围和主题允许 | {\fn华文楷体\fs20\bord1\shad1\1cHE0E0E0\2cH000000}去活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活 |
authCookie | 浏览器的会话 cookie | 登录用户自己的会话( E)/me外交部,密码... ) | 浏览器, 与认证主机同源 |
| (无) | —— 说 | 仅公用端点( 日志、 无密码开始、 设备流...) | 任何地方 |
安装
npm install @faable/auth-sdk
认证
认证是 明确和可插件: 你选一个 authStrategy 并通过它的
配置为 auth. SDK 软件 从未读取环境证书 —— 说
你自己看,然后传过来 您选择的战略驱动类型
auth,所以编辑器自动完成正确的字段. 战略是
从 @faable/auth-sdk,所以你只能从这个包中导入.
中断更改( v2 ) : 旧的
createClientCredentials()编号 :createApikeyAuth()帮助者( 读取FAABLE_*vars 自动) 被删除。 使用authStrategy+ 键auth下为一对.domain现在 所需经费 ——不再有硬码默认主机.
客户证书(建议)
authClientCredentials 这是 默认 策略,所以你只能通过 auth
与 { client_id, client_secret } - 无需设置 authStrategy数字 :
import { FaableAuthApi } from "@faable/auth-sdk";
const api = FaableAuthApi.create({
domain: "https://<your-account>.auth.faable.link",
auth: {
client_id: process.env.FAABLEAUTH_CLIENT_ID!,
client_secret: process.env.FAABLEAUTH_CLIENT_SECRET!,
},
});
允许客户端先使用管理API范围. 代号最多只能携带
客户端的允许列表( n)management_scopes: 没有 scope 内 auth,则
整个列表; 与 scope上面写着要求的 新客户列表
空的,所以直到你允许瞄准镜(dashboard) – 您的 Auth 租户 – 客户 →
(a) 与客户联系 管理 API 范围每一次通话都失败了
FaableApiError 其消息名称 management_scopes_empty 并说在哪里
修复; 仅询问列表名称以外的范围
management_scope_not_allowed。见
调用 Faable 管理 API。 。 。 .
默认情况下,请求从 <domain>/oauth/token。如果您的 API 主机
实值 没有 认证服务器,以 auth.domain数字 :
auth: {
client_id: "...",
client_secret: "...",
domain: "https://<your-account>.auth.faable.link", // where /oauth/token lives
}
API 密钥
import { FaableAuthApi, authApikey } from "@faable/auth-sdk";
const api = FaableAuthApi.create({
domain: "https://<your-account>.auth.faable.link",
authStrategy: authApikey,
auth: { apikey: "fak_xxxxxxxxxxxxxxxx" },
});
借记符
对于您已经持有的代币—— CLI 中的用户访问代币, 代币
别的地方 SDK不铸造或刷新;无论谁拥有该标志,都是如此.
token 可以是获取器(同步或同步),请参考: 每个 请,
因此返回当前符号的获取器保持一个长寿客户端正确
当符号旋转时.
import { FaableAuthApi, authBearer } from "@faable/auth-sdk";
const api = FaableAuthApi.create({
domain: "https://<your-account>.auth.faable.link",
authStrategy: authBearer,
auth: { token: () => session.accessToken },
});
这些电话可以做的是 无论信使的主题和范围允许什么——a 用户代号到达用户自己的资源,管理代号到达 管理 API.
会话 cookie (浏览器)
在租户的代理主机下提供的页面
浏览器的会话 cookie( 主机登录页面 : /me外交部 密码 没有
配置: 浏览器附加 cookie 本身; 策略会请求
withCredentials 因此它也做跨源, 其中认证服务器必须
允许页面的出处为证书.
import { FaableAuthApi, authCookie } from "@faable/auth-sdk";
const api = FaableAuthApi.create({
domain: "https://<your-account>.auth.faable.link",
authStrategy: authCookie,
});
无全权证书
奥米 auth 财务报告和审定财务报表 authStrategy 并且客户是匿名的
公共终点(login, /passwordless/start,设备流, OIDC
(原始内容存档于2018-10-21). Explaination. 这些不在生成的客户端上;通过
获取器 :
const api = FaableAuthApi.create({
domain: "https://<your-account>.auth.faable.link",
});
await api.fetcher.post("/passwordless/start", { email, client_id });
识别您的整合
每个请求都携带 x-faable-client: auth-sdk/<version>+<sha> 这么说
认证服务器可属性流量 。 将 SDK 包起来的应用程序可报告为
本身 —— 您所传递的值取代默认值, 在数据调用和调用时
类似符号请求:
FaableAuthApi.create({
domain,
clientInfo: { client: "my-app/1.4.0", name: "my-app" },
});
按呼选项
每个取取取方法都使用 timeout, (中文(简体) ), responseType 财务报告和审定财务报表 retry 那个
电话 重复只应用到 GET( 重复播放的写入会重复
资源),以及 timeout 财务报告和审定财务报表 retry 乘数——热路的短暂期限
想要吗 retry: false 旁边:
await api.fetcher.get(`/user/${id}`, { timeout: 800, retry: false });
构造选项
| 选项 | 类型 | 说明 |
|---|---|---|
domain | 字符串 | 要求. 账户主机到目标,例如. https://<your-account>.auth.faable.link没有默认。 议定书是任择性的—— <your-account>.auth.faable.link 财务报告和审定财务报表 https://<your-account>.auth.faable.link 等同起来. |
authStrategy | 战略制定者 | 授权战略( O)authClientCredentials | authApikey | authBearer | authCookie),从 @faable/auth-sdk默认为 authClientCredentials 何时 auth 被给出; 既无也无匿名. |
auth | 配置 | 选择策略的配置 。 它的形状是从 authStrategy (例如:. { client_id, client_secret }) (中文(简体) ). |
debug | 布尔 | 在下面的获取器中启用动词记录 . |
headers | { project_id?; account_id? } | 高级/测试出逃舱口——目标 domain 但服务器解决了不同的项目/账户(同意为 x-faable-project 编号 : x-faableauth-account) (中文(简体) ). team_id 是一个已贬值的别名,其名称是: project_id(单位:千美元) team_<hex> 值以 project_<hex>并用不同的标识来传递 SDK不再发送 x-faable-team。 。 。 . |
clientInfo | { client?; name?; instance? } | 这种一体化如何确定自身(x-faable-client 编号 : x-faable-instance) (中文(简体) ). client 替换 SDK 自己的 auth-sdk/<version>+<sha>。 。 。 . |
使用量
用户
// Get a user
const user = await api.getUser("user_xxx");
// Create a user
const created = await api.createUser({
email: "[email protected]",
password: "•••••••••",
});
// Update a user
const updated = await api.updateUser("user_xxx", { phone: "+34XXXXXXXXX" });
// List users (paginated) — first page of 30
const firstPage = await api.listUsers().first();
// Filter by email
const matches = await api.listUsers({ email: "[email protected]" }).first();
// Iterate every page
for await (const page of api.listUsers()) {
for (const user of page) {
// ...
}
}
用户元数据
const metadata = await api.getUserMetadata("user_xxx");
await api.setUserMetadata("user_xxx", {
onboarded: true,
plan: "pro",
});
团队
const team = await api.getTeam("team_xxx");
const newTeam = await api.createTeam({ name: "Acme Inc." });
await api.deleteTeam("team_xxx");
const myTeams = await api.listTeams({ user_id: "user_xxx" }).first();
小组成员
const members = await api.listTeamMembers({ query: "alice" }).first();
const isMember = await api.isUserMemberOfTeam("user_xxx", "team_xxx");
角色和权限
一个角色会授予你的API权限. 将其指定给账户级别的用户及其代币,用于一个 API rbac 启用可携带这些权限(团队角色不授予).
const role = await api.roleCreate({ name: "support" });
await api.roleAddPermissions(role.id, {
permissions: [{ api: "api_xxx", value: "tickets:write" }],
});
await api.userAssignRoles("user_xxx", { roles: [role.id] });
const roles = await api.userRoles("user_xxx");
const permissions = await api.userPermissions("user_xxx"); // with the role that grants each
await api.userRemoveRoles("user_xxx", { roles: [role.id] });
await api.roleRemovePermissions(role.id, {
permissions: [{ api: "api_xxx", value: "tickets:write" }],
});
连接
const connections = await api.listConections().first();
const connection = await api.getConection("conn_xxx");
客户
const clients = await api.listClients().first();
const client = await api.getClient("client_xxx");
经常账户
const account = await api.currentAccount();
倾斜
列表方法返回一个派吉纳特. 使用 .first() 来抓取第一页或以 for await ... of 移动所有页面:
const paginator = api.listUsers();
const firstPage = await paginator.first();
for await (const page of paginator) {
// each `page` is an array of items
}
网络呼号
签名的 Faable Auth 发送 POST当房客出事时 s 到您的服务器上user.created, (中文(简体) ), team.member.added....) 创建订阅 faable auth webhooks create --url https://… -e user.created (它印过签字的秘密一次) 然后在信任它之前验证每封邮件:
import {
constructWebhookEvent,
readRawBody,
WebhookVerificationError,
} from "@faable/auth-sdk";
// Next.js pages router: the signature is over the RAW body.
export const config = { api: { bodyParser: false } };
export default async function handler(req, res) {
let event;
try {
event = await constructWebhookEvent(
await readRawBody(req), // fetch-style handlers: await request.text()
req.headers,
process.env.FAABLEAUTH_WEBHOOK_SECRET!,
);
} catch (e) {
if (e instanceof WebhookVerificationError) return res.status(401).end();
throw e;
}
switch (event.type) {
case "user.created":
await welcome(event.payload.email); // payload is the User
break;
case "team.member.added":
await sync(event.payload.team_id, event.payload.user_id);
break;
}
res.status(200).end();
}
- 回答2xx只有在工作完成时. 超时,网络出错,5xx和429重审时间分别为1分,5分,30分,2分和12分.
- 同一事件可以来两次 (在失去的回复后重试).
event.delivery_id(单位:千美元)x-faable-delivery)每重试同:由来去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相去相相去相去相去相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相. - 旋转 :
faable auth webhooks rotate-secret保留24小时的旧秘密,交货时同时携带两种签名。 在不休息时间的情况下切换侧面,通过两个:await constructWebhookEvent(body, headers, [oldSecret, newSecret])。 。 。 . - 使用Web Crypto,所以它运行在"节点"19,"德诺","邦"和"边缘跑道"上;这就是为什么它是
async。 。 。 . - 超过5分钟的交货被拒绝作为回放(
toleranceMs以改变它.
WebhookEvent, (中文(简体) ), WebhookEventType, (中文(简体) ), WebhookEventOf<"user.created"> 财务报告和审定财务报表 WebhookPayload<"team.member.added"> 由 Auth OpenAPI 生成,与其他类型一样.
保护您的 API
校验您的 API 接收的访问符并检查其权限 :
import {
AccessTokenError,
bearerToken,
requirePermissions,
verifyAccessToken,
} from "@faable/auth-sdk";
export default async function handler(req, res) {
try {
const claims = await verifyAccessToken(bearerToken(req.headers.authorization), {
domain: process.env.FAABLEAUTH_DOMAIN!, // https://<tenant>.auth.faable.link
audience: "https://api.example.com", // your Api's identifier
});
requirePermissions(claims, "tickets:write");
// … claims.sub is the user (or the client, for machine tokens)
} catch (e) {
if (e instanceof AccessTokenError) return res.status(e.status).json({ error: e.reason });
throw e;
}
}
verifyAccessToken核对租户JWKS的签名(一次核对后缓存),iss, (中文(简体) ),aud财务报告和审定财务报表exp。它抛出AccessTokenError与status401号.requirePermissions掷出AccessTokenErrorinsufficient_scope与status第403和403段missing· ;hasPermissions返回布尔值。 两者都要求 全部 授权通过.- 这个
permissions索赔需要 Api 的token_dialect将会是access_token_authz与rbac上,一个用户符号带有客户端的权限 请求 用户的角色,所以要求它们作为范围.
类型
所有响应形状均由OpenAPI spec生成,再由包根导出:
import type {
User,
Team,
TeamMember,
Connection,
Client,
} from "@faable/auth-sdk";
许可证
麻省理工学院