@idp.global/sdk 18.2.0 → 18.3.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.
- package/changelog.md +9 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts_relyingparty/classes.idpoidcprovider.d.ts +17 -1
- package/dist_ts_relyingparty/classes.idpoidcprovider.js +20 -4
- package/dist_ts_server/classes.oidc-introspection-client.d.ts +7 -0
- package/dist_ts_server/classes.oidc-introspection-client.js +14 -6
- package/dist_ts_server/helpers.trusted-ca-fetch.d.ts +25 -0
- package/dist_ts_server/helpers.trusted-ca-fetch.js +179 -0
- package/dist_ts_server/index.d.ts +1 -0
- package/dist_ts_server/index.js +2 -1
- package/dist_ts_server/plugins.d.ts +3 -1
- package/dist_ts_server/plugins.js +4 -2
- package/package.json +1 -1
- package/readme.md +46 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_relyingparty/classes.idpoidcprovider.ts +35 -4
- package/ts_server/classes.oidc-introspection-client.ts +17 -3
- package/ts_server/helpers.trusted-ca-fetch.ts +204 -0
- package/ts_server/index.ts +1 -0
- package/ts_server/plugins.ts +3 -1
package/changelog.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026-09-29 - 18.3.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- reach an issuer under a private CA without process-wide trust (relyingparty, server)
|
|
8
|
+
- `IdpOidcProvider` option `trustedCaPem` (one PEM string or several): discovery, token, UserInfo, refresh, revocation and introspection go through one `node:https` agent of the provider that trusts those CAs only — for `@idp.global/devidp`'s `caCertificatePem` or a self-hosted idp.global on a LAN. The global `fetch`, its dispatcher and the default trust store stay untouched; https-only still holds, and an unreadable PEM is refused by the constructor.
|
|
9
|
+
- `IdpOidcProvider` option `fetch` (advanced, a `TOidcFetch`) carries every provider request instead; it is not combined with `trustedCaPem`.
|
|
10
|
+
- `@idp.global/sdk/server` exports `createTrustedCaFetch(pem | pem[])`, the https-only, non-redirecting transport behind `trustedCaPem`, with the types `TOidcFetch` and `IOidcFetchInit`; `OidcIntrospectionClient` takes an optional `fetch`.
|
|
11
|
+
|
|
3
12
|
## 2026-09-29 - 18.2.0
|
|
4
13
|
|
|
5
14
|
### Features
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@idp.global/sdk',
|
|
6
|
-
version: '18.
|
|
6
|
+
version: '18.3.0',
|
|
7
7
|
description: 'Reusable browser and server SDK for idp.global authentication.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxpQkFBaUI7SUFDdkIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLGdFQUFnRTtDQUM5RSxDQUFBIn0=
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type TOidcFetch } from '../dist_ts_server/helpers.trusted-ca-fetch.js';
|
|
1
2
|
export interface IOidcAuthorizationOptions {
|
|
2
3
|
state: string;
|
|
3
4
|
nonce: string;
|
|
@@ -92,7 +93,7 @@ export interface IOidcProvider {
|
|
|
92
93
|
export declare const IDP_OIDC_DEFAULT_SCOPES = "openid profile email organizations roles";
|
|
93
94
|
export declare const IDP_OIDC_DEFAULT_REQUEST_TIMEOUT_SECONDS = 10;
|
|
94
95
|
export interface IIdpOidcProviderOptions {
|
|
95
|
-
/** the issuer origin, `https://…`; the introspection client
|
|
96
|
+
/** the issuer origin, `https://…`; discovery and the introspection client refuse anything else */
|
|
96
97
|
issuer: URL;
|
|
97
98
|
clientId: string;
|
|
98
99
|
clientSecret: string;
|
|
@@ -103,6 +104,21 @@ export interface IIdpOidcProviderOptions {
|
|
|
103
104
|
requestTimeoutSeconds?: number;
|
|
104
105
|
/** deadline of one introspection; the introspection client's default applies when absent */
|
|
105
106
|
introspectionTimeoutMs?: number;
|
|
107
|
+
/**
|
|
108
|
+
* The CA certificates (PEM) the issuer's TLS certificate must chain to, for an
|
|
109
|
+
* issuer under a private CA such as `@idp.global/devidp`'s
|
|
110
|
+
* `caCertificatePem`. For this provider's requests they replace the public
|
|
111
|
+
* roots; the process-wide trust store, the global `fetch` and its dispatcher
|
|
112
|
+
* stay untouched. Not combined with `fetch`.
|
|
113
|
+
*/
|
|
114
|
+
trustedCaPem?: string | readonly string[];
|
|
115
|
+
/**
|
|
116
|
+
* Advanced: the fetch that carries every request of this provider —
|
|
117
|
+
* discovery, token, UserInfo, refresh, revocation and introspection.
|
|
118
|
+
* It owns the transport's trust decisions; https-only still holds. Not
|
|
119
|
+
* combined with `trustedCaPem`.
|
|
120
|
+
*/
|
|
121
|
+
fetch?: TOidcFetch;
|
|
106
122
|
}
|
|
107
123
|
/**
|
|
108
124
|
* Organization claims as idp.global documents them: `id`, `name`, `slug` and
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import { OidcIntrospectionClient, OidcIntrospectionError, } from '../dist_ts_server/classes.oidc-introspection-client.js';
|
|
3
|
+
import { createTrustedCaFetch } from '../dist_ts_server/helpers.trusted-ca-fetch.js';
|
|
3
4
|
/** The provider could not be asked, or did not answer in its own contract. The caller fails closed on it. */
|
|
4
5
|
export class OidcAuthorityUnavailableError extends Error {
|
|
5
6
|
reason;
|
|
@@ -73,6 +74,8 @@ export const readOrganizationClaims = (valueArg) => {
|
|
|
73
74
|
export class IdpOidcProvider {
|
|
74
75
|
requestTimeoutSeconds;
|
|
75
76
|
#options;
|
|
77
|
+
/** the transport of every request; the global `fetch` when absent */
|
|
78
|
+
#fetch;
|
|
76
79
|
#configuration;
|
|
77
80
|
#introspection;
|
|
78
81
|
constructor(optionsArg) {
|
|
@@ -87,6 +90,15 @@ export class IdpOidcProvider {
|
|
|
87
90
|
throw new Error('IdpOidcProvider requestTimeoutSeconds must be an integer from 1 to 60');
|
|
88
91
|
}
|
|
89
92
|
this.requestTimeoutSeconds = timeout;
|
|
93
|
+
if (optionsArg.trustedCaPem !== undefined && optionsArg.fetch !== undefined) {
|
|
94
|
+
throw new Error('IdpOidcProvider takes trustedCaPem or fetch, not both');
|
|
95
|
+
}
|
|
96
|
+
if (optionsArg.fetch !== undefined && typeof optionsArg.fetch !== 'function') {
|
|
97
|
+
throw new Error('IdpOidcProvider fetch must be a function');
|
|
98
|
+
}
|
|
99
|
+
this.#fetch = optionsArg.trustedCaPem !== undefined
|
|
100
|
+
? createTrustedCaFetch(optionsArg.trustedCaPem)
|
|
101
|
+
: optionsArg.fetch;
|
|
90
102
|
this.#options = optionsArg;
|
|
91
103
|
}
|
|
92
104
|
get configuration() {
|
|
@@ -100,13 +112,16 @@ export class IdpOidcProvider {
|
|
|
100
112
|
return;
|
|
101
113
|
}
|
|
102
114
|
const options = this.#options;
|
|
103
|
-
// the timeout given to discovery
|
|
104
|
-
// resolved configuration for every later request
|
|
115
|
+
// the timeout and the fetch given to discovery apply to discovery itself
|
|
116
|
+
// and stay on the resolved configuration for every later request
|
|
105
117
|
const configuration = await plugins.openidClient.discovery(options.issuer, options.clientId, {
|
|
106
118
|
client_secret: options.clientSecret,
|
|
107
119
|
token_endpoint_auth_method: 'client_secret_basic',
|
|
108
120
|
id_token_signed_response_alg: 'RS256',
|
|
109
|
-
}, plugins.openidClient.ClientSecretBasic(options.clientSecret), {
|
|
121
|
+
}, plugins.openidClient.ClientSecretBasic(options.clientSecret), {
|
|
122
|
+
timeout: this.requestTimeoutSeconds,
|
|
123
|
+
...(this.#fetch ? { [plugins.openidClient.customFetch]: this.#fetch } : {}),
|
|
124
|
+
});
|
|
110
125
|
const metadata = configuration.serverMetadata();
|
|
111
126
|
if (!metadata.authorization_endpoint || !metadata.token_endpoint || !metadata.jwks_uri) {
|
|
112
127
|
throw new Error('The identity provider is missing required OIDC endpoints');
|
|
@@ -130,6 +145,7 @@ export class IdpOidcProvider {
|
|
|
130
145
|
clientId: options.clientId,
|
|
131
146
|
clientSecret: options.clientSecret,
|
|
132
147
|
...(options.introspectionTimeoutMs !== undefined ? { timeoutMs: options.introspectionTimeoutMs } : {}),
|
|
148
|
+
...(this.#fetch ? { fetch: this.#fetch } : {}),
|
|
133
149
|
});
|
|
134
150
|
this.#configuration = configuration;
|
|
135
151
|
}
|
|
@@ -252,4 +268,4 @@ export class IdpOidcProvider {
|
|
|
252
268
|
};
|
|
253
269
|
}
|
|
254
270
|
}
|
|
255
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5pZHBvaWRjcHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19yZWx5aW5ncGFydHkvY2xhc3Nlcy5pZHBvaWRjcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixzQkFBc0IsR0FDdkIsTUFBTSxtREFBbUQsQ0FBQztBQTBEM0QsNkdBQTZHO0FBQzdHLE1BQU0sT0FBTyw2QkFBOEIsU0FBUSxLQUFLO0lBRXBDO0lBRGxCLFlBQ2tCLE1BQTZCLEVBQzdDLFFBQWtCO1FBRWxCLEtBQUssQ0FBQyw2Q0FBNkMsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBSDFELFdBQU0sR0FBTixNQUFNLENBQXVCO1FBSTdDLElBQUksQ0FBQyxJQUFJLEdBQUcsK0JBQStCLENBQUM7SUFDOUMsQ0FBQztDQUNGO0FBRUQsbUhBQW1IO0FBQ25ILE1BQU0sT0FBTyx1QkFBd0IsU0FBUSxLQUFLO0lBQ2hELFlBQVksUUFBa0I7UUFDNUIsS0FBSyxDQUFDLDJDQUEyQyxFQUFFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDeEUsSUFBSSxDQUFDLElBQUksR0FBRyx5QkFBeUIsQ0FBQztJQUN4QyxDQUFDO0NBQ0Y7QUFNRCxNQUFNLE9BQU8sbUJBQW9CLFNBQVEsS0FBSztJQUUxQjtJQURsQixZQUNrQixLQUFrQyxFQUNsRCxRQUFpQjtRQUVqQixLQUFLLENBQUMsd0JBQXdCLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUhyQyxVQUFLLEdBQUwsS0FBSyxDQUE2QjtRQUlsRCxJQUFJLENBQUMsSUFBSSxHQUFHLHFCQUFxQixDQUFDO0lBQ3BDLENBQUM7Q0FDRjtBQTBCRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSx1QkFB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
|
|
271
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5pZHBvaWRjcHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19yZWx5aW5ncGFydHkvY2xhc3Nlcy5pZHBvaWRjcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixzQkFBc0IsR0FDdkIsTUFBTSxtREFBbUQsQ0FBQztBQUMzRCxPQUFPLEVBQUUsb0JBQW9CLEVBQW1CLE1BQU0sMENBQTBDLENBQUM7QUEwRGpHLDZHQUE2RztBQUM3RyxNQUFNLE9BQU8sNkJBQThCLFNBQVEsS0FBSztJQUVwQztJQURsQixZQUNrQixNQUE2QixFQUM3QyxRQUFrQjtRQUVsQixLQUFLLENBQUMsNkNBQTZDLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUgxRCxXQUFNLEdBQU4sTUFBTSxDQUF1QjtRQUk3QyxJQUFJLENBQUMsSUFBSSxHQUFHLCtCQUErQixDQUFDO0lBQzlDLENBQUM7Q0FDRjtBQUVELG1IQUFtSDtBQUNuSCxNQUFNLE9BQU8sdUJBQXdCLFNBQVEsS0FBSztJQUNoRCxZQUFZLFFBQWtCO1FBQzVCLEtBQUssQ0FBQywyQ0FBMkMsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLElBQUksQ0FBQyxJQUFJLEdBQUcseUJBQXlCLENBQUM7SUFDeEMsQ0FBQztDQUNGO0FBTUQsTUFBTSxPQUFPLG1CQUFvQixTQUFRLEtBQUs7SUFFMUI7SUFEbEIsWUFDa0IsS0FBa0MsRUFDbEQsUUFBaUI7UUFFakIsS0FBSyxDQUFDLHdCQUF3QixFQUFFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFIckMsVUFBSyxHQUFMLEtBQUssQ0FBNkI7UUFJbEQsSUFBSSxDQUFDLElBQUksR0FBRyxxQkFBcUIsQ0FBQztJQUNwQyxD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
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
|
+
import type { TOidcFetch } from './helpers.trusted-ca-fetch.js';
|
|
2
3
|
export interface IOidcIntrospectionClientOptions {
|
|
3
4
|
issuer: string;
|
|
4
5
|
clientId: string;
|
|
5
6
|
clientSecret: string;
|
|
6
7
|
timeoutMs?: number;
|
|
7
8
|
maxResponseBytes?: number;
|
|
9
|
+
/**
|
|
10
|
+
* The fetch every introspection request goes through, e.g.
|
|
11
|
+
* `createTrustedCaFetch(caPem)` for an issuer under a private CA. The global
|
|
12
|
+
* `fetch` when absent.
|
|
13
|
+
*/
|
|
14
|
+
fetch?: TOidcFetch;
|
|
8
15
|
}
|
|
9
16
|
export interface IOidcIntrospectionClientRequest {
|
|
10
17
|
token: string;
|
|
@@ -22,6 +22,7 @@ export class OidcIntrospectionClient {
|
|
|
22
22
|
#authorization;
|
|
23
23
|
#timeoutMs;
|
|
24
24
|
#maxResponseBytes;
|
|
25
|
+
#fetch;
|
|
25
26
|
constructor(optionsArg) {
|
|
26
27
|
if (!optionsArg || !exactString(optionsArg.issuer, 2048) || !exactString(optionsArg.clientId)
|
|
27
28
|
|| !exactString(optionsArg.clientSecret, 4096))
|
|
@@ -44,6 +45,9 @@ export class OidcIntrospectionClient {
|
|
|
44
45
|
|| !Number.isSafeInteger(this.#maxResponseBytes) || this.#maxResponseBytes < 1 || this.#maxResponseBytes > 65536) {
|
|
45
46
|
throw new OidcIntrospectionError('invalid_request');
|
|
46
47
|
}
|
|
48
|
+
if (optionsArg.fetch !== undefined && typeof optionsArg.fetch !== 'function')
|
|
49
|
+
throw new OidcIntrospectionError('invalid_request');
|
|
50
|
+
this.#fetch = optionsArg.fetch;
|
|
47
51
|
this.#issuer = canonicalIssuer;
|
|
48
52
|
this.#clientId = optionsArg.clientId;
|
|
49
53
|
// OAuth Basic components are form-encoded separately before joining with ':'.
|
|
@@ -64,11 +68,15 @@ export class OidcIntrospectionClient {
|
|
|
64
68
|
});
|
|
65
69
|
let reader;
|
|
66
70
|
try {
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}),
|
|
71
|
+
const url = `${this.#issuer}/oauth/introspect`;
|
|
72
|
+
const init = {
|
|
73
|
+
method: 'POST', redirect: 'error', signal: controller.signal,
|
|
74
|
+
headers: { authorization: this.#authorization, 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' },
|
|
75
|
+
body: new URLSearchParams({ token, subject, organization_id: organizationId, nonce, token_type_hint: 'access_token' }),
|
|
76
|
+
};
|
|
77
|
+
const response = await Promise.race([this.#fetch
|
|
78
|
+
? this.#fetch(url, init)
|
|
79
|
+
: fetch(url, { ...init, credentials: 'omit', cache: 'no-store' }), deadline]);
|
|
72
80
|
if (response.status !== 200)
|
|
73
81
|
throw new OidcIntrospectionError('unavailable');
|
|
74
82
|
if (response.headers.get('content-type')?.split(';')[0].trim().toLowerCase() !== 'application/json'
|
|
@@ -141,4 +149,4 @@ export class OidcIntrospectionClient {
|
|
|
141
149
|
return valueArg;
|
|
142
150
|
}
|
|
143
151
|
}
|
|
144
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5vaWRjLWludHJvc3BlY3Rpb24tY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfc2VydmVyL2NsYXNzZXMub2lkYy1pbnRyb3NwZWN0aW9uLWNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQWdCeEMsTUFBTSxPQUFPLHNCQUF1QixTQUFRLEtBQUs7SUFDbkI7SUFBNUIsWUFBNEIsSUFBNEQ7UUFDdEYsS0FBSyxDQUFDLHNCQUFzQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFEOUIsU0FBSSxHQUFKLElBQUksQ0FBd0Q7UUFFdEYsSUFBSSxDQUFDLElBQUksR0FBRyx3QkFBd0IsQ0FBQztJQUN2QyxDQUFDO0NBQ0Y7QUFFRCxNQUFNLFdBQVcsR0FBRyxDQUFDLFFBQWlCLEVBQUUsVUFBVSxHQUFHLEdBQUcsRUFBc0IsRUFBRSxDQUM5RSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksUUFBUSxDQUFDLE1BQU0sSUFBSSxVQUFVO09BQ2pGLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxRQUFRLENBQUM7QUFDbEMsTUFBTSxNQUFNLEdBQUcsQ0FBQyxRQUFpQixFQUF1QyxFQUFFLENBQ3hFLFFBQVEsS0FBSyxJQUFJLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNoRixNQUFNLFNBQVMsR0FBRyxDQUFDLFFBQWlDLEVBQUUsT0FBaUIsRUFBRSxFQUFFLENBQ3pFLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxLQUFLLE9BQU8sQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFF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
|
|
152
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5vaWRjLWludHJvc3BlY3Rpb24tY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfc2VydmVyL2NsYXNzZXMub2lkYy1pbnRyb3NwZWN0aW9uLWNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQXVCeEMsTUFBTSxPQUFPLHNCQUF1QixTQUFRLEtBQUs7SUFDbkI7SUFBNUIsWUFBNEIsSUFBNEQ7UUFDdEYsS0FBSyxDQUFDLHNCQUFzQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFEOUIsU0FBSSxHQUFKLElBQUksQ0FBd0Q7UUFFdEYsSUFBSSxDQUFDLElBQUksR0FBRyx3QkFBd0IsQ0FBQztJQUN2QyxDQUFDO0NBQ0Y7QUFFRCxNQUFNLFdBQVcsR0FBRyxDQUFDLFFBQWlCLEVBQUUsVUFBVSxHQUFHLEdBQUcsRUFBc0IsRUFBRSxDQUM5RSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksUUFBUSxDQUFDLE1BQU0sSUFBSSxVQUFVO09BQ2pGLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxRQUFRLENBQUM7QUFDbEMsTUFBTSxNQUFNLEdBQUcsQ0FBQyxRQUFpQixFQUF1QyxFQUFFLENBQ3hFLFFBQVEsS0FBSyxJQUFJLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNoRixNQUFNLFNBQVMsR0FBRyxDQUFDLFFBQWlDLEVBQUUsT0FBaUIsRUFBRSxFQUFFLENBQ3pFLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxLQUFLLE9BQU8sQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFF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
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the sdk's OIDC clients pass to their fetch: the subset of `RequestInit`
|
|
3
|
+
* that `openid-client` and `OidcIntrospectionClient` use. Node's global `fetch`
|
|
4
|
+
* satisfies it.
|
|
5
|
+
*/
|
|
6
|
+
export interface IOidcFetchInit {
|
|
7
|
+
method: string;
|
|
8
|
+
headers: Record<string, string>;
|
|
9
|
+
body?: ArrayBuffer | ReadableStream | string | Uint8Array | URLSearchParams | null;
|
|
10
|
+
duplex?: 'half';
|
|
11
|
+
/** `manual` answers a redirect as it is; `error` rejects it. Neither follows it. */
|
|
12
|
+
redirect: 'manual' | 'error';
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
}
|
|
15
|
+
/** A fetch for one OIDC client's requests, e.g. one that trusts the issuer's private CA. */
|
|
16
|
+
export type TOidcFetch = (urlArg: string, initArg: IOidcFetchInit) => Promise<Response>;
|
|
17
|
+
/**
|
|
18
|
+
* A fetch over `node:https` whose connections trust the given CA certificates
|
|
19
|
+
* and nothing else. The agent belongs to this fetch alone: the process-wide
|
|
20
|
+
* trust store, the global `fetch` and its dispatcher stay untouched. Only
|
|
21
|
+
* `https:` URLs are fetched, redirects are never followed, and bodies are
|
|
22
|
+
* requested without a content coding. Idle pooled sockets are unreferenced, so
|
|
23
|
+
* they never keep the process alive.
|
|
24
|
+
*/
|
|
25
|
+
export declare const createTrustedCaFetch: (trustedCaPemArg: string | readonly string[]) => TOidcFetch;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
const pemCertificatePattern = /-----BEGIN CERTIFICATE-----\r?\n[A-Za-z0-9+/=\r\n]+-----END CERTIFICATE-----/g;
|
|
3
|
+
/** The statuses a fetch answers with a null body. */
|
|
4
|
+
const nullBodyStatuses = new Set([101, 103, 204, 205, 304]);
|
|
5
|
+
/** The statuses fetch treats as redirects. */
|
|
6
|
+
const redirectStatuses = new Set([301, 302, 303, 307, 308]);
|
|
7
|
+
/**
|
|
8
|
+
* Idle keep-alive sockets close after this delay, or earlier when the server
|
|
9
|
+
* announces a shorter `Keep-Alive: timeout`, so a pooled socket is not reused
|
|
10
|
+
* as the server closes it.
|
|
11
|
+
*/
|
|
12
|
+
const idleSocketTimeoutMs = 4_000;
|
|
13
|
+
/** A request body as bytes, with the content type fetch would give it. */
|
|
14
|
+
const encodeBody = async (bodyArg) => {
|
|
15
|
+
if (typeof bodyArg === 'string') {
|
|
16
|
+
return { bytes: Buffer.from(bodyArg, 'utf8'), contentType: 'text/plain;charset=UTF-8' };
|
|
17
|
+
}
|
|
18
|
+
if (bodyArg instanceof URLSearchParams) {
|
|
19
|
+
return { bytes: Buffer.from(bodyArg.toString(), 'utf8'), contentType: 'application/x-www-form-urlencoded;charset=UTF-8' };
|
|
20
|
+
}
|
|
21
|
+
if (bodyArg instanceof ArrayBuffer) {
|
|
22
|
+
return { bytes: Buffer.from(new Uint8Array(bodyArg)) };
|
|
23
|
+
}
|
|
24
|
+
if (bodyArg instanceof Uint8Array) {
|
|
25
|
+
return { bytes: Buffer.from(bodyArg) };
|
|
26
|
+
}
|
|
27
|
+
const chunks = [];
|
|
28
|
+
const reader = bodyArg.getReader();
|
|
29
|
+
while (true) {
|
|
30
|
+
const part = await reader.read();
|
|
31
|
+
if (part.done) {
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
if (!(part.value instanceof Uint8Array)) {
|
|
35
|
+
await reader.cancel();
|
|
36
|
+
throw new TypeError('A request body stream must yield bytes');
|
|
37
|
+
}
|
|
38
|
+
chunks.push(part.value);
|
|
39
|
+
}
|
|
40
|
+
return { bytes: Buffer.concat(chunks) };
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The response body as a fetch body stream, read as it is pulled. Cancelling
|
|
44
|
+
* it destroys the response and so its connection.
|
|
45
|
+
*/
|
|
46
|
+
const webStreamOf = (incomingArg) => {
|
|
47
|
+
const chunks = incomingArg[Symbol.asyncIterator]();
|
|
48
|
+
return new ReadableStream({
|
|
49
|
+
async pull(controllerArg) {
|
|
50
|
+
const part = await chunks.next();
|
|
51
|
+
if (part.done) {
|
|
52
|
+
controllerArg.close();
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
controllerArg.enqueue(part.value);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
async cancel() {
|
|
59
|
+
await chunks.return?.();
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Every certificate of the given PEM text, each parsed. Anything else in the
|
|
65
|
+
* text, or no certificate at all, is refused: an unreadable trust anchor must
|
|
66
|
+
* fail here, not as a TLS error at the first request.
|
|
67
|
+
*/
|
|
68
|
+
const readTrustedCertificates = (trustedCaPemArg) => {
|
|
69
|
+
const pems = typeof trustedCaPemArg === 'string' ? [trustedCaPemArg] : trustedCaPemArg;
|
|
70
|
+
if (!Array.isArray(pems) || pems.length === 0) {
|
|
71
|
+
throw new TypeError('trustedCaPem must name at least one PEM certificate');
|
|
72
|
+
}
|
|
73
|
+
const certificates = [];
|
|
74
|
+
for (const pem of pems) {
|
|
75
|
+
if (typeof pem !== 'string') {
|
|
76
|
+
throw new TypeError('trustedCaPem must be PEM certificate text');
|
|
77
|
+
}
|
|
78
|
+
const blocks = pem.match(pemCertificatePattern) ?? [];
|
|
79
|
+
if (blocks.length === 0 || pem.replace(pemCertificatePattern, '').trim() !== '') {
|
|
80
|
+
throw new TypeError('trustedCaPem must contain PEM certificates only');
|
|
81
|
+
}
|
|
82
|
+
for (const block of blocks) {
|
|
83
|
+
try {
|
|
84
|
+
new plugins.crypto.X509Certificate(block);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
throw new TypeError('trustedCaPem contains a certificate that cannot be parsed');
|
|
88
|
+
}
|
|
89
|
+
certificates.push(block);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return certificates;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* A fetch over `node:https` whose connections trust the given CA certificates
|
|
96
|
+
* and nothing else. The agent belongs to this fetch alone: the process-wide
|
|
97
|
+
* trust store, the global `fetch` and its dispatcher stay untouched. Only
|
|
98
|
+
* `https:` URLs are fetched, redirects are never followed, and bodies are
|
|
99
|
+
* requested without a content coding. Idle pooled sockets are unreferenced, so
|
|
100
|
+
* they never keep the process alive.
|
|
101
|
+
*/
|
|
102
|
+
export const createTrustedCaFetch = (trustedCaPemArg) => {
|
|
103
|
+
const agent = new plugins.https.Agent({
|
|
104
|
+
ca: readTrustedCertificates(trustedCaPemArg),
|
|
105
|
+
keepAlive: true,
|
|
106
|
+
timeout: idleSocketTimeoutMs,
|
|
107
|
+
});
|
|
108
|
+
return async (urlArg, initArg) => {
|
|
109
|
+
const url = new URL(urlArg);
|
|
110
|
+
if (url.protocol !== 'https:') {
|
|
111
|
+
throw new TypeError('A trusted-CA fetch only requests https URLs');
|
|
112
|
+
}
|
|
113
|
+
const signal = initArg.signal;
|
|
114
|
+
signal?.throwIfAborted();
|
|
115
|
+
const headers = new Headers(initArg.headers);
|
|
116
|
+
let body;
|
|
117
|
+
if (initArg.body !== undefined && initArg.body !== null) {
|
|
118
|
+
const encoded = await encodeBody(initArg.body);
|
|
119
|
+
body = encoded.bytes;
|
|
120
|
+
if (encoded.contentType && !headers.has('content-type')) {
|
|
121
|
+
headers.set('content-type', encoded.contentType);
|
|
122
|
+
}
|
|
123
|
+
headers.set('content-length', String(body.byteLength));
|
|
124
|
+
}
|
|
125
|
+
headers.set('accept-encoding', 'identity');
|
|
126
|
+
signal?.throwIfAborted();
|
|
127
|
+
return new Promise((resolve, reject) => {
|
|
128
|
+
const request = plugins.https.request(url, {
|
|
129
|
+
method: initArg.method,
|
|
130
|
+
headers: Object.fromEntries(headers.entries()),
|
|
131
|
+
agent,
|
|
132
|
+
});
|
|
133
|
+
// Stays attached for the request's lifetime, so a connection failure
|
|
134
|
+
// while the body is read never becomes an unhandled 'error' event.
|
|
135
|
+
request.on('error', reject);
|
|
136
|
+
// Destroyed without an error on purpose: an error would be re-emitted on
|
|
137
|
+
// the socket, which no longer has a listener once a keep-alive response
|
|
138
|
+
// completed. The response body errors as its connection goes.
|
|
139
|
+
const abort = () => {
|
|
140
|
+
reject(signal?.reason);
|
|
141
|
+
request.destroy();
|
|
142
|
+
};
|
|
143
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
144
|
+
request.once('close', () => signal?.removeEventListener('abort', abort));
|
|
145
|
+
request.on('response', (incoming) => {
|
|
146
|
+
try {
|
|
147
|
+
const status = incoming.statusCode ?? 0;
|
|
148
|
+
if (initArg.redirect === 'error' && redirectStatuses.has(status)) {
|
|
149
|
+
throw new TypeError('The response is a redirect');
|
|
150
|
+
}
|
|
151
|
+
const contentEncoding = incoming.headers['content-encoding'];
|
|
152
|
+
if (contentEncoding !== undefined && contentEncoding.trim().toLowerCase() !== 'identity') {
|
|
153
|
+
throw new TypeError('The response has a content coding');
|
|
154
|
+
}
|
|
155
|
+
// same combination rules as fetch: repeated fields join with ", "
|
|
156
|
+
const responseHeaders = new Headers();
|
|
157
|
+
for (let index = 0; index < incoming.rawHeaders.length; index += 2) {
|
|
158
|
+
responseHeaders.append(incoming.rawHeaders[index], incoming.rawHeaders[index + 1]);
|
|
159
|
+
}
|
|
160
|
+
const withoutBody = nullBodyStatuses.has(status) || initArg.method.toUpperCase() === 'HEAD';
|
|
161
|
+
if (withoutBody) {
|
|
162
|
+
incoming.resume();
|
|
163
|
+
}
|
|
164
|
+
resolve(new Response(withoutBody ? null : webStreamOf(incoming), {
|
|
165
|
+
status,
|
|
166
|
+
statusText: incoming.statusMessage,
|
|
167
|
+
headers: responseHeaders,
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
reject(error);
|
|
172
|
+
request.destroy();
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
request.end(body);
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy50cnVzdGVkLWNhLWZldGNoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfc2VydmVyL2hlbHBlcnMudHJ1c3RlZC1jYS1mZXRjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQW9CeEMsTUFBTSxxQkFBcUIsR0FBRywrRUFBK0UsQ0FBQztBQUU5RyxxREFBcUQ7QUFDckQsTUFBTSxnQkFBZ0IsR0FBd0IsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUVqRiw4Q0FBOEM7QUFDOUMsTUFBTSxnQkFBZ0IsR0FBd0IsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUVqRjs7OztHQUlHO0FBQ0gsTUFBTSxtQkFBbUIsR0FBRyxLQUFLLENBQUM7QUFFbEMsMEVBQTBFO0FBQzFFLE1BQU0sVUFBVSxHQUFHLEtBQUssRUFDdEIsT0FBNEMsRUFDTSxFQUFFO0lBQ3BELElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDaEMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsRUFBRSxXQUFXLEVBQUUsMEJBQTBCLEVBQUUsQ0FBQztJQUMxRixDQUFDO0lBQ0QsSUFBSSxPQUFPLFlBQVksZUFBZSxFQUFFLENBQUM7UUFDdkMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLENBQUMsRUFBRSxXQUFXLEVBQUUsaURBQWlELEVBQUUsQ0FBQztJQUM1SCxDQUFDO0lBQ0QsSUFBSSxPQUFPLFlBQVksV0FBVyxFQUFFLENBQUM7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
|
|
@@ -3,6 +3,7 @@ export * from './classes.account-auth-service.js';
|
|
|
3
3
|
export * from './classes.account-doc.js';
|
|
4
4
|
export * from './classes.account-store.js';
|
|
5
5
|
export * from './classes.idp-global-server-client.js';
|
|
6
|
+
export * from './helpers.trusted-ca-fetch.js';
|
|
6
7
|
export * from './classes.oidc-introspection-client.js';
|
|
7
8
|
export * from './classes.oidc-userinfo-client.js';
|
|
8
9
|
export * from './classes.password-hasher.js';
|
package/dist_ts_server/index.js
CHANGED
|
@@ -3,7 +3,8 @@ export * from './classes.account-auth-service.js';
|
|
|
3
3
|
export * from './classes.account-doc.js';
|
|
4
4
|
export * from './classes.account-store.js';
|
|
5
5
|
export * from './classes.idp-global-server-client.js';
|
|
6
|
+
export * from './helpers.trusted-ca-fetch.js';
|
|
6
7
|
export * from './classes.oidc-introspection-client.js';
|
|
7
8
|
export * from './classes.oidc-userinfo-client.js';
|
|
8
9
|
export * from './classes.password-hasher.js';
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19zZXJ2ZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLG1DQUFtQyxDQUFDO0FBQ2xELGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLHVDQUF1QyxDQUFDO0FBQ3RELGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyx3Q0FBd0MsQ0FBQztBQUN2RCxjQUFjLG1DQUFtQyxDQUFDO0FBQ2xELGNBQWMsOEJBQThCLENBQUMifQ==
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as crypto from 'crypto';
|
|
2
|
-
|
|
2
|
+
import * as http from 'node:http';
|
|
3
|
+
import * as https from 'node:https';
|
|
4
|
+
export { crypto, http, https };
|
|
3
5
|
import * as idpInterfaces from '@idp.global/interfaces';
|
|
4
6
|
export { idpInterfaces };
|
|
5
7
|
import * as typedrequest from '@api.global/typedrequest';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as crypto from 'crypto';
|
|
2
|
-
|
|
2
|
+
import * as http from 'node:http';
|
|
3
|
+
import * as https from 'node:https';
|
|
4
|
+
export { crypto, http, https };
|
|
3
5
|
import * as idpInterfaces from '@idp.global/interfaces';
|
|
4
6
|
export { idpInterfaces };
|
|
5
7
|
import * as typedrequest from '@api.global/typedrequest';
|
|
@@ -8,4 +10,4 @@ export { typedrequest, typedsocket };
|
|
|
8
10
|
import * as nosqldb from '@lossless.org/client/nosqldb';
|
|
9
11
|
import * as smartpromise from '@push.rocks/smartpromise';
|
|
10
12
|
export { nosqldb, smartpromise };
|
|
11
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3NlcnZlci9wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxLQUFLLE1BQU0sWUFBWSxDQUFDO0FBRXBDLE9BQU8sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDO0FBRS9CLE9BQU8sS0FBSyxhQUFhLE1BQU0sd0JBQXdCLENBQUM7QUFFeEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxDQUFDO0FBRXpCLE9BQU8sS0FBSyxZQUFZLE1BQU0sMEJBQTBCLENBQUM7QUFDekQsT0FBTyxLQUFLLFdBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUV2RCxPQUFPLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxDQUFDO0FBRXJDLE9BQU8sS0FBSyxPQUFPLE1BQU0sOEJBQThCLENBQUM7QUFDeEQsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUV6RCxPQUFPLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxDQUFDIn0=
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -343,6 +343,26 @@ are rejected. `OidcIntrospectionError` exposes only a sanitized `code`:
|
|
|
343
343
|
`invalid_request`, `invalid_response`, or `unavailable`. Deny the operation when
|
|
344
344
|
introspection fails.
|
|
345
345
|
|
|
346
|
+
An issuer under a private CA — `@idp.global/devidp`, which returns its CA as
|
|
347
|
+
`caCertificatePem`, or a self-hosted idp.global on a LAN — is reached through
|
|
348
|
+
its own transport instead of the process-wide `NODE_EXTRA_CA_CERTS`:
|
|
349
|
+
|
|
350
|
+
```ts
|
|
351
|
+
import { createTrustedCaFetch, OidcIntrospectionClient } from '@idp.global/sdk/server';
|
|
352
|
+
|
|
353
|
+
const introspection = new OidcIntrospectionClient({
|
|
354
|
+
issuer: 'https://idp.lan.example',
|
|
355
|
+
clientId: process.env.IDP_OIDC_CLIENT_ID!,
|
|
356
|
+
clientSecret: process.env.IDP_OIDC_CLIENT_SECRET!,
|
|
357
|
+
fetch: createTrustedCaFetch(caCertificatePem),
|
|
358
|
+
});
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
`createTrustedCaFetch(pem | pem[])` parses every certificate up front and
|
|
362
|
+
returns a `TOidcFetch` over `node:https` whose own agent trusts those CAs and
|
|
363
|
+
nothing else. It requests `https:` URLs only, never follows a redirect, and
|
|
364
|
+
leaves the global `fetch`, its dispatcher and the default trust store untouched.
|
|
365
|
+
|
|
346
366
|
An active result observes current authority while the provider holds its
|
|
347
367
|
mutation fences. It is not a cached membership grant: membership can change
|
|
348
368
|
after that observation. `exp` bounds token, session, and refresh-family expiry;
|
|
@@ -405,6 +425,7 @@ server-held token is no longer accepted. Errors omit token and provider content.
|
|
|
405
425
|
| `IdpGlobalServerClient` | Typed-socket client for idp.global password login, JWT refresh, `whoIs` lookup, backend JWT validation fetches, and JWT key/blocklist pushes. |
|
|
406
426
|
| `OidcIntrospectionClient` | Confidential server client for an exact live organization authority observation. |
|
|
407
427
|
| `OidcIntrospectionError` | Sanitized introspection failure with a stable error code. |
|
|
428
|
+
| `createTrustedCaFetch()` | A `TOidcFetch` whose connections trust the given PEM CA certificates only; https-only, no redirects, global `fetch` untouched. |
|
|
408
429
|
| `OidcUserInfoClient` | Subject-bound profile and organization display claims using a server-held OIDC token. |
|
|
409
430
|
| `OidcUserInfoError` | Sanitized UserInfo failure with a stable error code. |
|
|
410
431
|
| `IdpMfaRequiredError` | Password-login error carrying the MFA challenge token and available factor methods. |
|
|
@@ -419,7 +440,8 @@ The server export includes these TypeScript types:
|
|
|
419
440
|
|
|
420
441
|
| Type | Values or purpose |
|
|
421
442
|
| --- | --- |
|
|
422
|
-
| `IOidcIntrospectionClientOptions` | Exact HTTPS issuer, confidential client credentials,
|
|
443
|
+
| `IOidcIntrospectionClientOptions` | Exact HTTPS issuer, confidential client credentials, optional deadline/response limits, and an optional `fetch`. |
|
|
444
|
+
| `TOidcFetch`, `IOidcFetchInit` | The fetch an OIDC client sends its requests through, and the request options it passes. |
|
|
423
445
|
| `IOidcIntrospectionClientRequest` | Server-held access token, exact subject, and canonical organization ID. |
|
|
424
446
|
| `IOidcUserInfoClientOptions` | Exact HTTPS issuer and optional deadline/response limits. |
|
|
425
447
|
| `IOidcUserInfoClientRequest` | Server-held access token and the subject established by verified OIDC login. |
|
|
@@ -614,6 +636,28 @@ answer — the session is already over — and is reported as a `hook_failed`
|
|
|
614
636
|
route event (`hook: 'onLogout'`) through `onRouteEvent`. The hook runs without
|
|
615
637
|
a deadline of its own; bound a slow audit store inside it.
|
|
616
638
|
|
|
639
|
+
**Issuers under a private CA.** `IdpOidcProvider` takes `trustedCaPem` — one
|
|
640
|
+
PEM string or several, e.g. `@idp.global/devidp`'s `caCertificatePem` or a LAN
|
|
641
|
+
deployment's root. Discovery, token, UserInfo, refresh, revocation and
|
|
642
|
+
introspection then go through one `node:https` agent of this provider that
|
|
643
|
+
trusts those CAs and nothing else; the global `fetch`, its dispatcher and
|
|
644
|
+
`NODE_EXTRA_CA_CERTS` are not involved, and the issuer must still be `https:`.
|
|
645
|
+
An unreadable PEM is refused by the constructor.
|
|
646
|
+
|
|
647
|
+
```ts
|
|
648
|
+
const provider = new IdpOidcProvider({
|
|
649
|
+
issuer: new URL('https://idp.lan.example'),
|
|
650
|
+
clientId: process.env.IDP_CLIENT_ID!,
|
|
651
|
+
clientSecret: process.env.IDP_CLIENT_SECRET!,
|
|
652
|
+
redirectUri: new URL('/auth/callback', 'https://app.example'),
|
|
653
|
+
trustedCaPem: caCertificatePem,
|
|
654
|
+
});
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
Advanced: `fetch` (a `TOidcFetch`) replaces the transport of every provider
|
|
658
|
+
request instead, for a proxy or a client certificate; the trust decisions are
|
|
659
|
+
then the application's. The two options are not combined.
|
|
660
|
+
|
|
617
661
|
**Socket peers.** `RelyingPartySocketBinding.tagConnection` and `upgradeOf` take
|
|
618
662
|
the connection wrapper or the bare SmartServe peer (`TRelyingPartySocketPeer`),
|
|
619
663
|
the two forms `TypedSocket.setServerTag` accepts.
|
|
@@ -622,7 +666,7 @@ the two forms `TypedSocket.setServerTag` accepts.
|
|
|
622
666
|
|
|
623
667
|
| API | Description |
|
|
624
668
|
| --- | --- |
|
|
625
|
-
| `IdpOidcProvider` | Discovery, PKCE authorization URL, code exchange with UserInfo, refresh, revocation and organization introspection for idp.global. Implements `IOidcProvider`. |
|
|
669
|
+
| `IdpOidcProvider` | Discovery, PKCE authorization URL, code exchange with UserInfo, refresh, revocation and organization introspection for idp.global. Implements `IOidcProvider`. `trustedCaPem` or `fetch` for an issuer under a private CA. |
|
|
626
670
|
| `createRelyingPartyModels()` | Binds the session and login-attempt models to one `SmartdataDb`, or to a function asked for it on every use, optionally under existing collection names. |
|
|
627
671
|
| `RelyingPartySessions<TPrincipal>` | Login start/complete/abandon/finalize, `openSession`, `resolveCookieSession`, `revalidateSession`, `revalidateLiveSession`, `isSessionLive`, `validateCsrf`, `logout`/`endSession`, `endSessionsOfPrincipal`, `liveProviderToken`. Principals give `isActive` or `resolve` (`IRelyingPartyPrincipals`, `IRelyingPartyPrincipalResolver<TPrincipal>`); with `resolve`, live sessions carry `principal`. |
|
|
628
672
|
| `AuthorityObserver` | Live organization authority with opt-in positive and negative reuse. |
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
OidcIntrospectionClient,
|
|
4
4
|
OidcIntrospectionError,
|
|
5
5
|
} from '../ts_server/classes.oidc-introspection-client.js';
|
|
6
|
+
import { createTrustedCaFetch, type TOidcFetch } from '../ts_server/helpers.trusted-ca-fetch.js';
|
|
6
7
|
|
|
7
8
|
export interface IOidcAuthorizationOptions {
|
|
8
9
|
state: string;
|
|
@@ -126,7 +127,7 @@ export const IDP_OIDC_DEFAULT_SCOPES = 'openid profile email organizations roles
|
|
|
126
127
|
export const IDP_OIDC_DEFAULT_REQUEST_TIMEOUT_SECONDS = 10;
|
|
127
128
|
|
|
128
129
|
export interface IIdpOidcProviderOptions {
|
|
129
|
-
/** the issuer origin, `https://…`; the introspection client
|
|
130
|
+
/** the issuer origin, `https://…`; discovery and the introspection client refuse anything else */
|
|
130
131
|
issuer: URL;
|
|
131
132
|
clientId: string;
|
|
132
133
|
clientSecret: string;
|
|
@@ -137,6 +138,21 @@ export interface IIdpOidcProviderOptions {
|
|
|
137
138
|
requestTimeoutSeconds?: number;
|
|
138
139
|
/** deadline of one introspection; the introspection client's default applies when absent */
|
|
139
140
|
introspectionTimeoutMs?: number;
|
|
141
|
+
/**
|
|
142
|
+
* The CA certificates (PEM) the issuer's TLS certificate must chain to, for an
|
|
143
|
+
* issuer under a private CA such as `@idp.global/devidp`'s
|
|
144
|
+
* `caCertificatePem`. For this provider's requests they replace the public
|
|
145
|
+
* roots; the process-wide trust store, the global `fetch` and its dispatcher
|
|
146
|
+
* stay untouched. Not combined with `fetch`.
|
|
147
|
+
*/
|
|
148
|
+
trustedCaPem?: string | readonly string[];
|
|
149
|
+
/**
|
|
150
|
+
* Advanced: the fetch that carries every request of this provider —
|
|
151
|
+
* discovery, token, UserInfo, refresh, revocation and introspection.
|
|
152
|
+
* It owns the transport's trust decisions; https-only still holds. Not
|
|
153
|
+
* combined with `trustedCaPem`.
|
|
154
|
+
*/
|
|
155
|
+
fetch?: TOidcFetch;
|
|
140
156
|
}
|
|
141
157
|
|
|
142
158
|
const optionalString = (valueArg: unknown): string | undefined =>
|
|
@@ -187,6 +203,8 @@ export const readOrganizationClaims = (valueArg: unknown): IOidcOrganizationClai
|
|
|
187
203
|
export class IdpOidcProvider implements IOidcProvider {
|
|
188
204
|
public readonly requestTimeoutSeconds: number;
|
|
189
205
|
readonly #options: IIdpOidcProviderOptions;
|
|
206
|
+
/** the transport of every request; the global `fetch` when absent */
|
|
207
|
+
readonly #fetch?: TOidcFetch;
|
|
190
208
|
#configuration?: plugins.openidClient.Configuration;
|
|
191
209
|
#introspection?: OidcIntrospectionClient;
|
|
192
210
|
|
|
@@ -202,6 +220,15 @@ export class IdpOidcProvider implements IOidcProvider {
|
|
|
202
220
|
throw new Error('IdpOidcProvider requestTimeoutSeconds must be an integer from 1 to 60');
|
|
203
221
|
}
|
|
204
222
|
this.requestTimeoutSeconds = timeout;
|
|
223
|
+
if (optionsArg.trustedCaPem !== undefined && optionsArg.fetch !== undefined) {
|
|
224
|
+
throw new Error('IdpOidcProvider takes trustedCaPem or fetch, not both');
|
|
225
|
+
}
|
|
226
|
+
if (optionsArg.fetch !== undefined && typeof optionsArg.fetch !== 'function') {
|
|
227
|
+
throw new Error('IdpOidcProvider fetch must be a function');
|
|
228
|
+
}
|
|
229
|
+
this.#fetch = optionsArg.trustedCaPem !== undefined
|
|
230
|
+
? createTrustedCaFetch(optionsArg.trustedCaPem)
|
|
231
|
+
: optionsArg.fetch;
|
|
205
232
|
this.#options = optionsArg;
|
|
206
233
|
}
|
|
207
234
|
|
|
@@ -217,8 +244,8 @@ export class IdpOidcProvider implements IOidcProvider {
|
|
|
217
244
|
return;
|
|
218
245
|
}
|
|
219
246
|
const options = this.#options;
|
|
220
|
-
// the timeout given to discovery
|
|
221
|
-
// resolved configuration for every later request
|
|
247
|
+
// the timeout and the fetch given to discovery apply to discovery itself
|
|
248
|
+
// and stay on the resolved configuration for every later request
|
|
222
249
|
const configuration = await plugins.openidClient.discovery(
|
|
223
250
|
options.issuer,
|
|
224
251
|
options.clientId,
|
|
@@ -228,7 +255,10 @@ export class IdpOidcProvider implements IOidcProvider {
|
|
|
228
255
|
id_token_signed_response_alg: 'RS256',
|
|
229
256
|
},
|
|
230
257
|
plugins.openidClient.ClientSecretBasic(options.clientSecret),
|
|
231
|
-
{
|
|
258
|
+
{
|
|
259
|
+
timeout: this.requestTimeoutSeconds,
|
|
260
|
+
...(this.#fetch ? { [plugins.openidClient.customFetch]: this.#fetch } : {}),
|
|
261
|
+
},
|
|
232
262
|
);
|
|
233
263
|
const metadata = configuration.serverMetadata();
|
|
234
264
|
if (!metadata.authorization_endpoint || !metadata.token_endpoint || !metadata.jwks_uri) {
|
|
@@ -255,6 +285,7 @@ export class IdpOidcProvider implements IOidcProvider {
|
|
|
255
285
|
clientId: options.clientId,
|
|
256
286
|
clientSecret: options.clientSecret,
|
|
257
287
|
...(options.introspectionTimeoutMs !== undefined ? { timeoutMs: options.introspectionTimeoutMs } : {}),
|
|
288
|
+
...(this.#fetch ? { fetch: this.#fetch } : {}),
|
|
258
289
|
});
|
|
259
290
|
this.#configuration = configuration;
|
|
260
291
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
|
+
import type { TOidcFetch } from './helpers.trusted-ca-fetch.js';
|
|
2
3
|
|
|
3
4
|
export interface IOidcIntrospectionClientOptions {
|
|
4
5
|
issuer: string;
|
|
@@ -6,6 +7,12 @@ export interface IOidcIntrospectionClientOptions {
|
|
|
6
7
|
clientSecret: string;
|
|
7
8
|
timeoutMs?: number;
|
|
8
9
|
maxResponseBytes?: number;
|
|
10
|
+
/**
|
|
11
|
+
* The fetch every introspection request goes through, e.g.
|
|
12
|
+
* `createTrustedCaFetch(caPem)` for an issuer under a private CA. The global
|
|
13
|
+
* `fetch` when absent.
|
|
14
|
+
*/
|
|
15
|
+
fetch?: TOidcFetch;
|
|
9
16
|
}
|
|
10
17
|
|
|
11
18
|
export interface IOidcIntrospectionClientRequest {
|
|
@@ -40,6 +47,7 @@ export class OidcIntrospectionClient {
|
|
|
40
47
|
readonly #authorization: string;
|
|
41
48
|
readonly #timeoutMs: number;
|
|
42
49
|
readonly #maxResponseBytes: number;
|
|
50
|
+
readonly #fetch?: TOidcFetch;
|
|
43
51
|
|
|
44
52
|
constructor(optionsArg: IOidcIntrospectionClientOptions) {
|
|
45
53
|
if (!optionsArg || !exactString(optionsArg.issuer, 2048) || !exactString(optionsArg.clientId)
|
|
@@ -56,6 +64,8 @@ export class OidcIntrospectionClient {
|
|
|
56
64
|
|| !Number.isSafeInteger(this.#maxResponseBytes) || this.#maxResponseBytes < 1 || this.#maxResponseBytes > 65536) {
|
|
57
65
|
throw new OidcIntrospectionError('invalid_request');
|
|
58
66
|
}
|
|
67
|
+
if (optionsArg.fetch !== undefined && typeof optionsArg.fetch !== 'function') throw new OidcIntrospectionError('invalid_request');
|
|
68
|
+
this.#fetch = optionsArg.fetch;
|
|
59
69
|
this.#issuer = canonicalIssuer;
|
|
60
70
|
this.#clientId = optionsArg.clientId;
|
|
61
71
|
// OAuth Basic components are form-encoded separately before joining with ':'.
|
|
@@ -76,11 +86,15 @@ export class OidcIntrospectionClient {
|
|
|
76
86
|
});
|
|
77
87
|
let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;
|
|
78
88
|
try {
|
|
79
|
-
const
|
|
80
|
-
|
|
89
|
+
const url = `${this.#issuer}/oauth/introspect`;
|
|
90
|
+
const init = {
|
|
91
|
+
method: 'POST', redirect: 'error' as const, signal: controller.signal,
|
|
81
92
|
headers: { authorization: this.#authorization, 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' },
|
|
82
93
|
body: new URLSearchParams({ token, subject, organization_id: organizationId, nonce, token_type_hint: 'access_token' }),
|
|
83
|
-
}
|
|
94
|
+
};
|
|
95
|
+
const response = await Promise.race([this.#fetch
|
|
96
|
+
? this.#fetch(url, init)
|
|
97
|
+
: fetch(url, { ...init, credentials: 'omit', cache: 'no-store' }), deadline]);
|
|
84
98
|
if (response.status !== 200) throw new OidcIntrospectionError('unavailable');
|
|
85
99
|
if (response.headers.get('content-type')?.split(';')[0].trim().toLowerCase() !== 'application/json'
|
|
86
100
|
|| !response.headers.get('cache-control')?.toLowerCase().split(',').map((partArg) => partArg.trim()).includes('no-store')
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What the sdk's OIDC clients pass to their fetch: the subset of `RequestInit`
|
|
5
|
+
* that `openid-client` and `OidcIntrospectionClient` use. Node's global `fetch`
|
|
6
|
+
* satisfies it.
|
|
7
|
+
*/
|
|
8
|
+
export interface IOidcFetchInit {
|
|
9
|
+
method: string;
|
|
10
|
+
headers: Record<string, string>;
|
|
11
|
+
body?: ArrayBuffer | ReadableStream | string | Uint8Array | URLSearchParams | null;
|
|
12
|
+
duplex?: 'half';
|
|
13
|
+
/** `manual` answers a redirect as it is; `error` rejects it. Neither follows it. */
|
|
14
|
+
redirect: 'manual' | 'error';
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** A fetch for one OIDC client's requests, e.g. one that trusts the issuer's private CA. */
|
|
19
|
+
export type TOidcFetch = (urlArg: string, initArg: IOidcFetchInit) => Promise<Response>;
|
|
20
|
+
|
|
21
|
+
const pemCertificatePattern = /-----BEGIN CERTIFICATE-----\r?\n[A-Za-z0-9+/=\r\n]+-----END CERTIFICATE-----/g;
|
|
22
|
+
|
|
23
|
+
/** The statuses a fetch answers with a null body. */
|
|
24
|
+
const nullBodyStatuses: ReadonlySet<number> = new Set([101, 103, 204, 205, 304]);
|
|
25
|
+
|
|
26
|
+
/** The statuses fetch treats as redirects. */
|
|
27
|
+
const redirectStatuses: ReadonlySet<number> = new Set([301, 302, 303, 307, 308]);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Idle keep-alive sockets close after this delay, or earlier when the server
|
|
31
|
+
* announces a shorter `Keep-Alive: timeout`, so a pooled socket is not reused
|
|
32
|
+
* as the server closes it.
|
|
33
|
+
*/
|
|
34
|
+
const idleSocketTimeoutMs = 4_000;
|
|
35
|
+
|
|
36
|
+
/** A request body as bytes, with the content type fetch would give it. */
|
|
37
|
+
const encodeBody = async (
|
|
38
|
+
bodyArg: NonNullable<IOidcFetchInit['body']>,
|
|
39
|
+
): Promise<{ bytes: Buffer; contentType?: string }> => {
|
|
40
|
+
if (typeof bodyArg === 'string') {
|
|
41
|
+
return { bytes: Buffer.from(bodyArg, 'utf8'), contentType: 'text/plain;charset=UTF-8' };
|
|
42
|
+
}
|
|
43
|
+
if (bodyArg instanceof URLSearchParams) {
|
|
44
|
+
return { bytes: Buffer.from(bodyArg.toString(), 'utf8'), contentType: 'application/x-www-form-urlencoded;charset=UTF-8' };
|
|
45
|
+
}
|
|
46
|
+
if (bodyArg instanceof ArrayBuffer) {
|
|
47
|
+
return { bytes: Buffer.from(new Uint8Array(bodyArg)) };
|
|
48
|
+
}
|
|
49
|
+
if (bodyArg instanceof Uint8Array) {
|
|
50
|
+
return { bytes: Buffer.from(bodyArg) };
|
|
51
|
+
}
|
|
52
|
+
const chunks: Uint8Array[] = [];
|
|
53
|
+
const reader = bodyArg.getReader();
|
|
54
|
+
while (true) {
|
|
55
|
+
const part = await reader.read();
|
|
56
|
+
if (part.done) {
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
if (!(part.value instanceof Uint8Array)) {
|
|
60
|
+
await reader.cancel();
|
|
61
|
+
throw new TypeError('A request body stream must yield bytes');
|
|
62
|
+
}
|
|
63
|
+
chunks.push(part.value);
|
|
64
|
+
}
|
|
65
|
+
return { bytes: Buffer.concat(chunks) };
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The response body as a fetch body stream, read as it is pulled. Cancelling
|
|
70
|
+
* it destroys the response and so its connection.
|
|
71
|
+
*/
|
|
72
|
+
const webStreamOf = (incomingArg: plugins.http.IncomingMessage): ReadableStream<Uint8Array> => {
|
|
73
|
+
const chunks = incomingArg[Symbol.asyncIterator]();
|
|
74
|
+
return new ReadableStream<Uint8Array>({
|
|
75
|
+
async pull(controllerArg) {
|
|
76
|
+
const part = await chunks.next();
|
|
77
|
+
if (part.done) {
|
|
78
|
+
controllerArg.close();
|
|
79
|
+
} else {
|
|
80
|
+
controllerArg.enqueue(part.value);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
async cancel() {
|
|
84
|
+
await chunks.return?.();
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Every certificate of the given PEM text, each parsed. Anything else in the
|
|
91
|
+
* text, or no certificate at all, is refused: an unreadable trust anchor must
|
|
92
|
+
* fail here, not as a TLS error at the first request.
|
|
93
|
+
*/
|
|
94
|
+
const readTrustedCertificates = (trustedCaPemArg: string | readonly string[]): string[] => {
|
|
95
|
+
const pems = typeof trustedCaPemArg === 'string' ? [trustedCaPemArg] : trustedCaPemArg;
|
|
96
|
+
if (!Array.isArray(pems) || pems.length === 0) {
|
|
97
|
+
throw new TypeError('trustedCaPem must name at least one PEM certificate');
|
|
98
|
+
}
|
|
99
|
+
const certificates: string[] = [];
|
|
100
|
+
for (const pem of pems) {
|
|
101
|
+
if (typeof pem !== 'string') {
|
|
102
|
+
throw new TypeError('trustedCaPem must be PEM certificate text');
|
|
103
|
+
}
|
|
104
|
+
const blocks = pem.match(pemCertificatePattern) ?? [];
|
|
105
|
+
if (blocks.length === 0 || pem.replace(pemCertificatePattern, '').trim() !== '') {
|
|
106
|
+
throw new TypeError('trustedCaPem must contain PEM certificates only');
|
|
107
|
+
}
|
|
108
|
+
for (const block of blocks) {
|
|
109
|
+
try {
|
|
110
|
+
new plugins.crypto.X509Certificate(block);
|
|
111
|
+
} catch {
|
|
112
|
+
throw new TypeError('trustedCaPem contains a certificate that cannot be parsed');
|
|
113
|
+
}
|
|
114
|
+
certificates.push(block);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return certificates;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* A fetch over `node:https` whose connections trust the given CA certificates
|
|
122
|
+
* and nothing else. The agent belongs to this fetch alone: the process-wide
|
|
123
|
+
* trust store, the global `fetch` and its dispatcher stay untouched. Only
|
|
124
|
+
* `https:` URLs are fetched, redirects are never followed, and bodies are
|
|
125
|
+
* requested without a content coding. Idle pooled sockets are unreferenced, so
|
|
126
|
+
* they never keep the process alive.
|
|
127
|
+
*/
|
|
128
|
+
export const createTrustedCaFetch = (trustedCaPemArg: string | readonly string[]): TOidcFetch => {
|
|
129
|
+
const agent = new plugins.https.Agent({
|
|
130
|
+
ca: readTrustedCertificates(trustedCaPemArg),
|
|
131
|
+
keepAlive: true,
|
|
132
|
+
timeout: idleSocketTimeoutMs,
|
|
133
|
+
});
|
|
134
|
+
return async (urlArg, initArg) => {
|
|
135
|
+
const url = new URL(urlArg);
|
|
136
|
+
if (url.protocol !== 'https:') {
|
|
137
|
+
throw new TypeError('A trusted-CA fetch only requests https URLs');
|
|
138
|
+
}
|
|
139
|
+
const signal = initArg.signal;
|
|
140
|
+
signal?.throwIfAborted();
|
|
141
|
+
const headers = new Headers(initArg.headers);
|
|
142
|
+
let body: Buffer | undefined;
|
|
143
|
+
if (initArg.body !== undefined && initArg.body !== null) {
|
|
144
|
+
const encoded = await encodeBody(initArg.body);
|
|
145
|
+
body = encoded.bytes;
|
|
146
|
+
if (encoded.contentType && !headers.has('content-type')) {
|
|
147
|
+
headers.set('content-type', encoded.contentType);
|
|
148
|
+
}
|
|
149
|
+
headers.set('content-length', String(body.byteLength));
|
|
150
|
+
}
|
|
151
|
+
headers.set('accept-encoding', 'identity');
|
|
152
|
+
signal?.throwIfAborted();
|
|
153
|
+
|
|
154
|
+
return new Promise<Response>((resolve, reject) => {
|
|
155
|
+
const request = plugins.https.request(url, {
|
|
156
|
+
method: initArg.method,
|
|
157
|
+
headers: Object.fromEntries(headers.entries()),
|
|
158
|
+
agent,
|
|
159
|
+
});
|
|
160
|
+
// Stays attached for the request's lifetime, so a connection failure
|
|
161
|
+
// while the body is read never becomes an unhandled 'error' event.
|
|
162
|
+
request.on('error', reject);
|
|
163
|
+
// Destroyed without an error on purpose: an error would be re-emitted on
|
|
164
|
+
// the socket, which no longer has a listener once a keep-alive response
|
|
165
|
+
// completed. The response body errors as its connection goes.
|
|
166
|
+
const abort = () => {
|
|
167
|
+
reject(signal?.reason);
|
|
168
|
+
request.destroy();
|
|
169
|
+
};
|
|
170
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
171
|
+
request.once('close', () => signal?.removeEventListener('abort', abort));
|
|
172
|
+
request.on('response', (incoming) => {
|
|
173
|
+
try {
|
|
174
|
+
const status = incoming.statusCode ?? 0;
|
|
175
|
+
if (initArg.redirect === 'error' && redirectStatuses.has(status)) {
|
|
176
|
+
throw new TypeError('The response is a redirect');
|
|
177
|
+
}
|
|
178
|
+
const contentEncoding = incoming.headers['content-encoding'];
|
|
179
|
+
if (contentEncoding !== undefined && contentEncoding.trim().toLowerCase() !== 'identity') {
|
|
180
|
+
throw new TypeError('The response has a content coding');
|
|
181
|
+
}
|
|
182
|
+
// same combination rules as fetch: repeated fields join with ", "
|
|
183
|
+
const responseHeaders = new Headers();
|
|
184
|
+
for (let index = 0; index < incoming.rawHeaders.length; index += 2) {
|
|
185
|
+
responseHeaders.append(incoming.rawHeaders[index], incoming.rawHeaders[index + 1]);
|
|
186
|
+
}
|
|
187
|
+
const withoutBody = nullBodyStatuses.has(status) || initArg.method.toUpperCase() === 'HEAD';
|
|
188
|
+
if (withoutBody) {
|
|
189
|
+
incoming.resume();
|
|
190
|
+
}
|
|
191
|
+
resolve(new Response(withoutBody ? null : webStreamOf(incoming), {
|
|
192
|
+
status,
|
|
193
|
+
statusText: incoming.statusMessage,
|
|
194
|
+
headers: responseHeaders,
|
|
195
|
+
}));
|
|
196
|
+
} catch (error) {
|
|
197
|
+
reject(error);
|
|
198
|
+
request.destroy();
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
request.end(body);
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
};
|
package/ts_server/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './classes.account-auth-service.js';
|
|
|
3
3
|
export * from './classes.account-doc.js';
|
|
4
4
|
export * from './classes.account-store.js';
|
|
5
5
|
export * from './classes.idp-global-server-client.js';
|
|
6
|
+
export * from './helpers.trusted-ca-fetch.js';
|
|
6
7
|
export * from './classes.oidc-introspection-client.js';
|
|
7
8
|
export * from './classes.oidc-userinfo-client.js';
|
|
8
9
|
export * from './classes.password-hasher.js';
|
package/ts_server/plugins.ts
CHANGED