Repository: matrix-org/synapse

Issue:
`/_matrix/client/(r0|v3|unstable)/refresh` endpoint is not valid on workers
### Description

I assumed that the endpoint `/_matrix/client/(r0|v3|unstable)/refresh` can be routed to workers.

Why?
- as result of the helper script: #15243
- and it is loaded by workers:

https://github.com/matrix-org/synapse/blob/253e86a72e0c8e4e014b4b08fa587afe1de4db22/synapse/rest/__init__.py#L100

https://github.com/matrix-org/synapse/blob/253e86a72e0c8e4e014b4b08fa587afe1de4db22/synapse/rest/client/login.py#L671-L674

But it cannot routed to workers.

[`add_refresh_token_to_user`](https://github.com/matrix-org/synapse/blob/b40657314e03583f45ad49504711698a70735313/synapse/storage/databases/main/registration.py#L2212) is part of `RegistrationStore` and not `RegistrationWorkerStore`.

### Steps to reproduce

- make a call to a generic worker with a valid refresh token

`curl -X POST http://matrix.localhost/_matrix/client/v3/refresh -d '{"refresh_token": "syr_xxxx"}'`

### Homeserver

another homeserver

### Synapse Version

1.78.0

### Installation Method

Other (please mention below)

### Database

PostgreSQL

### Workers

Multiple workers

### Platform

Kubernetes

### Configuration

_No response_

### Relevant log output

```shell
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/synapse/http/server.py", line 306, in _async_render_wrapper
    callback_return = await self._async_render(request)
  File "/usr/local/lib/python3.10/dist-packages/synapse/http/server.py", line 516, in _async_render
    callback_return = await raw_callback_return
  File "/usr/local/lib/python3.10/dist-packages/synapse/rest/client/login.py", line 569, in on_POST
    ) = await self._auth_handler.refresh_token(
  File "/usr/local/lib/python3.10/dist-packages/synapse/handlers/auth.py", line 853, in refresh_token
    ) = await self.create_refresh_token_for_user_id(
  File "/usr/local/lib/python3.10/dist-packages/synapse/handlers/auth.py", line 942, in create_refresh_token_for_user_id
    refresh_token_id = await self.store.add_refresh_token_to_user(
AttributeError: 'GenericWorkerSlavedStore' object has no attribute 'add_refresh_token_to_user'
```


### Anything else that would be useful to know?

The documentation for [workers](https://matrix-org.github.io/synapse/latest/workers.html#synapseappgeneric_worker) is correct. The endpoint is not listed there.

I am not sure if `add_refresh_token_to_user` can be simply moved to `RegistrationWorkerStore` because there is an id generator
https://github.com/matrix-org/synapse/blob/b40657314e03583f45ad49504711698a70735313/synapse/storage/databases/main/registration.py#L2238-L2251


Discussion:
Well spotted!

> I am not sure if add_refresh_token_to_user can be simply moved to RegistrationWorkerStore because there is an id generator

I think that makes it tricky. For now, I suggest we disable it on workers until we can do the work needed to make it work on workers.

Resolving patch:
diff --git a/synapse/rest/client/login.py b/synapse/rest/client/login.py
--- a/synapse/rest/client/login.py
+++ b/synapse/rest/client/login.py
@@ -670,7 +670,10 @@ async def on_GET(self, request: SynapseRequest) -> None:
 
 def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
     LoginRestServlet(hs).register(http_server)
-    if hs.config.registration.refreshable_access_token_lifetime is not None:
+    if (
+        hs.config.worker.worker_app is None
+        and hs.config.registration.refreshable_access_token_lifetime is not None
+    ):
         RefreshTokenServlet(hs).register(http_server)
     SsoRedirectServlet(hs).register(http_server)
     if hs.config.cas.cas_enabled:


Test patch: