aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-06-03 11:49:12 -0500
committerFrederick Muriuki Muriithi2024-06-03 11:56:16 -0500
commitc3b940f89523d54d2e2baf436122a30fc0aafdd9 (patch)
tree9698d10855d8b2faa3fb9f378eb47f8a8abc4fc5
parent20b4be541b428d330033b5b9616ced3c154ca086 (diff)
downloadgn-auth-c3b940f89523d54d2e2baf436122a30fc0aafdd9.tar.gz
Handle unverified emails
If a user provides the correct credentials to login, but they are unverified, redirect them to the email verification page, where they are provided with a chance to verify their email, or send a new verification code.
-rw-r--r--gn_auth/auth/authentication/oauth2/views.py5
-rw-r--r--gn_auth/auth/authorisation/users/views.py34
-rw-r--r--gn_auth/templates/users/unverified-user.html69
3 files changed, 107 insertions, 1 deletions
diff --git a/gn_auth/auth/authentication/oauth2/views.py b/gn_auth/auth/authentication/oauth2/views.py
index 7600ada..cf815ea 100644
--- a/gn_auth/auth/authentication/oauth2/views.py
+++ b/gn_auth/auth/authentication/oauth2/views.py
@@ -53,7 +53,7 @@ def authorise():
redirect_uri=request.args["redirect_uri"])
form = request.form
- def __authorise__(conn: db.DbConnection) -> Response:
+ def __authorise__(conn: db.DbConnection):
email_passwd_msg = "Email or password is invalid!"
redirect_response = redirect(url_for("oauth2.auth.authorise",
response_type=form["response_type"],
@@ -64,6 +64,9 @@ def authorise():
form.get("user:email"), check_deliverability=False)
user = user_by_email(conn, email["email"])
if valid_login(conn, user, form.get("user:password", "")):
+ if not user.verified:
+ return redirect(url_for(
+ "oauth2.users.handle_unverified"), code=307)
return server.create_authorization_response(request=request, grant_user=user)
flash(email_passwd_msg, "alert-danger")
return redirect_response # type: ignore[return-value]
diff --git a/gn_auth/auth/authorisation/users/views.py b/gn_auth/auth/authorisation/users/views.py
index 638f0df..cb6775f 100644
--- a/gn_auth/auth/authorisation/users/views.py
+++ b/gn_auth/auth/authorisation/users/views.py
@@ -35,6 +35,7 @@ from gn_auth.auth.errors import (
UserVerificationError,
UserRegistrationError)
+from gn_auth.auth.authentication.users import valid_login, user_by_email
from gn_auth.auth.authentication.oauth2.resource_server import require_oauth
from gn_auth.auth.authentication.users import User, save_user, set_user_password
from gn_auth.auth.authentication.oauth2.models.oauth2token import (
@@ -275,3 +276,36 @@ def list_all_users() -> Response:
with require_oauth.acquire("profile group") as _the_token:
return jsonify(tuple(
asdict(user) for user in with_db_connection(list_users)))
+
+@users.route("/handle-unverified", methods=["POST"])
+def handle_unverified():
+ """Handle case where user tries to login but is unverified"""
+ form = request.form
+ # TODO: Maybe have a GN2_URI setting here?
+ # or pass the client_id here?
+ return render_template(
+ "users/unverified-user.html", email=form.get("user:email"))
+
+@users.route("/send-verification", methods=["POST"])
+def send_verification_code():
+ """Send verification code email."""
+ form = request.form
+ with (db.connection(current_app.config["AUTH_DB"]) as conn,
+ db.cursor(conn) as cursor):
+ user = user_by_email(conn, form["user_email"])
+ if valid_login(conn, user, form.get("user_password", "")):
+ cursor.execute(
+ "DELETE FROM user_verification_codes WHERE user_id=:user_id",
+ {"user_id": str(user.user_id)})
+ send_verification_email(conn, user)
+ return jsonify({
+ "status": "success",
+ "message": "Sent a verification code to your email."
+ })
+
+ resp = jsonify({
+ "error": "InvalidLogin",
+ "error-description": "Invalid email or password."
+ })
+ resp.code = 400
+ return resp
diff --git a/gn_auth/templates/users/unverified-user.html b/gn_auth/templates/users/unverified-user.html
new file mode 100644
index 0000000..b2c6992
--- /dev/null
+++ b/gn_auth/templates/users/unverified-user.html
@@ -0,0 +1,69 @@
+{%extends "base.html"%}
+
+{%block title%}gn-auth: Verify Email{%endblock%}
+
+{%block pagetitle%}Verify Email{%endblock%}
+
+{%block content%}
+{{flash_messages()}}
+
+<h1>Verify Your E-Mail</h1>
+
+<form id="frm-email-verification" method="POST"
+ action="{{url_for('oauth2.users.verify_user')}}">
+ <legend>Email Verification</legend>
+
+ <p>In order to reduce the number of bots we have to deal with, we no longer
+ allow sign-in with users who have not verified their accounts.</p>
+
+ <p>We know this is annoying &mdash; especially if you already have an account,
+ and have been using it just fine &mdash; however, we have found that without
+ this check in place, we will get overrun by silly bots, which will ruin
+ every user's experience.</p>
+
+ <p>
+ Do bear with us, enter the verification code you received via email below:
+ </p>
+
+ <input type="hidden" name="email" value="email" />
+
+ <fieldset class="form-group">
+ <label for="txt-verification-code" class="form-label">
+ Verification Code</label>
+ <input id="txt-verification-code" name="verificationcode" type="text"
+ required="required" class="form-control"
+ placeholder="Enter your verification code here." />
+ </fieldset>
+
+ <fieldset>
+ <input type="submit" value="Verify Email Address" class="btn btn-primary" />
+ </fieldset>
+</form>
+
+<h2>Send Verification Code</h2>
+
+<form id="frm-send-verification-code" method="POST"
+ action="{{url_for('oauth2.users.send_verification_code')}}">
+ <legend>Send Verification Code</legend>
+
+ <p>If you have not received a verification code, or your code is already
+ expired, provide <strong>your GeneNetwork</strong> password and
+ click the "<em>Send Verification Code</em>" button below and we will send
+ you a new verification code.</p>
+
+ <input type="hidden" name="user_email" value="{{email}}" />
+
+ <fieldset class="form-group">
+ <label class="form-label">Email</label>
+ <label class="form-control">{{email}}</label>
+ </fieldset>
+
+ <fieldset class="form-group">
+ <label for="txt-password" class="form-label">Password</label>
+ <input id="txt-password" name="user_password" type="password"
+ placeholder="Enter your GeneNetwork password"
+ class="form-control" />
+ </fieldset>
+ <input type="submit" value="Send Verification Code" class="btn btn-danger" />
+</form>
+{%endblock%}