Add 2FA gen qrcode

This commit is contained in:
kitoy 2025-11-09 01:53:00 +01:00
parent 42c610f37f
commit 3455795cdb
3 changed files with 25 additions and 3 deletions

View File

@ -13,7 +13,7 @@ on pourrait ajoute de la double authentification mais bon ...
### Sur OpenBSD (7.1) ### Sur OpenBSD (7.1)
Il faut installer FLask et quelques dépendances Il faut installer FLask et quelques dépendances
pkg_add py3-werkzeug py3-jinja2 py3-Pillow py3-wtforms py3-flask-wtf py3-flask \ pkg_add py3-werkzeug py3-jinja2 py3-Pillow py3-wtforms py3-flask-wtf py3-flask \
py3-bcrypt py3-markdown py3-gevent py3-zopeinterface py3-bcrypt py3-markdown py3-gevent py3-zopeinterface py3-qrcode
Il reste malheuresment une dépendances sur flask-bcrypt a installé avec pip: Il reste malheuresment une dépendances sur flask-bcrypt a installé avec pip:
@ -21,7 +21,7 @@ Il reste malheuresment une dépendances sur flask-bcrypt a installé avec pip:
### Sur Debian ### Sur Debian
apt install python3-flask python3-flask-bcrypt python3-wtforms python3-pil python3-markdown \ apt install python3-flask python3-flask-bcrypt python3-wtforms python3-pil python3-markdown \
python3-gevent python3-zope.interface python3-gevent python3-zope.interface python3-qrcode
## Démarrer le programme : ## Démarrer le programme :

View File

@ -27,9 +27,11 @@
<br/> <br/>
<p> Votre clef secrète : {{ totp_shared_key }} </p> <p> Votre clef secrète : {{ totp_shared_key }} </p>
<img src="{{ url_for('profil.totp_qrcode') }}" width="300" height="300"/>
{% if shared_key_validate %} {% if shared_key_validate %}
<p class="success"> Votre clef secrète est valide et activé </p> <p class="success"> Votre clef secrète est valide et activé </p>
{% else %} {% else %}
<p class="alert"> Votre clef secrète n'est pas validé et donc non active </p> <p class="alert"> Votre clef secrète n'est pas validé et donc non active </p>
{% endif %} {% endif %}
@ -41,6 +43,9 @@
</fieldset> </fieldset>
</form> </form>
{% if shared_key_validate %} {% if shared_key_validate %}
<p> Si vous voulez changer votre clef secrète vous devez d'abord supprimé votre clef actuelle</p> <p> Si vous voulez changer votre clef secrète vous devez d'abord supprimé votre clef actuelle</p>
<a href="{{ url_for('profil.del_totp') }}"> <button class="btn-alert"> Supprimer ma clef secrète </button></a> <a href="{{ url_for('profil.del_totp') }}"> <button class="btn-alert"> Supprimer ma clef secrète </button></a>

View File

@ -10,6 +10,8 @@ from socket import gethostname
from flask_bcrypt import Bcrypt from flask_bcrypt import Bcrypt
from tools.utils import email_disp, append_to_log, gen_token, valid_passwd, valid_token_register, get_user_by_token, totp_is_valid from tools.utils import email_disp, append_to_log, gen_token, valid_passwd, valid_token_register, get_user_by_token, totp_is_valid
from pyotp import random_base32 from pyotp import random_base32
import qrcode
profil = Blueprint('profil', __name__, template_folder='templates') profil = Blueprint('profil', __name__, template_folder='templates')
@ -195,6 +197,8 @@ def change_passwd() :
if not(account['totp']): if not(account['totp']):
account['totp'] = random_base32() account['totp'] = random_base32()
img = qrcode.make('otpauth://totp/'+BASE_URL+'?secret='+account['totp'])
img.save(DOSSIER_PERSO + user + "/totp.png")
shared_key_validate = False shared_key_validate = False
return render_template('mypassword.html', return render_template('mypassword.html',
@ -203,7 +207,8 @@ def change_passwd() :
alias=account['alias'], alias=account['alias'],
totp_shared_key=account['totp'], totp_shared_key=account['totp'],
shared_key_validate=shared_key_validate, shared_key_validate=shared_key_validate,
username=user) username=user,
base_url=BASE_URL)
else : else :
return redirect(BASE_URL, code=401) return redirect(BASE_URL, code=401)
@ -301,6 +306,8 @@ def set_totp():
print("shared_key: " +shared_key) print("shared_key: " +shared_key)
cursor.execute("""UPDATE users SET totp=? WHERE name=?""", (shared_key, user,)) cursor.execute("""UPDATE users SET totp=? WHERE name=?""", (shared_key, user,))
conn.commit() conn.commit()
img = qrcode.make('otpauth://totp/'+BASE_URL+'?secret='+shared_key)
img.save(DOSSIER_PERSO + user + "/totp.png")
flash(u'Votre mot de passe à usage unique est configuré et actif.', 'success') flash(u'Votre mot de passe à usage unique est configuré et actif.', 'success')
else: else:
flash(u'Le code de validation totp n\'est pas valide.', 'error') flash(u'Le code de validation totp n\'est pas valide.', 'error')
@ -322,6 +329,16 @@ def del_totp():
return redirect(url_for('profil.change_passwd', _external=True)) return redirect(url_for('profil.change_passwd', _external=True))
@profil.route('/totp.png', methods=['GET'])
def totp_qrcode():
if 'username' in session :
user='%s' % escape(session['username'])
return send_file(
os.path.join(DOSSIER_PERSO, user, "totp.png"), "totp.png")
else :
return redirect(BASE_URL, code=401)
@profil.route('/deltoken-password-lost/<token>', methods=['GET','POST'] ) @profil.route('/deltoken-password-lost/<token>', methods=['GET','POST'] )
def deltoken_passwd_lost(token) : def deltoken_passwd_lost(token) :