@adonis-agora/authkit-server 0.86.0 → 0.87.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 (37) hide show
  1. package/README.md +2 -2
  2. package/build/index.d.ts +1 -2
  3. package/build/index.js +0 -1
  4. package/build/src/agents/config.d.ts +1 -1
  5. package/build/src/agents/delegation_service.js +1 -1
  6. package/build/src/agents/poppy/client_registry.d.ts +5 -0
  7. package/build/src/agents/poppy/client_registry.js +35 -1
  8. package/build/src/agents/poppy/config.d.ts +111 -80
  9. package/build/src/agents/poppy/config.js +55 -35
  10. package/build/src/agents/poppy/dpop.d.ts +2 -2
  11. package/build/src/agents/poppy/dpop.js +3 -3
  12. package/build/src/agents/poppy/email_code_sign_in.d.ts +4 -4
  13. package/build/src/agents/poppy/email_code_sign_in.js +5 -5
  14. package/build/src/agents/poppy/errors.d.ts +7 -2
  15. package/build/src/agents/poppy/errors.js +5 -2
  16. package/build/src/agents/poppy/resource.d.ts +30 -25
  17. package/build/src/agents/poppy/resource.js +24 -20
  18. package/build/src/agents/poppy/safe_fetch.js +8 -2
  19. package/build/src/agents/poppy/service.d.ts +69 -62
  20. package/build/src/agents/poppy/service.js +540 -546
  21. package/build/src/agents/poppy/session_jwt.d.ts +30 -0
  22. package/build/src/agents/poppy/session_jwt.js +133 -0
  23. package/build/src/agents/poppy/store.d.ts +17 -22
  24. package/build/src/agents/poppy/store.js +22 -30
  25. package/build/src/agents/poppy/web_session.d.ts +23 -16
  26. package/build/src/agents/poppy/web_session.js +42 -24
  27. package/build/src/host/admin_sessions_service.js +3 -3
  28. package/build/src/host/controllers/account_apps_controller.js +1 -1
  29. package/build/src/host/controllers/poppy_consent_controller.d.ts +2 -2
  30. package/build/src/host/controllers/poppy_consent_controller.js +2 -2
  31. package/build/src/host/controllers/poppy_controller.d.ts +19 -11
  32. package/build/src/host/controllers/poppy_controller.js +93 -68
  33. package/build/src/host/csrf.d.ts +2 -4
  34. package/build/src/host/csrf.js +2 -3
  35. package/build/src/host/register_auth_host.js +10 -5
  36. package/build/src/schema/ensure.js +14 -9
  37. package/package.json +3 -3
@@ -4,10 +4,11 @@ import type { PoppyClient, PoppyClientRegistry } from './client_registry.js';
4
4
  import type { PoppyLimiter, PoppyPrincipalBase, PoppyReplayStore, ResolvedPoppyConfig } from './config.js';
5
5
  import { type DpopNonceSource } from './dpop.js';
6
6
  import type { PoppyStore, RequestRow } from './store.js';
7
- export declare const JWT_BEARER_GRANT = "urn:ietf:params:oauth:grant-type:jwt-bearer";
8
7
  export declare const DEVICE_CODE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
8
+ export declare const MEDIATED_SIGN_IN_GRANT = "https://personalagentprotocol.org/grant/mediated-sign-in";
9
+ export declare const MEDIATED_SIGN_IN_EXTENSION = "mediated-sign-in";
9
10
  export declare const CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
10
- export declare const BROWSER_ASSERTION_TYP = "poppy-browser+jwt";
11
+ export declare const POPPY_PROTOCOL_VERSION = "0.3";
11
12
  /** URLs públicas do authorization server Poppy. */
