Seamless user migration between domains

3 min

At the beginning of 2019, we rebranded and changed the name from RealtimeBoard to Miro. Consequently, the site domain has changed from to

When changing the domain, users would have to authorize on the new domain, local application settings would be lost, SSO users could not log in without additional settings on their part – all this was not User friendly, the frequency of password recovery would increase, and some users could not to use the application right away.

To minimize the loss of traffic after changing the domain, it was necessary to migrate authorized users from the old domain to the new one:

  • Support users who logged in using SSO providers through the old domain.
  • Transfer user authorization token from the old domain to the new one.
  • Transfer LocalStorage with user settings for the application.

Data Transfer and Encryption

It was decided to transfer the token using get-parameters, since the site did not use storages in which it would be possible to save the token and reuse it. It is not safe to pass the token open through the get-parameter; it must be protected from interception. We had two encryption methods: OpenSSL and Mcrypt. Mcrypt has not been updated for a long time, it encrypts data more slowly compared to OpenSSL, and we do not need extra load on the server. Therefore, we encrypted the token using OpenSSL.

However, the resulting hash could still be intercepted and used again. In order to prevent reuse of the token, we added the “encryption date” parameter, thereby the hash was valid for 10 seconds – this time was enough with a margin to perform all operations. We also added a replacement encryption key every 12 hours, the key was stored in Vault and was synchronized between sites.

The resulting hash was passed as a get-parameter and was further processed using url_encode for safe transfer through the URL, since the characters could escape or spoil the structure of the address.

Hash Structure:

  'token': 'токен',
  'date': 'Дата шифрования',
  'additional_values': ['param', 'param']

LocalStorage is only available through JavaScript. To solve this problem, the postMessage and iframe interface was chosen, which allowed to send cross-domain requests safely. The data in LocalStorage was converted to strings using JSON.stringify () and transferred to the domain, where it was converted back and written to the LocalStorage of the domain.

The scheme of work with a description of all steps

Easy-to-view diagram.

Users could get into the service in two ways: through the old domain (for example, from bookmarks) or through the new (for example, through advertising).

If the user went to the old domain:

  1. After opening any page on, the user’s token, creation date and additional service information are encrypted.
  2. After encryption, a redirect occurs to{hash} with the hash passed as the Get parameter. The token and service information are deleted on the old domain, because they were no longer needed.
  3. The hash is decrypted on the new domain, verifies that it has not expired, and sets the user’s token if it has been transferred.
  4. The migrationToken flag is set to not migrate again.
  5. For LocalStorage migration, we checked for migrationLocalstorage cookies. If the cookie did not exist, the page was rendered with a JS script that opened the page in iFrame and received messages from it using postmessage. After the migration was completed, the user redirected to the page that he was trying to open for the first time.

If the user went directly to the new domain, the user was checked for passing the token migration and LocalStorage. If the user has already completed the migration, then he remained on the domain. If you didn’t complete it, a redirect occurred on to get a token (for this we stored two flags in cookies: migrationToken and migrationLocalstorage).

This scheme worked just as well for SSO users who logged into the old domain. A list of routes was added that worked without migrating the token to the new domain. They included a route for SSO, which was executed as usual and redirected to / app / or / login / depending on the state of its work, after which the token migration mechanism was connected again.


I spent a month on research and preparation, another month on a run-in (at the same time I was engaged in other projects). Thanks to this solution, we were able to migrate authorized users from the old domain to the new one and support users who used SSO for authorization through the old domain.


Leave a Reply