@page "/setup-2fa" @inject IAuthService AuthService @inject NavigationManager Navigation @inject ISettingsService SettingsService @inject IJSRuntime JSRuntime @rendermode InteractiveServer @attribute [Microsoft.AspNetCore.Authorization.Authorize] @T("2FA einrichten - Author Buddy", "2FA setup - Author Buddy")

@T("Zwei-Faktor-Authentifizierung", "Two-Factor Authentication")

@if (isEnabled) {

@T("2FA ist aktiviert.", "2FA is enabled.")

} else if (showSecret) {

@T("Scanne den folgenden QR-Code mit deiner Authenticator-App (z.B. Google Authenticator, Microsoft Authenticator) oder gib den geheimen Schlüssel manuell ein:", "Scan the QR code below with your authenticator app (e.g. Google Authenticator, Microsoft Authenticator) or enter the secret key manually:")

QR Code
@secret
} else {

@T("Richte die Zwei-Faktor-Authentifizierung ein, um dein Konto zusätzlich zu schützen.", "Set up two-factor authentication to add an extra layer of security to your account.")

} @if (!string.IsNullOrEmpty(errorMessage)) {
@errorMessage
}
@code { private string _language = "de"; private string secret = string.Empty; private string verificationCode = string.Empty; private string errorMessage = string.Empty; private string? qrCodeDataUri; private bool showSecret; private bool isEnabled; private bool isBusy; private string? username; private string T(string de, string en) => _language == "en" ? en : de; protected override async Task OnInitializedAsync() { _language = await SettingsService.GetLanguageAsync() ?? "de"; isEnabled = await AuthService.Is2FAEnabledAsync(); var user = await AuthService.GetCurrentUserAsync(); username = user?.Name; } private async Task HandleKeyDown(KeyboardEventArgs e) { if (e.Key == "Enter") await Enable2FA(); } private async Task StartSetup() { isBusy = true; try { secret = await AuthService.Generate2FASecretAsync(); var uri = AuthService.Get2FAProvisioningUri(secret, username ?? "user"); qrCodeDataUri = await GenerateQRCodeDataUri(uri); showSecret = true; } catch (Exception ex) { errorMessage = $"{T("Fehler:", "Error:")} {ex.Message}"; } finally { isBusy = false; } } private async Task Enable2FA() { if (string.IsNullOrWhiteSpace(verificationCode) || verificationCode.Length != 6) { errorMessage = T("Bitte gib einen gültigen 6-stelligen Code ein.", "Please enter a valid 6-digit code."); return; } if (!TotpHelper.VerifyCode(secret, verificationCode)) { errorMessage = T("Code ungültig. Bitte versuche es erneut.", "Invalid code. Please try again."); return; } isBusy = true; errorMessage = string.Empty; try { var result = await AuthService.Enable2FAAsync(secret); if (result) { isEnabled = true; showSecret = false; } else { errorMessage = T("Fehler beim Aktivieren von 2FA.", "Failed to enable 2FA."); } } catch (Exception ex) { errorMessage = $"{T("Fehler:", "Error:")} {ex.Message}"; } finally { isBusy = false; } } private async Task Disable2FA() { isBusy = true; try { var result = await AuthService.Disable2FAAsync(); if (result) { isEnabled = false; showSecret = false; secret = string.Empty; } } catch (Exception ex) { errorMessage = $"{T("Fehler:", "Error:")} {ex.Message}"; } finally { isBusy = false; } } private async Task GenerateQRCodeDataUri(string uri) { try { var encoded = System.Web.HttpUtility.UrlEncode(uri); return $"https://api.qrserver.com/v1/create-qr-code/?size=200x200&data={encoded}"; } catch { return null; } } private async Task CopySecret() { if (!string.IsNullOrEmpty(secret)) await JSRuntime.InvokeVoidAsync("navigator.clipboard.writeText", secret); } private void Cancel() { Navigation.NavigateTo("/"); } }