@opendatalabs/personal-server-ts-core 1.33.8 → 1.34.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.
- package/dist/additions/budget.d.ts +28 -0
- package/dist/additions/budget.d.ts.map +1 -0
- package/dist/additions/budget.js +119 -0
- package/dist/additions/budget.js.map +1 -0
- package/dist/additions/durable.d.ts +64 -0
- package/dist/additions/durable.d.ts.map +1 -0
- package/dist/additions/durable.js +591 -0
- package/dist/additions/durable.js.map +1 -0
- package/dist/additions/first-added.d.ts +32 -48
- package/dist/additions/first-added.d.ts.map +1 -1
- package/dist/additions/first-added.js +68 -123
- package/dist/additions/first-added.js.map +1 -1
- package/dist/additions/index.d.ts +3 -0
- package/dist/additions/index.d.ts.map +1 -1
- package/dist/additions/index.js +3 -0
- package/dist/additions/index.js.map +1 -1
- package/dist/additions/ledger-store.js +1 -1
- package/dist/additions/record-rules.d.ts.map +1 -1
- package/dist/additions/record-rules.js +7 -0
- package/dist/additions/record-rules.js.map +1 -1
- package/dist/additions/summary.d.ts +88 -1
- package/dist/additions/summary.d.ts.map +1 -1
- package/dist/additions/summary.js +173 -8
- package/dist/additions/summary.js.map +1 -1
- package/dist/additions/version-inventory.d.ts +80 -0
- package/dist/additions/version-inventory.d.ts.map +1 -0
- package/dist/additions/version-inventory.js +232 -0
- package/dist/additions/version-inventory.js.map +1 -0
- package/dist/api/index.d.ts +70 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +506 -79
- package/dist/api/index.js.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/request.d.ts +6 -0
- package/dist/auth/request.d.ts.map +1 -1
- package/dist/auth/request.js +66 -4
- package/dist/auth/request.js.map +1 -1
- package/dist/contracts/data.d.ts +54 -8
- package/dist/contracts/data.d.ts.map +1 -1
- package/dist/contracts/data.js +178 -35
- package/dist/contracts/data.js.map +1 -1
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/derivatives/registration.d.ts +0 -5
- package/dist/derivatives/registration.d.ts.map +1 -1
- package/dist/derivatives/registration.js +2 -1
- package/dist/derivatives/registration.js.map +1 -1
- package/dist/errors/pdpp-catalog.d.ts +36 -0
- package/dist/errors/pdpp-catalog.d.ts.map +1 -0
- package/dist/errors/pdpp-catalog.js +86 -0
- package/dist/errors/pdpp-catalog.js.map +1 -0
- package/dist/grants/index.d.ts +2 -0
- package/dist/grants/index.d.ts.map +1 -1
- package/dist/grants/index.js +4 -0
- package/dist/grants/index.js.map +1 -1
- package/dist/grants/pdpp-binding-store.d.ts +89 -0
- package/dist/grants/pdpp-binding-store.d.ts.map +1 -0
- package/dist/grants/pdpp-binding-store.js +112 -0
- package/dist/grants/pdpp-binding-store.js.map +1 -0
- package/dist/grants/pdpp-binding.d.ts +169 -0
- package/dist/grants/pdpp-binding.d.ts.map +1 -0
- package/dist/grants/pdpp-binding.js +236 -0
- package/dist/grants/pdpp-binding.js.map +1 -0
- package/dist/legacy-projection/bindings.d.ts +28 -1
- package/dist/legacy-projection/bindings.d.ts.map +1 -1
- package/dist/legacy-projection/bindings.js +622 -189
- package/dist/legacy-projection/bindings.js.map +1 -1
- package/dist/legacy-projection/claude-source-record.d.ts +22 -0
- package/dist/legacy-projection/claude-source-record.d.ts.map +1 -0
- package/dist/legacy-projection/claude-source-record.js +360 -0
- package/dist/legacy-projection/claude-source-record.js.map +1 -0
- package/dist/legacy-projection/declared-text.d.ts +41 -0
- package/dist/legacy-projection/declared-text.d.ts.map +1 -0
- package/dist/legacy-projection/declared-text.js +199 -0
- package/dist/legacy-projection/declared-text.js.map +1 -0
- package/dist/legacy-projection/github-browser-bindings.d.ts.map +1 -1
- package/dist/legacy-projection/github-browser-bindings.js +89 -5
- package/dist/legacy-projection/github-browser-bindings.js.map +1 -1
- package/dist/legacy-projection/github-legacy-fields.d.ts +6 -0
- package/dist/legacy-projection/github-legacy-fields.d.ts.map +1 -0
- package/dist/legacy-projection/github-legacy-fields.js +202 -0
- package/dist/legacy-projection/github-legacy-fields.js.map +1 -0
- package/dist/legacy-projection/index.d.ts +5 -1
- package/dist/legacy-projection/index.d.ts.map +1 -1
- package/dist/legacy-projection/index.js +55 -1
- package/dist/legacy-projection/index.js.map +1 -1
- package/dist/legacy-projection/oura-browser-bindings.d.ts.map +1 -1
- package/dist/legacy-projection/oura-browser-bindings.js +43 -41
- package/dist/legacy-projection/oura-browser-bindings.js.map +1 -1
- package/dist/legacy-projection/types.d.ts +38 -2
- package/dist/legacy-projection/types.d.ts.map +1 -1
- package/dist/mcp/read-client.d.ts.map +1 -1
- package/dist/mcp/read-client.js +10 -1
- package/dist/mcp/read-client.js.map +1 -1
- package/dist/mcp/resources.d.ts.map +1 -1
- package/dist/mcp/resources.js +3 -0
- package/dist/mcp/resources.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +11 -2
- package/dist/mcp/tools.js.map +1 -1
- package/dist/pdpp/approval.d.ts +271 -0
- package/dist/pdpp/approval.d.ts.map +1 -0
- package/dist/pdpp/approval.js +467 -0
- package/dist/pdpp/approval.js.map +1 -0
- package/dist/pdpp/client-identity.d.ts +88 -0
- package/dist/pdpp/client-identity.d.ts.map +1 -0
- package/dist/pdpp/client-identity.js +196 -0
- package/dist/pdpp/client-identity.js.map +1 -0
- package/dist/pdpp/client-metadata.d.ts +95 -0
- package/dist/pdpp/client-metadata.d.ts.map +1 -0
- package/dist/pdpp/client-metadata.js +96 -0
- package/dist/pdpp/client-metadata.js.map +1 -0
- package/dist/pdpp/commitments.d.ts +75 -0
- package/dist/pdpp/commitments.d.ts.map +1 -0
- package/dist/pdpp/commitments.js +113 -0
- package/dist/pdpp/commitments.js.map +1 -0
- package/dist/pdpp/declaration.d.ts +118 -0
- package/dist/pdpp/declaration.d.ts.map +1 -0
- package/dist/pdpp/declaration.js +836 -0
- package/dist/pdpp/declaration.js.map +1 -0
- package/dist/pdpp/index.d.ts +37 -0
- package/dist/pdpp/index.d.ts.map +1 -0
- package/dist/pdpp/index.js +23 -0
- package/dist/pdpp/index.js.map +1 -0
- package/dist/pdpp/issuance.d.ts +126 -0
- package/dist/pdpp/issuance.d.ts.map +1 -0
- package/dist/pdpp/issuance.js +180 -0
- package/dist/pdpp/issuance.js.map +1 -0
- package/dist/pdpp/pkce.d.ts +53 -0
- package/dist/pdpp/pkce.d.ts.map +1 -0
- package/dist/pdpp/pkce.js +109 -0
- package/dist/pdpp/pkce.js.map +1 -0
- package/dist/pdpp/redirect.d.ts +60 -0
- package/dist/pdpp/redirect.d.ts.map +1 -0
- package/dist/pdpp/redirect.js +125 -0
- package/dist/pdpp/redirect.js.map +1 -0
- package/dist/pdpp/resolve.d.ts +109 -0
- package/dist/pdpp/resolve.d.ts.map +1 -0
- package/dist/pdpp/resolve.js +393 -0
- package/dist/pdpp/resolve.js.map +1 -0
- package/dist/pdpp/review.d.ts +280 -0
- package/dist/pdpp/review.d.ts.map +1 -0
- package/dist/pdpp/review.js +205 -0
- package/dist/pdpp/review.js.map +1 -0
- package/dist/pdpp/selection.d.ts +50 -0
- package/dist/pdpp/selection.d.ts.map +1 -0
- package/dist/pdpp/selection.js +442 -0
- package/dist/pdpp/selection.js.map +1 -0
- package/dist/pdpp/store.d.ts +228 -0
- package/dist/pdpp/store.d.ts.map +1 -0
- package/dist/pdpp/store.js +542 -0
- package/dist/pdpp/store.js.map +1 -0
- package/dist/pdpp/tokens.d.ts +181 -0
- package/dist/pdpp/tokens.d.ts.map +1 -0
- package/dist/pdpp/tokens.js +419 -0
- package/dist/pdpp/tokens.js.map +1 -0
- package/dist/pdpp/types.d.ts +441 -0
- package/dist/pdpp/types.d.ts.map +1 -0
- package/dist/pdpp/types.js +61 -0
- package/dist/pdpp/types.js.map +1 -0
- package/dist/pdpp-version.d.ts +28 -0
- package/dist/pdpp-version.d.ts.map +1 -0
- package/dist/pdpp-version.js +28 -0
- package/dist/pdpp-version.js.map +1 -0
- package/dist/policy/data-read.d.ts +24 -0
- package/dist/policy/data-read.d.ts.map +1 -1
- package/dist/policy/data-read.js +60 -3
- package/dist/policy/data-read.js.map +1 -1
- package/dist/policy/data-write.d.ts.map +1 -1
- package/dist/policy/data-write.js +3 -0
- package/dist/policy/data-write.js.map +1 -1
- package/dist/policy/index.d.ts +1 -0
- package/dist/policy/index.d.ts.map +1 -1
- package/dist/policy/index.js +1 -0
- package/dist/policy/index.js.map +1 -1
- package/dist/policy/reserved-scopes.d.ts +3 -0
- package/dist/policy/reserved-scopes.d.ts.map +1 -0
- package/dist/policy/reserved-scopes.js +5 -0
- package/dist/policy/reserved-scopes.js.map +1 -0
- package/dist/ports/index.d.ts +63 -0
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/pdpp-auth.d.ts +129 -0
- package/dist/ports/pdpp-auth.d.ts.map +1 -0
- package/dist/ports/pdpp-auth.js +60 -0
- package/dist/ports/pdpp-auth.js.map +1 -0
- package/dist/ports/pdpp-auth.test-utils.d.ts +9 -0
- package/dist/ports/pdpp-auth.test-utils.d.ts.map +1 -0
- package/dist/ports/pdpp-auth.test-utils.js +18 -0
- package/dist/ports/pdpp-auth.test-utils.js.map +1 -0
- package/dist/schemas/server-config.d.ts +44 -0
- package/dist/schemas/server-config.d.ts.map +1 -1
- package/dist/schemas/server-config.js +91 -0
- package/dist/schemas/server-config.js.map +1 -1
- package/dist/signing/request-signer.d.ts +2 -0
- package/dist/signing/request-signer.d.ts.map +1 -1
- package/dist/signing/request-signer.js +1 -0
- package/dist/signing/request-signer.js.map +1 -1
- package/dist/storage/adapters/interface.d.ts +3 -0
- package/dist/storage/adapters/interface.d.ts.map +1 -1
- package/dist/storage/adapters/vana-audience.d.ts +12 -0
- package/dist/storage/adapters/vana-audience.d.ts.map +1 -0
- package/dist/storage/adapters/vana-audience.js +72 -0
- package/dist/storage/adapters/vana-audience.js.map +1 -0
- package/dist/storage/adapters/vana.d.ts +2 -0
- package/dist/storage/adapters/vana.d.ts.map +1 -1
- package/dist/storage/adapters/vana.js +53 -20
- package/dist/storage/adapters/vana.js.map +1 -1
- package/dist/storage/canonical-legacy-projection.d.ts +262 -0
- package/dist/storage/canonical-legacy-projection.d.ts.map +1 -0
- package/dist/storage/canonical-legacy-projection.js +761 -0
- package/dist/storage/canonical-legacy-projection.js.map +1 -0
- package/dist/storage/index/manager.d.ts +29 -2
- package/dist/storage/index/manager.d.ts.map +1 -1
- package/dist/storage/index/schema.d.ts +1 -1
- package/dist/storage/index/schema.js +1 -1
- package/dist/storage/index/types.d.ts +7 -1
- package/dist/storage/index/types.d.ts.map +1 -1
- package/dist/storage/legacy-projection.d.ts +13 -10
- package/dist/storage/legacy-projection.d.ts.map +1 -1
- package/dist/storage/legacy-projection.js +269 -74
- package/dist/storage/legacy-projection.js.map +1 -1
- package/dist/storage/legacy-scope-coverage-exceptions.d.ts +8 -0
- package/dist/storage/legacy-scope-coverage-exceptions.d.ts.map +1 -0
- package/dist/storage/legacy-scope-coverage-exceptions.js +10 -0
- package/dist/storage/legacy-scope-coverage-exceptions.js.map +1 -0
- package/dist/storage/legacy-scope-coverage.d.ts +53 -0
- package/dist/storage/legacy-scope-coverage.d.ts.map +1 -0
- package/dist/storage/legacy-scope-coverage.js +403 -0
- package/dist/storage/legacy-scope-coverage.js.map +1 -0
- package/dist/storage/legacy-scope-entity-keys.d.ts +4 -0
- package/dist/storage/legacy-scope-entity-keys.d.ts.map +1 -0
- package/dist/storage/legacy-scope-entity-keys.js +92 -0
- package/dist/storage/legacy-scope-entity-keys.js.map +1 -0
- package/dist/storage/legacy-scope-view.d.ts +154 -0
- package/dist/storage/legacy-scope-view.d.ts.map +1 -0
- package/dist/storage/legacy-scope-view.js +735 -0
- package/dist/storage/legacy-scope-view.js.map +1 -0
- package/dist/storage/pdpp-records/completion.d.ts +91 -0
- package/dist/storage/pdpp-records/completion.d.ts.map +1 -0
- package/dist/storage/pdpp-records/completion.js +170 -0
- package/dist/storage/pdpp-records/completion.js.map +1 -0
- package/dist/storage/pdpp-records/cursor.d.ts +41 -0
- package/dist/storage/pdpp-records/cursor.d.ts.map +1 -0
- package/dist/storage/pdpp-records/cursor.js +49 -0
- package/dist/storage/pdpp-records/cursor.js.map +1 -0
- package/dist/storage/pdpp-records/declaration-witness.d.ts +58 -0
- package/dist/storage/pdpp-records/declaration-witness.d.ts.map +1 -0
- package/dist/storage/pdpp-records/declaration-witness.js +230 -0
- package/dist/storage/pdpp-records/declaration-witness.js.map +1 -0
- package/dist/storage/pdpp-records/enforcement.d.ts +52 -0
- package/dist/storage/pdpp-records/enforcement.d.ts.map +1 -0
- package/dist/storage/pdpp-records/enforcement.js +116 -0
- package/dist/storage/pdpp-records/enforcement.js.map +1 -0
- package/dist/storage/pdpp-records/index.d.ts +5 -0
- package/dist/storage/pdpp-records/index.d.ts.map +1 -0
- package/dist/storage/pdpp-records/index.js +5 -0
- package/dist/storage/pdpp-records/index.js.map +1 -0
- package/dist/storage/pdpp-records/ingest-plan.d.ts +39 -0
- package/dist/storage/pdpp-records/ingest-plan.d.ts.map +1 -0
- package/dist/storage/pdpp-records/ingest-plan.js +103 -0
- package/dist/storage/pdpp-records/ingest-plan.js.map +1 -0
- package/dist/storage/pdpp-records/interface.d.ts +104 -0
- package/dist/storage/pdpp-records/interface.d.ts.map +1 -0
- package/dist/storage/pdpp-records/interface.js +2 -0
- package/dist/storage/pdpp-records/interface.js.map +1 -0
- package/dist/storage/pdpp-records/memory-store.d.ts +9 -0
- package/dist/storage/pdpp-records/memory-store.d.ts.map +1 -0
- package/dist/storage/pdpp-records/memory-store.js +466 -0
- package/dist/storage/pdpp-records/memory-store.js.map +1 -0
- package/dist/storage/pdpp-records/portable.d.ts +9 -0
- package/dist/storage/pdpp-records/portable.d.ts.map +1 -0
- package/dist/storage/pdpp-records/portable.js +8 -0
- package/dist/storage/pdpp-records/portable.js.map +1 -0
- package/dist/storage/pdpp-records/read-port.d.ts +44 -0
- package/dist/storage/pdpp-records/read-port.d.ts.map +1 -0
- package/dist/storage/pdpp-records/read-port.js +22 -0
- package/dist/storage/pdpp-records/read-port.js.map +1 -0
- package/dist/storage/pdpp-records/record-key.d.ts +52 -0
- package/dist/storage/pdpp-records/record-key.d.ts.map +1 -0
- package/dist/storage/pdpp-records/record-key.js +97 -0
- package/dist/storage/pdpp-records/record-key.js.map +1 -0
- package/dist/storage/pdpp-records/schema.d.ts +41 -0
- package/dist/storage/pdpp-records/schema.d.ts.map +1 -0
- package/dist/storage/pdpp-records/schema.js +153 -0
- package/dist/storage/pdpp-records/schema.js.map +1 -0
- package/dist/storage/pdpp-records/stream-declaration.d.ts +88 -0
- package/dist/storage/pdpp-records/stream-declaration.d.ts.map +1 -0
- package/dist/storage/pdpp-records/stream-declaration.js +57 -0
- package/dist/storage/pdpp-records/stream-declaration.js.map +1 -0
- package/dist/storage/pdpp-records/types.d.ts +138 -0
- package/dist/storage/pdpp-records/types.d.ts.map +1 -0
- package/dist/storage/pdpp-records/types.js +38 -0
- package/dist/storage/pdpp-records/types.js.map +1 -0
- package/dist/sync/data-point-feed.d.ts +3 -0
- package/dist/sync/data-point-feed.d.ts.map +1 -1
- package/dist/sync/data-point-feed.js +17 -1
- package/dist/sync/data-point-feed.js.map +1 -1
- package/dist/sync/delete-data-port.d.ts +2 -0
- package/dist/sync/delete-data-port.d.ts.map +1 -1
- package/dist/sync/delete-data-port.js +1 -1
- package/dist/sync/delete-data-port.js.map +1 -1
- package/dist/sync/engine/sync-manager.d.ts.map +1 -1
- package/dist/sync/engine/sync-manager.js +5 -2
- package/dist/sync/engine/sync-manager.js.map +1 -1
- package/dist/sync/index.d.ts +3 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +4 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/pdpp-import.d.ts +192 -0
- package/dist/sync/pdpp-import.d.ts.map +1 -0
- package/dist/sync/pdpp-import.js +441 -0
- package/dist/sync/pdpp-import.js.map +1 -0
- package/dist/sync/scope-deletions.d.ts +10 -0
- package/dist/sync/scope-deletions.d.ts.map +1 -1
- package/dist/sync/scope-deletions.js +40 -7
- package/dist/sync/scope-deletions.js.map +1 -1
- package/dist/sync/workers/download.d.ts +14 -0
- package/dist/sync/workers/download.d.ts.map +1 -1
- package/dist/sync/workers/download.js +149 -13
- package/dist/sync/workers/download.js.map +1 -1
- package/dist/sync/workers/upload.d.ts +2 -0
- package/dist/sync/workers/upload.d.ts.map +1 -1
- package/dist/sync/workers/upload.js +7 -0
- package/dist/sync/workers/upload.js.map +1 -1
- package/dist/test-utils/memory-storage.d.ts +1 -1
- package/dist/test-utils/memory-storage.d.ts.map +1 -1
- package/dist/test-utils/memory-storage.js +11 -5
- package/dist/test-utils/memory-storage.js.map +1 -1
- package/package.json +54 -4
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redirect URI validation (RFC 6749 §3.1.2, §10.6; RFC 8252 §7.3).
|
|
3
|
+
*
|
|
4
|
+
* The authorization code travels to the client in this redirect. If the AS
|
|
5
|
+
* honours whatever `redirect_uri` a caller supplies, the attack is direct: an
|
|
6
|
+
* attacker opens an authorization session pointing at their own host, the
|
|
7
|
+
* owner sees a consent screen that looks entirely legitimate (it is — the AS
|
|
8
|
+
* generated it), approves, and the code is delivered to the attacker.
|
|
9
|
+
*
|
|
10
|
+
* **PKCE does not mitigate this.** PKCE binds the code to whoever chose the
|
|
11
|
+
* challenge, and in this attack that is the attacker. They hold the matching
|
|
12
|
+
* verifier, so they redeem the stolen code and receive a grant-bound token
|
|
13
|
+
* over the owner's personal data. Code interception and code *misdelivery* are
|
|
14
|
+
* different problems; §10.6 is the one that covers misdelivery.
|
|
15
|
+
*
|
|
16
|
+
* Validation is by exact match against the client's registered redirect URIs.
|
|
17
|
+
* RFC 6749 §3.1.2.2 requires registration, and §3.1.2.3 allows fuzzier
|
|
18
|
+
* matching only for clients that registered a full URI — we do not take that
|
|
19
|
+
* latitude. Prefix or subdomain matching is where open-redirect bugs live: a
|
|
20
|
+
* registered `https://app.example.com/cb` "matching"
|
|
21
|
+
* `https://app.example.com.evil.test/cb` or `https://app.example.com/cb/../x`
|
|
22
|
+
* is the classic failure. Exact string equality after normalization has no
|
|
23
|
+
* such edge, and the cost is that a client registers each callback it uses.
|
|
24
|
+
*/
|
|
25
|
+
export type RedirectFailureCode = "unregistered_redirect_uri" | "insecure_redirect_uri" | "malformed_redirect_uri" | "no_registered_redirect_uris";
|
|
26
|
+
export interface RedirectFailure {
|
|
27
|
+
code: RedirectFailureCode;
|
|
28
|
+
message: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Registered metadata for a client, as the deployment holds it.
|
|
32
|
+
*
|
|
33
|
+
* `redirect_uris` is required and non-empty for the code flow: a client with
|
|
34
|
+
* no registered callback cannot safely receive a code, and defaulting to
|
|
35
|
+
* "accept anything" would reintroduce exactly the hole this module closes.
|
|
36
|
+
*/
|
|
37
|
+
export interface RegisteredRedirectPolicy {
|
|
38
|
+
client_id: string;
|
|
39
|
+
redirect_uris: string[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Validate a requested redirect URI against the client's registered set.
|
|
43
|
+
*
|
|
44
|
+
* Returns null when the URI is acceptable. Every rejection is deliberately
|
|
45
|
+
* the same shape, so a caller probing for registered URIs learns only that
|
|
46
|
+
* theirs was not one.
|
|
47
|
+
*/
|
|
48
|
+
export declare function validateRedirectUri(requested: string | undefined, policy: RegisteredRedirectPolicy | null): RedirectFailure | null;
|
|
49
|
+
/**
|
|
50
|
+
* Whether a redirect failure may be reported *by redirecting*.
|
|
51
|
+
*
|
|
52
|
+
* RFC 6749 §4.1.2.1 is explicit: when the redirect URI is invalid or
|
|
53
|
+
* unregistered, the AS MUST NOT automatically redirect the user-agent to it.
|
|
54
|
+
* Doing so would turn the authorization endpoint into an open redirector and
|
|
55
|
+
* would hand the attacker the error response they were fishing for. Every
|
|
56
|
+
* failure from `validateRedirectUri` is therefore reported directly to the
|
|
57
|
+
* caller and never as a redirect.
|
|
58
|
+
*/
|
|
59
|
+
export declare const REDIRECT_FAILURES_ARE_NEVER_REDIRECTED: true;
|
|
60
|
+
//# sourceMappingURL=redirect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../../src/pdpp/redirect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,MAAM,MAAM,mBAAmB,GAC3B,2BAA2B,GAC3B,uBAAuB,GACvB,wBAAwB,GACxB,6BAA6B,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAmBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,wBAAwB,GAAG,IAAI,GACtC,eAAe,GAAG,IAAI,CAqExB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,sCAAsC,EAAG,IAAa,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redirect URI validation (RFC 6749 §3.1.2, §10.6; RFC 8252 §7.3).
|
|
3
|
+
*
|
|
4
|
+
* The authorization code travels to the client in this redirect. If the AS
|
|
5
|
+
* honours whatever `redirect_uri` a caller supplies, the attack is direct: an
|
|
6
|
+
* attacker opens an authorization session pointing at their own host, the
|
|
7
|
+
* owner sees a consent screen that looks entirely legitimate (it is — the AS
|
|
8
|
+
* generated it), approves, and the code is delivered to the attacker.
|
|
9
|
+
*
|
|
10
|
+
* **PKCE does not mitigate this.** PKCE binds the code to whoever chose the
|
|
11
|
+
* challenge, and in this attack that is the attacker. They hold the matching
|
|
12
|
+
* verifier, so they redeem the stolen code and receive a grant-bound token
|
|
13
|
+
* over the owner's personal data. Code interception and code *misdelivery* are
|
|
14
|
+
* different problems; §10.6 is the one that covers misdelivery.
|
|
15
|
+
*
|
|
16
|
+
* Validation is by exact match against the client's registered redirect URIs.
|
|
17
|
+
* RFC 6749 §3.1.2.2 requires registration, and §3.1.2.3 allows fuzzier
|
|
18
|
+
* matching only for clients that registered a full URI — we do not take that
|
|
19
|
+
* latitude. Prefix or subdomain matching is where open-redirect bugs live: a
|
|
20
|
+
* registered `https://app.example.com/cb` "matching"
|
|
21
|
+
* `https://app.example.com.evil.test/cb` or `https://app.example.com/cb/../x`
|
|
22
|
+
* is the classic failure. Exact string equality after normalization has no
|
|
23
|
+
* such edge, and the cost is that a client registers each callback it uses.
|
|
24
|
+
*/
|
|
25
|
+
/** Loopback hosts, where RFC 8252 §7.3 permits plain http for native apps. */
|
|
26
|
+
const LOOPBACK_HOSTS = new Set(["127.0.0.1", "[::1]", "::1", "localhost"]);
|
|
27
|
+
/**
|
|
28
|
+
* Normalize for comparison without loosening the match.
|
|
29
|
+
*
|
|
30
|
+
* `URL` resolves dot-segments and lowercases scheme and host, so
|
|
31
|
+
* `https://App.Example.com/cb/../cb` and `https://app.example.com/cb` compare
|
|
32
|
+
* equal — that is canonicalization, not fuzzy matching. Query and fragment are
|
|
33
|
+
* preserved, because a registered URI that carries a query is a different
|
|
34
|
+
* endpoint from one that does not.
|
|
35
|
+
*/
|
|
36
|
+
function normalize(raw) {
|
|
37
|
+
try {
|
|
38
|
+
return new URL(raw);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Validate a requested redirect URI against the client's registered set.
|
|
46
|
+
*
|
|
47
|
+
* Returns null when the URI is acceptable. Every rejection is deliberately
|
|
48
|
+
* the same shape, so a caller probing for registered URIs learns only that
|
|
49
|
+
* theirs was not one.
|
|
50
|
+
*/
|
|
51
|
+
export function validateRedirectUri(requested, policy) {
|
|
52
|
+
if (!requested || requested.length === 0) {
|
|
53
|
+
return {
|
|
54
|
+
code: "malformed_redirect_uri",
|
|
55
|
+
message: "redirect_uri is required",
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const url = normalize(requested);
|
|
59
|
+
if (!url) {
|
|
60
|
+
return {
|
|
61
|
+
code: "malformed_redirect_uri",
|
|
62
|
+
message: "redirect_uri is not a valid absolute URI",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// RFC 6749 §3.1.2: the endpoint URI MUST NOT include a fragment. A fragment
|
|
66
|
+
// is also how a target gets smuggled past a naive prefix check.
|
|
67
|
+
if (url.hash.length > 0) {
|
|
68
|
+
return {
|
|
69
|
+
code: "malformed_redirect_uri",
|
|
70
|
+
message: "redirect_uri must not include a fragment component",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// Scheme gate before anything else. `javascript:` and `data:` are the
|
|
74
|
+
// XSS-on-redirect shapes; everything non-http(s) is refused outright rather
|
|
75
|
+
// than enumerated, so a scheme nobody thought of is refused by default.
|
|
76
|
+
const isLoopback = LOOPBACK_HOSTS.has(url.hostname);
|
|
77
|
+
if (url.protocol === "http:") {
|
|
78
|
+
// RFC 8252 §7.3: loopback http is the native-app redirect, and is fine.
|
|
79
|
+
if (!isLoopback) {
|
|
80
|
+
return {
|
|
81
|
+
code: "insecure_redirect_uri",
|
|
82
|
+
message: "redirect_uri must use https except for loopback addresses",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else if (url.protocol !== "https:") {
|
|
87
|
+
return {
|
|
88
|
+
code: "insecure_redirect_uri",
|
|
89
|
+
message: `redirect_uri scheme '${url.protocol}' is not permitted`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (!policy || policy.redirect_uris.length === 0) {
|
|
93
|
+
// No registration means no safe target. Failing closed here is the whole
|
|
94
|
+
// point: an AS that falls back to "trust the request" when it has no
|
|
95
|
+
// policy has no policy.
|
|
96
|
+
return {
|
|
97
|
+
code: "no_registered_redirect_uris",
|
|
98
|
+
message: "client has no registered redirect URIs; register one before requesting authorization",
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// Exact match after canonicalization. No prefix, no subdomain, no wildcard.
|
|
102
|
+
const matched = policy.redirect_uris.some((candidate) => {
|
|
103
|
+
const registered = normalize(candidate);
|
|
104
|
+
return registered !== null && registered.toString() === url.toString();
|
|
105
|
+
});
|
|
106
|
+
if (!matched) {
|
|
107
|
+
return {
|
|
108
|
+
code: "unregistered_redirect_uri",
|
|
109
|
+
message: "redirect_uri does not exactly match a registered redirect URI",
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Whether a redirect failure may be reported *by redirecting*.
|
|
116
|
+
*
|
|
117
|
+
* RFC 6749 §4.1.2.1 is explicit: when the redirect URI is invalid or
|
|
118
|
+
* unregistered, the AS MUST NOT automatically redirect the user-agent to it.
|
|
119
|
+
* Doing so would turn the authorization endpoint into an open redirector and
|
|
120
|
+
* would hand the attacker the error response they were fishing for. Every
|
|
121
|
+
* failure from `validateRedirectUri` is therefore reported directly to the
|
|
122
|
+
* caller and never as a redirect.
|
|
123
|
+
*/
|
|
124
|
+
export const REDIRECT_FAILURES_ARE_NEVER_REDIRECTED = true;
|
|
125
|
+
//# sourceMappingURL=redirect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect.js","sourceRoot":"","sources":["../../src/pdpp/redirect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,8EAA8E;AAC9E,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC;AAyB3E;;;;;;;;GAQG;AACH,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAA6B,EAC7B,MAAuC;IAEvC,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzC,OAAO;YACL,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,0BAA0B;SACpC,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;YACL,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,0CAA0C;SACpD,CAAC;IACJ,CAAC;IAED,4EAA4E;IAC5E,gEAAgE;IAChE,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,oDAAoD;SAC9D,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,4EAA4E;IAC5E,wEAAwE;IACxE,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpD,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC7B,wEAAwE;QACxE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO;gBACL,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,2DAA2D;aACrE,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO;YACL,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,wBAAwB,GAAG,CAAC,QAAQ,oBAAoB;SAClE,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjD,yEAAyE;QACzE,qEAAqE;QACrE,wBAAwB;QACxB,OAAO;YACL,IAAI,EAAE,6BAA6B;YACnC,OAAO,EACL,sFAAsF;SACzF,CAAC;IACJ,CAAC;IAED,4EAA4E;IAC5E,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;QACtD,MAAM,UAAU,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QACxC,OAAO,UAAU,KAAK,IAAI,IAAI,UAAU,CAAC,QAAQ,EAAE,KAAK,GAAG,CAAC,QAAQ,EAAE,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,IAAI,EAAE,2BAA2B;YACjC,OAAO,EAAE,+DAA+D;SACzE,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAG,IAAa,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PDPP Core §6→§7 resolution: turn a validated selection request into the
|
|
3
|
+
* explicit grant facts that get frozen at issuance.
|
|
4
|
+
*
|
|
5
|
+
* Every request-only convenience dies here. Wildcards and presets expand to
|
|
6
|
+
* concrete stream rows, views resolve to field lists, omitted fields become
|
|
7
|
+
* the declaration's full field set, omitted instance handles resolve against
|
|
8
|
+
* the owner's connection inventory, and `time_range` freezes against the
|
|
9
|
+
* declaration's `consent_time_field`. §7 is explicit that none of these
|
|
10
|
+
* conveniences are continuing authority in the grant — the RS must never have
|
|
11
|
+
* to resolve anything, which is also what the AS→RS contract promises.
|
|
12
|
+
*
|
|
13
|
+
* Resolution runs against the same retained snapshot `selection.ts` validated
|
|
14
|
+
* against. Passing a newer declaration here is the bug §9 AS item 16 exists to
|
|
15
|
+
* prevent: it would let a later declaration widen an in-flight authorization.
|
|
16
|
+
*/
|
|
17
|
+
import { type DeclarationSnapshot, type RequestedStream, type SelectionRequest, type StreamGrant, type StreamRequest, type TimeRange } from "./types.js";
|
|
18
|
+
/**
|
|
19
|
+
* The owner's v0.2 narrowing decisions, keyed by stream name.
|
|
20
|
+
*
|
|
21
|
+
* Every member narrows and none widens. That is enforced by intersection
|
|
22
|
+
* rather than by trust: a choice is applied against the request's own upper
|
|
23
|
+
* limit, so a caller that forwards a tampered choice gets the ceiling, not an
|
|
24
|
+
* escalation. Instance picks stay where they already are — overlaid onto the
|
|
25
|
+
* `InstanceInventory` — because they narrow *eligibility*, which is owner
|
|
26
|
+
* state rather than request shape.
|
|
27
|
+
*
|
|
28
|
+
* Ignored entirely for a v0.1 request: that revision defines no narrowing
|
|
29
|
+
* step, and a v0.1 client's grant must be the same one it has always had.
|
|
30
|
+
*/
|
|
31
|
+
export interface OwnerChoices {
|
|
32
|
+
/** Streams the owner removed. Only an `optional` stream may appear. */
|
|
33
|
+
declined_streams?: string[];
|
|
34
|
+
/** Per-stream field narrowing, intersected with the requested allowlist. */
|
|
35
|
+
fields?: Record<string, string[]>;
|
|
36
|
+
/** Per-stream window narrowing, clamped into the requested window. */
|
|
37
|
+
time_ranges?: Record<string, TimeRange>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The owner's connected instances for a source, as the AS knows them at
|
|
41
|
+
* resolution time. §6 is strict that omitting `instance_ids` never means
|
|
42
|
+
* fan-in: the AS resolves exactly one eligible handle or requires an explicit
|
|
43
|
+
* owner choice.
|
|
44
|
+
*/
|
|
45
|
+
export interface InstanceInventory {
|
|
46
|
+
/** Eligible opaque handles for a given stream, in the owner's connection state. */
|
|
47
|
+
eligibleFor(streamName: string): string[];
|
|
48
|
+
}
|
|
49
|
+
export type ResolutionFailureCode = "unknown_stream" | "unknown_instance" | "instance_choice_required" | "no_eligible_instance" | "unknown_view" | "empty_field_set"
|
|
50
|
+
/** v0.2: a required stream's explicit minimum cannot be satisfied. */
|
|
51
|
+
| "minimum_not_met"
|
|
52
|
+
/** v0.2: the owner declined a stream the request marks `required`. */
|
|
53
|
+
| "required_stream_declined"
|
|
54
|
+
/** v0.2: nothing survived the owner's choices. No empty grants. */
|
|
55
|
+
| "no_streams_approved";
|
|
56
|
+
export interface ResolutionFailure {
|
|
57
|
+
code: ResolutionFailureCode;
|
|
58
|
+
message: string;
|
|
59
|
+
/** The stream that could not be resolved, when the failure is stream-scoped. */
|
|
60
|
+
stream?: string;
|
|
61
|
+
/** For `instance_choice_required`: the handles the owner must choose between. */
|
|
62
|
+
candidates?: string[];
|
|
63
|
+
}
|
|
64
|
+
export type ResolutionResult = {
|
|
65
|
+
ok: true;
|
|
66
|
+
streams: StreamGrant[];
|
|
67
|
+
/**
|
|
68
|
+
* v0.2: optional streams the owner removed, or whose minimum their
|
|
69
|
+
* narrowing could not meet. Present only when non-empty, and only for
|
|
70
|
+
* v0.2 — an omitted stream is not a grant and must never read as
|
|
71
|
+
* authorized, so it travels beside the approved streams rather than in
|
|
72
|
+
* them.
|
|
73
|
+
*/
|
|
74
|
+
omittedStreams?: string[];
|
|
75
|
+
/**
|
|
76
|
+
* v0.2: the requested upper limits, so the grant can record what was
|
|
77
|
+
* asked for beside what was approved.
|
|
78
|
+
*/
|
|
79
|
+
requestedStreams?: RequestedStream[];
|
|
80
|
+
} | {
|
|
81
|
+
ok: false;
|
|
82
|
+
failure: ResolutionFailure;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Expand the request's stream selections into the concrete list to resolve.
|
|
86
|
+
*
|
|
87
|
+
* A wildcard entry fans out to every declared stream, carrying its own
|
|
88
|
+
* per-stream parameters with it — §6 says a wildcard's `instance_ids` apply to
|
|
89
|
+
* every expanded stream, and each handle is then verified per stream by
|
|
90
|
+
* `resolveInstances`. A preset expands from the snapshot instead.
|
|
91
|
+
*
|
|
92
|
+
* Exported because the consent surface must expand a request the same way
|
|
93
|
+
* resolution does. `approval.ts` collects the owner's pending instance
|
|
94
|
+
* choices over these expanded streams; when it derived its own list from
|
|
95
|
+
* `request.streams` alone, a `selection_preset` expanded to nothing there and
|
|
96
|
+
* to two eligible instances here, so the owner was never asked and the
|
|
97
|
+
* request died as unresolvable. One expansion, two readers.
|
|
98
|
+
*/
|
|
99
|
+
export declare function expandSelections(request: SelectionRequest, snapshot: DeclarationSnapshot): StreamRequest[];
|
|
100
|
+
/**
|
|
101
|
+
* Resolve every enforcement axis for a validated selection request.
|
|
102
|
+
*
|
|
103
|
+
* Call this before showing the final approval surface: §7 requires the
|
|
104
|
+
* approval artifact to contain the exact resolved instance handles, stream
|
|
105
|
+
* names, fields, resources, and temporal bounds, which only exist once this
|
|
106
|
+
* has run.
|
|
107
|
+
*/
|
|
108
|
+
export declare function resolveSelection(request: SelectionRequest, snapshot: DeclarationSnapshot, inventory: InstanceInventory, choices?: OwnerChoices): ResolutionResult;
|
|
109
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/pdpp/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAEL,KAAK,mBAAmB,EAExB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,aAAa,EAElB,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAClC,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACzC;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC3C;AAED,MAAM,MAAM,qBAAqB,GAC7B,gBAAgB,GAChB,kBAAkB,GAClB,0BAA0B,GAC1B,sBAAsB,GACtB,cAAc,GACd,iBAAiB;AACnB,sEAAsE;GACpE,iBAAiB;AACnB,sEAAsE;GACpE,0BAA0B;AAC5B,mEAAmE;GACjE,qBAAqB,CAAC;AAE1B,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,MAAM,gBAAgB,GACxB;IACE,EAAE,EAAE,IAAI,CAAC;IACT,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;CACtC,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAkV9C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,mBAAmB,GAC5B,aAAa,EAAE,CAyBjB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,iBAAiB,EAC5B,OAAO,CAAC,EAAE,YAAY,GACrB,gBAAgB,CAuGlB"}
|