@boopkit/cap-oauth-server 0.1.4 → 0.3.1

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 (91) hide show
  1. package/capability.json +14 -2
  2. package/dist/authorization-code-service.d.ts +40 -11
  3. package/dist/authorization-code-service.d.ts.map +1 -1
  4. package/dist/authorization-code-service.js +93 -41
  5. package/dist/authorization-code-service.js.map +1 -1
  6. package/dist/bearer.d.ts +27 -4
  7. package/dist/bearer.d.ts.map +1 -1
  8. package/dist/bearer.js +4 -4
  9. package/dist/bearer.js.map +1 -1
  10. package/dist/client-prune.d.ts +102 -0
  11. package/dist/client-prune.d.ts.map +1 -0
  12. package/dist/client-prune.js +51 -0
  13. package/dist/client-prune.js.map +1 -0
  14. package/dist/client-registry-service.d.ts +85 -8
  15. package/dist/client-registry-service.d.ts.map +1 -1
  16. package/dist/client-registry-service.js +267 -64
  17. package/dist/client-registry-service.js.map +1 -1
  18. package/dist/config.d.ts +6 -0
  19. package/dist/config.d.ts.map +1 -1
  20. package/dist/config.js +1 -0
  21. package/dist/config.js.map +1 -1
  22. package/dist/connections-controller.js +1 -1
  23. package/dist/connections-controller.js.map +1 -1
  24. package/dist/consent-controller.d.ts +80 -6
  25. package/dist/consent-controller.d.ts.map +1 -1
  26. package/dist/consent-controller.js +134 -18
  27. package/dist/consent-controller.js.map +1 -1
  28. package/dist/discovery-controller.d.ts +2 -1
  29. package/dist/discovery-controller.d.ts.map +1 -1
  30. package/dist/discovery-controller.js +14 -4
  31. package/dist/discovery-controller.js.map +1 -1
  32. package/dist/discovery.d.ts +26 -0
  33. package/dist/discovery.d.ts.map +1 -1
  34. package/dist/discovery.js +55 -1
  35. package/dist/discovery.js.map +1 -1
  36. package/dist/errors.d.ts +38 -0
  37. package/dist/errors.d.ts.map +1 -1
  38. package/dist/errors.js +59 -0
  39. package/dist/errors.js.map +1 -1
  40. package/dist/grant-service.d.ts +11 -4
  41. package/dist/grant-service.d.ts.map +1 -1
  42. package/dist/grant-service.js +6 -3
  43. package/dist/grant-service.js.map +1 -1
  44. package/dist/index.d.ts +10 -5
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +18 -3
  47. package/dist/index.js.map +1 -1
  48. package/dist/metadata-document.d.ts +22 -0
  49. package/dist/metadata-document.d.ts.map +1 -1
  50. package/dist/metadata-document.js +44 -2
  51. package/dist/metadata-document.js.map +1 -1
  52. package/dist/outbound-target.d.ts +48 -0
  53. package/dist/outbound-target.d.ts.map +1 -0
  54. package/dist/outbound-target.js +211 -0
  55. package/dist/outbound-target.js.map +1 -0
  56. package/dist/rate-limit.d.ts +53 -11
  57. package/dist/rate-limit.d.ts.map +1 -1
  58. package/dist/rate-limit.js +27 -4
  59. package/dist/rate-limit.js.map +1 -1
  60. package/dist/redirect-uri.d.ts +17 -9
  61. package/dist/redirect-uri.d.ts.map +1 -1
  62. package/dist/redirect-uri.js +26 -10
  63. package/dist/redirect-uri.js.map +1 -1
  64. package/dist/registration-controller.d.ts +10 -0
  65. package/dist/registration-controller.d.ts.map +1 -1
  66. package/dist/registration-controller.js +10 -0
  67. package/dist/registration-controller.js.map +1 -1
  68. package/dist/request-client.d.ts +7 -1
  69. package/dist/request-client.d.ts.map +1 -1
  70. package/dist/request-client.js +31 -13
  71. package/dist/request-client.js.map +1 -1
  72. package/dist/revocation-controller.d.ts +5 -0
  73. package/dist/revocation-controller.d.ts.map +1 -1
  74. package/dist/revocation-controller.js +5 -1
  75. package/dist/revocation-controller.js.map +1 -1
  76. package/dist/same-site.d.ts +54 -0
  77. package/dist/same-site.d.ts.map +1 -0
  78. package/dist/same-site.js +124 -0
  79. package/dist/same-site.js.map +1 -0
  80. package/dist/token-controller.d.ts +26 -0
  81. package/dist/token-controller.d.ts.map +1 -1
  82. package/dist/token-controller.js +44 -19
  83. package/dist/token-controller.js.map +1 -1
  84. package/dist/types.d.ts +4 -0
  85. package/dist/types.d.ts.map +1 -1
  86. package/package.json +2 -2
  87. package/scaffold/reference/oauth-server.ref.md +359 -11
  88. package/scaffold/src/middleware/oauth-server.ts +33 -17
  89. package/scaffold/src/scripts/prune-oauth-clients.ts +86 -0
  90. package/scaffold/src/services/oauth-server.service.ts +24 -0
  91. package/scaffold/views/oauth-consent-error.hbs +10 -3
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createClientInUsePredicate = createClientInUsePredicate;
4
+ exports.createClientPruneJob = createClientPruneJob;
5
+ const client_registry_service_js_1 = require("./client-registry-service.js");
6
+ const grant_service_js_1 = require("./grant-service.js");
7
+ /**
8
+ * The real `isInUse` predicate: is anybody still connected to this client?
9
+ *
10
+ * Suitable for passing straight to `pruneAbandonedClients`. It is `false` for a
11
+ * client nobody ever connected and for one every user has disconnected, and
12
+ * `true` the moment one live grant names the client's `publicId`.
13
+ */
14
+ function createClientInUsePredicate(options) {
15
+ const { grantService, tokenService } = options;
16
+ return async function isInUse(client) {
17
+ const userIds = await tokenService.findUserIdsForClient(client.publicId);
18
+ for (const userId of userIds) {
19
+ const grants = await grantService.list(userId);
20
+ // The full `client_public_id`, never a prefix of it: a `startsWith` here
21
+ // would let a neighbouring client's live grant keep this row alive, which
22
+ // is the same too-broad match `revokeClient` refuses for the same reason.
23
+ const connected = grants.some((grant) => grant.client_public_id === client.publicId && (0, grant_service_js_1.isGrantActive)(grant));
24
+ if (connected)
25
+ return true;
26
+ }
27
+ return false;
28
+ };
29
+ }
30
+ /**
31
+ * The scheduled sweep, as one callable object.
32
+ *
33
+ * A job rather than a loose function because the thing that was missing was a
34
+ * *call site*: a scaffolded application schedules `run()` — from its own cron,
35
+ * from Heroku Scheduler, or from a cap-background-jobs consumer — and the
36
+ * capability owns which rows go and which stay.
37
+ */
38
+ function createClientPruneJob(options) {
39
+ const { clientRegistry } = options;
40
+ const ttlMs = options.ttlMs ?? client_registry_service_js_1.DEFAULT_ABANDONED_CLIENT_TTL_MS;
41
+ const now = options.now ?? (() => new Date());
42
+ const isInUse = createClientInUsePredicate(options);
43
+ return {
44
+ async run() {
45
+ const before = new Date(now().getTime() - ttlMs);
46
+ const removed = await clientRegistry.pruneAbandonedClients({ before, isInUse });
47
+ return { before, removed };
48
+ },
49
+ };
50
+ }
51
+ //# sourceMappingURL=client-prune.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-prune.js","sourceRoot":"","sources":["../src/client-prune.ts"],"names":[],"mappings":";;AA0EA,gEAqBC;AAkCD,oDAaC;AA7ID,6EAA+E;AAC/E,yDAAsE;AAiEtE;;;;;;GAMG;AACH,SAAgB,0BAA0B,CACxC,OAA2B;IAE3B,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IAE/C,OAAO,KAAK,UAAU,OAAO,CAAC,MAAmB;QAC/C,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,oBAAoB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEzE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/C,yEAAyE;YACzE,0EAA0E;YAC1E,0EAA0E;YAC1E,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAC3B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,gBAAgB,KAAK,MAAM,CAAC,QAAQ,IAAI,IAAA,gCAAa,EAAC,KAAK,CAAC,CAC9E,CAAC;YACF,IAAI,SAAS;gBAAE,OAAO,IAAI,CAAC;QAC7B,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AA0BD;;;;;;;GAOG;AACH,SAAgB,oBAAoB,CAAC,OAA2B;IAC9D,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IACnC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,4DAA+B,CAAC;IAC/D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAC;IAEpD,OAAO;QACL,KAAK,CAAC,GAAG;YACP,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAChF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { type FetchLike } from './metadata-document.js';
2
- import type { ClientMetadataInput, OauthClient, OauthClientDelegate, StaticClientInput } from './types.js';
2
+ import type { ClientMetadataInput, ClientMode, OauthClient, OauthClientDelegate, StaticClientInput } from './types.js';
3
3
  /**
4
4
  * The client registry — who is asking, and what they are allowed to ask for.
5
5
  *
@@ -26,6 +26,11 @@ import type { ClientMetadataInput, OauthClient, OauthClientDelegate, StaticClien
26
26
  * `redirect_uris` required and validated at registration, a ceiling on total
27
27
  * rows, per-IP rate limiting at the transport, and a prune for rows that never
28
28
  * went anywhere.
29
+ *
30
+ * All four cover `metadata_document` as well as `dynamic`, because both modes
31
+ * are written on behalf of somebody nobody authenticated. Scoping them to
32
+ * `dynamic` is the shape of boop-jd4x: the CIMD path wrote an uncounted,
33
+ * unlimited, uncollected row per distinct URL a caller named.
29
34
  */
