diff --git a/backend/web/static/base.js b/backend/web/static/base.js
index 606f1ab758a5acc7e6d3075d6e681bf14b047222..aeae22daaade6f8def3f55caf679f1d8eb61ae16 100644
--- a/backend/web/static/base.js
+++ b/backend/web/static/base.js
@@ -98,6 +98,12 @@ function flow_login() {
 				// Render login form (group: password)
 				var form_html = render_form(data, group, "login");
 				$("#contentLogin_" + group).html(form_html);
+				// Hide the recovery link on the TOTP entry
+				// form. It's not really useful at that point, and
+				// you get a redirect loop if you use it.
+				if (group == 'totp') {
+					$("#recoveryLink").hide();
+				}
 			}
 
 			render_messages(data);
diff --git a/backend/web/templates/login.html b/backend/web/templates/login.html
index 6bcde578eba827158ab355730e577a937a6623b2..3c623bf7b89fed3c8a8ef934df789a422c8cea0e 100644
--- a/backend/web/templates/login.html
+++ b/backend/web/templates/login.html
@@ -86,7 +86,7 @@
 	class="font-medium text-primary-600 mt-0 pt-2 border-t-gray-50 border-t-2 flex justify-end"
 >
 	<div id="contentHelp" class="flex flex-col text-right">
-		<a href="recovery" class="hover:text-primary-700 mb-2">Set new password</a
+		<a id="recoveryLink" href="recovery" class="hover:text-primary-700 mb-2">Set new password</a
 		><a
 			href="https://stackspin.net"
 			class="text-sm text-gray-400 hover:text-primary-500"