@adonis-agora/authkit-server 0.77.0 → 0.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +4 -0
  2. package/build/host/views/agents/consent.edge +13 -2
  3. package/build/host/views/agents/done.edge +3 -0
  4. package/build/index.d.ts +10 -0
  5. package/build/index.js +8 -0
  6. package/build/providers/authkit_server_provider.js +15 -1
  7. package/build/src/agents/config.d.ts +22 -3
  8. package/build/src/agents/config.js +22 -4
  9. package/build/src/agents/delegation_service.js +18 -8
  10. package/build/src/agents/delegation_store.d.ts +16 -0
  11. package/build/src/agents/delegation_store.js +44 -0
  12. package/build/src/agents/middleware.js +2 -1
  13. package/build/src/agents/poppy/client_registry.d.ts +45 -0
  14. package/build/src/agents/poppy/client_registry.js +226 -0
  15. package/build/src/agents/poppy/config.d.ts +365 -0
  16. package/build/src/agents/poppy/config.js +208 -0
  17. package/build/src/agents/poppy/dpop.d.ts +61 -0
  18. package/build/src/agents/poppy/dpop.js +158 -0
  19. package/build/src/agents/poppy/errors.d.ts +20 -0
  20. package/build/src/agents/poppy/errors.js +22 -0
  21. package/build/src/agents/poppy/replay.d.ts +25 -0
  22. package/build/src/agents/poppy/replay.js +106 -0
  23. package/build/src/agents/poppy/resource.d.ts +95 -0
  24. package/build/src/agents/poppy/resource.js +125 -0
  25. package/build/src/agents/poppy/safe_fetch.d.ts +48 -0
  26. package/build/src/agents/poppy/safe_fetch.js +256 -0
  27. package/build/src/agents/poppy/service.d.ts +286 -0
  28. package/build/src/agents/poppy/service.js +1464 -0
  29. package/build/src/agents/poppy/store.d.ts +111 -0
  30. package/build/src/agents/poppy/store.js +269 -0
  31. package/build/src/agents/poppy/web_session.d.ts +32 -0
  32. package/build/src/agents/poppy/web_session.js +104 -0
  33. package/build/src/agents/protocol.d.ts +8 -4
  34. package/build/src/agents/registry_store.d.ts +41 -0
  35. package/build/src/agents/registry_store.js +138 -0
  36. package/build/src/agents/runtime.d.ts +30 -1
  37. package/build/src/agents/runtime.js +221 -14
  38. package/build/src/audit/audit_sink.d.ts +1 -1
  39. package/build/src/audit/audit_sink.js +6 -0
  40. package/build/src/define_config.js +6 -0
  41. package/build/src/host/account_api/account_api_controller.d.ts +12 -1
  42. package/build/src/host/account_api/account_api_controller.js +10 -5
  43. package/build/src/host/admin_api/dto.d.ts +1 -1
  44. package/build/src/host/admin_console/admin_shell_controller.js +7 -0
  45. package/build/src/host/admin_console/console_personal_agents_controller.d.ts +83 -0
  46. package/build/src/host/admin_console/console_personal_agents_controller.js +337 -0
  47. package/build/src/host/admin_sessions_service.js +8 -5
  48. package/build/src/host/auth_host_config.d.ts +2 -1
  49. package/build/src/host/controllers/account_apps_controller.js +13 -3
  50. package/build/src/host/controllers/poppy_consent_controller.d.ts +19 -0
  51. package/build/src/host/controllers/poppy_consent_controller.js +173 -0
  52. package/build/src/host/controllers/poppy_controller.d.ts +25 -0
  53. package/build/src/host/controllers/poppy_controller.js +194 -0
  54. package/build/src/host/csrf.d.ts +7 -0
  55. package/build/src/host/csrf.js +16 -1
  56. package/build/src/host/i18n.d.ts +4 -0
  57. package/build/src/host/i18n.js +4 -0
  58. package/build/src/host/poppy_session_key.d.ts +9 -0
  59. package/build/src/host/poppy_session_key.js +9 -0
  60. package/build/src/host/register_auth_host.js +76 -0
  61. package/build/src/host/ui-dist/assets/index-LrScaR9C.js +155 -0
  62. package/build/src/host/ui-dist/index.html +1 -1
  63. package/build/src/provider/oidc_service.d.ts +5 -0
  64. package/build/src/provider/oidc_service.js +9 -2
  65. package/build/src/schema/ensure.js +152 -0
  66. package/package.json +2 -2
  67. package/build/src/host/ui-dist/assets/index-CIqtoNcO.js +0 -155
