Switching Two-Factor Authentication Apps
Photo by Pixabay: https://www.pexels.com/photo/qr-code-on-screengrab-278430/
As I'm preparing to update the firmware on my mobile, updating the ROM and rooting it I'm currently in the "Backup, document and save everything" phase. This means I'm checking that I can backup and restore all my Two-Factor authentication codes (2FA) properly.
Partly because I didn't backup the enrolment QR-Codes for every service I signed up over the years. Documenting the otpauth:// URL and/or the initial QR-Code is still the best way. Then it doesn't even matter if all your devices get lost. You can just enter the information in your 2FA app use the code to sign in and then disable 2FA and re-enable it to invalidate the old secret. Locking out anyone else possibly using your devices/accounts.
As I played around a little bit with 2FA apps over the time I got three apps installed:
And here my problems are starting.
Google Authenticator: Only allows you to export your entries in a QR-Code. (Beside the Cloud sync, but whoever uses this hasn't properly understood 2FA in my personal opinion..)
Aegis Authenticator: Allows the export in un-/encrypted clear text. Even with proper otpauth:// URLs. Nice!
FreeOTP: Offers exporting your entries in an externalBackup.xml called file which contains JSON structured data!? Okay.. The secrets are encrypted with the password you chose when you installed the app. It cannot be changed or retrieved otherwise afterwards so I hope you remember it. 😉
There is a discussion on GitHub about how to decrypt that file, extract the secrets and build proper otpauth:// URLs, but that solution didn't work for me.
I only got the following error message:
user@host:~$ python3 freeotp.py
Traceback (most recent call last):
File "/home/user/freeotp.py", line 26, in <module>
tree = ET.parse("externalBackup.xml")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/xml/etree/ElementTree.py", line 1218, in parse
tree.parse(source, parser)
File "/usr/lib/python3.11/xml/etree/ElementTree.py", line 580, in parse
self._root = parser._parse_whole(source)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 1, column 0
Anyway, after deleting myself from several services in the last years only two entries were still needed and it was easier and faster to just disable 2FA on these accounts. So that is what I did.
EDIT November 2025: I only learned recently that Aegis supports the import of entries from FreeOTP and FreeOTP+ (along many other 2FA apps for that matter..). Either by importing the entries directly from the FreeOTP apps (requires root rights) or by exporting the entries from FreeOTP and importing the generated externalBackup.xml into Aegis. Technically this isn't a pro-argument for FreeOTP but rather another for Aegis. But it can also help FreeOTP users so...
Use the 3 vertical dots menu in the top-right of Aegis, choose Settings and navigate to: Imports and exports. There you have two options to import from file or from an app. EDIT END.
Using Aegis Authenticator to migrate to any 2FA app of choice
Regarding my entries in the Google Authenticator I generated the QR-Code and scanned that with Aegis Authenticator. Aegis properly imported all entries and the generated 2FA tokens were correct when I checked them against Google Authenticator.
As Aegis allows me to export everything in clear text I can use that to migrate to any 2FA app of my choice. But most likely I will stick to Aegis.
Yes, this clear text export is a potential security risk. I get it. But if it means I have a way to easily migrate 30+ 2FA accounts I'm willing to make that compromise. Yes, I mean.. Now that I have all my secrets and otpauth:// URLs that shouldn't be a concern anymore, right? Well, now I have everything. I'm pretty sure in the future I'm forgetting to properly document some 2FA codes again, hence this being the better choice.
Or are there other solutions I'm missing?
And what about the Microsoft Authenticator?
Honestly? I'm forced to use this by my employer as we don't allow any other form of 2FA for authentication in our company. This is a configured setting in our MS365 organisation. Therefore I can't replace the Microsoft Authenticator with another app.
Additionally the Microsoft Authenticator also implements the so-called "Number matching" 2FA method (this blogpost provides a bit more detail: Advanced Microsoft Authenticator security features are now generally available!). This is where the user has to enter a 2 digit long number shown on another user-owned device. It was developed to combat the Multi-factor authentication fatigue where users are bombarded with dozens or hundreds of authorisation requests - until they finally click accept and allow the attack to be authenticated.
And while it seems that Google also implemented this method, it seems that the technical background workings are strictly coupled with the Microsoft Authenticator app. And it seems that neither Aegis nor FreeOTP support this method yet.
Hence there is only one account tied to it. So I did what was reasonable: I removed the app, deleted all settings and cached files, reinstalled the app and just enrolled my account again.
Yes, this required a ticket for our IT Helpdesk to remove the old Authenticator from my account, but I had no problem with that.