12
13
  export interface PoppyUrls {
13
14
  origin: string;
@@ -20,29 +21,25 @@ export interface PoppyUrls {
20
21
  deviceAuthorization: string;
21
22
  /** Tela do device flow (`verification_uri`). */
22
23
  device: string;
23
- mediated: string;
24
24
  browserSession: string;
25
25
  discovery: string;
26
26
  }
27
27
  /** Deriva as URLs da ORIGEM do issuer configurado — nunca do Host da request. */
28
28
  export declare function poppyUrls(oidcIssuer: string, prefix: string): PoppyUrls;
29
- /** Resposta do token endpoint (§4.2, §4.4). */
29
+ /** Resposta do token endpoint (§4.7, RFC 6749 §5.1). */
30
30
  export interface PoppyTokenResponse {
31
31
  access_token: string;
32
32
  token_type: 'DPoP' | 'Bearer';
33
33
  expires_in: number;
34
34
  scope: string;
35
- session_id: string;
36
- signed_in: boolean;
37
35
  refresh_token?: string;
38
- refresh_token_expires_in?: number;
39
36
  }
40
- /** Ponte com o oidc-provider para os tokens Bearer de MCP (§4.3, §6). */
37
+ /** Ponte com o oidc-provider para os tokens Bearer de MCP (§7). */
41
38
  export interface PoppyMcpBridge {
42
39
  /** `url` é um servidor MCP deste app (de `apis` ou do registro de resources)? */
43
40
  isMcpResource(url: string): boolean;
44
41
  /**
45
- * Emite o Bearer de uma Session LOGADA como access token do oidc-provider,
42
+ * Emite o Bearer de um sign-in como access token do oidc-provider,
46
43
  * para que a integração MCP existente (`AccessToken.find`) o aceite. `null` =
47
44
  * sem ponte (o token fica só no store do Poppy).
48
45
  */
@@ -79,9 +76,9 @@ export interface PoppyRequestInput {
79
76
  headers: Record<string, string | string[] | undefined>;
80
77
  }
81
78
  export interface PoppyVerifyOptions {
82
- /** Scopes exigidos (todos). Faltando: `sign_in_required` (deslogado) ou `insufficient_scope`. */
79
+ /** Scopes exigidos (todos). Sem access token: challenge 401; sem o scope: `insufficient_scope`. */
83
80
  scopes?: string[];
84
- /** Exige Session logada. */
81
+ /** Exige acesso à conta (um access token). */
85
82
  signedIn?: boolean;
86
83
  /**
87
84
  * `resource` exigido por este endpoint. Default: derivado da URL contra
@@ -89,19 +86,22 @@ export interface PoppyVerifyOptions {
89
86
  */
90
87
  resource?: string | null;
91
88
  }
92
- export type PoppyAuthError = 'invalid_token' | 'sign_in_required' | 'insufficient_scope' | 'invalid_dpop_proof' | 'use_dpop_nonce';
89
+ export type PoppyAuthError = 'invalid_session' | 'invalid_token' | 'insufficient_scope' | 'invalid_dpop_proof' | 'use_dpop_nonce';
93
90
  export type PoppyVerifyResult = {
94
91
  ok: true;
95
92
  principal: PoppyPrincipalBase;
96
- jkt: string | null;
93
+ /** Grant (refresh token) do access token — `null` deslogado. */
94
+ grantId: string | null;
97
95
  } | {
98
96
  ok: false;
99
- status: 401 | 403;
100
- error: PoppyAuthError;
97
+ status: 400 | 401 | 403 | 429;
98
+ /** `null`: challenge sem código (§7, falta o access token) ou limite de taxa (§5.6). */
99
+ error: PoppyAuthError | null;
101
100
  description: string;
102
101
  scope?: string;
103
- wwwAuthenticate: string;
104
- /** Headers extras (`DPoP-Nonce`). */
102
+ /** `null` nos erros que vão no corpo (`invalid_session`) e no 429. */
103
+ wwwAuthenticate: string | null;
104
+ /** Headers extras (`DPoP-Nonce`, `Retry-After`). */
105
105
  headers: Record<string, string>;
106
106
  };
107
107
  /** Pedido Direct aguardando o usuário na tela de consentimento. */
@@ -138,29 +138,17 @@ export interface PoppyGrantSummary {
138
138
  updatedAt: Date;
139
139
  expiresAt: Date;
140
140
  }
141
- export type PoppyMediatedResponse = ({
142
- status: 'complete';
143
- } & PoppyTokenResponse) | {
144
- status: 'code_required';
145
- sign_in_id: string;
146
- code: {
147
- sent_to: string;
148
- };
149
- expires_at: string;
150
- } | {
151
- status: 'failed';
152
- } | {
153
- status: 'expired';
154
- };
155
- export interface PoppyBrowserSessionResult {
141
+ /** O que a entrada de um navegador autorizou (§6, passo 3). */
142
+ export interface PoppyBrowserJoin {
156
143
  sessionId: string;
157
144
  clientId: string;
158
145
  userId: string;
146
+ /** Conta autorizada no passo 2; `null` = entrada sem access token. */
159
147
  accountId: string | null;
148
+ grantId: string | null;
160
149
  scopes: string[];
161
- returnTo: string;
162
150
  }
163
- /** Estado atual de uma Session (para o cookie do site acompanhar — §5). */
151
+ /** Estado atual de um navegador que entrou numa Session (§6, "The cookie"). */
164
152
  export interface PoppySessionState {
165
153
  active: boolean;
166
154
  sessionId: string;
@@ -182,10 +170,10 @@ export declare const POPPY_ENDPOINTS_SLOT: unique symbol;
182
170
  export declare function registeredConversationProtocols(): {
183
171
  type: string;
184
172
  endpoint: string;
185
- resource?: string;
173
+ access?: 'session' | 'signed_in';
186
174
  }[];
187
175
  /**
188
- * @experimental Poppy (Personal Agent Protocol) Draft 0.1 — pode mudar de forma incompatível enquanto a spec for draft.
176
+ * @experimental Poppy (Personal Agent Protocol) Draft 0.3 — pode mudar de forma incompatível enquanto a spec for draft.
189
177
  */
190
178
  export declare class PoppyService {
191
179
  #private;
@@ -202,25 +190,28 @@ export declare class PoppyService {
202
190
  id: string;
203
191
  description: string;
204
192
  }[];
193
+ /** `www.{domínio}` não é a empresa (§3.1): a descoberta redireciona para o domínio (§3). */
194
+ discoveryRedirect(requestHost: string): string | null;
205
195
  /** `/.well-known/poppy.json` (§3) para o domínio pedido; `null` = domínio que não é nosso. */
206
196
  discoveryDocument(requestHost: string): Record<string, unknown> | null;
207
- /** RFC 8414 com `poppy_domains` (§3.2). */
197
+ /** `/.well-known/oauth-protected-resource` do domínio (§3.2, RFC 9728): aponta o issuer. */
198
+ protectedResourceMetadata(requestHost: string): Record<string, unknown> | null;
199
+ /** RFC 8414 com `protected_resources` (§3.2). */
208
200
  authorizationServerMetadata(): Record<string, unknown>;
209
201
  /**
210
- * `private_key_jwt` (RFC 7523 §2.2, §3): `client_assertion` assinada por uma
211
- * chave do `jwks_uri`, `iss` = `sub` = `client_id`, `aud` = o endpoint
212
- * chamado (ou o token endpoint/issuer), `exp` curto, `jti` único.
202
+ * `private_key_jwt` (§4.1, RFC 7523): `client_assertion` assinada por uma chave do `jwks_uri`,
203
+ * `iss` = `sub` = `client_id`, `aud` = o issuer como UMA string, curta, com `iat` e `jti` únicos.
213
204
  */
214
- authenticateClient(form: Record<string, unknown>, endpoint: string): Promise<PoppyClient>;
215
- /** `POST token_endpoint` (§4.2, §4.3, §4.5, §4.6, §4.8). */
216
- token(form: Record<string, unknown>, dpopHeader: string | string[] | undefined): Promise<PoppyTokenResponse>;
205
+ authenticateClient(form: Record<string, unknown>): Promise<PoppyClient>;
206
+ /** `POST token_endpoint` (§4.2–§4.4, §4.7, extensão Mediated Sign-In). */
207
+ token(form: Record<string, unknown>, dpopHeader: string | string[] | undefined, ctx?: HttpContext): Promise<PoppyTokenResponse>;
217
208
  /** `POST device_authorization_endpoint` (§4.6). */
218
209
  deviceAuthorization(form: Record<string, unknown>): Promise<Record<string, unknown>>;
219
- /** `POST revocation_endpoint` (§4.9, RFC 7009). */
210
+ /** `POST revocation_endpoint` (§4.6, RFC 7009). */
220
211
  revoke(form: Record<string, unknown>): Promise<void>;
221
212
  /**
222
- * Revoga um Account Token (grant): as Sessions logadas com ele continuam
223
- * deslogadas (§4.9) e os Bearer de MCP no oidc-provider morrem junto.
213
+ * Revoga um refresh token (grant): os access tokens dele morrem junto (RFC 7009 §2.1), as
214
+ * Sessions continuam deslogadas (§5.5) e os Bearer de MCP no oidc-provider também caem.
224
215
  */
225
216
  revokeGrant(grantId: string): Promise<void>;
226
217
  /**
@@ -255,31 +246,47 @@ export declare class PoppyService {
255
246
  approved: string[] | null;
256
247
  clientId: string;
257
248
  } | null>;
258
- /** `POST auth.mediated.endpoint` — já autenticado pelo Session Token (DPoP). */
259
- mediatedStart(principal: PoppyPrincipalBase, jkt: string | null, body: unknown, ctx: HttpContext): Promise<PoppyMediatedResponse>;
260
- /** `POST {mediated}/{sign_in_id}` com o código de uso único. */
261
- mediatedCode(principal: PoppyPrincipalBase, jkt: string | null, signInId: string, body: unknown): Promise<PoppyMediatedResponse | null>;
262
249
  /**
263
- * Verifica `Authorization: DPoP|Bearer` (+ prova DPoP) de uma request a uma API
264
- * ou conversa do app. Nunca lê token da URL (§4.3).
250
+ * Verifica uma request às APIs/conversas do app: o header `Poppy-Session` (§5.3) e, se houver, o
251
+ * access token (`Authorization: Bearer|DPoP`, com a prova DPoP). Um `sid` novo começa uma Session
252
+ * deslogada; a request é logada só quando traz access token. Nunca lê token da URL (§5.6).
265
253
  */
266
254
  verifyAccess(input: PoppyRequestInput, options?: PoppyVerifyOptions): Promise<PoppyVerifyResult>;
255
+ /** Passo 1: gera o código de uso único e o valor do cookie que o prende a este navegador. */
256
+ startBrowserJoin(): Promise<{
257
+ code: string;
258
+ cookie: string;
259
+ maxAge: number;
260
+ }>;
261
+ /**
262
+ * Passo 2: o agente autoriza o código, com o header da Session e, se logado, o access token.
263
+ * `{ ok: true }` = 204; um código inválido lança `invalid_request`.
264
+ */
265
+ authorizeBrowserJoin(input: PoppyRequestInput, code: unknown): Promise<Extract<PoppyVerifyResult, {
266
+ ok: false;
267
+ }> | {
268
+ ok: true;
269
+ }>;
267
270
  /**
268
- * Confere a asserção de navegador (`typ` `poppy-browser+jwt`). `requestOrigin`
269
- * é a origem em que o POST chegou — o cookie precisa nascer nela.
271
+ * Passo 3: o navegador submete o código. O primeiro envio o consome, qualquer que seja o
272
+ * resultado; `null` = sem cookie para a Session (página de erro).
270
273
  */
271
- verifyBrowserAssertion(assertion: unknown, requestOrigin: string): Promise<PoppyBrowserSessionResult>;
272
- /** Estado atual da Session (ativa? logada? scopes) — o cookie do site segue isto. */
273
- sessionState(sessionId: string): Promise<PoppySessionState | null>;
274
+ completeBrowserJoin(code: unknown, cookie: unknown): Promise<PoppyBrowserJoin | null>;
275
+ /** O cookie age pela conta e pelos scopes do passo 2, enquanto o refresh token viver (§6). */
276
+ browserState(marker: {
277
+ sessionId: string;
278
+ accountId?: string | null;
279
+ grantId?: string | null;
280
+ scopes?: string[];
281
+ }): Promise<PoppySessionState | null>;
274
282
  listGrants(accountId: string): Promise<PoppyGrantSummary[]>;
275
- /** Desconectar o agente pela conta (§4.9): revoga um Account Token DA CONTA. */
283
+ /** Desconectar o agente pela conta (§5.5): revoga um refresh token DA CONTA. */
276
284
  revokeAccountGrant(accountId: string, grantId: string): Promise<boolean>;
277
- /** Revoga todos os Account Tokens da conta (sair de tudo, conta suspensa…). */
285
+ /** Revoga todos os refresh tokens da conta (sair de tudo, conta suspensa…). */
278
286
  revokeAllAccountGrants(accountId: string): Promise<number>;
279
287
  /**
280
- * Bloqueio pelo console admin: revoga todos os Account Tokens do agente (todas as
281
- * contas) e encerra as Sessions dele — os Session Tokens param na próxima request.
282
- * Devolve quantos Account Tokens estavam vivos.
288
+ * Bloqueio pelo console admin: revoga todos os refresh tokens do agente (todas as contas) e
289
+ * encerra as Sessions dele — param na próxima request. Devolve quantos estavam vivos.
283
290
  */
284
291
  disconnectClient(clientId: string): Promise<number>;
285
292
  }