@@ -8,7 +8,7 @@
8
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
10
  <link href="https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600;700&family=JetBrains+Mono:ital,wght@0,400;0,500;0,600;1,400&display=swap" rel="stylesheet">
11
- <script type="module" crossorigin src="/__AUTHKIT_BASE__/assets/index-CIqtoNcO.js"></script>
11
+ <script type="module" crossorigin src="/__AUTHKIT_BASE__/assets/index-LrScaR9C.js"></script>
12
12
  <link rel="stylesheet" crossorigin href="/__AUTHKIT_BASE__/assets/index-DTSmD4RU.css">
13
13
  </head>
14
14
  <body>
@@ -25,6 +25,11 @@ export declare class OidcService {
25
25
  get signingJwks(): {
26
26
  keys: Record<string, any>[];
27
27
  };
28
+ /**
29
+ * @internal Segredo derivado da app key para um uso (`label`) — HMAC dos nonces
30
+ * DPoP do Poppy, por exemplo. Igual em todas as instâncias, sem expor a chave.
31
+ */
32
+ deriveSecret(label: string): Buffer;
28
33
  /** Pathname do issuer sem barra final (ex.: `/oidc`). Vazio quando montado na raiz. */
29
34
  readonly mountPath: string;
30
35
  readonly recorder: MetricsRecorder;
@@ -1,4 +1,4 @@
1
- import { timingSafeEqual } from 'node:crypto';
1
+ import { createHmac, timingSafeEqual } from 'node:crypto';
2
2
  import { NoopRecorder } from '@adonis-agora/authkit-core';
3
3
  import Koa from 'koa';
4
4
  import mount from 'koa-mount';
@@ -41,6 +41,13 @@ export class OidcService {
41
41
  get signingJwks() {
42
42
  return this.#signingJwks;
43
43
  }
44
+ /**
45
+ * @internal Segredo derivado da app key para um uso (`label`) — HMAC dos nonces
46
+ * DPoP do Poppy, por exemplo. Igual em todas as instâncias, sem expor a chave.
47
+ */
48
+ deriveSecret(label) {
49
+ return createHmac('sha256', this.#appKey).update(`authkit:${label}`).digest();
50
+ }
44
51
  /** Pathname do issuer sem barra final (ex.: `/oidc`). Vazio quando montado na raiz. */
45
52
  mountPath;
46
53
  recorder;
@@ -325,7 +332,7 @@ export class OidcService {
325
332
  /** Verifica client_id + client_secret contra os clients da config (p/ endpoints custom como introspecção de PAT). */
326
333
  verifyClientCredentials(clientId, clientSecret) {
327
334
  const client = this.#clients.find((c) => c.clientId === clientId);
328
- if (!client || !client.clientSecret)
335
+ if (!client?.clientSecret)
329
336
  return false;
330
337
  const a = Buffer.from(client.clientSecret);
331
338
  const b = Buffer.from(clientSecret);
@@ -295,6 +295,158 @@ const TABLES = [
295
295
  created_at: (t) => t.dateTime('created_at', { useTz: true, precision: 3 }).nullable(),
296
296
  },
297
297
  },
298
+ {
299
+ name: 'auth_agent_registry',
300
+ /**
301
+ * Agentes liberados (`allowed`) ou bloqueados (`blocked`) pelo console admin,
302
+ * somados ao `defineConfig` — PACT pelo `iss`, Poppy pelo `client_id`.
303
+ */
304
+ create: (t) => {
305
+ t.string('id').primary();
306
+ t.string('protocol', 16).notNullable();
307
+ t.string('identifier', 2048).notNullable();
308
+ t.string('status', 16).notNullable();
309
+ t.string('name').nullable();
310
+ t.string('jwks_uri', 2048).nullable();
311
+ t.string('updated_by').nullable();
312
+ t.dateTime('created_at', { useTz: true, precision: 3 }).notNullable();
313
+ t.dateTime('updated_at', { useTz: true, precision: 3 }).notNullable();
314
+ },
315
+ columns: {
316
+ protocol: (t) => t.string('protocol', 16),
317
+ identifier: (t) => t.string('identifier', 2048),
318
+ status: (t) => t.string('status', 16),
319
+ name: (t) => t.string('name').nullable(),
320
+ jwks_uri: (t) => t.string('jwks_uri', 2048).nullable(),
321
+ updated_by: (t) => t.string('updated_by').nullable(),
322
+ created_at: (t) => t.dateTime('created_at', { useTz: true, precision: 3 }).nullable(),
323
+ updated_at: (t) => t.dateTime('updated_at', { useTz: true, precision: 3 }).nullable(),
324
+ },
325
+ },
326
+ /*
327
+ * Personal Agent Protocol (Poppy). Os Account Tokens são grants de
328
+ * `auth_agent_grants` (prefixo `pgrant_`) com o hash em
329
+ * `auth_agent_refresh_tokens`; aqui ficam Sessions, Session Tokens, pedidos de
330
+ * sign-in e os `jti` vistos. Mesmas regras de data das tabelas acima.
331
+ */
332
+ {
333
+ name: 'auth_poppy_sessions',
334
+ /**
335
+ * Uma Session: um usuário do agente (`user_id`, opaco) num agente
336
+ * (`client_id`). `account_id` é a conta a que ficou PRESA ao logar (não troca);
337
+ * `grant_id` o Account Token com que está logada agora (`null` = deslogada).
338
+ */
339
+ create: (t) => {
340
+ t.string('id').primary();
341
+ t.string('client_id', 2048).notNullable();
342
+ t.string('user_id').notNullable();
343
+ t.string('account_id').nullable().index();
344
+ t.string('grant_id').nullable().index();
345
+ t.text('scope').notNullable();
346
+ t.dateTime('expires_at', { useTz: true, precision: 3 }).notNullable();
347
+ t.dateTime('ended_at', { useTz: true, precision: 3 }).nullable();
348
+ t.dateTime('created_at', { useTz: true, precision: 3 }).notNullable();
349
+ t.dateTime('updated_at', { useTz: true, precision: 3 }).notNullable();
350
+ },
351
+ columns: {
352
+ client_id: (t) => t.string('client_id', 2048),
353
+ user_id: (t) => t.string('user_id'),
354
+ account_id: (t) => t.string('account_id').nullable().index(),
355
+ grant_id: (t) => t.string('grant_id').nullable().index(),
356
+ scope: (t) => t.text('scope'),
357
+ expires_at: (t) => t.dateTime('expires_at', { useTz: true, precision: 3 }).nullable(),
358
+ ended_at: (t) => t.dateTime('ended_at', { useTz: true, precision: 3 }).nullable(),
359
+ created_at: (t) => t.dateTime('created_at', { useTz: true, precision: 3 }).nullable(),
360
+ updated_at: (t) => t.dateTime('updated_at', { useTz: true, precision: 3 }).nullable(),
361
+ },
362
+ },
363
+ {
364
+ name: 'auth_poppy_tokens',
365
+ /** Session Tokens — só o hash. `jkt` = chave DPoP; `null` = Bearer (MCP). */
366
+ create: (t) => {
367
+ t.string('token_hash', 64).primary();
368
+ t.string('session_id').notNullable().index();
369
+ t.string('client_id', 2048).notNullable();
370
+ t.string('user_id').notNullable();
371
+ t.string('account_id').nullable();
372
+ t.string('grant_id').nullable().index();
373
+ t.text('scope').notNullable();
374
+ t.string('resource', 2048).nullable();
375
+ t.string('jkt', 64).nullable();
376
+ t.dateTime('expires_at', { useTz: true, precision: 3 }).notNullable().index();
377
+ t.dateTime('created_at', { useTz: true, precision: 3 }).notNullable();
378
+ },
379
+ columns: {
380
+ session_id: (t) => t.string('session_id').index(),
381
+ client_id: (t) => t.string('client_id', 2048),
382
+ user_id: (t) => t.string('user_id'),
383
+ account_id: (t) => t.string('account_id').nullable(),
384
+ grant_id: (t) => t.string('grant_id').nullable().index(),
385
+ scope: (t) => t.text('scope'),
386
+ resource: (t) => t.string('resource', 2048).nullable(),
387
+ jkt: (t) => t.string('jkt', 64).nullable(),
388
+ expires_at: (t) => t.dateTime('expires_at', { useTz: true, precision: 3 }).nullable(),
389
+ created_at: (t) => t.dateTime('created_at', { useTz: true, precision: 3 }).nullable(),
390
+ },
391
+ },
392
+ {
393
+ name: 'auth_poppy_requests',
394
+ /**
395
+ * Pedidos de sign-in: `authorize` (Direct — vira código após o consentimento),
396
+ * `device` (RFC 8628) e `mediated` (§4.7, aguardando o código de uso único).
397
+ * Códigos só como hash. Linhas expiradas são apagadas no próximo pedido.
398
+ */
399
+ create: (t) => {
400
+ t.string('id').primary();
401
+ t.string('kind', 16).notNullable();
402
+ t.string('code_hash', 64).nullable().unique();
403
+ t.string('user_code', 16).nullable().unique();
404
+ t.string('client_id', 2048).notNullable();
405
+ t.string('session_id').nullable();
406
+ t.string('account_id').nullable();
407
+ t.text('requested_scope').notNullable();
408
+ t.text('granted_scope').nullable();
409
+ t.string('redirect_uri', 2048).nullable();
410
+ t.string('code_challenge', 128).nullable();
411
+ t.string('status', 16).notNullable();
412
+ t.integer('attempts').notNullable().defaultTo(0);
413
+ t.integer('interval_seconds').nullable();
414
+ t.dateTime('last_polled_at', { useTz: true, precision: 3 }).nullable();
415
+ t.text('data').nullable();
416
+ t.dateTime('expires_at', { useTz: true, precision: 3 }).notNullable().index();
417
+ t.dateTime('created_at', { useTz: true, precision: 3 }).notNullable();
418
+ },
419
+ columns: {
420
+ kind: (t) => t.string('kind', 16),
421
+ code_hash: (t) => t.string('code_hash', 64).nullable(),
422
+ user_code: (t) => t.string('user_code', 16).nullable(),
423
+ client_id: (t) => t.string('client_id', 2048),
424
+ session_id: (t) => t.string('session_id').nullable(),
425
+ account_id: (t) => t.string('account_id').nullable(),
426
+ requested_scope: (t) => t.text('requested_scope'),
427
+ granted_scope: (t) => t.text('granted_scope').nullable(),
428
+ redirect_uri: (t) => t.string('redirect_uri', 2048).nullable(),
429
+ code_challenge: (t) => t.string('code_challenge', 128).nullable(),
430
+ status: (t) => t.string('status', 16),
431
+ attempts: (t) => t.integer('attempts').defaultTo(0),
432
+ interval_seconds: (t) => t.integer('interval_seconds').nullable(),
433
+ last_polled_at: (t) => t.dateTime('last_polled_at', { useTz: true, precision: 3 }).nullable(),
434
+ data: (t) => t.text('data').nullable(),
435
+ expires_at: (t) => t.dateTime('expires_at', { useTz: true, precision: 3 }).nullable(),
436
+ created_at: (t) => t.dateTime('created_at', { useTz: true, precision: 3 }).nullable(),
437
+ },
438
+ },
439
+ {
440
+ name: 'auth_poppy_jtis',
441
+ /** `jti` já aceitos (asserções, provas DPoP), até expirarem — anti-replay entre instâncias. */
442
+ create: (t) => {
443
+ t.string('key', 100).primary();
444
+ t.dateTime('expires_at', { useTz: true, precision: 3 }).notNullable().index();
445
+ },
446
+ columns: {
447
+ expires_at: (t) => t.dateTime('expires_at', { useTz: true, precision: 3 }).nullable(),
448
+ },
449
+ },
298
450
  ];
299
451
  /**
300
452
  * Probe searchPath-aware: `schema.hasTable` no Postgres ignora o
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adonis-agora/authkit-server",
3
- "version": "0.77.0",
3
+ "version": "0.79.0",
4
4
  "description": "AdonisJS OIDC/OAuth2 provider (Identity Provider) toolkit: ejectable auth server with sessions, rate-limiting, MFA/TOTP, audit log, federated logout and OpenTelemetry metrics.",
5
5
  "license": "MIT",
6
6
  "author": "dudousxd",
@@ -113,7 +113,7 @@
113
113
  "qrcode": "1.5.4"
114
114
  },
115
115
  "devDependencies": {
116
- "@adonis-agora/authkit-react": "0.23.0",
116
+ "@adonis-agora/authkit-react": "0.24.0",
117
117
  "@adonis-agora/durable": "0.40.0",
118
118
  "@adonis-agora/telescope": "0.21.1",
119
119
  "@adonisjs/ally": "6.3.0",