diff --git a/templates/zerver/log_into_subdomain_token_invalid.html b/templates/zerver/log_into_subdomain_token_invalid.html
new file mode 100644
index 0000000000..8f36e9a359
--- /dev/null
+++ b/templates/zerver/log_into_subdomain_token_invalid.html
@@ -0,0 +1,14 @@
+{% extends "zerver/portico_signup.html" %}
+
+{% block portico_content %}
+
+{% endblock %}
diff --git a/zerver/tests/test_auth_backends.py b/zerver/tests/test_auth_backends.py
index ee34585144..300a5f0e7e 100644
--- a/zerver/tests/test_auth_backends.py
+++ b/zerver/tests/test_auth_backends.py
@@ -2122,6 +2122,7 @@ class GoogleAuthBackendTest(SocialAuthBase):
result = self.get_log_into_subdomain(data, force_token=token)
mock_warn.assert_called_once_with("log_into_subdomain: Invalid token given: %s" % (token,))
self.assertEqual(result.status_code, 400)
+ self.assert_in_response("Invalid or expired login session.", result)
def test_prevent_duplicate_signups(self) -> None:
existing_user = self.example_user('hamlet')
diff --git a/zerver/views/auth.py b/zerver/views/auth.py
index 0cd4d8581d..85703d09d4 100644
--- a/zerver/views/auth.py
+++ b/zerver/views/auth.py
@@ -523,7 +523,7 @@ def log_into_subdomain(request: HttpRequest, token: str) -> HttpResponse:
data = get_login_data(token)
if data is None:
logging.warning("log_into_subdomain: Invalid token given: %s" % (token,))
- return HttpResponse(status=400)
+ return render(request, 'zerver/log_into_subdomain_token_invalid.html', status=400)
# We extract fields provided by the caller via the data object.
# The only fields that are required are email and subdomain (if we