@genesislcap/foundation-auth 15.22.0 → 15.22.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"authFormEntry.d.ts","sourceRoot":"","sources":["../../../src/store/authFormEntry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authFormEntry.d.ts","sourceRoot":"","sources":["../../../src/store/authFormEntry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { CredentialData, GetCredentialOptions } from '../credential/types';
2
+ /**
3
+ * The subset of `CredentialManager` this helper needs. Structural on purpose: it keeps this module
4
+ * free of the store/config import chain (which reaches image and translation assets and so cannot
5
+ * be loaded by the unit-test runner), so the behaviour below is directly testable.
6
+ *
7
+ * @internal
8
+ */
9
+ export interface StoredCredentialSources {
10
+ getCredentialsFromContainer(options?: GetCredentialOptions): Promise<CredentialData | null>;
11
+ /**
12
+ * Note the asymmetry with the container: this one is SYNCHRONOUS and yields `undefined`, not a
13
+ * promise of `null`. Mirrored exactly from `CredentialManager` so a real manager is assignable
14
+ * without a cast, and so the `?? null` normalisation below is visibly necessary rather than
15
+ * defensive noise.
16
+ */
17
+ getCredentialsFromCookie(): CredentialData | undefined;
18
+ }
19
+ /**
20
+ * Read any stored credential, tolerating sources that are unavailable.
21
+ *
22
+ * GENC-1581. `getCredentialsFromContainer` calls `navigator.credentials.get()`, which REJECTS
23
+ * outright where the Credential Management API is not permitted — most commonly a cross-origin
24
+ * iframe, where it throws:
25
+ *
26
+ * ```
27
+ * NotAllowedError: The following credential operations can only occur in a document which is
28
+ * same-origin with all of its ancestors: storage/retrieval of 'PasswordCredential' …
29
+ * ```
30
+ *
31
+ * That rejection used to propagate out of `autofill`, whose single `try` also wrapped the
32
+ * `DEFAULT_USER` / `DEFAULT_PASSWORD` fallback — so the defaults were skipped and the login form
33
+ * was left blank with nothing but a logged error. Any cross-origin embed of a Genesis app (the
34
+ * Genesis Create preview being the case that surfaced it) could therefore never use the configured
35
+ * defaults.
36
+ *
37
+ * Failing to READ a stored credential is not a reason to withhold the defaults: it means we do not
38
+ * know of one, which is precisely the case the fallback exists to cover. Each source is isolated so
39
+ * one throwing does not lose the other — a usable cookie still survives an unavailable container,
40
+ * which matters for the Neptune cookie upgrade path.
41
+ *
42
+ * @param sources - the credential manager
43
+ * @returns `[containerData, cookieData]`, either slot `null` when that source threw or held nothing
44
+ * @internal
45
+ */
46
+ export declare function readStoredCredentials(sources: StoredCredentialSources, onError?: (message: string, err: unknown) => void): Promise<[CredentialData | null, CredentialData | null]>;
47
+ //# sourceMappingURL=readStoredCredentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readStoredCredentials.d.ts","sourceRoot":"","sources":["../../../src/store/readStoredCredentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhF;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC,2BAA2B,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC5F;;;;;OAKG;IACH,wBAAwB,IAAI,cAAc,GAAG,SAAS,CAAC;CACxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,uBAAuB,EAChC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,GAChD,OAAO,CAAC,CAAC,cAAc,GAAG,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC,CAAC,CAiBzD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=readStoredCredentials.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readStoredCredentials.test.d.ts","sourceRoot":"","sources":["../../../src/store/readStoredCredentials.test.ts"],"names":[],"mappings":""}
@@ -6,6 +6,7 @@ import { AuthConfig } from '../config/config';
6
6
  import { CredentialManager, credentialSeparator } from '../credential';
7
7
  import { IDPService } from '../services';
8
8
  import { logger } from '../utils';
9
+ import { readStoredCredentials } from './readStoredCredentials';
9
10
  /**
10
11
  * Default AuthFormEntryStore.
11
12
  * @public
@@ -120,8 +121,40 @@ export class DefaultAuthFormEntryStore extends AbstractStore {
120
121
  * from cookies if the container is empty. These cookies become irrelevant after first login using container.
121
122
  */
122
123
  this.autofilling = true;
123
- const containerData = yield this.credentialManager.getCredentialsFromContainer();
124
- const cookieData = yield this.credentialManager.getCredentialsFromCookie();
124
+ /**
125
+ * Stored-credential lookup is BEST EFFORT and must not take the DEFAULT_* fallback below down
126
+ * with it. `getCredentialsFromContainer` calls `navigator.credentials.get()`, which REJECTS
127
+ * outright in contexts where the Credential Management API is unavailable — most commonly a
128
+ * cross-origin iframe, where it throws
129
+ *
130
+ * NotAllowedError: The following credential operations can only occur in a document which
131
+ * is same-origin with all of its ancestors: storage/retrieval of 'PasswordCredential' …
132
+ *
133
+ * Previously one `try` wrapped both this lookup and the DEFAULT_USER/DEFAULT_PASSWORD
134
+ * fallback, so that rejection skipped the fallback entirely and the form was left blank with
135
+ * only a logged error to show for it. Anything that embeds a Genesis app cross-origin — the
136
+ * Genesis Create preview being the case that surfaced it — could therefore never use the
137
+ * configured defaults.
138
+ *
139
+ * Failing to READ a stored credential is not a reason to withhold the defaults: it means we
140
+ * do not know of one, which is exactly the `!credentialData` case the fallback exists for.
141
+ */
142
+ const [containerData, cookieData] = yield readStoredCredentials(this.credentialManager,
143
+ /**
144
+ * An unavailable credential store is EXPECTED in a cross-origin embed, so it logs at
145
+ * `debug` — but a genuine malfunction should still be audible. `getCredentialsFromCookie`
146
+ * does `JSON.parse(cookie)`, so a malformed cookie throws a SyntaxError through here, and
147
+ * that wants saying out loud. `credentialManager` already uses `warn` for the adjacent
148
+ * "not available in this browser" case.
149
+ */
150
+ (message, err) => {
151
+ const name = err instanceof Error ? err.name : '';
152
+ const expected = name === 'NotAllowedError' || name === 'SecurityError';
153
+ if (expected)
154
+ logger.debug(message, err);
155
+ else
156
+ logger.warn(message, err);
157
+ });
125
158
  const [normalisedData, canRemoveCookie] = this.credentialManager.normaliseLegacyCredentialData(containerData, cookieData);
126
159
  if (cookieData && canRemoveCookie) {
127
160
  /**
@@ -130,13 +163,6 @@ export class DefaultAuthFormEntryStore extends AbstractStore {
130
163
  this.credentialManager.removeCookie();
131
164
  }
132
165
  credentialData = normalisedData;
133
- if (!credentialData && (DEFAULT_USER || DEFAULT_PASSWORD || DEFAULT_ORGANISATION)) {
134
- this.username = DEFAULT_USER !== null && DEFAULT_USER !== void 0 ? DEFAULT_USER : '';
135
- this.password = DEFAULT_PASSWORD !== null && DEFAULT_PASSWORD !== void 0 ? DEFAULT_PASSWORD : '';
136
- if (this.config.fields.organisation && DEFAULT_ORGANISATION) {
137
- this.organisation = DEFAULT_ORGANISATION;
138
- }
139
- }
140
166
  if (credentialData) {
141
167
  const passwordCredentials = credentialData;
142
168
  this.username = (_a = passwordCredentials.name) !== null && _a !== void 0 ? _a : '';
@@ -176,6 +202,20 @@ export class DefaultAuthFormEntryStore extends AbstractStore {
176
202
  catch (err) {
177
203
  logger.error('An error occurred attempting to get and autofill from stored credentials.', err);
178
204
  }
205
+ /**
206
+ * OUTSIDE the try on purpose. The defaults are the fallback for "we have no stored credential",
207
+ * and every way of arriving there — none stored, an unreadable store, or an unexpected throw
208
+ * anywhere above — must reach them. Keeping this inside the try is what made a single rejecting
209
+ * call silently skip it, and leaving it there would preserve that shape while relying on
210
+ * nothing above it ever throwing again.
211
+ */
212
+ if (!credentialData && (DEFAULT_USER || DEFAULT_PASSWORD || DEFAULT_ORGANISATION)) {
213
+ this.username = DEFAULT_USER !== null && DEFAULT_USER !== void 0 ? DEFAULT_USER : '';
214
+ this.password = DEFAULT_PASSWORD !== null && DEFAULT_PASSWORD !== void 0 ? DEFAULT_PASSWORD : '';
215
+ if (this.config.fields.organisation && DEFAULT_ORGANISATION) {
216
+ this.organisation = DEFAULT_ORGANISATION;
217
+ }
218
+ }
179
219
  this.autofilling = false;
180
220
  return Promise.resolve(!!credentialData);
181
221
  });
@@ -0,0 +1,48 @@
1
+ import { __awaiter } from "tslib";
2
+ /**
3
+ * Read any stored credential, tolerating sources that are unavailable.
4
+ *
5
+ * GENC-1581. `getCredentialsFromContainer` calls `navigator.credentials.get()`, which REJECTS
6
+ * outright where the Credential Management API is not permitted — most commonly a cross-origin
7
+ * iframe, where it throws:
8
+ *
9
+ * ```
10
+ * NotAllowedError: The following credential operations can only occur in a document which is
11
+ * same-origin with all of its ancestors: storage/retrieval of 'PasswordCredential' …
12
+ * ```
13
+ *
14
+ * That rejection used to propagate out of `autofill`, whose single `try` also wrapped the
15
+ * `DEFAULT_USER` / `DEFAULT_PASSWORD` fallback — so the defaults were skipped and the login form
16
+ * was left blank with nothing but a logged error. Any cross-origin embed of a Genesis app (the
17
+ * Genesis Create preview being the case that surfaced it) could therefore never use the configured
18
+ * defaults.
19
+ *
20
+ * Failing to READ a stored credential is not a reason to withhold the defaults: it means we do not
21
+ * know of one, which is precisely the case the fallback exists to cover. Each source is isolated so
22
+ * one throwing does not lose the other — a usable cookie still survives an unavailable container,
23
+ * which matters for the Neptune cookie upgrade path.
24
+ *
25
+ * @param sources - the credential manager
26
+ * @returns `[containerData, cookieData]`, either slot `null` when that source threw or held nothing
27
+ * @internal
28
+ */
29
+ export function readStoredCredentials(sources, onError) {
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ var _a, _b;
32
+ let containerData = null;
33
+ let cookieData = null;
34
+ try {
35
+ containerData = (_a = (yield sources.getCredentialsFromContainer())) !== null && _a !== void 0 ? _a : null;
36
+ }
37
+ catch (err) {
38
+ onError === null || onError === void 0 ? void 0 : onError('Credential container unavailable; continuing without a stored credential.', err);
39
+ }
40
+ try {
41
+ cookieData = (_b = (yield sources.getCredentialsFromCookie())) !== null && _b !== void 0 ? _b : null;
42
+ }
43
+ catch (err) {
44
+ onError === null || onError === void 0 ? void 0 : onError('Credential cookie unavailable; continuing without a stored credential.', err);
45
+ }
46
+ return [containerData, cookieData];
47
+ });
48
+ }
@@ -0,0 +1,100 @@
1
+ import { __awaiter } from "tslib";
2
+ import { assert, suite } from '@genesislcap/foundation-testing';
3
+ import { readStoredCredentials } from './readStoredCredentials';
4
+ /**
5
+ * GENC-1581 — the DEFAULT_USER / DEFAULT_PASSWORD fallback must survive a Credential Management
6
+ * API that rejects.
7
+ *
8
+ * `getCredentialsFromContainer()` calls `navigator.credentials.get()`, which throws outright where
9
+ * the API is unavailable — most commonly a cross-origin iframe:
10
+ *
11
+ * NotAllowedError: The following credential operations can only occur in a document which is
12
+ * same-origin with all of its ancestors: storage/retrieval of 'PasswordCredential' …
13
+ *
14
+ * One `try` used to wrap both that lookup and the DEFAULT_* fallback, so the rejection skipped the
15
+ * fallback and left the form blank. `readStoredCredentials` now isolates the lookup.
16
+ *
17
+ * These tests drive `readStoredCredentials` directly rather than `autofill`, because `autofill`
18
+ * reads the DEFAULT_* values from build-time defines that a unit test cannot set. What is testable
19
+ * — and what actually broke — is that a throwing source degrades to `null` instead of propagating.
20
+ */
21
+ const s = suite('readStoredCredentials (GENC-1581)');
22
+ /**
23
+ * The helper lives in its own module precisely so it can be tested: `authFormEntry` transitively
24
+ * imports image and translation assets through `config/config.ts`, which the unit-test runner
25
+ * cannot load.
26
+ */
27
+ const read = (manager) => readStoredCredentials(manager);
28
+ const NOT_ALLOWED = () => {
29
+ const err = new Error("The following credential operations can only occur in a document which is same-origin with all of its ancestors: storage/retrieval of 'PasswordCredential' and 'FederatedCredential', storage of 'PublicKeyCredential'.");
30
+ err.name = 'NotAllowedError';
31
+ throw err;
32
+ };
33
+ s('a rejecting credential container degrades to null instead of throwing', () => __awaiter(void 0, void 0, void 0, function* () {
34
+ const result = read({
35
+ getCredentialsFromContainer: NOT_ALLOWED,
36
+ getCredentialsFromCookie: () => undefined,
37
+ });
38
+ const [containerData, cookieData] = yield result;
39
+ assert.is(containerData, null, 'a NotAllowedError must not escape');
40
+ assert.is(cookieData, null);
41
+ }));
42
+ s('a rejecting cookie read degrades to null too', () => __awaiter(void 0, void 0, void 0, function* () {
43
+ const result = read({
44
+ getCredentialsFromContainer: () => __awaiter(void 0, void 0, void 0, function* () { return null; }),
45
+ getCredentialsFromCookie: NOT_ALLOWED,
46
+ });
47
+ const [containerData, cookieData] = yield result;
48
+ assert.is(containerData, null);
49
+ assert.is(cookieData, null);
50
+ }));
51
+ s('both rejecting still resolves — the caller can reach its fallback', () => __awaiter(void 0, void 0, void 0, function* () {
52
+ // The exact cross-origin-iframe shape: neither source is usable. Before the fix this rejected
53
+ // and the DEFAULT_* fallback below the call site never ran.
54
+ const result = read({
55
+ getCredentialsFromContainer: NOT_ALLOWED,
56
+ getCredentialsFromCookie: NOT_ALLOWED,
57
+ });
58
+ assert.equal(yield result, [null, null]);
59
+ }));
60
+ s('a real stored credential is still returned untouched', () => __awaiter(void 0, void 0, void 0, function* () {
61
+ // The guard must not swallow success: a working container still wins over the defaults.
62
+ const stored = { id: 'JohnDoe', name: 'JohnDoe', password: 'hunter2' };
63
+ const result = read({
64
+ getCredentialsFromContainer: () => __awaiter(void 0, void 0, void 0, function* () { return stored; }),
65
+ getCredentialsFromCookie: () => undefined,
66
+ });
67
+ const [containerData] = yield result;
68
+ assert.is(containerData, stored);
69
+ }));
70
+ s('a cookie credential survives a throwing container (the legacy upgrade path)', () => __awaiter(void 0, void 0, void 0, function* () {
71
+ // Neptune upgrade: container unavailable, cookie present. Isolating the two reads means the
72
+ // cookie is still found — previously the container throw lost it as well.
73
+ const cookie = { id: 'JaneDoe', name: 'JaneDoe', password: 'hunter2' };
74
+ const result = read({
75
+ getCredentialsFromContainer: NOT_ALLOWED,
76
+ getCredentialsFromCookie: () => cookie,
77
+ });
78
+ const [containerData, cookieData] = yield result;
79
+ assert.is(containerData, null);
80
+ assert.is(cookieData, cookie, 'a usable cookie must not be lost to an unrelated container error');
81
+ }));
82
+ s('reports each failure through onError so the caller can choose a log level', () => {
83
+ // The helper deliberately does not decide severity: an unavailable store is expected in a
84
+ // cross-origin embed (debug), while a malformed cookie hitting JSON.parse is a real malfunction
85
+ // (warn). authFormEntry discriminates on error name, which it can only do if BOTH the message
86
+ // and the original error reach it.
87
+ const seen = [];
88
+ const bad = () => {
89
+ const e = new Error('Unexpected token in JSON');
90
+ e.name = 'SyntaxError';
91
+ throw e;
92
+ };
93
+ return readStoredCredentials({ getCredentialsFromContainer: NOT_ALLOWED, getCredentialsFromCookie: bad }, (message, err) => seen.push({ message, name: err instanceof Error ? err.name : '' })).then(() => {
94
+ assert.is(seen.length, 2, 'both sources report');
95
+ assert.equal(seen.map((x) => x.name), ['NotAllowedError', 'SyntaxError'], 'the original error is passed through, not just a message');
96
+ assert.ok(seen[0].message.includes('container'));
97
+ assert.ok(seen[1].message.includes('cookie'));
98
+ });
99
+ });
100
+ s.run();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/foundation-auth",
3
3
  "description": "Genesis Foundation Auth",