30
35
  /** Sensible RFC 7591 defaults for a client that asked for nothing specific. */
31
36
  export declare const DEFAULT_GRANT_TYPES: string[];
@@ -36,6 +41,22 @@ export declare const DEFAULT_METADATA_MAX_AGE_MS: number;
36
41
  export declare const DEFAULT_ABANDONED_CLIENT_TTL_MS: number;
37
42
  /** How many rows open registration may create before it starts refusing. */
38
43
  export declare const DEFAULT_MAX_REGISTERED_CLIENTS = 1000;
44
+ /**
45
+ * The modes the ceiling and the prune are about: every row a stranger caused.
46
+ *
47
+ * `dynamic` is the obvious one — `POST /oauth/register` is an unauthenticated
48
+ * write. `metadata_document` is the one that was missed, and it is the same
49
+ * thing wearing a different hat: an unauthenticated `GET /oauth/authorize`
50
+ * naming an https `client_id` nobody vetted writes a permanent row too. Scoping
51
+ * the abuse controls to `dynamic` left that path with no ceiling, no limiter and
52
+ * no collector, so a loop over `?client_id=https://attacker.example/c?n=<N>`
53
+ * filled the table one row at a time (boop-jd4x).
54
+ *
55
+ * `static` is deliberately absent. An operator wrote those rows, and letting
56
+ * them consume the ceiling would let an operator's own seed script lock open
57
+ * registration shut.
58
+ */
59
+ export declare const STRANGER_CREATED_MODES: readonly ClientMode[];
39
60
  export interface ClientRegistryServiceOptions {
40
61
  /**
41
62
  * The HTTP boundary for metadata documents. Required only if
@@ -43,22 +64,53 @@ export interface ClientRegistryServiceOptions {
43
64
  * never calls it.
44
65
  */
45
66
  fetch?: FetchLike;
46
- /** Ceiling on `dynamic` rows. `Infinity` disables the check. */
67
+ /**
68
+ * Ceiling on rows a stranger caused — `dynamic` *and* `metadata_document`.
69
+ * `Infinity` disables the check. See `STRANGER_CREATED_MODES`.
70
+ */
47
71
  maxRegisteredClients?: number;
48
72
  /** Cache age past which a metadata document is re-fetched. */
49
73
  metadataMaxAgeMs?: number;
50
74
  metadataTimeoutMs?: number;
51
75
  metadataMaxBytes?: number;
52
76
  metadataMaxRedirects?: number;
77
+ /**
78
+ * Resolve a hostname to the addresses it points at, so that a *name* aimed at
79
+ * the internal network is refused like a literal address is.
80
+ *
81
+ * Optional and injected because this package has no business importing
82
+ * `node:dns` — the scaffold wires `dns.promises.lookup`. Without it the guard
83
+ * still refuses every literal private, loopback and link-local target; with
84
+ * it, `internal.example` resolving to `10.0.0.5` is refused too.
85
+ */
86
+ metadataResolveHost?: (hostname: string) => Promise<string[]>;
53
87
  /** Scopes a client may be granted, if it named none. */
54
88
  defaultScopes?: string[];
89
+ /**
90
+ * Every scope this server advertises — the ceiling on what any registration
91
+ * may claim, whoever wrote it.
92
+ *
93
+ * Registration is unauthenticated, so `scope` on the way in is a string a
94
+ * stranger chose. Storing it unfiltered makes the discovery document's
95
+ * `scopes_supported` untrue and puts an undescribed word in front of a user
96
+ * on the consent screen. Defaults to `defaultScopes`, which for a correctly
97
+ * wired server is the same list; an empty list bounds nothing, which is what
98
+ * a registry built with no scope configuration at all has always done.
99
+ */
100
+ scopesSupported?: string[];
55
101
  /** Injectable clock, so expiry and cache-age tests do not sleep. */
56
102
  now?: () => Date;
57
- /** Called when a re-fetch fails and the cached copy is used instead. */
103
+ /**
104
+ * Called when a re-fetch fails and the cached copy is used instead.
105
+ *
106
+ * Not called for the one re-fetch failure that is thrown to the caller
107
+ * instead: a document that now declares an authentication method without
108
+ * offering `none`. See `resolveMetadataDocument`.
109
+ */
58
110
  onMetadataRefreshFailed?(clientId: string, err: unknown): void;
59
111
  }
