@camstack/addon-auth 1.2.171 → 1.2.172
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 +6 -0
- package/dist/{dist-CAPIgbvM.mjs → dist-Dvcuof5S.mjs} +901 -115
- package/dist/{dist-BCzztoSM.js → dist-xyaDmv1T.js} +901 -115
- package/dist/oidc/auth-oidc.addon.js +76 -130
- package/dist/oidc/auth-oidc.addon.mjs +76 -130
- package/dist/webauthn/_stub.js +1 -1
- package/dist/webauthn/{_virtual_mf-localSharedImportMap___mfe_internal__addon_auth_webauthn_widgets-cmM4lkBD.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_auth_webauthn_widgets-U5-CdChb.mjs} +2 -2
- package/dist/webauthn/_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CQJ6wKXR.mjs +26 -0
- package/dist/webauthn/auth-webauthn.addon.js +1 -1
- package/dist/webauthn/auth-webauthn.addon.mjs +1 -1
- package/dist/webauthn/{hostInit-hRFE010M.mjs → hostInit-D-l58LQN.mjs} +2 -2
- package/dist/webauthn/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/dist/webauthn/_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Di6YsQxe.mjs +0 -26
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
5
|
+
const require_dist = require("../dist-xyaDmv1T.js");
|
|
6
6
|
let node_crypto = require("node:crypto");
|
|
7
7
|
node_crypto = require_dist.__toESM(node_crypto);
|
|
8
8
|
//#region ../../node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
@@ -867,16 +867,6 @@ function updateOidcConnection(config, id, patch) {
|
|
|
867
867
|
clearClientSecret: patch.clearClientSecret === true
|
|
868
868
|
};
|
|
869
869
|
}
|
|
870
|
-
function deleteOidcConnection(config, id) {
|
|
871
|
-
if (!config.providers.some((p) => p.id === id)) return {
|
|
872
|
-
ok: false,
|
|
873
|
-
reason: "not-found"
|
|
874
|
-
};
|
|
875
|
-
return {
|
|
876
|
-
ok: true,
|
|
877
|
-
config: { providers: config.providers.filter((p) => p.id !== id) }
|
|
878
|
-
};
|
|
879
|
-
}
|
|
880
870
|
/** Map a wire `clientSecret` field into an update patch fragment. */
|
|
881
871
|
function clientSecretPatchOf(value) {
|
|
882
872
|
if (value === void 0) return {};
|
|
@@ -897,7 +887,7 @@ var OidcProviderBodySchema = require_dist.object({
|
|
|
897
887
|
icon: require_dist.string(),
|
|
898
888
|
issuerUrl: require_dist.string(),
|
|
899
889
|
clientId: require_dist.string(),
|
|
900
|
-
clientSecret: require_dist.string().meta({ secret: true }),
|
|
890
|
+
clientSecret: require_dist.string().optional().meta({ secret: true }),
|
|
901
891
|
redirectUri: require_dist.string(),
|
|
902
892
|
scopes: require_dist.string(),
|
|
903
893
|
usernameClaim: usernameClaimSchema
|
|
@@ -917,6 +907,14 @@ function rowToProvider(id, data) {
|
|
|
917
907
|
id
|
|
918
908
|
};
|
|
919
909
|
}
|
|
910
|
+
/** The stored body of a row; an empty or non-text secret is left out. */
|
|
911
|
+
function bodyOf(row) {
|
|
912
|
+
const { id: _id, clientSecret, ...rest } = row;
|
|
913
|
+
return typeof clientSecret === "string" && clientSecret !== "" ? {
|
|
914
|
+
...rest,
|
|
915
|
+
clientSecret
|
|
916
|
+
} : rest;
|
|
917
|
+
}
|
|
920
918
|
var OidcProviderStore = class OidcProviderStore {
|
|
921
919
|
kind;
|
|
922
920
|
constructor(kind) {
|
|
@@ -929,46 +927,60 @@ var OidcProviderStore = class OidcProviderStore {
|
|
|
929
927
|
const page = await this.kind.query({ limit: 1e3 });
|
|
930
928
|
const out = [];
|
|
931
929
|
for (const record of page.records) {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
const resolved = await this.kind.getResolved(record.id);
|
|
935
|
-
if (resolved !== null) data = resolved.data;
|
|
936
|
-
} catch (err) {
|
|
937
|
-
if (!(err instanceof require_dist.RecordSecretUnavailableError)) throw err;
|
|
938
|
-
}
|
|
939
|
-
const parsed = OidcProviderBodySchema.safeParse(data);
|
|
940
|
-
if (!parsed.success) continue;
|
|
941
|
-
out.push(rowToProvider(record.id, parsed.data));
|
|
930
|
+
const row = await this.getResolved(record.id);
|
|
931
|
+
if (row !== null) out.push(row);
|
|
942
932
|
}
|
|
943
933
|
return out;
|
|
944
934
|
}
|
|
935
|
+
/** One row with its secret resolved for the runtime token call; null when absent. */
|
|
936
|
+
async getResolved(id) {
|
|
937
|
+
let record;
|
|
938
|
+
try {
|
|
939
|
+
record = await this.kind.getResolved(id);
|
|
940
|
+
} catch (err) {
|
|
941
|
+
if (!(err instanceof require_dist.RecordSecretUnavailableError)) throw err;
|
|
942
|
+
const stored = await this.kind.get(id);
|
|
943
|
+
if (stored === null) return null;
|
|
944
|
+
const { clientSecret: _unreadable, ...rest } = stored.data;
|
|
945
|
+
record = {
|
|
946
|
+
...stored,
|
|
947
|
+
data: rest
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
if (record === null) return null;
|
|
951
|
+
const parsed = OidcProviderBodySchema.safeParse(record.data);
|
|
952
|
+
return parsed.success ? rowToProvider(id, parsed.data) : null;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Insert ONE new row (`ifRev: 0`: an existing id is refused). A plaintext
|
|
956
|
+
* `clientSecret` is stored by the records facade under the row's own ref.
|
|
957
|
+
*/
|
|
958
|
+
async create(row) {
|
|
959
|
+
const body = bodyOf(row);
|
|
960
|
+
const parsed = OidcProviderBodySchema.safeParse(body);
|
|
961
|
+
if (!parsed.success) throw new Error(`invalid OIDC provider '${row.id}': ${parsed.error.message}`);
|
|
962
|
+
await this.kind.put({
|
|
963
|
+
id: row.id,
|
|
964
|
+
data: parsed.data
|
|
965
|
+
}, { ifRev: 0 });
|
|
966
|
+
return this.requireRow(row.id);
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Merge a partial into ONE row. `clientSecret`: a plaintext sets it, `undefined`
|
|
970
|
+
* keeps the stored one, `null` clears it.
|
|
971
|
+
*/
|
|
972
|
+
async update(id, partial) {
|
|
973
|
+
await this.kind.patch(id, partial);
|
|
974
|
+
return this.requireRow(id);
|
|
975
|
+
}
|
|
945
976
|
/** Delete one provider record; no other row (nor its secrets) is touched. */
|
|
946
977
|
async remove(id) {
|
|
947
978
|
await this.kind.delete(id);
|
|
948
979
|
}
|
|
949
|
-
async
|
|
950
|
-
const
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
for (const row of providers) {
|
|
954
|
-
const { id, displayName, icon, issuerUrl, clientId, clientSecret, redirectUri, scopes, usernameClaim } = row;
|
|
955
|
-
const body = {
|
|
956
|
-
displayName,
|
|
957
|
-
icon,
|
|
958
|
-
issuerUrl,
|
|
959
|
-
clientId,
|
|
960
|
-
clientSecret,
|
|
961
|
-
redirectUri,
|
|
962
|
-
scopes,
|
|
963
|
-
usernameClaim
|
|
964
|
-
};
|
|
965
|
-
const parsed = oidcProviderEntryKind.schema.safeParse(body);
|
|
966
|
-
if (!parsed.success) throw new Error(`invalid OIDC provider '${id}': ${parsed.error.message}`);
|
|
967
|
-
await this.kind.put({
|
|
968
|
-
id,
|
|
969
|
-
data: parsed.data
|
|
970
|
-
});
|
|
971
|
-
}
|
|
980
|
+
async requireRow(id) {
|
|
981
|
+
const row = await this.getResolved(id);
|
|
982
|
+
if (row === null) throw new Error(`OIDC provider '${id}' is not readable after the write`);
|
|
983
|
+
return row;
|
|
972
984
|
}
|
|
973
985
|
};
|
|
974
986
|
//#endregion
|
|
@@ -1073,7 +1085,7 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
|
|
|
1073
1085
|
super({ ...DEFAULT_CONFIG });
|
|
1074
1086
|
}
|
|
1075
1087
|
async onConfigChanged() {
|
|
1076
|
-
this.activeProviders = await this.
|
|
1088
|
+
if (this.providerStore !== null) this.activeProviders = await this.providerStore.listResolved();
|
|
1077
1089
|
this.rebuildInstances();
|
|
1078
1090
|
}
|
|
1079
1091
|
async onInitialize() {
|
|
@@ -1081,16 +1093,7 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
|
|
|
1081
1093
|
if (records === void 0) throw new Error("auth-oidc: ctx.records is required (hub-only addon)");
|
|
1082
1094
|
await records.declare({ "oidc-provider": oidcProviderEntryKind });
|
|
1083
1095
|
this.providerStore = OidcProviderStore.of(records);
|
|
1084
|
-
this.activeProviders = await this.
|
|
1085
|
-
if ((await this.providerStore.listResolved()).length === 0 && this.config.providers.length > 0) try {
|
|
1086
|
-
await this.providerStore.replaceAll(await this.adoptSecrets(this.config.providers));
|
|
1087
|
-
this.activeProviders = await this.loadPersistedProviders();
|
|
1088
|
-
} catch (err) {
|
|
1089
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1090
|
-
if (!msg.startsWith("records/foreign-marker:")) throw err;
|
|
1091
|
-
this.ctx.logger.warn("OIDC: deferred config→records copy (a secret marker is bound to another row)", { meta: { error: msg } });
|
|
1092
|
-
this.activeProviders = [...this.config.providers];
|
|
1093
|
-
}
|
|
1096
|
+
this.activeProviders = await this.providerStore.listResolved();
|
|
1094
1097
|
this.rebuildInstances();
|
|
1095
1098
|
const authProvider = {
|
|
1096
1099
|
validateCredentials: async () => null,
|
|
@@ -1176,7 +1179,10 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
|
|
|
1176
1179
|
createConnection: async (input) => {
|
|
1177
1180
|
const result = createOidcConnection(this.providersConfig(), input);
|
|
1178
1181
|
if (!result.ok) throw new Error(result.reason === "duplicate-id" ? `An OIDC connection with id "${input.id}" already exists` : `Invalid connection id "${input.id}" — use a lowercase slug`);
|
|
1179
|
-
|
|
1182
|
+
const row = result.config.providers.find((p) => p.id === result.id);
|
|
1183
|
+
if (row === void 0) throw new Error(`Invalid connection id "${input.id}"`);
|
|
1184
|
+
const stored = await this.requireStore().create(row);
|
|
1185
|
+
this.activeProviders = [...this.activeProviders, stored];
|
|
1180
1186
|
this.rebuildInstances();
|
|
1181
1187
|
return { id: result.id };
|
|
1182
1188
|
},
|
|
@@ -1193,21 +1199,21 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
|
|
|
1193
1199
|
...input.usernameClaim !== void 0 ? { usernameClaim: input.usernameClaim } : {}
|
|
1194
1200
|
});
|
|
1195
1201
|
if (!result.ok) throw new Error(`Unknown OIDC connection "${input.id}"`);
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
}
|
|
1202
|
+
const next = result.config.providers.find((p) => p.id === input.id);
|
|
1203
|
+
if (next === void 0) throw new Error(`Unknown OIDC connection "${input.id}"`);
|
|
1204
|
+
const { id: _id, clientSecret: _carried, ...fields } = next;
|
|
1205
|
+
const stored = await this.requireStore().update(input.id, {
|
|
1206
|
+
...fields,
|
|
1207
|
+
...result.clearClientSecret ? { clientSecret: null } : secretPatch.clientSecret !== void 0 ? { clientSecret: secretPatch.clientSecret } : {}
|
|
1208
|
+
});
|
|
1209
|
+
this.activeProviders = this.activeProviders.map((p) => p.id === input.id ? stored : p);
|
|
1203
1210
|
this.rebuildInstances();
|
|
1204
1211
|
return { ok: true };
|
|
1205
1212
|
},
|
|
1206
1213
|
deleteConnection: async (input) => {
|
|
1207
1214
|
if (findOidcProvider(this.providersConfig(), input.id) === null) throw new Error(`Unknown OIDC connection "${input.id}"`);
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
await this.removeProvider(input.id, result.config.providers);
|
|
1215
|
+
await this.requireStore().remove(input.id);
|
|
1216
|
+
this.activeProviders = this.activeProviders.filter((p) => p.id !== input.id);
|
|
1211
1217
|
this.rebuildInstances();
|
|
1212
1218
|
return { ok: true };
|
|
1213
1219
|
}
|
|
@@ -1249,69 +1255,9 @@ var AuthOidcAddon = class extends require_dist.BaseAddon {
|
|
|
1249
1255
|
providersConfig() {
|
|
1250
1256
|
return { providers: this.activeProviders };
|
|
1251
1257
|
}
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
const fromRecords = await store.listResolved();
|
|
1256
|
-
if (fromRecords.length > 0) return fromRecords;
|
|
1257
|
-
}
|
|
1258
|
-
return this.config.providers;
|
|
1259
|
-
}
|
|
1260
|
-
async persistProviders(providers) {
|
|
1261
|
-
const adopted = await this.adoptSecrets(providers);
|
|
1262
|
-
this.activeProviders = [...adopted];
|
|
1263
|
-
const store = this.providerStore;
|
|
1264
|
-
if (store !== null) {
|
|
1265
|
-
await store.replaceAll(adopted);
|
|
1266
|
-
return;
|
|
1267
|
-
}
|
|
1268
|
-
await this.updateGlobalSettings({ providers: [...adopted] });
|
|
1269
|
-
}
|
|
1270
|
-
async removeProvider(id, remaining) {
|
|
1271
|
-
this.activeProviders = [...remaining];
|
|
1272
|
-
const store = this.providerStore;
|
|
1273
|
-
if (store !== null) {
|
|
1274
|
-
await store.remove(id);
|
|
1275
|
-
return;
|
|
1276
|
-
}
|
|
1277
|
-
await this.updateGlobalSettings({ providers: [...remaining] });
|
|
1278
|
-
}
|
|
1279
|
-
/**
|
|
1280
|
-
* A row can still carry a keychain marker bound to the old settings array
|
|
1281
|
-
* (`providers[<id>].clientSecret`, owner auth-oidc) — config rows that never
|
|
1282
|
-
* moved into records. Records refuse a marker that is not the row's own ref, so
|
|
1283
|
-
* every such row is resolved to its value here (re-bound to the record's own ref
|
|
1284
|
-
* on write); a marker that no longer resolves becomes an empty secret the
|
|
1285
|
-
* operator can retype. The value is never logged.
|
|
1286
|
-
*/
|
|
1287
|
-
async adoptSecrets(providers) {
|
|
1288
|
-
const out = [];
|
|
1289
|
-
for (const row of providers) {
|
|
1290
|
-
const secret = row.clientSecret;
|
|
1291
|
-
if (typeof secret === "string") {
|
|
1292
|
-
out.push(row);
|
|
1293
|
-
continue;
|
|
1294
|
-
}
|
|
1295
|
-
if (!require_dist.isSecretMarker(secret)) {
|
|
1296
|
-
out.push({
|
|
1297
|
-
...row,
|
|
1298
|
-
clientSecret: ""
|
|
1299
|
-
});
|
|
1300
|
-
continue;
|
|
1301
|
-
}
|
|
1302
|
-
let plain = "";
|
|
1303
|
-
const secrets = this.ctx.secrets;
|
|
1304
|
-
if (secrets !== void 0) try {
|
|
1305
|
-
const entry = (await secrets.resolve([secret.$secret]))[secret.$secret];
|
|
1306
|
-
if (entry?.kind === "value") plain = entry.value;
|
|
1307
|
-
} catch {}
|
|
1308
|
-
if (plain === "") this.ctx.logger.warn(`OIDC: the client secret of connection "${row.id}" could not be read from the keychain; retype it in its settings`);
|
|
1309
|
-
out.push({
|
|
1310
|
-
...row,
|
|
1311
|
-
clientSecret: plain
|
|
1312
|
-
});
|
|
1313
|
-
}
|
|
1314
|
-
return out;
|
|
1258
|
+
requireStore() {
|
|
1259
|
+
if (this.providerStore === null) throw new Error("auth-oidc: the records store is not ready");
|
|
1260
|
+
return this.providerStore;
|
|
1315
1261
|
}
|
|
1316
1262
|
rebuildInstances() {
|
|
1317
1263
|
this.instances.clear();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as _enum, C as arrayItemFieldPath, D as isSecretClear, E as globalSecretScope, F as string, O as isSecretMarker, P as object, S as RecordSecretUnavailableError, _ as requestMountPrefix, b as errMsg, c as authProviderCapability, d as loginMethodCapability, f as normalizeOrigin, g as pickRequestOrigin, h as parseAppPageLang, i as addonRoutesCapability, k as toSecretFieldView, l as buildAddonRouteProvider, m as parseAppFlowRequest, n as APP_REFUSED_PATH, o as advertisedHubOrigins, p as oidcConnectionsCapability, r as SSO_STATE_COOKIE, s as appFlowLocation, t as APP_FLOW_DEFAULT_REDIRECT, u as claimedRequestOrigins, v as resolveIconKey, w as defineEntryKind, x as BaseAddon } from "../dist-
|
|
1
|
+
import { A as _enum, C as arrayItemFieldPath, D as isSecretClear, E as globalSecretScope, F as string, O as isSecretMarker, P as object, S as RecordSecretUnavailableError, _ as requestMountPrefix, b as errMsg, c as authProviderCapability, d as loginMethodCapability, f as normalizeOrigin, g as pickRequestOrigin, h as parseAppPageLang, i as addonRoutesCapability, k as toSecretFieldView, l as buildAddonRouteProvider, m as parseAppFlowRequest, n as APP_REFUSED_PATH, o as advertisedHubOrigins, p as oidcConnectionsCapability, r as SSO_STATE_COOKIE, s as appFlowLocation, t as APP_FLOW_DEFAULT_REDIRECT, u as claimedRequestOrigins, v as resolveIconKey, w as defineEntryKind, x as BaseAddon } from "../dist-Dvcuof5S.mjs";
|
|
2
2
|
import * as crypto$1 from "node:crypto";
|
|
3
3
|
//#region ../../node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
4
4
|
var encoder = new TextEncoder(), decoder = new TextDecoder(), strictDecoder = new TextDecoder("utf-8", { fatal: !0 });
|
|
@@ -862,16 +862,6 @@ function updateOidcConnection(config, id, patch) {
|
|
|
862
862
|
clearClientSecret: patch.clearClientSecret === true
|
|
863
863
|
};
|
|
864
864
|
}
|
|
865
|
-
function deleteOidcConnection(config, id) {
|
|
866
|
-
if (!config.providers.some((p) => p.id === id)) return {
|
|
867
|
-
ok: false,
|
|
868
|
-
reason: "not-found"
|
|
869
|
-
};
|
|
870
|
-
return {
|
|
871
|
-
ok: true,
|
|
872
|
-
config: { providers: config.providers.filter((p) => p.id !== id) }
|
|
873
|
-
};
|
|
874
|
-
}
|
|
875
865
|
/** Map a wire `clientSecret` field into an update patch fragment. */
|
|
876
866
|
function clientSecretPatchOf(value) {
|
|
877
867
|
if (value === void 0) return {};
|
|
@@ -892,7 +882,7 @@ var OidcProviderBodySchema = object({
|
|
|
892
882
|
icon: string(),
|
|
893
883
|
issuerUrl: string(),
|
|
894
884
|
clientId: string(),
|
|
895
|
-
clientSecret: string().meta({ secret: true }),
|
|
885
|
+
clientSecret: string().optional().meta({ secret: true }),
|
|
896
886
|
redirectUri: string(),
|
|
897
887
|
scopes: string(),
|
|
898
888
|
usernameClaim: usernameClaimSchema
|
|
@@ -912,6 +902,14 @@ function rowToProvider(id, data) {
|
|
|
912
902
|
id
|
|
913
903
|
};
|
|
914
904
|
}
|
|
905
|
+
/** The stored body of a row; an empty or non-text secret is left out. */
|
|
906
|
+
function bodyOf(row) {
|
|
907
|
+
const { id: _id, clientSecret, ...rest } = row;
|
|
908
|
+
return typeof clientSecret === "string" && clientSecret !== "" ? {
|
|
909
|
+
...rest,
|
|
910
|
+
clientSecret
|
|
911
|
+
} : rest;
|
|
912
|
+
}
|
|
915
913
|
var OidcProviderStore = class OidcProviderStore {
|
|
916
914
|
kind;
|
|
917
915
|
constructor(kind) {
|
|
@@ -924,46 +922,60 @@ var OidcProviderStore = class OidcProviderStore {
|
|
|
924
922
|
const page = await this.kind.query({ limit: 1e3 });
|
|
925
923
|
const out = [];
|
|
926
924
|
for (const record of page.records) {
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
const resolved = await this.kind.getResolved(record.id);
|
|
930
|
-
if (resolved !== null) data = resolved.data;
|
|
931
|
-
} catch (err) {
|
|
932
|
-
if (!(err instanceof RecordSecretUnavailableError)) throw err;
|
|
933
|
-
}
|
|
934
|
-
const parsed = OidcProviderBodySchema.safeParse(data);
|
|
935
|
-
if (!parsed.success) continue;
|
|
936
|
-
out.push(rowToProvider(record.id, parsed.data));
|
|
925
|
+
const row = await this.getResolved(record.id);
|
|
926
|
+
if (row !== null) out.push(row);
|
|
937
927
|
}
|
|
938
928
|
return out;
|
|
939
929
|
}
|
|
930
|
+
/** One row with its secret resolved for the runtime token call; null when absent. */
|
|
931
|
+
async getResolved(id) {
|
|
932
|
+
let record;
|
|
933
|
+
try {
|
|
934
|
+
record = await this.kind.getResolved(id);
|
|
935
|
+
} catch (err) {
|
|
936
|
+
if (!(err instanceof RecordSecretUnavailableError)) throw err;
|
|
937
|
+
const stored = await this.kind.get(id);
|
|
938
|
+
if (stored === null) return null;
|
|
939
|
+
const { clientSecret: _unreadable, ...rest } = stored.data;
|
|
940
|
+
record = {
|
|
941
|
+
...stored,
|
|
942
|
+
data: rest
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
if (record === null) return null;
|
|
946
|
+
const parsed = OidcProviderBodySchema.safeParse(record.data);
|
|
947
|
+
return parsed.success ? rowToProvider(id, parsed.data) : null;
|
|
948
|
+
}
|
|
949
|
+
/**
|
|
950
|
+
* Insert ONE new row (`ifRev: 0`: an existing id is refused). A plaintext
|
|
951
|
+
* `clientSecret` is stored by the records facade under the row's own ref.
|
|
952
|
+
*/
|
|
953
|
+
async create(row) {
|
|
954
|
+
const body = bodyOf(row);
|
|
955
|
+
const parsed = OidcProviderBodySchema.safeParse(body);
|
|
956
|
+
if (!parsed.success) throw new Error(`invalid OIDC provider '${row.id}': ${parsed.error.message}`);
|
|
957
|
+
await this.kind.put({
|
|
958
|
+
id: row.id,
|
|
959
|
+
data: parsed.data
|
|
960
|
+
}, { ifRev: 0 });
|
|
961
|
+
return this.requireRow(row.id);
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Merge a partial into ONE row. `clientSecret`: a plaintext sets it, `undefined`
|
|
965
|
+
* keeps the stored one, `null` clears it.
|
|
966
|
+
*/
|
|
967
|
+
async update(id, partial) {
|
|
968
|
+
await this.kind.patch(id, partial);
|
|
969
|
+
return this.requireRow(id);
|
|
970
|
+
}
|
|
940
971
|
/** Delete one provider record; no other row (nor its secrets) is touched. */
|
|
941
972
|
async remove(id) {
|
|
942
973
|
await this.kind.delete(id);
|
|
943
974
|
}
|
|
944
|
-
async
|
|
945
|
-
const
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
for (const row of providers) {
|
|
949
|
-
const { id, displayName, icon, issuerUrl, clientId, clientSecret, redirectUri, scopes, usernameClaim } = row;
|
|
950
|
-
const body = {
|
|
951
|
-
displayName,
|
|
952
|
-
icon,
|
|
953
|
-
issuerUrl,
|
|
954
|
-
clientId,
|
|
955
|
-
clientSecret,
|
|
956
|
-
redirectUri,
|
|
957
|
-
scopes,
|
|
958
|
-
usernameClaim
|
|
959
|
-
};
|
|
960
|
-
const parsed = oidcProviderEntryKind.schema.safeParse(body);
|
|
961
|
-
if (!parsed.success) throw new Error(`invalid OIDC provider '${id}': ${parsed.error.message}`);
|
|
962
|
-
await this.kind.put({
|
|
963
|
-
id,
|
|
964
|
-
data: parsed.data
|
|
965
|
-
});
|
|
966
|
-
}
|
|
975
|
+
async requireRow(id) {
|
|
976
|
+
const row = await this.getResolved(id);
|
|
977
|
+
if (row === null) throw new Error(`OIDC provider '${id}' is not readable after the write`);
|
|
978
|
+
return row;
|
|
967
979
|
}
|
|
968
980
|
};
|
|
969
981
|
//#endregion
|
|
@@ -1068,7 +1080,7 @@ var AuthOidcAddon = class extends BaseAddon {
|
|
|
1068
1080
|
super({ ...DEFAULT_CONFIG });
|
|
1069
1081
|
}
|
|
1070
1082
|
async onConfigChanged() {
|
|
1071
|
-
this.activeProviders = await this.
|
|
1083
|
+
if (this.providerStore !== null) this.activeProviders = await this.providerStore.listResolved();
|
|
1072
1084
|
this.rebuildInstances();
|
|
1073
1085
|
}
|
|
1074
1086
|
async onInitialize() {
|
|
@@ -1076,16 +1088,7 @@ var AuthOidcAddon = class extends BaseAddon {
|
|
|
1076
1088
|
if (records === void 0) throw new Error("auth-oidc: ctx.records is required (hub-only addon)");
|
|
1077
1089
|
await records.declare({ "oidc-provider": oidcProviderEntryKind });
|
|
1078
1090
|
this.providerStore = OidcProviderStore.of(records);
|
|
1079
|
-
this.activeProviders = await this.
|
|
1080
|
-
if ((await this.providerStore.listResolved()).length === 0 && this.config.providers.length > 0) try {
|
|
1081
|
-
await this.providerStore.replaceAll(await this.adoptSecrets(this.config.providers));
|
|
1082
|
-
this.activeProviders = await this.loadPersistedProviders();
|
|
1083
|
-
} catch (err) {
|
|
1084
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1085
|
-
if (!msg.startsWith("records/foreign-marker:")) throw err;
|
|
1086
|
-
this.ctx.logger.warn("OIDC: deferred config→records copy (a secret marker is bound to another row)", { meta: { error: msg } });
|
|
1087
|
-
this.activeProviders = [...this.config.providers];
|
|
1088
|
-
}
|
|
1091
|
+
this.activeProviders = await this.providerStore.listResolved();
|
|
1089
1092
|
this.rebuildInstances();
|
|
1090
1093
|
const authProvider = {
|
|
1091
1094
|
validateCredentials: async () => null,
|
|
@@ -1171,7 +1174,10 @@ var AuthOidcAddon = class extends BaseAddon {
|
|
|
1171
1174
|
createConnection: async (input) => {
|
|
1172
1175
|
const result = createOidcConnection(this.providersConfig(), input);
|
|
1173
1176
|
if (!result.ok) throw new Error(result.reason === "duplicate-id" ? `An OIDC connection with id "${input.id}" already exists` : `Invalid connection id "${input.id}" — use a lowercase slug`);
|
|
1174
|
-
|
|
1177
|
+
const row = result.config.providers.find((p) => p.id === result.id);
|
|
1178
|
+
if (row === void 0) throw new Error(`Invalid connection id "${input.id}"`);
|
|
1179
|
+
const stored = await this.requireStore().create(row);
|
|
1180
|
+
this.activeProviders = [...this.activeProviders, stored];
|
|
1175
1181
|
this.rebuildInstances();
|
|
1176
1182
|
return { id: result.id };
|
|
1177
1183
|
},
|
|
@@ -1188,21 +1194,21 @@ var AuthOidcAddon = class extends BaseAddon {
|
|
|
1188
1194
|
...input.usernameClaim !== void 0 ? { usernameClaim: input.usernameClaim } : {}
|
|
1189
1195
|
});
|
|
1190
1196
|
if (!result.ok) throw new Error(`Unknown OIDC connection "${input.id}"`);
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
}
|
|
1197
|
+
const next = result.config.providers.find((p) => p.id === input.id);
|
|
1198
|
+
if (next === void 0) throw new Error(`Unknown OIDC connection "${input.id}"`);
|
|
1199
|
+
const { id: _id, clientSecret: _carried, ...fields } = next;
|
|
1200
|
+
const stored = await this.requireStore().update(input.id, {
|
|
1201
|
+
...fields,
|
|
1202
|
+
...result.clearClientSecret ? { clientSecret: null } : secretPatch.clientSecret !== void 0 ? { clientSecret: secretPatch.clientSecret } : {}
|
|
1203
|
+
});
|
|
1204
|
+
this.activeProviders = this.activeProviders.map((p) => p.id === input.id ? stored : p);
|
|
1198
1205
|
this.rebuildInstances();
|
|
1199
1206
|
return { ok: true };
|
|
1200
1207
|
},
|
|
1201
1208
|
deleteConnection: async (input) => {
|
|
1202
1209
|
if (findOidcProvider(this.providersConfig(), input.id) === null) throw new Error(`Unknown OIDC connection "${input.id}"`);
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
await this.removeProvider(input.id, result.config.providers);
|
|
1210
|
+
await this.requireStore().remove(input.id);
|
|
1211
|
+
this.activeProviders = this.activeProviders.filter((p) => p.id !== input.id);
|
|
1206
1212
|
this.rebuildInstances();
|
|
1207
1213
|
return { ok: true };
|
|
1208
1214
|
}
|
|
@@ -1244,69 +1250,9 @@ var AuthOidcAddon = class extends BaseAddon {
|
|
|
1244
1250
|
providersConfig() {
|
|
1245
1251
|
return { providers: this.activeProviders };
|
|
1246
1252
|
}
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
const fromRecords = await store.listResolved();
|
|
1251
|
-
if (fromRecords.length > 0) return fromRecords;
|
|
1252
|
-
}
|
|
1253
|
-
return this.config.providers;
|
|
1254
|
-
}
|
|
1255
|
-
async persistProviders(providers) {
|
|
1256
|
-
const adopted = await this.adoptSecrets(providers);
|
|
1257
|
-
this.activeProviders = [...adopted];
|
|
1258
|
-
const store = this.providerStore;
|
|
1259
|
-
if (store !== null) {
|
|
1260
|
-
await store.replaceAll(adopted);
|
|
1261
|
-
return;
|
|
1262
|
-
}
|
|
1263
|
-
await this.updateGlobalSettings({ providers: [...adopted] });
|
|
1264
|
-
}
|
|
1265
|
-
async removeProvider(id, remaining) {
|
|
1266
|
-
this.activeProviders = [...remaining];
|
|
1267
|
-
const store = this.providerStore;
|
|
1268
|
-
if (store !== null) {
|
|
1269
|
-
await store.remove(id);
|
|
1270
|
-
return;
|
|
1271
|
-
}
|
|
1272
|
-
await this.updateGlobalSettings({ providers: [...remaining] });
|
|
1273
|
-
}
|
|
1274
|
-
/**
|
|
1275
|
-
* A row can still carry a keychain marker bound to the old settings array
|
|
1276
|
-
* (`providers[<id>].clientSecret`, owner auth-oidc) — config rows that never
|
|
1277
|
-
* moved into records. Records refuse a marker that is not the row's own ref, so
|
|
1278
|
-
* every such row is resolved to its value here (re-bound to the record's own ref
|
|
1279
|
-
* on write); a marker that no longer resolves becomes an empty secret the
|
|
1280
|
-
* operator can retype. The value is never logged.
|
|
1281
|
-
*/
|
|
1282
|
-
async adoptSecrets(providers) {
|
|
1283
|
-
const out = [];
|
|
1284
|
-
for (const row of providers) {
|
|
1285
|
-
const secret = row.clientSecret;
|
|
1286
|
-
if (typeof secret === "string") {
|
|
1287
|
-
out.push(row);
|
|
1288
|
-
continue;
|
|
1289
|
-
}
|
|
1290
|
-
if (!isSecretMarker(secret)) {
|
|
1291
|
-
out.push({
|
|
1292
|
-
...row,
|
|
1293
|
-
clientSecret: ""
|
|
1294
|
-
});
|
|
1295
|
-
continue;
|
|
1296
|
-
}
|
|
1297
|
-
let plain = "";
|
|
1298
|
-
const secrets = this.ctx.secrets;
|
|
1299
|
-
if (secrets !== void 0) try {
|
|
1300
|
-
const entry = (await secrets.resolve([secret.$secret]))[secret.$secret];
|
|
1301
|
-
if (entry?.kind === "value") plain = entry.value;
|
|
1302
|
-
} catch {}
|
|
1303
|
-
if (plain === "") this.ctx.logger.warn(`OIDC: the client secret of connection "${row.id}" could not be read from the keychain; retype it in its settings`);
|
|
1304
|
-
out.push({
|
|
1305
|
-
...row,
|
|
1306
|
-
clientSecret: plain
|
|
1307
|
-
});
|
|
1308
|
-
}
|
|
1309
|
-
return out;
|
|
1253
|
+
requireStore() {
|
|
1254
|
+
if (this.providerStore === null) throw new Error("auth-oidc: the records store is not ready");
|
|
1255
|
+
return this.providerStore;
|
|
1310
1256
|
}
|
|
1311
1257
|
rebuildInstances() {
|
|
1312
1258
|
this.instances.clear();
|
package/dist/webauthn/_stub.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as e, r as t, t as n } from "./_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare__react__loadShare__.js-BIIa6vDX.mjs";
|
|
2
2
|
import { n as r, t as i } from "./_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-CQ-aEQ9b.mjs";
|
|
3
|
-
import { n as a, t as o } from "./_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-
|
|
3
|
+
import { n as a, t as o } from "./_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-CQJ6wKXR.mjs";
|
|
4
4
|
import { n as s, r as c, t as l } from "./_virtual_mf___mfe_internal__addon_auth_webauthn_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-BL2etuqg.mjs";
|
|
5
5
|
//#region ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
|
|
6
6
|
var u = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), d = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), f = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), p = (e) => {
|
|
@@ -18,7 +18,7 @@ var e = {
|
|
|
18
18
|
},
|
|
19
19
|
"@camstack/types": {
|
|
20
20
|
name: "@camstack/types",
|
|
21
|
-
version: "1.2.
|
|
21
|
+
version: "1.2.452",
|
|
22
22
|
scope: ["default"],
|
|
23
23
|
loaded: !1,
|
|
24
24
|
from: "addon_auth_webauthn_widgets",
|
|
@@ -33,7 +33,7 @@ var e = {
|
|
|
33
33
|
},
|
|
34
34
|
"@camstack/ui-library": {
|
|
35
35
|
name: "@camstack/ui-library",
|
|
36
|
-
version: "1.2.
|
|
36
|
+
version: "1.2.357",
|
|
37
37
|
scope: ["default"],
|
|
38
38
|
loaded: !1,
|
|
39
39
|
from: "addon_auth_webauthn_widgets",
|