4
- "version": "15.22.0",
4
+ "version": "15.22.2",
5
5
  "license": "SEE LICENSE IN license.txt",
6
6
  "main": "dist/esm/index.js",
7
7
  "types": "dist/foundation-auth.d.ts",
@@ -134,25 +134,25 @@
134
134
  }
135
135
  },
136
136
  "devDependencies": {
137
- "@genesislcap/foundation-testing": "15.22.0",
138
- "@genesislcap/genx": "15.22.0",
139
- "@genesislcap/rollup-builder": "15.22.0",
140
- "@genesislcap/ts-builder": "15.22.0",
141
- "@genesislcap/uvu-playwright-builder": "15.22.0",
142
- "@genesislcap/vite-builder": "15.22.0",
143
- "@genesislcap/webpack-builder": "15.22.0"
137
+ "@genesislcap/foundation-testing": "15.22.2",
138
+ "@genesislcap/genx": "15.22.2",
139
+ "@genesislcap/rollup-builder": "15.22.2",
140
+ "@genesislcap/ts-builder": "15.22.2",
141
+ "@genesislcap/uvu-playwright-builder": "15.22.2",
142
+ "@genesislcap/vite-builder": "15.22.2",
143
+ "@genesislcap/webpack-builder": "15.22.2"
144
144
  },
