From 67ec8333d2b58fc044830fc3063801ddef79a848 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Mon, 20 Jun 2022 13:03:36 -0400 Subject: [PATCH] User experience updates for authentication. modified: remarkbox/routes.py modified: remarkbox/templates/verification-challenge.j2 modified: remarkbox/views/authentication.py --- remarkbox/routes.py | 4 +- remarkbox/templates/verification-challenge.j2 | 23 ++-- remarkbox/views/authentication.py | 113 +----------------- 3 files changed, 17 insertions(+), 123 deletions(-) diff --git a/remarkbox/routes.py b/remarkbox/routes.py index ce396a5..7fd724b 100644 --- a/remarkbox/routes.py +++ b/remarkbox/routes.py @@ -65,6 +65,8 @@ def includeme(config): # embed routes: config.add_route("embed-join-or-log-in", "/embed/ns/{namespace}/join-or-log-in") + config.add_route("embed-verification-challenge", "/embed/ns/{namespace}/verification-challenge") + config.add_route("embed-log-out", "/embed/ns/{namespace}/log-out") config.add_route("embed-namespace-nodes", "/embed/ns/{namespace}/nodes") @@ -96,7 +98,7 @@ def includeme(config): # basic routes: config.add_route("basic-join-or-log-in", "/join-or-log-in") - config.add_route("verification-challenge", "/verification-challenge") + config.add_route("basic-verification-challenge", "/verification-challenge") config.add_route("basic-namespace-nodes", "/ns/{namespace}/nodes") config.add_route("basic-namespace-settings", "/ns/{namespace}/settings") diff --git a/remarkbox/templates/verification-challenge.j2 b/remarkbox/templates/verification-challenge.j2 index ad07899..0128edf 100644 --- a/remarkbox/templates/verification-challenge.j2 +++ b/remarkbox/templates/verification-challenge.j2 @@ -1,13 +1,12 @@ {% extends request.base_funnel_template -%} {% block title %}verify code | {{ request.domain }}{% endblock -%} {% block content %} -
- {%- endblock -%} diff --git a/remarkbox/views/authentication.py b/remarkbox/views/authentication.py index 82c0f38..c209eac 100644 --- a/remarkbox/views/authentication.py +++ b/remarkbox/views/authentication.py @@ -22,112 +22,6 @@ def log_out(request): request.session["authenticated_user_id"] = None return HTTPFound(uri) -''' - -# disable CSRF checking for iframe embedded version of this view. -# If a client has 3rd party cookies disabled this security feature causes -# more trouble then it helps, essentially blocking unauthenticated users. -# disable CSRF checking for basic mode since we only set the -# CSRF token for logged in users. -@view_config(route_name="basic-join-or-log-in", renderer="join-or-log-in.j2", require_csrf=False) -@view_config(route_name="embed-join-or-log-in", renderer="join-or-log-in.j2", require_csrf=False) -def join_or_log_in(request): - """ - This view handles user registration, verification, and log in. - It uses "password-less" authentication by sending OTP (one-time-password) - links to the user's email address. - """ - _email_regex = re.compile("^[^@]+@[^@]+\.[^.@]+$") - - # get the raw OTP (one-time-password) from posted parameters. - raw_otp = request.params.get("raw-otp", "") - - # get the email_id from posted parameters. - email_id = request.params.get("email-id", "") - - if email_id and _email_regex.match(email_id) is None: - # posted email does not pass regex, set it to None. - email_id = "" - request.session.flash(("That email address is invalid.", "error")) - - if request.spam: - return request.spam - - if request.user is not None: - - if request.user.authenticated: - # user already authenticated, return early. - return HTTPFound(get_referer_or_home(request)) - - user = request.user - - if raw_otp and user.check_password(raw_otp): - # success: the user was verified. - user.verified = True - msg = ("Welcome {}".format(user.name), "success") - request.session["authenticated_user_id"] = str(user.id) - request.session.flash(msg) - - # attempt to verify all nodes_pending_verify in user's session. - verify_pending_nodes_in_session(request, user) - - # Idempotent operation. Make certain a user has at least one reply_watcher. - user.create_default_reply_watcher() - - request.dbsession.add(user) - request.dbsession.flush() - - return HTTPFound("/") - - if user.throttle_password(): - msg = ( - "We already sent a link to {}. Click it to log in.".format(user.email), - "info", - ) - - else: - # generate a new one-time-password and save to database - raw_otp = user.new_password() - request.dbsession.add(user) - request.dbsession.flush() - - # email user the one-time-password and flash message. - send_otp_email(request, user.email, raw_otp) - - msg = ( - "We just sent a link to {}. Click it to log in.".format(user.email), - "info", - ) - - request.session.flash(msg) - - if request.mode == "basic": - return HTTPFound(return_to) - - if request.mode == "embed": - # determine if fragment is a valid node.id. - if "#" in return_to: - node = get_node_by_id(request.dbsession, return_to.split("#")[-1]) - if node is not None: - if node.root.uri: - return HTTPFound( - get_embed_route_uri(request, node.root.uri.data, node.id) - ) - - # determine if return_to is a valid uri in database. - root = get_node_by_uri(request.dbsession, return_to.split("#")[0]) - if root is not None: - # embeded external site, uses embed routes. - return HTTPFound(get_embed_route_uri(request, root.uri.data)) - - return { - # 'the_title' : 'join or log in', - "title": "join or log in", - "return_to": return_to, - } - -''' - #@view_config(route_name="join-or-log-in", renderer="join-or-log-in.j2") @view_config(route_name="basic-join-or-log-in", renderer="join-or-log-in.j2", require_csrf=False) @@ -184,14 +78,15 @@ def join_or_log_in(request): request.session.flash(msg) - return HTTPFound("/verification-challenge?email={}".format(email)) + return HTTPFound("{}/verification-challenge?email={}".format(request.link_prefix, email)) return { "title": "join or log in", } -@view_config(route_name="verification-challenge", renderer="verification-challenge.j2", require_csrf=False) +@view_config(route_name="basic-verification-challenge", renderer="verification-challenge.j2", require_csrf=False) +@view_config(route_name="embed-verification-challenge", renderer="verification-challenge.j2", require_csrf=False) def verification_challenge(request): # get the raw OTP (one-time-password) from posted parameters. @@ -222,7 +117,7 @@ def verification_challenge(request): request.dbsession.add(user) request.dbsession.flush() - #return HTTPFound("/") + return HTTPFound("{}/u/settings".format(request.link_prefix)) else: msg = ("Invalid Verification Code", "error")