@voltro/plugin-sso-saml 0.33.0 → 0.35.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/dist/index.d.ts CHANGED
@@ -290,6 +290,33 @@ export declare interface SamlSsoPluginOptions {
290
290
  * `NotOnOrAfter` rejections. Wired to node-saml's `acceptedClockSkewMs`.
291
291
  */
292
292
  readonly acceptedClockSkewMs?: number;
293
+ /**
294
+ * Require the `<samlp:Response>` ENVELOPE to carry its own signature, in
295
+ * addition to the assertion signature.
296
+ *
297
+ * **The assertion signature is always required and is not configurable.** It
298
+ * is the one that matters: only signature-covered XML is ever read, and the
299
+ * assertion is what carries the NameID, the attributes, the audience
300
+ * restriction, the validity window and the `SubjectConfirmationData`. An
301
+ * envelope signature adds coverage of the response-level `Status`,
302
+ * `Destination` and `InResponseTo` — real, but a smaller surface than the
303
+ * name suggests.
304
+ *
305
+ * - `false` (default) — assertion-signed responses are accepted. This is
306
+ * Okta's default application profile ("Sign assertion", response
307
+ * unsigned), and Azure AD's, so it is what most deployments send.
308
+ * - `true` — both signatures required. Set this when your IdP signs the
309
+ * response (it is one checkbox on Okta and Azure AD) — it is the stronger
310
+ * posture and costs nothing once the IdP is configured for it.
311
+ *
312
+ * Why the default is `false`: it was effectively `true` before this option
313
+ * existed (node-saml's own default) and there was no way to say otherwise, so
314
+ * an Okta deployment on the default application could not log in at all. A
315
+ * refusal an operator cannot configure their way out of is not a stronger
316
+ * posture — it is a wall people climb by abandoning the plugin. The floor
317
+ * that actually protects the identity, `wantAssertionsSigned`, never moved.
318
+ */
319
+ readonly wantAuthnResponseSigned?: boolean;
293
320
  /**
294
321
  * Assertion-replay / `InResponseTo` protection. When enabled, node-saml is
295
322
  * configured with `validateInResponseTo: 'always'` and a cache: the
@@ -297,17 +324,32 @@ export declare interface SamlSsoPluginOptions {
297
324
  * a captured `SAMLResponse` can't be replayed and an unsolicited IdP-initiated
298
325
  * POST (no matching request) is rejected.
299
326
  *
300
- * - `false` (default) — OFF (node-saml default; single captured response
301
- * replayable within its validity window). Keep the default only for a
302
- * single-replica dev/PoC.
327
+ * - `{ store: true }` (**default**) — ON, backed by the framework DataStore
328
+ * (a contributed `_voltro_saml_replay` table). Shared across replicas, so
329
+ * a login on one process and its ACS on another still pair up. Requires
330
+ * `store:write` (table DDL); the plugin declares it. `ttlMs` bounds how
331
+ * long an outstanding request stays valid (default 10 min).
303
332
  * - `true` — ON with an in-PROCESS cache. Correct for ONE replica; under
304
333
  * >1 replica a login and its ACS can land on different processes and the
305
334
  * check breaks. Boot warns when this is used.
306
- * - `{ store: true }` — ON backed by the framework DataStore (a contributed
307
- * `_voltro_saml_replay` table). Shared across replicas the correct
308
- * production choice. Requires `store:write` (table DDL); the plugin
309
- * declares it. `ttlMs` bounds how long an outstanding request stays valid
310
- * (default 10 min).
335
+ * - `false` — OFF. **This is also the switch that re-enables IdP-INITIATED
336
+ * SSO** (the app-tile flow)see below.
337
+ *
338
+ * **What ON costs: unsolicited responses are refused.** `validateInResponseTo:
339
+ * 'always'` means a `SAMLResponse` with no `InResponseTo` — which is exactly
340
+ * an IdP-initiated login, started from the Okta / Azure dashboard tile rather
341
+ * than from `/saml/login` — is rejected. There is no way to keep replay
342
+ * protection and IdP-initiated SSO at the same time, and the reason is
343
+ * structural rather than an implementation limit: the protection IS the
344
+ * requirement that the response answer a request this SP issued, and an
345
+ * unsolicited response answers none. `'ifPresent'` looks like the compromise
346
+ * and is not one — an attacker replaying a captured response simply DELETES
347
+ * the attribute and the check declines to run.
348
+ *
349
+ * So if you need the app tile, set `replayProtection: false` deliberately and
350
+ * know what you are accepting: a captured response is replayable for as long
351
+ * as its assertion is valid. Prefer pointing users at `/saml/login`, and
352
+ * prefer setting `wantAuthnResponseSigned: true` if you must run unsolicited.
311
353
  */
312
354
  readonly replayProtection?: boolean | {
313
355
  readonly store: true;
@@ -326,6 +368,19 @@ export declare interface SamlSsoPluginOptions {
326
368
  readonly sloStore?: boolean | {
327
369
  readonly store: true;
328
370
  };
371
+ /**
372
+ * Namespace for this plugin's HTTP mount + inspect surface. Default `sso-saml`.
373
+ *
374
+ * Set it when your app already publishes under that name — an exact tag
375
+ * collision is fatal at codegen, and this is the way out. Orthogonal to
376
+ * `name` below: `alias` REPLACES the namespace, `name` distinguishes two
377
+ * installations within it.
378
+ */
379
+ readonly alias?: string;
380
+ /**
381
+ * Discriminator for a SECOND installation of this plugin, when one app runs
382
+ * two (`@voltro/plugin-sso-saml#eu`). Not a rename — for that use `alias`.
383
+ */
329
384
  readonly name?: string;
330
385
  }
331
386