Support factor hint in web login

This commit is contained in:
LittleSheep 2025-06-29 00:38:00 +08:00
parent d7b443e678
commit ee5d6ef821
4 changed files with 50 additions and 16 deletions

View File

@ -6,7 +6,7 @@
} }
<div class="h-full flex items-center justify-center bg-gray-100 dark:bg-gray-900"> <div class="h-full flex items-center justify-center bg-gray-100 dark:bg-gray-900">
<div class="bg-white dark:bg-gray-800 px-8 rounded-lg shadow-md w-full max-w-md"> <div class="bg-white dark:bg-gray-800 p-8 rounded-lg shadow-md w-full max-w-md">
<h1 class="text-2xl font-bold text-center text-gray-900 dark:text-white mb-6">Select Authentication Method</h1> <h1 class="text-2xl font-bold text-center text-gray-900 dark:text-white mb-6">Select Authentication Method</h1>
@if (Model.AuthChallenge == null) @if (Model.AuthChallenge == null)
@ -24,16 +24,32 @@
<div class="space-y-4"> <div class="space-y-4">
@foreach (var factor in Model.AuthFactors) @foreach (var factor in Model.AuthFactors)
{ {
<form method="post" asp-page-handler="SelectFactor" class="w-full"> <div class="mb-4">
<form method="post" asp-page-handler="SelectFactor" class="w-full" id="factor-@factor.Id">
<input type="hidden" name="factorId" value="@factor.Id"/> <input type="hidden" name="factorId" value="@factor.Id"/>
@if (factor.Type == AccountAuthFactorType.EmailCode)
{
<div class="mb-3">
<label for="hint-@factor.Id" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Email to send code to
</label>
<input type="email"
id="hint-@factor.Id"
name="hint"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
placeholder="Enter your email"
required>
</div>
}
<button type="submit" <button type="submit"
class="w-full text-left p-4 bg-gray-50 dark:bg-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 rounded-lg transition-colors"> class="w-full text-left p-4 bg-gray-50 dark:bg-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 rounded-lg transition-colors">
<div <div class="font-medium text-gray-900 dark:text-white">@GetFactorDisplayName(factor.Type)</div>
class="font-medium text-gray-900 dark:text-white">@GetFactorDisplayName(factor.Type)</div> <div class="text-sm text-gray-500 dark:text-gray-400">@GetFactorDescription(factor.Type)</div>
<div
class="text-sm text-gray-500 dark:text-gray-400">@GetFactorDescription(factor.Type)</div>
</button> </button>
</form> </form>
</div>
} }
</div> </div>
} }

View File

@ -25,7 +25,7 @@ public class SelectFactorModel(
return Page(); return Page();
} }
public async Task<IActionResult> OnPostSelectFactorAsync(Guid factorId) public async Task<IActionResult> OnPostSelectFactorAsync(Guid factorId, string? hint = null)
{ {
var challenge = await db.AuthChallenges var challenge = await db.AuthChallenges
.Include(e => e.Account) .Include(e => e.Account)
@ -40,11 +40,20 @@ public class SelectFactorModel(
// For OTP factors that require code delivery // For OTP factors that require code delivery
try try
{ {
await accounts.SendFactorCode(challenge.Account, factor); // Validate hint for factors that require it
} if (factor.Type == AccountAuthFactorType.EmailCode
catch (Exception) && string.IsNullOrWhiteSpace(hint))
{ {
ModelState.AddModelError(string.Empty, "An error occurred while sending the verification code."); ModelState.AddModelError(string.Empty, $"Please provide a {factor.Type.ToString().ToLower().Replace("code", "")} to send the code to.");
await LoadChallengeAndFactors();
return Page();
}
await accounts.SendFactorCode(challenge.Account, factor, hint);
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, $"An error occurred while sending the verification code: {ex.Message}");
await LoadChallengeAndFactors(); await LoadChallengeAndFactors();
return Page(); return Page();
} }

View File

@ -6,7 +6,7 @@
} }
<div class="h-full flex items-center justify-center bg-gray-100 dark:bg-gray-900"> <div class="h-full flex items-center justify-center bg-gray-100 dark:bg-gray-900">
<div class="bg-white dark:bg-gray-800 p-8 rounded-lg shadow-md w-full max-w-md"> <div class="bg-white dark:bg-gray-800 px-8 pt-8 pb-4 rounded-lg shadow-md w-full max-w-md">
<h1 class="text-2xl font-bold text-center text-gray-900 dark:text-white mb-2">Verify Your Identity</h1> <h1 class="text-2xl font-bold text-center text-gray-900 dark:text-white mb-2">Verify Your Identity</h1>
<p class="text-center text-gray-600 dark:text-gray-300 mb-6"> <p class="text-center text-gray-600 dark:text-gray-300 mb-6">
@switch (Model.FactorType) @switch (Model.FactorType)

View File

@ -285,6 +285,9 @@
.mb-2 { .mb-2 {
margin-bottom: calc(var(--spacing) * 2); margin-bottom: calc(var(--spacing) * 2);
} }
.mb-3 {
margin-bottom: calc(var(--spacing) * 3);
}
.mb-4 { .mb-4 {
margin-bottom: calc(var(--spacing) * 4); margin-bottom: calc(var(--spacing) * 4);
} }
@ -452,6 +455,12 @@
.py-12 { .py-12 {
padding-block: calc(var(--spacing) * 12); padding-block: calc(var(--spacing) * 12);
} }
.pt-8 {
padding-top: calc(var(--spacing) * 8);
}
.pb-4 {
padding-bottom: calc(var(--spacing) * 4);
}
.text-center { .text-center {
text-align: center; text-align: center;
} }