@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 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.2.0',
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 refuses anything else */
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 bounds discovery itself and stays on the
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), { timeout: this.requestTimeoutSeconds });
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 response = await Promise.race([fetch(`${this.#issuer}/oauth/introspect`, {
68
- method: 'POST', redirect: 'error', credentials: 'omit', cache: 'no-store', signal: controller.signal,
69
- headers: { authorization: this.#authorization, 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' },
70
- body: new URLSearchParams({ token, subject, organization_id: organizationId, nonce, token_type_hint: 'access_token' }),
71
- }), deadline]);
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';
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19zZXJ2ZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLG1DQUFtQyxDQUFDO0FBQ2xELGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLHVDQUF1QyxDQUFDO0FBQ3RELGNBQWMsd0NBQXdDLENBQUM7QUFDdkQsY0FBYyxtQ0FBbUMsQ0FBQztBQUNsRCxjQUFjLDhCQUE4QixDQUFDIn0=
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19zZXJ2ZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxjQUFjLG1DQUFtQyxDQUFDO0FBQ2xELGNBQWMsMEJBQTBCLENBQUM7QUFDekMsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLHVDQUF1QyxDQUFDO0FBQ3RELGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyx3Q0FBd0MsQ0FBQztBQUN2RCxjQUFjLG1DQUFtQyxDQUFDO0FBQ2xELGNBQWMsOEJBQThCLENBQUMifQ==
@@ -1,5 +1,7 @@
1
1
  import * as crypto from 'crypto';
2
- export { crypto };
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
- export { crypto };
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3NlcnZlci9wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBRWpDLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQztBQUVsQixPQUFPLEtBQUssYUFBYSxNQUFNLHdCQUF3QixDQUFDO0FBRXhELE9BQU8sRUFBRSxhQUFhLEVBQUUsQ0FBQztBQUV6QixPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFFdkQsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsQ0FBQztBQUVyQyxPQUFPLEtBQUssT0FBTyxNQUFNLDhCQUE4QixDQUFDO0FBQ3hELE9BQU8sS0FBSyxZQUFZLE1BQU0sMEJBQTBCLENBQUM7QUFFekQsT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsQ0FBQyJ9
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3NlcnZlci9wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxLQUFLLE1BQU0sWUFBWSxDQUFDO0FBRXBDLE9BQU8sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDO0FBRS9CLE9BQU8sS0FBSyxhQUFhLE1BQU0sd0JBQXdCLENBQUM7QUFFeEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxDQUFDO0FBRXpCLE9BQU8sS0FBSyxZQUFZLE1BQU0sMEJBQTBCLENBQUM7QUFDekQsT0FBTyxLQUFLLFdBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUV2RCxPQUFPLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxDQUFDO0FBRXJDLE9BQU8sS0FBSyxPQUFPLE1BQU0sOEJBQThCLENBQUM7QUFDeEQsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUV6RCxPQUFPLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxDQUFDIn0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idp.global/sdk",
3
- "version": "18.2.0",
3
+ "version": "18.3.0",
4
4
  "private": false,
5
5
  "description": "Reusable browser and server SDK for idp.global authentication.",
6
6
  "type": "module",
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, and optional deadline/response limits. |
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. |
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@idp.global/sdk',
6
- version: '18.2.0',
6
+ version: '18.3.0',
7
7
  description: 'Reusable browser and server SDK for idp.global authentication.'
8
8
  }
@@ -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 refuses anything else */
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 bounds discovery itself and stays on the
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
- { timeout: this.requestTimeoutSeconds },
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 response = await Promise.race([fetch(`${this.#issuer}/oauth/introspect`, {
80
- method: 'POST', redirect: 'error', credentials: 'omit', cache: 'no-store', signal: controller.signal,
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
- }), deadline]);
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
+ };
@@ -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';
@@ -1,6 +1,8 @@
1
1
  import * as crypto from 'crypto';
2
+ import * as http from 'node:http';
3
+ import * as https from 'node:https';
2
4
 
3
- export { crypto };
5
+ export { crypto, http, https };
4
6
 
5
7
  import * as idpInterfaces from '@idp.global/interfaces';
6
8