@idp.global/catalog 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +9 -0
- package/dist_bundle/bundle.js +198 -161
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/idp-admin-shell.d.ts +38 -0
- package/dist_ts_web/elements/idp-admin-shell.js +130 -6
- package/package.json +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/idp-admin-shell.ts +148 -4
package/package.json
CHANGED
|
@@ -163,6 +163,24 @@ export interface IIdpAdminPassportEnrollment {
|
|
|
163
163
|
expiresAt: number;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
export interface IIdpAdminPasskey {
|
|
167
|
+
id: string;
|
|
168
|
+
label: string;
|
|
169
|
+
credentialId?: string;
|
|
170
|
+
status: string;
|
|
171
|
+
backedUp?: boolean;
|
|
172
|
+
deviceType?: string;
|
|
173
|
+
transports?: string[];
|
|
174
|
+
createdAt: number;
|
|
175
|
+
lastUsedAt?: number | null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface IIdpAdminTotpEnrollment {
|
|
179
|
+
credentialId: string;
|
|
180
|
+
secret: string;
|
|
181
|
+
otpauthUrl: string;
|
|
182
|
+
}
|
|
183
|
+
|
|
166
184
|
export interface IIdpAdminSessionEventDetail {
|
|
167
185
|
sessionId: string;
|
|
168
186
|
}
|
|
@@ -237,6 +255,23 @@ export interface IIdpAdminPassportDeviceEventDetail {
|
|
|
237
255
|
deviceId: string;
|
|
238
256
|
}
|
|
239
257
|
|
|
258
|
+
export interface IIdpAdminTotpVerifyEventDetail {
|
|
259
|
+
credentialId: string;
|
|
260
|
+
code: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface IIdpAdminTotpCodeEventDetail {
|
|
264
|
+
code: string;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export interface IIdpAdminPasskeyRegistrationEventDetail {
|
|
268
|
+
label: string;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export interface IIdpAdminPasskeyEventDetail {
|
|
272
|
+
passkeyId: string;
|
|
273
|
+
}
|
|
274
|
+
|
|
240
275
|
@customElement('idp-admin-shell')
|
|
241
276
|
export class IdpAdminShell extends DeesElement {
|
|
242
277
|
public static demo = () => html`<idp-admin-shell global-admin></idp-admin-shell>`;
|
|
@@ -1239,6 +1274,18 @@ export class IdpAdminShell extends DeesElement {
|
|
|
1239
1274
|
@property({ type: Object })
|
|
1240
1275
|
public accessor passportEnrollment: IIdpAdminPassportEnrollment | null = null;
|
|
1241
1276
|
|
|
1277
|
+
@property({ type: Boolean, attribute: 'totp-enabled' })
|
|
1278
|
+
public accessor totpEnabled = false;
|
|
1279
|
+
|
|
1280
|
+
@property({ type: Number, attribute: 'backup-codes-remaining' })
|
|
1281
|
+
public accessor backupCodesRemaining = 0;
|
|
1282
|
+
|
|
1283
|
+
@property({ type: Object })
|
|
1284
|
+
public accessor totpEnrollment: IIdpAdminTotpEnrollment | null = null;
|
|
1285
|
+
|
|
1286
|
+
@property({ type: Array })
|
|
1287
|
+
public accessor passkeys: IIdpAdminPasskey[] = [];
|
|
1288
|
+
|
|
1242
1289
|
@property({ type: String, attribute: 'credential-message' })
|
|
1243
1290
|
public accessor credentialMessage = '';
|
|
1244
1291
|
|
|
@@ -1523,6 +1570,51 @@ export class IdpAdminShell extends DeesElement {
|
|
|
1523
1570
|
});
|
|
1524
1571
|
}
|
|
1525
1572
|
|
|
1573
|
+
private requestTotpEnrollment() {
|
|
1574
|
+
this.dispatchShellEvent('idp-admin-totp-start', {});
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
private verifyTotpEnrollment() {
|
|
1578
|
+
if (!this.totpEnrollment) {
|
|
1579
|
+
return;
|
|
1580
|
+
}
|
|
1581
|
+
const code = globalThis.prompt?.('Authenticator code')?.trim();
|
|
1582
|
+
if (!code) {
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1585
|
+
this.dispatchShellEvent<IIdpAdminTotpVerifyEventDetail>('idp-admin-totp-verify', {
|
|
1586
|
+
credentialId: this.totpEnrollment.credentialId,
|
|
1587
|
+
code,
|
|
1588
|
+
});
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
private disableTotp() {
|
|
1592
|
+
const code = globalThis.prompt?.('Enter your current authenticator code to disable TOTP')?.trim();
|
|
1593
|
+
if (!code) {
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
this.dispatchShellEvent<IIdpAdminTotpCodeEventDetail>('idp-admin-totp-disable', { code });
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
private regenerateBackupCodes() {
|
|
1600
|
+
const code = globalThis.prompt?.('Enter your current authenticator code to regenerate backup codes')?.trim();
|
|
1601
|
+
if (!code) {
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1604
|
+
this.dispatchShellEvent<IIdpAdminTotpCodeEventDetail>('idp-admin-backup-codes-regenerate', { code });
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
private requestPasskeyRegistration() {
|
|
1608
|
+
const fallbackLabel = typeof navigator !== 'undefined'
|
|
1609
|
+
? navigator.userAgent.includes('Mobile') ? 'Mobile passkey' : 'Desktop passkey'
|
|
1610
|
+
: 'Passkey';
|
|
1611
|
+
const label = globalThis.prompt?.('Passkey label', fallbackLabel)?.trim();
|
|
1612
|
+
if (!label) {
|
|
1613
|
+
return;
|
|
1614
|
+
}
|
|
1615
|
+
this.dispatchShellEvent<IIdpAdminPasskeyRegistrationEventDetail>('idp-admin-passkey-register', { label });
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1526
1618
|
private setPage(pageArg: TIdpAdminPage) {
|
|
1527
1619
|
this.page = pageArg;
|
|
1528
1620
|
this.orgMenuOpen = false;
|
|
@@ -2172,6 +2264,23 @@ export class IdpAdminShell extends DeesElement {
|
|
|
2172
2264
|
html`<div class="cell-actions"><button class="table-action destructive" @click=${() => this.dispatchShellEvent<IIdpAdminPassportDeviceEventDetail>('idp-admin-passport-revoke', { deviceId: deviceArg.id })}>Revoke</button></div>`,
|
|
2173
2265
|
],
|
|
2174
2266
|
}));
|
|
2267
|
+
const passkeyRows = this.passkeys.map((passkeyArg) => ({
|
|
2268
|
+
cells: [
|
|
2269
|
+
html`
|
|
2270
|
+
<div class="identity-cell">
|
|
2271
|
+
<span class="identity-avatar">${this.getInitials(passkeyArg.label)}</span>
|
|
2272
|
+
<div>
|
|
2273
|
+
<div class="identity-primary">${passkeyArg.label}</div>
|
|
2274
|
+
<div class="identity-secondary">${passkeyArg.deviceType || 'passkey'}${passkeyArg.backedUp ? ' - backed up' : ''}</div>
|
|
2275
|
+
</div>
|
|
2276
|
+
</div>
|
|
2277
|
+
`,
|
|
2278
|
+
html`<idp-badge variant=${passkeyArg.status === 'active' ? 'ok' : 'error'}>${passkeyArg.status}</idp-badge>`,
|
|
2279
|
+
(passkeyArg.transports || []).join(', ') || '-',
|
|
2280
|
+
passkeyArg.lastUsedAt ? this.formatTimeAgo(passkeyArg.lastUsedAt) : 'never',
|
|
2281
|
+
html`<div class="cell-actions"><button class="table-action destructive" @click=${() => this.dispatchShellEvent<IIdpAdminPasskeyEventDetail>('idp-admin-passkey-revoke', { passkeyId: passkeyArg.id })}>Revoke</button></div>`,
|
|
2282
|
+
],
|
|
2283
|
+
}));
|
|
2175
2284
|
|
|
2176
2285
|
return html`
|
|
2177
2286
|
${this.renderPageHeader('Security', 'Manage how you authenticate and protect your account.')}
|
|
@@ -2190,6 +2299,45 @@ export class IdpAdminShell extends DeesElement {
|
|
|
2190
2299
|
<div class="divider"></div>
|
|
2191
2300
|
<button class="plain-button primary" @click=${() => this.submitPasswordChange()}>Update password</button>
|
|
2192
2301
|
`)}
|
|
2302
|
+
${this.renderSectionCard('Authenticator app', 'TOTP protects password and magic-link sign-ins with a six-digit code from an authenticator app.', html`
|
|
2303
|
+
<div class="split-row"><div><div class="section-title">Status</div><div class="muted">${this.totpEnabled ? `${this.backupCodesRemaining} backup codes remaining.` : 'No authenticator app is enrolled.'}</div></div><idp-badge variant=${this.totpEnabled ? 'ok' : 'warn'}>${this.totpEnabled ? 'Enabled' : 'Disabled'}</idp-badge></div>
|
|
2304
|
+
${this.totpEnrollment ? html`
|
|
2305
|
+
<div class="divider"></div>
|
|
2306
|
+
<div class="notice-card"><idp-icon name="qr" size="16"></idp-icon><div><div class="section-title">TOTP setup pending</div><div class="muted">Scan the otpauth URL or enter the manual secret, then verify the current code.</div></div></div>
|
|
2307
|
+
${this.renderFormRow('Manual secret', '', this.renderCodeBlock(this.totpEnrollment.secret))}
|
|
2308
|
+
${this.renderFormRow('otpauth URL', '', this.renderCodeBlock(this.totpEnrollment.otpauthUrl))}
|
|
2309
|
+
<button class="plain-button primary" @click=${() => this.verifyTotpEnrollment()}>Verify setup code</button>
|
|
2310
|
+
` : html`
|
|
2311
|
+
<div class="divider"></div>
|
|
2312
|
+
${this.totpEnabled ? html`
|
|
2313
|
+
<div class="cell-actions" style="justify-content:flex-start">
|
|
2314
|
+
<button class="plain-button outline" @click=${() => this.regenerateBackupCodes()}>Regenerate backup codes</button>
|
|
2315
|
+
<button class="plain-button ghost" style="color:var(--idp-error)" @click=${() => this.disableTotp()}>Disable TOTP</button>
|
|
2316
|
+
</div>
|
|
2317
|
+
` : html`<button class="plain-button primary" @click=${() => this.requestTotpEnrollment()}>Enable authenticator app</button>`}
|
|
2318
|
+
`}
|
|
2319
|
+
`)}
|
|
2320
|
+
<idp-data-table
|
|
2321
|
+
title="Passkeys"
|
|
2322
|
+
subtitle="WebAuthn credentials for passwordless login and MFA step-up."
|
|
2323
|
+
badge=${`${this.passkeys.length} total`}
|
|
2324
|
+
empty-title="No passkeys"
|
|
2325
|
+
empty-description="Register a passkey to sign in with platform authenticators or security keys."
|
|
2326
|
+
.columns=${[
|
|
2327
|
+
{ label: 'Passkey' },
|
|
2328
|
+
{ label: 'Status' },
|
|
2329
|
+
{ label: 'Transports', hideBelow: 'mobile' },
|
|
2330
|
+
{ label: 'Last used', mono: true, hideBelow: 'mobile' },
|
|
2331
|
+
{ label: 'Action', align: 'right' },
|
|
2332
|
+
]}
|
|
2333
|
+
.rows=${passkeyRows}
|
|
2334
|
+
></idp-data-table>
|
|
2335
|
+
<div class="section-card">
|
|
2336
|
+
<div class="section-headline">
|
|
2337
|
+
<div><div class="section-title">Register passkey</div><div class="section-description">Creates a WebAuthn registration challenge in this browser.</div></div>
|
|
2338
|
+
<button class="plain-button outline" @click=${() => this.requestPasskeyRegistration()}>Register passkey</button>
|
|
2339
|
+
</div>
|
|
2340
|
+
</div>
|
|
2193
2341
|
<idp-data-table
|
|
2194
2342
|
title="Passport devices"
|
|
2195
2343
|
subtitle="Cryptographic IDP Passport devices registered for this account."
|
|
@@ -2217,10 +2365,6 @@ export class IdpAdminShell extends DeesElement {
|
|
|
2217
2365
|
${this.renderFormRow('Signing payload', '', this.renderCodeBlock(this.passportEnrollment.signingPayload))}
|
|
2218
2366
|
` : html`<div class="muted">No active enrollment challenge.</div>`}
|
|
2219
2367
|
</div>
|
|
2220
|
-
<div class="primary-grid">
|
|
2221
|
-
${this.renderStateCard('TOTP controls not connected', 'No TOTP secret, enrollment, or verification endpoints exist in this backend yet, so no fake TOTP toggle is shown.', 'lock')}
|
|
2222
|
-
${this.renderStateCard('WebAuthn passkeys not connected', 'No WebAuthn passkey credential model or assertion endpoints exist yet. Passport devices are the available cryptographic credential path.', 'key')}
|
|
2223
|
-
</div>
|
|
2224
2368
|
</div>
|
|
2225
2369
|
`;
|
|
2226
2370
|
}
|