summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.md61
-rw-r--r--changelog.d/3778.misc1
-rw-r--r--changelog.d/4004.feature1
-rw-r--r--changelog.d/4006.misc1
-rw-r--r--changelog.d/4091.feature1
-rw-r--r--changelog.d/4095.bugfix1
-rw-r--r--changelog.d/4099.feature1
-rw-r--r--changelog.d/4100.feature1
-rw-r--r--changelog.d/4101.feature1
-rw-r--r--changelog.d/4106.removal1
-rw-r--r--changelog.d/4108.misc1
-rw-r--r--changelog.d/4109.misc1
-rw-r--r--changelog.d/4110.misc1
-rw-r--r--changelog.d/4113.bugfix1
-rw-r--r--changelog.d/4118.removal1
-rw-r--r--changelog.d/4119.removal1
-rw-r--r--changelog.d/4120.removal1
-rw-r--r--changelog.d/4121.misc1
-rw-r--r--changelog.d/4122.bugfix1
-rw-r--r--changelog.d/4123.bugfix1
-rw-r--r--changelog.d/4124.misc1
-rw-r--r--changelog.d/4127.bugfix1
-rw-r--r--changelog.d/4128.misc1
-rw-r--r--changelog.d/4132.bugfix1
-rw-r--r--changelog.d/4133.feature1
-rw-r--r--changelog.d/4135.bugfix1
-rw-r--r--changelog.d/4137.misc1
-rw-r--r--changelog.d/4138.misc1
-rw-r--r--changelog.d/4139.misc1
-rw-r--r--changelog.d/4140.bugfix1
-rw-r--r--changelog.d/4142.feature1
-rw-r--r--changelog.d/4149.misc1
-rw-r--r--changelog.d/4155.misc1
-rw-r--r--changelog.d/4156.misc1
-rw-r--r--changelog.d/4157.bugfix1
-rw-r--r--changelog.d/4161.bugfix1
-rw-r--r--changelog.d/4163.bugfix1
-rw-r--r--changelog.d/4164.bugfix1
-rw-r--r--changelog.d/4165.misc1
-rw-r--r--changelog.d/4184.feature1
-rw-r--r--changelog.d/4197.bugfix1
-rw-r--r--synapse/__init__.py2
-rw-r--r--synapse/rest/client/v2_alpha/auth.py38
-rw-r--r--tests/rest/client/v2_alpha/test_auth.py104
44 files changed, 183 insertions, 62 deletions
diff --git a/CHANGES.md b/CHANGES.md
index 8302610585..1c3d575c37 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,64 @@
+Synapse 0.33.9 (2018-11-19)
+===========================
+
+No significant changes.
+
+
+Synapse 0.33.9rc1 (2018-11-14)
+==============================
+
+Features
+--------
+
+- Include flags to optionally add `m.login.terms` to the registration flow when consent tracking is enabled. ([\#4004](https://github.com/matrix-org/synapse/issues/4004), [\#4133](https://github.com/matrix-org/synapse/issues/4133), [\#4142](https://github.com/matrix-org/synapse/issues/4142), [\#4184](https://github.com/matrix-org/synapse/issues/4184))
+- Support for replacing rooms with new ones ([\#4091](https://github.com/matrix-org/synapse/issues/4091), [\#4099](https://github.com/matrix-org/synapse/issues/4099), [\#4100](https://github.com/matrix-org/synapse/issues/4100), [\#4101](https://github.com/matrix-org/synapse/issues/4101))
+
+
+Bugfixes
+--------
+
+- Fix exceptions when using the email mailer on Python 3. ([\#4095](https://github.com/matrix-org/synapse/issues/4095))
+- Fix e2e key backup with more than 9 backup versions ([\#4113](https://github.com/matrix-org/synapse/issues/4113))
+- Searches that request profile info now no longer fail with a 500. ([\#4122](https://github.com/matrix-org/synapse/issues/4122))
+- fix return code of empty key backups ([\#4123](https://github.com/matrix-org/synapse/issues/4123))
+- If the typing stream ID goes backwards (as on a worker when the master restarts), the worker's typing handler will no longer erroneously report rooms containing new typing events. ([\#4127](https://github.com/matrix-org/synapse/issues/4127))
+- Fix table lock of device_lists_remote_cache which could freeze the application ([\#4132](https://github.com/matrix-org/synapse/issues/4132))
+- Fix exception when using state res v2 algorithm ([\#4135](https://github.com/matrix-org/synapse/issues/4135))
+- Generating the user consent URI no longer fails on Python 3. ([\#4140](https://github.com/matrix-org/synapse/issues/4140), [\#4163](https://github.com/matrix-org/synapse/issues/4163))
+- Loading URL previews from the DB cache on Postgres will no longer cause Unicode type errors when responding to the request, and URL previews will no longer fail if the remote server returns a Content-Type header with the chartype in quotes. ([\#4157](https://github.com/matrix-org/synapse/issues/4157))
+- The hash_password script now works on Python 3. ([\#4161](https://github.com/matrix-org/synapse/issues/4161))
+- Fix noop checks when updating device keys, reducing spurious device list update notifications. ([\#4164](https://github.com/matrix-org/synapse/issues/4164))
+
+
+Deprecations and Removals
+-------------------------
+
+- The disused and un-specced identicon generator has been removed. ([\#4106](https://github.com/matrix-org/synapse/issues/4106))
+- The obsolete and non-functional /pull federation endpoint has been removed. ([\#4118](https://github.com/matrix-org/synapse/issues/4118))
+- The deprecated v1 key exchange endpoints have been removed. ([\#4119](https://github.com/matrix-org/synapse/issues/4119))
+- Synapse will no longer fetch keys using the fallback deprecated v1 key exchange method and will now always use v2. ([\#4120](https://github.com/matrix-org/synapse/issues/4120))
+
+
+Internal Changes
+----------------
+
+- Fix build of Docker image with docker-compose ([\#3778](https://github.com/matrix-org/synapse/issues/3778))
+- Delete unreferenced state groups during history purge ([\#4006](https://github.com/matrix-org/synapse/issues/4006))
+- The "Received rdata" log messages on workers is now logged at DEBUG, not INFO. ([\#4108](https://github.com/matrix-org/synapse/issues/4108))
+- Reduce replication traffic for device lists ([\#4109](https://github.com/matrix-org/synapse/issues/4109))
+- Fix `synapse_replication_tcp_protocol_*_commands` metric label to be full command name, rather than just the first character ([\#4110](https://github.com/matrix-org/synapse/issues/4110))
+- Log some bits about room creation ([\#4121](https://github.com/matrix-org/synapse/issues/4121))
+- Fix `tox` failure on old systems ([\#4124](https://github.com/matrix-org/synapse/issues/4124))
+- Add STATE_V2_TEST room version ([\#4128](https://github.com/matrix-org/synapse/issues/4128))
+- Clean up event accesses and tests ([\#4137](https://github.com/matrix-org/synapse/issues/4137))
+- The default logging config will now set an explicit log file encoding of UTF-8. ([\#4138](https://github.com/matrix-org/synapse/issues/4138))
+- Add helpers functions for getting prev and auth events of an event ([\#4139](https://github.com/matrix-org/synapse/issues/4139))
+- Add some tests for the HTTP pusher. ([\#4149](https://github.com/matrix-org/synapse/issues/4149))
+- add purge_history.sh and purge_remote_media.sh scripts to contrib/ ([\#4155](https://github.com/matrix-org/synapse/issues/4155))
+- HTTP tests have been refactored to contain less boilerplate. ([\#4156](https://github.com/matrix-org/synapse/issues/4156))
+- Drop incoming events from federation for unknown rooms ([\#4165](https://github.com/matrix-org/synapse/issues/4165))
+
+
 Synapse 0.33.8 (2018-11-01)
 ===========================
 
diff --git a/changelog.d/3778.misc b/changelog.d/3778.misc
deleted file mode 100644
index b78a2c9f42..0000000000
--- a/changelog.d/3778.misc
+++ /dev/null
@@ -1 +0,0 @@
-Fix build of Docker image with docker-compose
diff --git a/changelog.d/4004.feature b/changelog.d/4004.feature
deleted file mode 100644
index 89975f4c6e..0000000000
--- a/changelog.d/4004.feature
+++ /dev/null
@@ -1 +0,0 @@
-Include flags to optionally add `m.login.terms` to the registration flow when consent tracking is enabled.
diff --git a/changelog.d/4006.misc b/changelog.d/4006.misc
deleted file mode 100644
index 35ffa1c2d2..0000000000
--- a/changelog.d/4006.misc
+++ /dev/null
@@ -1 +0,0 @@
-Delete unreferenced state groups during history purge
diff --git a/changelog.d/4091.feature b/changelog.d/4091.feature
deleted file mode 100644
index a3f7dbdcdd..0000000000
--- a/changelog.d/4091.feature
+++ /dev/null
@@ -1 +0,0 @@
-Support for replacing rooms with new ones
diff --git a/changelog.d/4095.bugfix b/changelog.d/4095.bugfix
deleted file mode 100644
index 76ee7148c2..0000000000
--- a/changelog.d/4095.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Fix exceptions when using the email mailer on Python 3.
diff --git a/changelog.d/4099.feature b/changelog.d/4099.feature
deleted file mode 100644
index a3f7dbdcdd..0000000000
--- a/changelog.d/4099.feature
+++ /dev/null
@@ -1 +0,0 @@
-Support for replacing rooms with new ones
diff --git a/changelog.d/4100.feature b/changelog.d/4100.feature
deleted file mode 100644
index a3f7dbdcdd..0000000000
--- a/changelog.d/4100.feature
+++ /dev/null
@@ -1 +0,0 @@
-Support for replacing rooms with new ones
diff --git a/changelog.d/4101.feature b/changelog.d/4101.feature
deleted file mode 100644
index a3f7dbdcdd..0000000000
--- a/changelog.d/4101.feature
+++ /dev/null
@@ -1 +0,0 @@
-Support for replacing rooms with new ones
diff --git a/changelog.d/4106.removal b/changelog.d/4106.removal
deleted file mode 100644
index 7e63208daa..0000000000
--- a/changelog.d/4106.removal
+++ /dev/null
@@ -1 +0,0 @@
-The disused and un-specced identicon generator has been removed.
diff --git a/changelog.d/4108.misc b/changelog.d/4108.misc
deleted file mode 100644
index 85810c3d83..0000000000
--- a/changelog.d/4108.misc
+++ /dev/null
@@ -1 +0,0 @@
-The "Received rdata" log messages on workers is now logged at DEBUG, not INFO.
diff --git a/changelog.d/4109.misc b/changelog.d/4109.misc
deleted file mode 100644
index 566c683119..0000000000
--- a/changelog.d/4109.misc
+++ /dev/null
@@ -1 +0,0 @@
-Reduce replication traffic for device lists
diff --git a/changelog.d/4110.misc b/changelog.d/4110.misc
deleted file mode 100644
index a50327ae34..0000000000
--- a/changelog.d/4110.misc
+++ /dev/null
@@ -1 +0,0 @@
-Fix `synapse_replication_tcp_protocol_*_commands` metric label to be full command name, rather than just the first character
diff --git a/changelog.d/4113.bugfix b/changelog.d/4113.bugfix
deleted file mode 100644
index 7f9d8ee032..0000000000
--- a/changelog.d/4113.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Fix e2e key backup with more than 9 backup versions
diff --git a/changelog.d/4118.removal b/changelog.d/4118.removal
deleted file mode 100644
index 6fb1d67b47..0000000000
--- a/changelog.d/4118.removal
+++ /dev/null
@@ -1 +0,0 @@
-The obsolete and non-functional /pull federation endpoint has been removed.
diff --git a/changelog.d/4119.removal b/changelog.d/4119.removal
deleted file mode 100644
index 81383ece6b..0000000000
--- a/changelog.d/4119.removal
+++ /dev/null
@@ -1 +0,0 @@
-The deprecated v1 key exchange endpoints have been removed.
diff --git a/changelog.d/4120.removal b/changelog.d/4120.removal
deleted file mode 100644
index a7a567098f..0000000000
--- a/changelog.d/4120.removal
+++ /dev/null
@@ -1 +0,0 @@
-Synapse will no longer fetch keys using the fallback deprecated v1 key exchange method and will now always use v2.
diff --git a/changelog.d/4121.misc b/changelog.d/4121.misc
deleted file mode 100644
index 9c29d80c3f..0000000000
--- a/changelog.d/4121.misc
+++ /dev/null
@@ -1 +0,0 @@
-Log some bits about room creation
diff --git a/changelog.d/4122.bugfix b/changelog.d/4122.bugfix
deleted file mode 100644
index 66dcfb18b9..0000000000
--- a/changelog.d/4122.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Searches that request profile info now no longer fail with a 500.
diff --git a/changelog.d/4123.bugfix b/changelog.d/4123.bugfix
deleted file mode 100644
index b82bc2aad3..0000000000
--- a/changelog.d/4123.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-fix return code of empty key backups
diff --git a/changelog.d/4124.misc b/changelog.d/4124.misc
deleted file mode 100644
index 28f438b9b2..0000000000
--- a/changelog.d/4124.misc
+++ /dev/null
@@ -1 +0,0 @@
-Fix `tox` failure on old systems
diff --git a/changelog.d/4127.bugfix b/changelog.d/4127.bugfix
deleted file mode 100644
index 0701d2ceaa..0000000000
--- a/changelog.d/4127.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-If the typing stream ID goes backwards (as on a worker when the master restarts), the worker's typing handler will no longer erroneously report rooms containing new typing events.
diff --git a/changelog.d/4128.misc b/changelog.d/4128.misc
deleted file mode 100644
index 76ab4b085c..0000000000
--- a/changelog.d/4128.misc
+++ /dev/null
@@ -1 +0,0 @@
-Add STATE_V2_TEST room version
diff --git a/changelog.d/4132.bugfix b/changelog.d/4132.bugfix
deleted file mode 100644
index 2304a40f05..0000000000
--- a/changelog.d/4132.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Fix table lock of device_lists_remote_cache which could freeze the application
\ No newline at end of file
diff --git a/changelog.d/4133.feature b/changelog.d/4133.feature
deleted file mode 100644
index 89975f4c6e..0000000000
--- a/changelog.d/4133.feature
+++ /dev/null
@@ -1 +0,0 @@
-Include flags to optionally add `m.login.terms` to the registration flow when consent tracking is enabled.
diff --git a/changelog.d/4135.bugfix b/changelog.d/4135.bugfix
deleted file mode 100644
index 6879b1c162..0000000000
--- a/changelog.d/4135.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Fix exception when using state res v2 algorithm
diff --git a/changelog.d/4137.misc b/changelog.d/4137.misc
deleted file mode 100644
index 4fe933e33c..0000000000
--- a/changelog.d/4137.misc
+++ /dev/null
@@ -1 +0,0 @@
-Clean up event accesses and tests
diff --git a/changelog.d/4138.misc b/changelog.d/4138.misc
deleted file mode 100644
index 300199f8e8..0000000000
--- a/changelog.d/4138.misc
+++ /dev/null
@@ -1 +0,0 @@
-The default logging config will now set an explicit log file encoding of UTF-8.
diff --git a/changelog.d/4139.misc b/changelog.d/4139.misc
deleted file mode 100644
index d63d9e7003..0000000000
--- a/changelog.d/4139.misc
+++ /dev/null
@@ -1 +0,0 @@
-Add helpers functions for getting prev and auth events of an event
diff --git a/changelog.d/4140.bugfix b/changelog.d/4140.bugfix
deleted file mode 100644
index c7e0ee229d..0000000000
--- a/changelog.d/4140.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Generating the user consent URI no longer fails on Python 3.
diff --git a/changelog.d/4142.feature b/changelog.d/4142.feature
deleted file mode 100644
index 89975f4c6e..0000000000
--- a/changelog.d/4142.feature
+++ /dev/null
@@ -1 +0,0 @@
-Include flags to optionally add `m.login.terms` to the registration flow when consent tracking is enabled.
diff --git a/changelog.d/4149.misc b/changelog.d/4149.misc
deleted file mode 100644
index 0b299f0c6e..0000000000
--- a/changelog.d/4149.misc
+++ /dev/null
@@ -1 +0,0 @@
-Add some tests for the HTTP pusher.
diff --git a/changelog.d/4155.misc b/changelog.d/4155.misc
deleted file mode 100644
index 4a7d5acb66..0000000000
--- a/changelog.d/4155.misc
+++ /dev/null
@@ -1 +0,0 @@
-add purge_history.sh and purge_remote_media.sh scripts to contrib/
diff --git a/changelog.d/4156.misc b/changelog.d/4156.misc
deleted file mode 100644
index 20d404406c..0000000000
--- a/changelog.d/4156.misc
+++ /dev/null
@@ -1 +0,0 @@
-HTTP tests have been refactored to contain less boilerplate.
diff --git a/changelog.d/4157.bugfix b/changelog.d/4157.bugfix
deleted file mode 100644
index 265514c3af..0000000000
--- a/changelog.d/4157.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Loading URL previews from the DB cache on Postgres will no longer cause Unicode type errors when responding to the request, and URL previews will no longer fail if the remote server returns a Content-Type header with the chartype in quotes.
\ No newline at end of file
diff --git a/changelog.d/4161.bugfix b/changelog.d/4161.bugfix
deleted file mode 100644
index 252a40376b..0000000000
--- a/changelog.d/4161.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-The hash_password script now works on Python 3.
diff --git a/changelog.d/4163.bugfix b/changelog.d/4163.bugfix
deleted file mode 100644
index c7e0ee229d..0000000000
--- a/changelog.d/4163.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Generating the user consent URI no longer fails on Python 3.
diff --git a/changelog.d/4164.bugfix b/changelog.d/4164.bugfix
deleted file mode 100644
index f70e0b2056..0000000000
--- a/changelog.d/4164.bugfix
+++ /dev/null
@@ -1 +0,0 @@
-Fix noop checks when updating device keys, reducing spurious device list update notifications.
diff --git a/changelog.d/4165.misc b/changelog.d/4165.misc
deleted file mode 100644
index 415d80aeab..0000000000
--- a/changelog.d/4165.misc
+++ /dev/null
@@ -1 +0,0 @@
-Drop incoming events from federation for unknown rooms
diff --git a/changelog.d/4184.feature b/changelog.d/4184.feature
deleted file mode 100644
index 89975f4c6e..0000000000
--- a/changelog.d/4184.feature
+++ /dev/null
@@ -1 +0,0 @@
-Include flags to optionally add `m.login.terms` to the registration flow when consent tracking is enabled.
diff --git a/changelog.d/4197.bugfix b/changelog.d/4197.bugfix
new file mode 100644
index 0000000000..c7c01da0f3
--- /dev/null
+++ b/changelog.d/4197.bugfix
@@ -0,0 +1 @@
+Fallback auth now accepts the session parameter on Python 3.
diff --git a/synapse/__init__.py b/synapse/__init__.py
index 89ea9a9775..5a28fe2b82 100644
--- a/synapse/__init__.py
+++ b/synapse/__init__.py
@@ -27,4 +27,4 @@ try:
 except ImportError:
     pass
 
-__version__ = "0.33.8"
+__version__ = "0.33.9"
diff --git a/synapse/rest/client/v2_alpha/auth.py b/synapse/rest/client/v2_alpha/auth.py
index c39f53b987..fa73bdf3a1 100644
--- a/synapse/rest/client/v2_alpha/auth.py
+++ b/synapse/rest/client/v2_alpha/auth.py
@@ -21,7 +21,7 @@ from synapse.api.constants import LoginType
 from synapse.api.errors import SynapseError
 from synapse.api.urls import CLIENT_V2_ALPHA_PREFIX
 from synapse.http.server import finish_request
-from synapse.http.servlet import RestServlet
+from synapse.http.servlet import RestServlet, parse_string
 
 from ._base import client_v2_patterns
 
@@ -131,16 +131,12 @@ class AuthRestServlet(RestServlet):
         self.auth_handler = hs.get_auth_handler()
         self.registration_handler = hs.get_handlers().registration_handler
 
-    @defer.inlineCallbacks
     def on_GET(self, request, stagetype):
-        yield
-        if stagetype == LoginType.RECAPTCHA:
-            if ('session' not in request.args or
-                    len(request.args['session']) == 0):
-                raise SynapseError(400, "No session supplied")
-
-            session = request.args["session"][0]
+        session = parse_string(request, "session")
+        if not session:
+            raise SynapseError(400, "No session supplied")
 
+        if stagetype == LoginType.RECAPTCHA:
             html = RECAPTCHA_TEMPLATE % {
                 'session': session,
                 'myurl': "%s/auth/%s/fallback/web" % (
@@ -155,10 +151,8 @@ class AuthRestServlet(RestServlet):
 
             request.write(html_bytes)
             finish_request(request)
-            defer.returnValue(None)
+            return None
         elif stagetype == LoginType.TERMS:
-            session = request.args['session'][0]
-
             html = TERMS_TEMPLATE % {
                 'session': session,
                 'terms_url': "%s_matrix/consent?v=%s" % (
@@ -176,25 +170,25 @@ class AuthRestServlet(RestServlet):
 
             request.write(html_bytes)
             finish_request(request)
-            defer.returnValue(None)
+            return None
         else:
             raise SynapseError(404, "Unknown auth stage type")
 
     @defer.inlineCallbacks
     def on_POST(self, request, stagetype):
-        yield
+
+        session = parse_string(request, "session")
+        if not session:
+            raise SynapseError(400, "No session supplied")
+
         if stagetype == LoginType.RECAPTCHA:
-            if ('g-recaptcha-response' not in request.args or
-                    len(request.args['g-recaptcha-response'])) == 0:
-                raise SynapseError(400, "No captcha response supplied")
-            if ('session' not in request.args or
-                    len(request.args['session'])) == 0:
-                raise SynapseError(400, "No session supplied")
+            response = parse_string(request, "g-recaptcha-response")
 
-            session = request.args['session'][0]
+            if not response:
+                raise SynapseError(400, "No captcha response supplied")
 
             authdict = {
-                'response': request.args['g-recaptcha-response'][0],
+                'response': response,
                 'session': session,
             }
 
diff --git a/tests/rest/client/v2_alpha/test_auth.py b/tests/rest/client/v2_alpha/test_auth.py
new file mode 100644
index 0000000000..7fa120a10f
--- /dev/null
+++ b/tests/rest/client/v2_alpha/test_auth.py
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+# Copyright 2018 New Vector
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from twisted.internet.defer import succeed
+
+from synapse.api.constants import LoginType
+from synapse.rest.client.v1 import admin
+from synapse.rest.client.v2_alpha import auth, register
+
+from tests import unittest
+
+
+class FallbackAuthTests(unittest.HomeserverTestCase):
+
+    servlets = [
+        auth.register_servlets,
+        admin.register_servlets,
+        register.register_servlets,
+    ]
+    hijack_auth = False
+
+    def make_homeserver(self, reactor, clock):
+
+        config = self.default_config()
+
+        config.enable_registration_captcha = True
+        config.recaptcha_public_key = "brokencake"
+        config.registrations_require_3pid = []
+
+        hs = self.setup_test_homeserver(config=config)
+        return hs
+
+    def prepare(self, reactor, clock, hs):
+        auth_handler = hs.get_auth_handler()
+
+        self.recaptcha_attempts = []
+
+        def _recaptcha(authdict, clientip):
+            self.recaptcha_attempts.append((authdict, clientip))
+            return succeed(True)
+
+        auth_handler.checkers[LoginType.RECAPTCHA] = _recaptcha
+
+    @unittest.INFO
+    def test_fallback_captcha(self):
+
+        request, channel = self.make_request(
+            "POST",
+            "register",
+            {"username": "user", "type": "m.login.password", "password": "bar"},
+        )
+        self.render(request)
+
+        # Returns a 401 as per the spec
+        self.assertEqual(request.code, 401)
+        # Grab the session
+        session = channel.json_body["session"]
+        # Assert our configured public key is being given
+        self.assertEqual(
+            channel.json_body["params"]["m.login.recaptcha"]["public_key"], "brokencake"
+        )
+
+        request, channel = self.make_request(
+            "GET", "auth/m.login.recaptcha/fallback/web?session=" + session
+        )
+        self.render(request)
+        self.assertEqual(request.code, 200)
+
+        request, channel = self.make_request(
+            "POST",
+            "auth/m.login.recaptcha/fallback/web?session="
+            + session
+            + "&g-recaptcha-response=a",
+        )
+        self.render(request)
+        self.assertEqual(request.code, 200)
+
+        # The recaptcha handler is called with the response given
+        self.assertEqual(len(self.recaptcha_attempts), 1)
+        self.assertEqual(self.recaptcha_attempts[0][0]["response"], "a")
+
+        # Now we have fufilled the recaptcha fallback step, we can then send a
+        # request to the register API with the session in the authdict.
+        request, channel = self.make_request(
+            "POST", "register", {"auth": {"session": session}}
+        )
+        self.render(request)
+        self.assertEqual(channel.code, 200)
+
+        # We're given a registered user.
+        self.assertEqual(channel.json_body["user_id"], "@user:test")