@adonis-agora/奥斯基特服务器
AdonisJS 的 OpenID 连接 / OAuth2 授权服务器( 身份提供者) —— 平庸
包起来 oidc-provider。 。 。 .
特征
- OIDC / OAuth2 AS 数据 ——授权代码+PKCE,刷新令牌(旋转),令牌交换, ,JWKS(管理型+可旋转型),撤销型,内向型.
- 外交部 ——TOTP,WebAuthn密码,恢复代码,可信设备跳过.
- 无密码 ——魔法链接电子邮件登录和密码第一登录.
- 议定书延期 - 设备流动(RFC 8628)、DPoP(RFC 9449)、PAR(RFC 9126),升级
通过认证
acr_values《动态客户登记》(RFC 7591/7592). - 个人代理人 ——为用户代理的AI助手:由JWT签名的代理身份
(JWKS,没有共享的秘密) 和用户批准,可撤销的授权 范围你定义,
在一个可插件协议适配器上(密码 ))),该建筑.
再加上 个人代理协议( “ Poppy ”)数字 :
发现,签名
Poppy-Session代理会话,Direct/Device/Medified sign-in,MCP和浏览器会话. ⚠️ 实验 ——跟踪光谱的0.3草案并会改变(可能断开,外部) semver majors),而spec是一个草案. - 原生应用程序 - RFC 8252本地客户(
authkit:clients:create --native: 私人使用 方案 / 要求 https / 循环重定向, 总是公开 + PKCE ) 和@adonisjs/auth警卫oidcRpGuard(届会)和oidcBearerGuard(单位:千美元)Authorization: Bearer进入标志, 正在处理或远程资源服务器). - 管理控制台 ——用户 CRUD (+禁用),客户端 CRUD,会话,审计日志(opt-in, (原始内容存档于2017-03-27). policy-gated.
- 账户控制台 自助应用程序/同意、安全(密码/电子邮件/会议), 简介.
- 托肯斯联合会( F) ——个人上网. 托肯斯,管理员冒充, 后通道登录, 由RP发起的登录.
- 硬化 - 逐步关闭账户、限制每个IP费率、审计记录 事件/webhook fan-out, 新登录邮件提示.
- 可操作性 i18n(英语默认, pt-BR 已建入), OpenTeleometry 度量衡, the
authkit:doctor财务报告和审定财务报表authkit:rotate-keys命令.
其余部分为葡萄牙语,等待完整的翻译通行证.
英斯特拉桑
node ace add @adonis-agora/authkit-server
# ou: pnpm add @adonis-agora/authkit-server && node ace configure @adonis-agora/authkit-server
欧 configure 公众a config/authkit.ts型号 app/models/auth_user.ts, (中文(简体) ),
o 控制器的相互作用(app/controllers/auth_interaction_controller.ts页:1
{\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}请说 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}请说.
轮回的蒙塔尔 OIDC
// start/routes.ts
import router from '@adonisjs/core/services/router'
import { registerOidcRoutes } from '@adonis-agora/authkit-server'
registerOidcRoutes(router) // monta em /oidc por padrão
德文纳 AUTHKIT_ISSUER 阿蓬坦多段落 <host>/oidc (一个发行人 deve terminar 不挂载路径).
Rotas de 交互( 日志/ consentimento)
欧 oidc-provider 乌斯瓦里奥·南昂蒂卡多(签名) interactions.url
(单位:千美元)/auth/interaction/:uid) (中文(简体) ). 国家 护栏 (单位:千美元) configure 埃杰塔语name
app/controllers/auth_interaction_controller.ts) (中文(简体) ). 登记为rotas que apontam para ele:
// start/routes.ts
import AuthInteractionController from '#controllers/auth_interaction_controller'
router.get('/auth/interaction/:uid', [AuthInteractionController, 'show'])
router.post('/auth/interaction/:uid/login', [AuthInteractionController, 'login'])
router.post('/auth/interaction/:uid/consent', [AuthInteractionController, 'consent'])
Sem essas rotas o tumpto de autirização cai num 404 ao chegar na tela de login. 中国植物物种信息数据库.
用户登录/ 同意( 配置)
欧 configure ejeta作为 telas de interactive 的一个 partir de um preset escolhido :
node ace configure @adonis-agora/authkit-server --ui=edge
# valores: edge | react | headless — se omitir, o configure pergunta
卡达预设公示a:
headless控制器app/controllers/auth_interaction_controller.ts) (中文(简体) ).show解除JSON(美国){ uid, prompt, params }页:1login编号 :consent请回答JSON/erro. (原始内容存档于2018-10-26). Você constrói o front como quiser.edge——控制器+视图边缘(resources/views/authkit/login.edge电子consent.edge) (中文(简体) ).show使风景迅速.react控制器 + páginas Inertia/反应(inertia/pages/authkit/login.tsx电子consent.tsx) (中文(简体) ).show法兹inertia.renderB. 离开@adonisjs/inertia+ Vite + 反应否 应用程序 - oconfigureexista essa sack antes de publicar o presset. [永久失效連結] 互联网档案馆的存檔,存档日期2013-12-02.
Em todos os 预设 o 控制器 ejetado é 卡斯卡语name{\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}我们一起来
service.interactions (resolvido通过 containerResolver.make('authkit.server')页:1
details(ctx), (中文(简体) ), login(ctx, { email, password }) 电子 consent(ctx)Você 编辑 a parte de
进行/定向.
Quem 自己决定作为认证 valem o verifyCredentials 对 config/authkit.ts
{\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}你觉得呢 service.interactions.login 查马 默认咨询a o AuthUser 电子邮件
我们a verifyPassword; sobrescreva para placear sua própria base de usuários. 中国植物物种信息数据库.
作为前身
import AuthInteractionController from '#controllers/auth_interaction_controller'
router.get('/auth/interaction/:uid', [AuthInteractionController, 'show'])
router.post('/auth/interaction/:uid/login', [AuthInteractionController, 'login'])
router.post('/auth/interaction/:uid/consent', [AuthInteractionController, 'consent'])
佩尔西斯特翁西亚
后端没有 config/authkit.ts数字 :
adapters.redis({ connection })- 重新征服@adonisjs/redis相会道.adapters.database({ connection? })- 路西德;塔贝拉authkit_oidc_payloads, criada pelo (英语)ensureAuthkitSchema无启动( com)schema: { autoManage: false }(原始内容存档于2018-10-29). chame-o numa Migração. 库纳指数化account_idmantém as buscas e revogações por conta em SQL; 林哈斯反气相机account_idNULL continuam sento encontradas. 中国植物物种信息数据库. Postgres, MySQL e SQLite (英语).
观察
A. 注册、签章、刷新、转赠、转赠 e作为选择加入的expãe de forma ext.
配置
没有 config/authkit.ts,使用阴道 observability数字 :
observability: {
metrics: true, // habilita a coleta/agregação de métricas
jsonRoutes: true, // libera a rota JSON de snapshot
dashboard: true, // libera o dashboard HTML embutido
}
罗塔
升起旗帜 registerOidcRoutes 没有 start/routes.ts数字 :
import { registerOidcRoutes } from '@adonis-agora/authkit-server'
registerOidcRoutes(router, { metrics: true, dashboard: true })
GET /authkit/metrics——快照aregado em JSON(英语:{ counters, histograms, updatedAt }) (中文(简体) ).GET /authkit/dashboard- 仪表板 HTML embutido(自动更新 Cada 5s, sem) (原始内容存档于2018-10-21). dependência do Edge do Consumidor.
打开几何
透过开放的遥测作为 métricas são immitidas 夸多 @opentelemetry/api 电子 @adonisjs/otel
(原始内容存档于2018-10-21). estão instalados. 女神使出家出家
JSON/HTML)为杜鹃花科杜鹃花属下的一个种.
格拉法纳
奥尔基沃 assets/grafana/authkit-dashboard.json (原始内容存档于2012-10-12) (英语). Cole ser importado prontamente no Grafana
(磁盘-导入). (原始内容存档于2018-09-26) (英语). Ele usa nomes de métrica no paderão OTel Prometheus (pontos viram)
强调电子计数器 ganham _total), portanto 重置 um 出口商 Prometheus 没有管道
以奥特尔·帕克(英语:Otel para que as séries)存在.
无
- 访问标志 são opacos; ID标志 são JWT (assinados pelo JWKS gerido).
- PKCE(S256) obrigatório; 刷新符号 são rotacionados.
自定义主登录方法
注册特定主机认证流量的类别或实例 。 AuthKit 通过请求容器解决类, 所以普通的 Adonis @inject() 依赖性有效。 主机验证和消耗证书; AuthKit 应用账户政策,维护,MFA,审计,OIDC会话完成.
import { inject } from '@adonisjs/core';
import type { HttpContext } from '@adonisjs/core/http';
import type { CustomLoginMethod } from '@adonis-agora/authkit-server';
import PhoneProofs from '#services/phone_proofs';
@inject()
export default class WhatsappLogin implements CustomLoginMethod {
readonly passwordless = true;
constructor(private proofs: PhoneProofs) {}
async authenticate(ctx: HttpContext) {
// Host service validates and atomically consumes the proof bound to this
// browser session and OIDC interaction. Never trust request.accountId.
const accountId = await this.proofs.consume(ctx);
return accountId ? { accountId } : null;
}
}
// config/authkit.ts
import WhatsappLogin from '#auth/whatsapp_login';
export default defineConfig({
// issuer, adapter, accountStore, ...
customLoginMethods: { whatsapp: WhatsappLogin },
});
// Native form controller, on the host's POST /auth/interaction/:uid/... route
return authenticateCustomLogin(ctx, 'whatsapp');
authenticate 返回时 { accountId } 只有在有有效证据后,或 null 拒绝登录。 也可能还给一个被验证的宿主 remember 布尔; 默认禁用并遵守运行时间会话政策 。 同一会议政策适用于外交部之后。 归还身份不能跳过外交部。 方法名称保留在 OIDC 中 amr 索赔,包括随后的第二个因素。 密码策略的默认方法; 设置 passwordless = true 用于不使用账户密码的OTP、硬件或外部证明.
可采用的方法 begin(ctx) 开始挑战。 打电话 beginCustomLogin(ctx, 'whatsapp') 从主机路线。 两个调度员检查当前 OIDC 交互及其 :uid 在引用方法之前, 方法名称包含小写字母,数字, :, (中文(简体) ), _ 或者说 -,从字母开始,最多有64个字符。 内置因子名称( Q)pwd, (中文(简体) ), email, (中文(简体) ), mfa, (中文(简体) ), totp, (中文(简体) ), webauthn, (中文(简体) ), recovery页:1 注册不会自动创建路由或UI:主机拥有验证,CSRF,速率限制,瓶装保护,交付,证明过期,回放保护,账户查询/签名以及响应渲染器. 使用本地形式导航进行最终完成,以便 AuthKit 能够制取 MFA 或重定向给依赖方 .
对于已经核实其可信度的任意流动, completeCustomLogin(ctx, { accountId, method, passwordless }) 是值得信赖的逃生舱门。 不要把它曝光为接受浏览器的账户ID的终点. 仅使用电话的账户可能代表缺失的电子邮件作为遗留的空字符串 AuthAccount DTO; OIDC 省略 email 财务报告和审定财务报表 email_verified 在这样的情况下. AuthAccount.phone提供时必须代表经核实的电话身份.
拒绝证明和处理者例外产生 login.failure 带有方法ID和消毒理由的审计事件;从未包括证明内容和例外消息. 主机拥有的挑战/OTP核查端点必须审计自己先前的失败.
检察官办公室提供商
whatsapp.sender 接受任意 WhatsappCodeSender 实例或类。 这是分开的 customLoginMethods:登录类验证身份,发送者只提供代码. 配置发件人不会创建OTP商店、路由、验证器、签名流程或UI.
import { inject } from '@adonisjs/core';
import type { WhatsappCodeInput, WhatsappCodeSender } from '@adonis-agora/authkit-server';
import MyWhatsappSdk from '#services/my_whatsapp_sdk';
@inject()
class MyProvider implements WhatsappCodeSender {
constructor(private sdk: MyWhatsappSdk) {}
async sendCode(input: WhatsappCodeInput): Promise<void> {
await this.sdk.sendText(input.phone, input.text ?? input.code);
}
}
export default defineConfig({
// issuer, adapter, accountStore, ...
customLoginMethods: { whatsapp: WhatsappLogin },
whatsapp: { sender: MyProvider }, // or an already-created instance
});
生成检察官办公室后,通过请求容器解决发送者:
const service = await ctx.containerResolver.make('authkit.server');
const binding = service.config.whatsapp?.sender;
if (!binding) throw new Error('WhatsApp login is not configured');
const sender = await resolveWhatsappCodeSender(ctx.containerResolver, binding);
await sender.sendCode({
phone: '5511999999999', code, locale: 'pt-BR', expiresInSeconds: 300,
text: ctx.i18n.t('auth.code_message', { code }),
});
发件人必须拒绝交货失败。 东道主只有在接受交货后才能激活所储存的检察官办公室,并强制执行过期、重试、要求装订、重放保护和费率限制。 提供者的接受不是交货/阅读收据. text 是支持自由格式消息的提供者的可选本地化副本;结构化提供者独立接收原始代码.
本地适配器可按下列情况提供:
whatsapp: {
sender: new WhatsmiauCodeSender({ apiKey, instanceName }),
}
whatsapp: {
sender: new MetaWhatsappCodeSender({
accessToken, phoneNumberId, apiVersion, templateName,
languageCode: 'pt_BR',
}),
}
什么smiau的可选 baseUrl 包括 API 版本路径和默认为 https://api.whatsmiau.dev/v2. Meta 需要一个明确支持的Graph API版本和一个经核准的认证模板,并有一个OTP/复制码按钮。 所配置的模板必须存在模板语言; languageCode 覆盖自动定位映射( n)pt-BR → pt_BR, (中文(简体) ), en → en_US, (中文(简体) ), es → es) (中文(简体) ). Meta模板文本和显示的过期时间在核准的模板中管理; expiresInSeconds 描述主机的校验 TTL 并且不更改模板过期。 两种本地适配器都使用受限请求,拒绝重定向并丢弃提供者出错机构,因此资信/OTP不会输入出错消息.
自定义的外交部方法(类或例)
与主登录方法分开登记其他方法。 注册从不注册账户: isEnabled 请咨询您的入学商店。 一种方法可能会在 begin,描述其形式字段,并验证其中的证明 verify。 。 。 .
import { inject } from '@adonisjs/core'
import type { CustomMfaContext, CustomMfaMethod } from '@adonis-agora/authkit-server'
// Enrollment and challenge services belong to your application and are injected by Adonis.
@inject()
export class WhatsappMfa implements CustomMfaMethod {
readonly factorId = 'phone'
constructor(private enrollment: PhoneEnrollment, private challenges: PhoneChallenges) {}
async isEnabled({ accountId }: CustomMfaContext) {
return this.enrollment.hasVerifiedPhone(accountId)
}
async describe() {
return { label: 'WhatsApp', fields: [{ name: 'code', label: 'Code', inputMode: 'numeric' as const }] }
}
async begin({ accountId, challengeId }: CustomMfaContext) {
await this.challenges.sendWhatsapp(accountId, challengeId)
}
async verify({ ctx, accountId, challengeId }: CustomMfaContext) {
const { code } = await ctx.request.validateUsing(phoneCodeValidator)
return this.challenges.consume(accountId, challengeId, code)
}
}
// In defineConfig:
mfa: {
methods: { whatsapp: WhatsappMfa, sms: smsMfaInstance },
requiredFactors: 3,
}
抽样入学/质疑服务和Vine验证器是主机执行。 将证据绑在一起 accountId 财务报告和审定财务报表 challengeId; 过期, 散列存储代码, 限制发送, 并在解剖上消耗成功的证据 。 交付可以使用WhatsApp发送器接口或任何短消息/提供者SDK. 证明书和提供者证书绝不能出现在说明中.
requiredFactors 计算主登录加上不同的附加组(默认情况下为2个,可配置2至8个)。 允许它仅用注册方法对账户提出质疑;设置它也明确要求未注册的账户注册后才能认证. 此扩展名不提供入学屏幕 。 原生的TOTP,恢复代码和密码仍然可用;恢复和TOTP共享一个组. 使用同一电话的WhatsApp和短消息必须共享 factorId: 'phone'“WhatsApp”初级登录课也应揭露该群体,防止同一电话两次计数。 组名表达应用程序政策;它们不能证明独立的物理认证因素.
AuthKit 绑定当前登录交互和浏览器会话的挑战,在10分钟后到期,封口失败的自定义证明在5分后,并且只有在需要的组数后才能完成OIDC. 边缘和生成的 React 挑战屏幕会渲染自定义描述符和可选的启动按钮. 命名的 POST 路线 authkit.mfa.custom.begin 财务报告和审定财务报表 authkit.mfa.custom.verify 使用现有的登录节流和CSRF管道。 公开 beginCustomMfa, (中文(简体) ), verifyCustomMfa,以及 customMfaViewProps 支持主机集成;仅凭验证不能完成认证。 使用已注册的路线完成政策控制.
无 mfa 配置,保留了现有的本地的MFA行为. 应用程序可以在不增加方法的情况下运送这种扩展.