145
145
  "dependencies": {
146
- "@genesislcap/foundation-comms": "15.22.0",
147
- "@genesislcap/foundation-events": "15.22.0",
148
- "@genesislcap/foundation-i18n": "15.22.0",
149
- "@genesislcap/foundation-logger": "15.22.0",
150
- "@genesislcap/foundation-state-machine": "15.22.0",
151
- "@genesislcap/foundation-store": "15.22.0",
152
- "@genesislcap/foundation-ui": "15.22.0",
153
- "@genesislcap/foundation-user": "15.22.0",
154
- "@genesislcap/foundation-utils": "15.22.0",
155
- "@genesislcap/foundation-zero": "15.22.0",
146
+ "@genesislcap/foundation-comms": "15.22.2",
147
+ "@genesislcap/foundation-events": "15.22.2",
148
+ "@genesislcap/foundation-i18n": "15.22.2",
149
+ "@genesislcap/foundation-logger": "15.22.2",
150
+ "@genesislcap/foundation-state-machine": "15.22.2",
151
+ "@genesislcap/foundation-store": "15.22.2",
152
+ "@genesislcap/foundation-ui": "15.22.2",
153
+ "@genesislcap/foundation-user": "15.22.2",
154
+ "@genesislcap/foundation-utils": "15.22.2",
155
+ "@genesislcap/foundation-zero": "15.22.2",
156
156
  "@microsoft/fast-components": "2.30.6",
157
157
  "@microsoft/fast-element": "1.14.0",
158
158
  "@microsoft/fast-foundation": "2.50.0",