Skip to content

Commit 0972973

Browse files
Update auth.py
1 parent 57bbb81 commit 0972973

File tree

1 file changed

+106
-27
lines changed

1 file changed

+106
-27
lines changed

app/auth.py

Lines changed: 106 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
from flask import Blueprint, render_template, redirect, url_for, flash, request
1+
from flask import Blueprint, render_template, redirect, url_for, request, flash, jsonify, session
22
from flask_login import login_user, logout_user, login_required, current_user
3-
from werkzeug.security import generate_password_hash
43
from app.models import db, User
54
import pyotp
65
import qrcode
76
import io
87
import base64
8+
from datetime import datetime
99

1010
auth_bp = Blueprint('auth', __name__)
1111

@@ -14,19 +14,30 @@ def login():
1414
if request.method == 'POST':
1515
username = request.form.get('username')
1616
password = request.form.get('password')
17-
totp_token = request.form.get('totp_token', '')
17+
totp_code = request.form.get('totp_code', '')
1818

1919
user = User.query.filter_by(username=username).first()
2020

2121
if user and user.check_password(password):
22-
if user.totp_enabled and not user.verify_totp(totp_token):
23-
flash('Invalid 2FA token', 'error')
24-
return redirect(url_for('auth.login'))
22+
# Check TOTP if enabled
23+
if user.totp_enabled:
24+
if not totp_code:
25+
flash('2FA code required', 'error')
26+
return render_template('login.html', require_totp=True, username=username)
2527

26-
login_user(user)
27-
return redirect(url_for('main.dashboard'))
28+
if not user.verify_totp(totp_code):
29+
flash('Invalid 2FA code', 'error')
30+
return render_template('login.html', require_totp=True, username=username)
31+
32+
# Update last login
33+
user.last_login = datetime.utcnow()
34+
db.session.commit()
2835

29-
flash('Invalid credentials', 'error')
36+
login_user(user)
37+
next_page = request.args.get('next')
38+
return redirect(next_page) if next_page else redirect(url_for('index'))
39+
else:
40+
flash('Invalid username or password', 'error')
3041

3142
return render_template('login.html')
3243

@@ -36,30 +47,98 @@ def logout():
3647
logout_user()
3748
return redirect(url_for('auth.login'))
3849

50+
@auth_bp.route('/profile')
51+
@login_required
52+
def profile():
53+
return render_template('profile.html', user=current_user)
54+
3955
@auth_bp.route('/setup-2fa', methods=['GET', 'POST'])
4056
@login_required
4157
def setup_2fa():
42-
if request.method == 'POST':
43-
if 'enable' in request.form:
44-
secret = current_user.generate_totp_secret()
45-
current_user.totp_enabled = True
46-
db.session.commit()
58+
"""Setup 2FA for user"""
59+
try:
60+
print(f"Setup 2FA called for user: {current_user.username}")
4761

48-
# Generate QR code
49-
qr = qrcode.QRCode(version=1, box_size=10, border=5)
50-
qr.add_data(current_user.get_totp_uri())
51-
qr.make(fit=True)
52-
img = qr.make_image(fill_color="black", back_color="white")
62+
if request.method == 'POST':
63+
# Verify the TOTP code
64+
token = request.form.get('token')
65+
print(f"Verifying token: {token}")
5366

54-
buf = io.BytesIO()
55-
img.save(buf, format='PNG')
56-
qr_code = base64.b64encode(buf.getvalue()).decode()
67+
if not token:
68+
flash('Please enter the verification code', 'error')
69+
return redirect(url_for('auth.setup_2fa'))
5770

58-
return {'qr_code': qr_code, 'secret': secret}
71+
# Verify the token
72+
if current_user.verify_totp(token):
73+
current_user.totp_enabled = True
74+
db.session.commit()
75+
flash('2FA has been enabled successfully!', 'success')
76+
print(f"2FA enabled for user: {current_user.username}")
77+
return redirect(url_for('auth.profile'))
78+
else:
79+
flash('Invalid verification code. Please try again.', 'error')
80+
print(f"Invalid token for user: {current_user.username}")
5981

60-
elif 'disable' in request.form:
61-
current_user.totp_enabled = False
62-
current_user.totp_secret = None
82+
# Generate new secret if needed
83+
if not current_user.totp_secret:
84+
print("Generating new TOTP secret")
85+
current_user.generate_totp_secret()
6386
db.session.commit()
6487

65-
return redirect(url_for('main.dashboard'))
88+
# Generate QR code
89+
print("Generating QR code")
90+
qr_code = generate_qr_code(current_user)
91+
92+
return render_template('setup_2fa.html', qr_code=qr_code, user=current_user)
93+
94+
except Exception as e:
95+
print(f"ERROR in setup_2fa: {str(e)}")
96+
import traceback
97+
traceback.print_exc()
98+
flash('An error occurred while setting up 2FA', 'error')
99+
return redirect(url_for('auth.profile'))
100+
101+
@auth_bp.route('/disable-2fa', methods=['POST'])
102+
@login_required
103+
def disable_2fa():
104+
"""Disable 2FA for user"""
105+
try:
106+
print(f"Disabling 2FA for user: {current_user.username}")
107+
108+
current_user.totp_enabled = False
109+
current_user.totp_secret = None
110+
db.session.commit()
111+
112+
flash('2FA has been disabled', 'success')
113+
return redirect(url_for('auth.profile'))
114+
115+
except Exception as e:
116+
print(f"ERROR in disable_2fa: {str(e)}")
117+
flash('An error occurred while disabling 2FA', 'error')
118+
return redirect(url_for('auth.profile'))
119+
120+
def generate_qr_code(user):
121+
"""Generate QR code for TOTP setup"""
122+
try:
123+
# Get the provisioning URI
124+
uri = user.get_totp_uri()
125+
print(f"TOTP URI: {uri}")
126+
127+
# Generate QR code
128+
qr = qrcode.QRCode(version=1, box_size=10, border=5)
129+
qr.add_data(uri)
130+
qr.make(fit=True)
131+
132+
img = qr.make_image(fill_color="black", back_color="white")
133+
134+
# Convert to base64
135+
buf = io.BytesIO()
136+
img.save(buf, format='PNG')
137+
buf.seek(0)
138+
139+
qr_code = base64.b64encode(buf.getvalue()).decode()
140+
return f"data:image/png;base64,{qr_code}"
141+
142+
except Exception as e:
143+
print(f"ERROR generating QR code: {str(e)}")
144+
raise

0 commit comments

Comments
 (0)