('idp-admin-passkey-register', { label });
+ }
+
private setPage(pageArg: TIdpAdminPage) {
this.page = pageArg;
this.orgMenuOpen = false;
@@ -2172,6 +2264,23 @@ export class IdpAdminShell extends DeesElement {
html` this.dispatchShellEvent('idp-admin-passport-revoke', { deviceId: deviceArg.id })}>Revoke
`,
],
}));
+ const passkeyRows = this.passkeys.map((passkeyArg) => ({
+ cells: [
+ html`
+
+
${this.getInitials(passkeyArg.label)}
+
+
${passkeyArg.label}
+
${passkeyArg.deviceType || 'passkey'}${passkeyArg.backedUp ? ' - backed up' : ''}
+
+
+ `,
+ html`${passkeyArg.status} `,
+ (passkeyArg.transports || []).join(', ') || '-',
+ passkeyArg.lastUsedAt ? this.formatTimeAgo(passkeyArg.lastUsedAt) : 'never',
+ html` this.dispatchShellEvent('idp-admin-passkey-revoke', { passkeyId: passkeyArg.id })}>Revoke
`,
+ ],
+ }));
return html`
${this.renderPageHeader('Security', 'Manage how you authenticate and protect your account.')}
@@ -2190,6 +2299,45 @@ export class IdpAdminShell extends DeesElement {
this.submitPasswordChange()}>Update password
`)}
+ ${this.renderSectionCard('Authenticator app', 'TOTP protects password and magic-link sign-ins with a six-digit code from an authenticator app.', html`
+ Status
${this.totpEnabled ? `${this.backupCodesRemaining} backup codes remaining.` : 'No authenticator app is enrolled.'}
${this.totpEnabled ? 'Enabled' : 'Disabled'}
+ ${this.totpEnrollment ? html`
+
+ TOTP setup pending
Scan the otpauth URL or enter the manual secret, then verify the current code.
+ ${this.renderFormRow('Manual secret', '', this.renderCodeBlock(this.totpEnrollment.secret))}
+ ${this.renderFormRow('otpauth URL', '', this.renderCodeBlock(this.totpEnrollment.otpauthUrl))}
+ this.verifyTotpEnrollment()}>Verify setup code
+ ` : html`
+
+ ${this.totpEnabled ? html`
+
+ this.regenerateBackupCodes()}>Regenerate backup codes
+ this.disableTotp()}>Disable TOTP
+
+ ` : html` this.requestTotpEnrollment()}>Enable authenticator app `}
+ `}
+ `)}
+
+
+
+
Register passkey
Creates a WebAuthn registration challenge in this browser.
+
this.requestPasskeyRegistration()}>Register passkey
+
+
No active enrollment challenge.`}
-
- ${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')}
- ${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')}
-
`;
}