Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Fix using dehydrated devices & refresh tokens #16288

Merged
merged 5 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix: invalidated refresh tokens for rehydrated devices
  • Loading branch information
Hanadi Tamimi authored and hanadi92 committed Sep 11, 2023
commit db34eb7166bf68469f82c943f2fe4244faefcd4c
7 changes: 4 additions & 3 deletions synapse/handlers/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -758,12 +758,13 @@ async def rehydrate_device(

# If the dehydrated device was successfully deleted (the device ID
# matched the stored dehydrated device), then modify the access
# token to use the dehydrated device's ID and copy the old device
# display name to the dehydrated device, and destroy the old device
# ID
# token and refresh token to use the dehydrated device's ID and
# copy the old device display name to the dehydrated device,
# and destroy the old device ID
old_device_id = await self.store.set_device_for_access_token(
access_token, device_id
)
await self.store.move_device_refresh_token(old_device_id, device_id)
old_device = await self.store.get_device(user_id, old_device_id)
if old_device is None:
raise errors.NotFoundError()
Expand Down
31 changes: 31 additions & 0 deletions synapse/storage/databases/main/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2312,6 +2312,37 @@ async def add_refresh_token_to_user(

return next_id

def _move_device_refresh_token_txn(
self, txn: LoggingTransaction, old_device_id: str, device_id: str
) -> None:
"""Updates rows of old_device_id with current device_id"""

self.db_pool.simple_update_txn(
txn,
"refresh_tokens",
{"device_id": old_device_id},
{"device_id": device_id},
)

async def move_device_refresh_token(
self, old_device_id: str, device_id: str
) -> None:
"""Moves refresh tokens from old device to current device

Args:
old_device_id: The old device.
device_id: The new device ID.
Returns:
None
"""

await self.db_pool.runInteraction(
"move_device_refresh_token",
self._move_device_refresh_token_txn,
old_device_id,
device_id,
)

def _set_device_for_access_token_txn(
self, txn: LoggingTransaction, token: str, device_id: str
) -> str:
Expand Down
10 changes: 10 additions & 0 deletions tests/handlers/test_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
self.message_handler = hs.get_device_message_handler()
self.registration = hs.get_registration_handler()
self.auth = hs.get_auth()
self.auth_handler = hs.get_auth_handler()
self.store = hs.get_datastores().main
return hs

Expand Down Expand Up @@ -492,6 +493,7 @@ def test_dehydrate_and_rehydrate_device(self) -> None:
user_id=user_id,
device_id=None,
initial_display_name="new device",
should_issue_refresh_token=True,
)
)

Expand Down Expand Up @@ -522,6 +524,14 @@ def test_dehydrate_and_rehydrate_device(self) -> None:

self.assertEqual(user_info.device_id, retrieved_device_id)

# make sure the user device has the refresh token
if _refresh_token:
self.get_success(
self.auth_handler.refresh_token(
_refresh_token, 5 * 60 * 1000, 5 * 60 * 1000
)
)

# make sure the device has the display name that was set from the login
res = self.get_success(self.handler.get_device(user_id, retrieved_device_id))

Expand Down