60
112
  export interface PruneOptions {
61
- /** Delete abandoned `dynamic` rows created before this instant. */
113
+ /** Delete abandoned stranger-created rows created before this instant. */
62
114
  before?: Date;
63
115
  /**
64
116
  * Is this row still in use?
@@ -91,13 +143,38 @@ export interface ClientRegistryService {
91
143
  suspend(clientId: string): Promise<OauthClient>;
92
144
  /** Re-enable a suspended client. */
93
145
  unsuspend(clientId: string): Promise<OauthClient>;
94
- /** Registration-surface update. Refuses a `static` row. */
146
+ /**
147
+ * Amend a registered client's metadata. Refuses a `static` row.
148
+ *
149
+ * There is no HTTP route behind this and there is not meant to be: RFC 7592
150
+ * client management is deliberately not implemented (see the note on
151
+ * `refuseStatic`). This is the host application's own management API — what
152
+ * an admin screen or a support script calls — and it validates exactly what
153
+ * `registerDynamic` validates, so a client cannot reach a value through an
154
+ * amendment that it could not have registered in the first place.
155
+ */
95
156
  updateRegistration(clientId: string, input: ClientMetadataInput): Promise<OauthClient>;
96
- /** Registration-surface delete. Refuses a `static` row. */
157
+ /**
158
+ * Remove a registered client. Refuses a `static` row.
159
+ *
160
+ * The same host-application surface as `updateRegistration`, and the blunt
161
+ * instrument of the two: it drops the row, and with it the `publicId` that
162
+ * every live token for that client carries as its prefix. Prefer `suspend`
163
+ * for a client that may still have tokens outstanding — see
164
+ * `pruneAbandonedClients`, which asks `isInUse` before deleting anything.
165
+ */
97
166
  deleteRegistration(clientId: string): Promise<void>;
98
- /** How many rows the ceiling counts. */
167
+ /** How many rows the ceiling counts — see `STRANGER_CREATED_MODES`. */
99
168
  countRegistered(): Promise<number>;
100
- /** Garbage-collect abandoned dynamic rows. Returns the client ids removed. */
169
+ /**
170
+ * Garbage-collect abandoned stranger-created rows. Returns the client ids
171
+ * removed.
172
+ *
173
+ * A `metadata_document` row is swept on the same terms as a `dynamic` one.
174
+ * Its metadata is re-fetchable, so re-creating it costs one request; what is
175
+ * not re-creatable is its `publicId`, which is the prefix every live token for
176
+ * that client carries — and that is exactly what `isInUse` is for.
177
+ */
101
178
  pruneAbandonedClients(options?: PruneOptions): Promise<string[]>;
102
179
  }
103
180
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"client-registry-service.d.ts","sourceRoot":"","sources":["../src/client-registry-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client-registry-service.d.ts","sourceRoot":"","sources":["../src/client-registry-service.ts"],"names":[],"mappings":"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"}