Add remember option to FIDO mfa path

This commit is contained in:
Sibren Vasse 2020-05-23 21:56:42 +02:00
parent 097ac771b0
commit 3c7e03f83d
2 changed files with 45 additions and 11 deletions

View File

@ -26,6 +26,13 @@
<div class="text-center"> <div class="text-center">
<button id="btnVerifyKey" class="btn btn-success mt-2" onclick="verifyKey();">Use your security key</button> <button id="btnVerifyKey" class="btn btn-success mt-2" onclick="verifyKey();">Use your security key</button>
</div> </div>
<div class="form-check">
{{ fido_token_form.remember(class="form-check-input", id="remember") }}
<label class="form-check-label" for="remember">
{{ fido_token_form.remember.description }}
</label>
</div>
</form> </form>

View File

@ -1,22 +1,32 @@
import json import json
import secrets import secrets
import webauthn import webauthn
from flask import request, render_template, redirect, url_for, flash, session from flask import (
request,
render_template,
redirect,
url_for,
flash,
session,
make_response,
)
from flask_login import login_user from flask_login import login_user
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import HiddenField, validators from wtforms import HiddenField, validators, BooleanField
from app.auth.base import auth_bp from app.auth.base import auth_bp
from app.config import MFA_USER_ID from app.config import MFA_USER_ID
from app.config import RP_ID, URL from app.config import RP_ID, URL
from app.extensions import db from app.extensions import db
from app.log import LOG from app.log import LOG
from app.models import User, Fido from app.models import User, Fido, MfaBrowser
class FidoTokenForm(FlaskForm): class FidoTokenForm(FlaskForm):
sk_assertion = HiddenField("sk_assertion", validators=[validators.DataRequired()]) sk_assertion = HiddenField("sk_assertion", validators=[validators.DataRequired()])
remember = BooleanField(
"attr", default=False, description="Remember this browser for 30 days"
)
@auth_bp.route("/fido", methods=["GET", "POST"]) @auth_bp.route("/fido", methods=["GET", "POST"])
@ -40,6 +50,14 @@ def fido():
next_url = request.args.get("next") next_url = request.args.get("next")
if request.cookies.get("mfa"):
browser = MfaBrowser.get_by(token=request.cookies.get("mfa"))
if browser and not browser.is_expired() and browser.user_id == user.id:
login_user(user)
flash(f"Welcome back {user.name}!", "success")
# Redirect user to correct page
return redirect(next_url or url_for("dashboard.index"))
# Handling POST requests # Handling POST requests
if fido_token_form.validate_on_submit(): if fido_token_form.validate_on_submit():
try: try:
@ -80,13 +98,22 @@ def fido():
login_user(user) login_user(user)
flash(f"Welcome back {user.name}!", "success") flash(f"Welcome back {user.name}!", "success")
# User comes to login page from another page # Redirect user to correct page
if next_url: response = make_response(redirect(next_url or url_for("dashboard.index")))
LOG.debug("redirect user to %s", next_url)
return redirect(next_url) if fido_token_form.remember.data:
else: browser = MfaBrowser.create_new(user=user)
LOG.debug("redirect user to dashboard") db.session.commit()
return redirect(url_for("dashboard.index")) response.set_cookie(
"mfa",
value=browser.token,
expires=browser.expires.datetime,
secure=True if URL.startswith("https") else False,
httponly=True,
samesite="Lax",
)
return response
# Prepare information for key registration process # Prepare information for key registration process
session.pop("challenge", None) session.pop("challenge", None)