- Add django-otp and qrcode dependencies - Create comprehensive 2FA views and templates in German - Add 2FA setup, verification, and management interfaces - Implement backup token system with 10 recovery codes - Add TwoFactorMiddleware for session enforcement - Integrate 2FA controls into user navigation menu - Support QR code generation for authenticator apps - Add forms for secure 2FA operations with validation - Configure OTP settings and admin site integration Features: - Optional 2FA (users can enable/disable) - TOTP compatible with Google Authenticator, Authy, etc. - Backup codes for emergency access - German language interface - Session-based 2FA enforcement - Password confirmation for sensitive operations - Production-ready with HTTPS support
157 lines
7.0 KiB
HTML
157 lines
7.0 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}{{ title }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-8">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4 class="mb-0">
|
|
<i class="fas fa-key text-success"></i>
|
|
Backup-Codes für Zwei-Faktor-Authentifizierung
|
|
</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-success">
|
|
<h5><i class="fas fa-check-circle"></i> Zwei-Faktor-Authentifizierung aktiviert!</h5>
|
|
<p class="mb-0">
|
|
Ihr Konto ist jetzt mit Zwei-Faktor-Authentifizierung geschützt.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="alert alert-warning">
|
|
<h6><i class="fas fa-exclamation-triangle"></i> Wichtig: Backup-Codes sicher speichern</h6>
|
|
<p class="mb-0">
|
|
Diese Backup-Codes können Sie verwenden, falls Sie keinen Zugriff auf Ihre
|
|
Authenticator-App haben. <strong>Speichern Sie diese Codes an einem sicheren Ort!</strong>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h5>Ihre Backup-Codes:</h5>
|
|
<div class="bg-light p-3 rounded mb-3" id="backup-codes">
|
|
{% for token in backup_tokens %}
|
|
<div class="font-monospace fw-bold mb-2">{{ token }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="d-grid gap-2">
|
|
<button type="button" class="btn btn-outline-primary" onclick="copyBackupCodes()">
|
|
<i class="fas fa-copy"></i>
|
|
Codes kopieren
|
|
</button>
|
|
<button type="button" class="btn btn-outline-secondary" onclick="printBackupCodes()">
|
|
<i class="fas fa-print"></i>
|
|
Codes drucken
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<h5>Verwendung der Backup-Codes:</h5>
|
|
<ul class="text-muted">
|
|
<li>Jeder Code kann nur <strong>einmal</strong> verwendet werden</li>
|
|
<li>Geben Sie den Code anstelle des Authenticator-Codes ein</li>
|
|
<li>Codes sind 8 Zeichen lang (Buchstaben und Zahlen)</li>
|
|
<li>Bewahren Sie die Codes sicher und vertraulich auf</li>
|
|
</ul>
|
|
|
|
<div class="alert alert-info small">
|
|
<h6><i class="fas fa-lightbulb"></i> Empfohlene Aufbewahrung:</h6>
|
|
<ul class="mb-0 small">
|
|
<li>In einem Passwort-Manager</li>
|
|
<li>Ausgedruckt in einem Tresor</li>
|
|
<li>Verschlüsselt auf einem sicheren Gerät</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-center mt-4">
|
|
<a href="{% url 'stiftung:dashboard' %}" class="btn btn-primary btn-lg">
|
|
<i class="fas fa-home"></i>
|
|
Weiter zum Dashboard
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function copyBackupCodes() {
|
|
const codes = [
|
|
{% for token in backup_tokens %}'{{ token }}'{% if not forloop.last %},{% endif %}{% endfor %}
|
|
];
|
|
const text = codes.join('\n');
|
|
|
|
navigator.clipboard.writeText(text).then(function() {
|
|
// Show success message
|
|
const btn = event.target.closest('button');
|
|
const originalText = btn.innerHTML;
|
|
btn.innerHTML = '<i class="fas fa-check text-success"></i> Kopiert!';
|
|
btn.classList.add('btn-success');
|
|
btn.classList.remove('btn-outline-primary');
|
|
|
|
setTimeout(function() {
|
|
btn.innerHTML = originalText;
|
|
btn.classList.remove('btn-success');
|
|
btn.classList.add('btn-outline-primary');
|
|
}, 2000);
|
|
}).catch(function(err) {
|
|
alert('Fehler beim Kopieren: ' + err);
|
|
});
|
|
}
|
|
|
|
function printBackupCodes() {
|
|
const codes = [
|
|
{% for token in backup_tokens %}'{{ token }}'{% if not forloop.last %},{% endif %}{% endfor %}
|
|
];
|
|
|
|
const printWindow = window.open('', '_blank');
|
|
printWindow.document.write(`
|
|
<html>
|
|
<head>
|
|
<title>Backup-Codes - Stiftung Management System</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; margin: 40px; }
|
|
h1 { color: #333; }
|
|
.codes { background: #f8f9fa; padding: 20px; border-radius: 5px; }
|
|
.code { font-family: monospace; font-size: 14px; margin: 10px 0; font-weight: bold; }
|
|
.warning { color: #d63384; font-weight: bold; margin: 20px 0; }
|
|
.date { color: #666; font-size: 12px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Backup-Codes für Zwei-Faktor-Authentifizierung</h1>
|
|
<p><strong>Konto:</strong> ${window.location.hostname}</p>
|
|
<p class="date"><strong>Generiert am:</strong> ${new Date().toLocaleString('de-DE')}</p>
|
|
|
|
<div class="warning">
|
|
⚠️ WICHTIG: Diese Codes sind vertraulich und können nur einmal verwendet werden!
|
|
</div>
|
|
|
|
<div class="codes">
|
|
${codes.map(code => '<div class="code">' + code + '</div>').join('')}
|
|
</div>
|
|
|
|
<p><strong>Verwendung:</strong></p>
|
|
<ul>
|
|
<li>Verwenden Sie diese Codes, falls Sie keinen Zugriff auf Ihre Authenticator-App haben</li>
|
|
<li>Geben Sie einen Code anstelle des Authenticator-Codes ein</li>
|
|
<li>Jeder Code kann nur einmal verwendet werden</li>
|
|
<li>Bewahren Sie diese Codes sicher auf</li>
|
|
</ul>
|
|
</body>
|
|
</html>
|
|
`);
|
|
printWindow.document.close();
|
|
printWindow.print();
|
|
}
|
|
</script>
|
|
{% endblock %} |