Files
WRNexusJS/packages/auth/components/TwoFactorChallenge.wrn
T
2026-07-29 12:51:10 +05:30

59 lines
3.7 KiB
Plaintext

component TwoFactorChallenge {
props {
action = "/api/auth/mfa/complete"
schema = "auth-mfa"
otpAction = "/api/auth/mfa/otp"
mfaToken = ""
challengeId = ""
method = "totp"
returnTo = "/"
title = "Two-step verification"
description = "Choose a verification method and enter the code."
submitLabel = "Verify"
recoveryHref = "/recover"
color = "primary"
size = "md"
class = ""
}
view {
<section
{...attrs}
data-wrnexus-runtime="auth"
data-auth-mfa-challenge
data-mfa-otp-action='{otpAction}'
data-mfa-initial-method='{method}'
class='w-full max-w-md rounded-[var(--wire-radius-lg)] border border-[var(--wire-color-border)] bg-[var(--wire-color-surface)] p-6 text-[var(--wire-color-text)] shadow-[var(--wire-shadow-2)] {class}'
>
<div class="mb-5 flex size-11 items-center justify-center rounded-full bg-[color-mix(in_srgb,var(--wire-color-primary)_12%,transparent)] text-[var(--wire-color-primary)]"><span class="icon-[lucide--shield-check] size-5"></span></div>
<h1 class="m-0 text-2xl font-semibold">{title}</h1>
<p class="mt-2 text-sm text-[var(--wire-color-muted)]">{description}</p>
<form method="post" action='{action}' data-schema='{schema}' data-auth-mfa-form novalidate class="mt-6 space-y-4">
<input type="hidden" name="mfaToken" value='{mfaToken}' />
<input type="hidden" name="challengeId" value='{challengeId}' />
<input type="hidden" name="returnTo" value='{returnTo}' />
<div class="space-y-1.5">
<label for="auth-mfa-method" class="block text-sm font-medium">Verification method</label>
<select id="auth-mfa-method" name="method" data-auth-mfa-method class="h-11 w-full rounded-[var(--wire-radius-sm)] border border-[var(--wire-color-border)] bg-[var(--wire-color-surface-2)] px-3">
<option value="totp">Authenticator app</option>
<option value="recovery-code">Recovery code</option>
<option value="email-otp">Email code</option>
<option value="sms-otp">SMS code</option>
</select>
<p data-error="method" class="m-0 min-h-4 text-xs text-[var(--wire-color-danger)]"></p>
</div>
<div class="space-y-1.5">
<label for="auth-mfa-code" class="block text-sm font-medium">Verification code</label>
<input id="auth-mfa-code" name="code" inputmode="numeric" autocomplete="one-time-code" class="h-12 w-full rounded-[var(--wire-radius-sm)] border border-[var(--wire-color-border)] bg-[var(--wire-color-surface-2)] px-3 text-center text-xl tracking-[0.35em]" />
<p data-error="code" class="m-0 min-h-4 text-xs text-[var(--wire-color-danger)]"></p>
</div>
<p data-auth-mfa-status role="status" hidden class="m-0 rounded-[var(--wire-radius-sm)] bg-[color-mix(in_srgb,var(--wire-color-primary)_10%,transparent)] p-3 text-sm text-[var(--wire-color-primary)]"></p>
<p data-error="mfaToken" class="m-0 min-h-4 text-xs text-[var(--wire-color-danger)]"></p>
<p data-error="challengeId" class="m-0 min-h-4 text-xs text-[var(--wire-color-danger)]"></p>
<p data-error="_form" role="alert" class="m-0 hidden rounded-[var(--wire-radius-sm)] bg-[color-mix(in_srgb,var(--wire-color-danger)_10%,transparent)] p-3 text-sm text-[var(--wire-color-danger)]"></p>
<button type="submit" class="h-11 w-full rounded-[var(--wire-radius-sm)] bg-[var(--wire-color-primary)] font-semibold text-white disabled:cursor-wait disabled:opacity-60">{submitLabel}</button>
</form>
<a href='{recoveryHref}' class="mt-4 inline-flex text-sm text-[var(--wire-color-primary)] hover:underline">Account recovery options</a>
</section>
}
}