flu0r1ne.net/logs/choosing-an-authenticatorLast Updated: 2023-09-23

Choosing an Authenticator: Who Can You Trust?

Recently, I found myself on the hunt for a 2FA authenticator app. I realized that in-depth reviews were scarce, if not nonexistent. So, I did some digging and was surprised at what I found.

Background

Two truisms persist in password security: humans are bad at generating strong passwords, and corporations are equally bad at safeguarding these fragile human creations. In an era where data breaches have become daily news items, mistakes in companies' products expose consumer information, including passwords, to hackers and sleuths. Many companies "hash" their passwords — a method by which passwords are scrambled before they are stored to make them computationally impracticable to reverse. Now, if companies adhered to strong hashing practices only those with particularly weak passwords would be at risk. However, the effectiveness of hashing relies on both the user's password strength and the available computational power. As technology advances, what was once considered unbreakable can become vulnerable.

Fortunately, ingenious cryptographers have been hard at work developing stronger hash functions to counterbalance increasing computational power. Unfortunately, the vast majority of websites have yet to adopt these fortified mechanisms, leaving their hashed passwords susceptible to cracking. The situation is exacerbated by the common practice of reusing passwords across multiple platforms, allowing attackers to target victims' banks, credit accounts, and online stores.

In light of this fragile ecosystem — characterized by poor memorization, reuse, and frequent leaks — a secondary authentication layer has become essential to combat fraud and identity theft. Enter OTPs, or One-Time Passwords. These codes, either generated by an app on your phone or sent via text message, serve to confirm that you are, indeed, not a hacker located on a different continent. Most internet users will have received these codes via text message. While text messages are the default delivery method for many companies, this method has its drawbacks. Skilled hackers can circumvent it by calling your cellular service provider, impersonating you, and having your service redirected. Therefore, the more secure option is to use authenticator apps that typically employ TOTP, or Time-Based One-Time Passwords.

How TOTP Works

Here's a non-technical summary: every 30 seconds, your phone generates a unique code, usually six to eight digits long. When logging into a site, you provide this code. If entered correctly, you gain access; input a series of incorrect codes, and you'll find yourself temporarily locked out. Ideally, the lockout period increases with each successive incorrect attempt to deter brute-force attacks.

The beauty of the TOTP protocol lies in its simplicity, which is advantageous from a cryptographic perspective. Simplicity allows for easier scrutiny of the protocol's security features and straightforward implementation. A developer could grab their nearest crypto library and whip up a basic app within a few hours. However, this ease of creation is a double-edged sword. It enables anyone to develop an authenticator app, sometimes incorporating features that inadvertently weaken the overall security — either by mistake or by design.

The Lineup

So, which authenticator should you pick? I was hunting for an authenticator app that withstood scrutiny. Oddly enough, most reviews tended to omit two crucial details:

  1. The actual effectiveness of the authentication process
  2. The privacy profile of the application

Starting with the first point, not all authenticators are created equal. For instance, Latch stores all your authentication codes on a remote server, unencrypted. A single breach could jeopardize all of Latch's tokens and, by extension, your accounts. While any TOTP app offers an improvement over mere passwords, such practices expose users to unnecessary risk.

Secondly, TOTP apps function as repositories of sensitive information, including usernames, affiliated websites, and device data.

For this review, I've scrutinized four leading contenders: FreeOTP, Google Authenticator, Authy, and Duo. These apps were selected based on their cross-platform compatibility, popularity, and security merits, to my knowledge. The evaluations aim for broad appeal but will delve into technical nuances for those who are technically adept. Most insights on the security of these apps originate from the comprehensive paper "Security and Privacy Failures in Popular 2FA Apps" by Conor Gilsenan, Fuzail Shakir, and Noura Alomar, all of whom are affiliated with UC Berkeley. Independently, I also intercepted the communications between the apps and their servers to identify if they were collecting unnecessary information.

FreeOTP: Trading Features for Privacy and Security

You may be surprised to learn that, in principle, there's absolutely no reason that an authenticator needs to contact a centralized server. The TOTP protocol merely requires that the authenticator and server share a master code, which forms the basis for generating the rolling codes. Technically, you could even manually calculate these codes on paper, although this would not be practical.

Developed by Red Hat, FreeOTP is an open-source, cross-platform solution. The motivation behind its creation is somewhat opaque, as Red Hat primarily serves enterprise-level clients. Nonetheless, they've developed an app that forgoes bells and whistles, opting instead for maximal security and privacy. FreeOTP doesn't back up or sync tokens across devices; its minimalist approach makes it arguably the most secure software-based option, short of using dedicated hardware.

Using FreeOTP is largely intuitive, albeit with some awkward design choices — for instance, requiring a right-swipe to delete an old token. If you decide to adopt it, make sure you have a fallback 2FA strategy, such as storing printed recovery codes in a secure location or keeping a secondary 2FA device that you don't typically carry.

You might wonder how a 2FA app can run offline if it requires scanning a QR code. While the specification doesn't provide any guidance on how these codes are communicated with the client, Google Authenticator introduced the practice of encoding the master secret in QR codes. Scanning the code doesn't reach out to a website; instead, it uses the URL protocol to auto-redirect the QR scanner to the authenticator app. Even though QR codes weren't part of the original TOTP specs, they have become practically ubiquitous today.

Offline Backup and Syncing

TOTP (Time-based One-time Password) QR codes are inherently versatile; they don't store device-specific information. This universal feature allows you to pair multiple authenticators with the same QR code, bypassing the need for cross-device syncing. However, capturing screenshots or printing out these QR codes for backup isn't without risks. If you go this route, make sure to store them in a secure location, such as a locked drawer, wallet, or safe — never alongside your passwords. Should you lose or damage your phone, a quick rescan of these QR codes will restore your access. But proceed with caution: print these codes before scanning to ensure legibility. For the tech-savvy who can confidently remember a robust password, storing these screenshots in an encrypted VeraCrypt container is also a viable option.

Note: This approach is applicable only for TOTP tokens, not for the older HOTP (HMAC-based One-time Passwords) technology. HOTP tokens don't refresh automatically every 30 seconds but rather change upon use. Although most authenticators support HOTP, it's a fading standard due to the risk of de-synchronization when misused.

Google Authenticator: Convenient Syncing, Worse Security, Questionable Privacy

Until 2023, Google Authenticator served as a minimalist, offline solution for two-factor authentication. It was considered inherently privacy-friendly due to its lack of server communication and was even open-source. However, the introduction of an automatic cloud-syncing feature has dramatically undercut its security stance. This new feature syncs authentication codes across devices but crucially lacks end-to-end encryption.

The convenience is alluring, but it also represents a significant security flaw. Anyone who gains access to your Google Account can subsequently access all your authentication tokens. The point of vulnerability shifts from hacking your individual device to impersonating you to Google. This isn't mere speculation; as journalist Dan Goodin recently reported, Google Authenticator has already been exploited to amplify a security breach. Worse still, if Google's servers were ever compromised, all your tokens would be up for grabs. I suspect Google is aware of this Faustian bargain and recognizes that using OTP at all would be an advancement in security for most of their users.

Privacy is another casualty. With your account information and secret keys stored on Google's servers, you're entrusting Google not to misuse this data. Google could also be required to provide this data to authorities if served with a warrant. While in my limited testing I didn't detect any logging, the application is not open-source, so there may be data collection I didn't identify. Privacy-wise, I believe there are better options.

"Two-factor" or "One-factor" Authentication?

Google Authenticator and Microsoft Authenticator dominate the authenticator install base, comprising upwards of 80% of Android installs. Both of these authenticators offer automatic syncing features, which impose inherent risks. Access to your Google or Microsoft account essentially grants an intruder access to your underlying TOTP tokens. What's worrisome is that many websites offer account recovery through OTP tokens and email access, often linked to the same Google or Microsoft account. Users may believe they've employed two separate security layers, but in reality, they're relying on a single point of vulnerability — providing only a facade of enhanced security.

Duo: Cloud Backups Done (Mostly) Right

Duo, a product from corporate security company Duo Security, unsurprisingly gets a lot right — especially when it comes to cryptographic primitives for its cloud backups. The app strikes a balance between user-friendliness and robust features. It offers cloud backup capabilities, enabling your 2FA tokens to be securely stored in iCloud on iOS devices and Google Drive on Android. The 2FA tokens are strongly encrypted and require a password to recover them from the backup. Lost your password? Tough luck. This app doesn't use a child lock. Choose a strong and unique password. It should go without saying, but if you use 2FA with a password that is shared across other websites, it's not true 2FA since this password can be cracked following a data breach and used to break into your Duo backup.

Duo's approach to privacy is not perfect, but I came away believing it offers the best privacy protections of any app with cloud backups, especially if it's used as a TOTP authenticator. First, the company's primary allegiance is to its business clients, who use the Duo authenticator to protect business resources like VPNs and login portals. In this context, these organizations have legitimate interests in information about the authenticating devices, such as its IP address, operating system version, and the identity of the account holder. When used as a standalone TOTP authenticator, all indications suggest that it is private. Duo has a clear privacy policy and states they do not sell your personal data. The app doesn't require a user account to function as an authenticator. When I disabled analytics, I did not detect any surreptitious server communication. There is one minor caveat: the encryption does not extend to the site usernames and identities; it only encrypts the secret tokens. Any party with access to your backups could identify what sites you access and your usernames on those sites. It is worth noting that unlike Google Authenticator, Duo uses third-party storage to facilitate cloud backups. Since they are not in control of these backups, you are entrusting Apple or Google with this data; Duo doesn't collect it. I find it highly unlikely that Apple or Google is associating this data with your account in a systematic way.

Ideally, an authenticator app would embrace a "zero-trust" architecture, encrypting all backup data, from site usernames and identities to secret codes. Unfortunately, there seems to be no commercial entity that offers this service. Duo seems to be the next best thing.

Authy: End-to-End Encryption with a Mixed Record on Security and Privacy

The feature that distinguishes Authy from other authenticators is its ability to sync tokens across multiple devices with end-to-end encryption. At first glance, this might seem like an ideal solution. However, Authy, a company focused on security, has shown inconsistent performance in this domain.

In August 2022, Authy suffered a data breach due to a phishing campaign. While Twilio's subsequent investigation indicated that the impact was limited to around 100 Authy users, it is concerning that their production environment was accessible via a phishing attack. Even more worrisome, a paper by Gilsenan et al. revealed that they had alerted Authy two years before the breach about a weakness in the encryption protecting their cloud backups. Astonishingly, Authy didn't address these concerns until October, after the breach had already occurred, and it remains uncertain whether the issue has been fully resolved. Furthermore, Authy discourages security researchers from publicly disclosing reported issues. Open disclosure, a standard practice in the industry, encourages transparency and accountability.

Despite these security concerns, it's worth noting that Authy's encrypted backups could be rendered more secure with some straightforward adjustments. After all, weak encryption is still preferable to Google Authenticator's lack of encryption.

When it comes to privacy, Authy leaves much to be desired. The app requires both an email and phone number to set up an account, ostensibly linking it to your real identity. Like Duo, Authy stores site identity and issuer information in an unencrypted format. Unlike Duo, this information is backed up to servers they control, meaning they could potentially use the information if they so desired. In my own testing, I discovered that Authy employs extensive, non-discretionary event-based logging. The app logs nearly every transaction and relays this data to remote servers. This includes when a user taps on an authentication code, and the corresponding event logs the transaction with a unique tag that identifies the token. This means that Authy has the technical capability to record all authentication attempts. They state that they do not share or sell information with companies for advertising purposes, but they do share information with companies that use their API. This can include limited location data.

The Details

What information can these apps really access?

The TOTP specification RFC 6238 and its predecessor RFC 4226 only define how the one-time passwords are derived from the shared secret. They do not define how the secrets should be shared. Fortunately, this process has been de facto standardized to use special URI encoding, as laid out by Google. These URIs contain three pieces of personal information:

  • Label: Typically a combination of site and username
  • Secret: The key used to generate the TOTPs
  • Issuer: The site which issued the token

Duo Security - Backup

According to Gilsenan et al., Duo uses the argon2i Password-Based Key Derivation Function. Argon2 won the 2015 Password Hashing Competition and offers significantly higher resistance against brute-force attacks on low-entropy passwords. The parameters also seem to have been conservatively chosen. I could find no exact references validating these parameter choices, but RFC9106 offers:

The best-known attack on the 1-pass and 2-pass Argon2i is the low- storage attack described in [CBS16], which reduces the time-area product (using the peak memory value) by the factor of 5. The best attack on Argon2i with 3 passes or more is described in [AB16], with the reduction factor being a function of memory size and the number of passes (e.g., for 1 gibibyte of memory, a reduction factor of 3 for 3 passes, 2.5 for 4 passes, 2 for 6 passes). The reduction factor grows by about 0.5 with every doubling of the memory size. To completely prevent time-space trade-offs from [AB16], the number of passes MUST exceed the binary logarithm of memory minus 26.

With six passes, Duo is well above this threshold. They also set a high memory parameter of 128 MB. For encryption, they use XSalsa20-Poly1305. From what I've read, the XChaCha20-Poly1305 variant is preferred, but both are secure and widely adopted.

Authy Security - Backup

Authy uses the PBKDF2 Password-Based Key Derivation Function. As of 2022, the iteration count was set at 10,000, and I could find no reference indicating they've increased it since. The use of PBKDF2 is no longer considered best practice. Even if it has to be used due to outdated compliance requirements, OWASP recommends that the iteration count should be set above 600,000. Twilio uses the AES-256-CBC cipher to encrypt the data, which is considered secure and is recognized by NIST.

Logging and Data Collection

In order to observe apps' data collection practices, I used the Waydroid Android emulator and performed a man-in-the-middle attack, sniffing the traffic between the client application and the server. This was accomplished with mitmproxy running in transparent mode. I chose three apps to test: Authy, Duo, and Google Authenticator, since they were all closed source. Waydroid is based on Lineage OS and does not have Google Services, which may have affected these tests. I did not log into an account if it was not required. On all authenticators, I created two tokens, entered secrets I generated manually, provided a fake and unique account label, and then requested OTP codes from these two tokens.

I found that Duo did not make any requests to the server with logging disabled. Google Authenticator also did not contact the server. Authy, on the other hand, had extensive event-based logging. Most UI events sent data to Amazon's Kinesis service, in my case kinesis.us-east-1.amazonaws.com. These were sent in the form of HTTP POST requests. For instance, when the app is opened, it fires off a message to the server. A typical message looked like this:

{"Records":[{"Data":"ewogICJldmVudCI6ICJhcHBfc2Vzc2lvbl9pbml0aWFsaXplZCIsCiAgImV4dHJhIjogewogICAgImF1dGhlbnRpY2F0aW9uX2xvZ190b2tlbiI6ICJleUpoYkdjaU9pSklVekkxTmlKOS5leUpoZFhSb2VWOXBaQ0k2T0Rjd09UZzJOREF3TENKbGVIQWlPakUyT1RVeU9ERXdOVElzSW5abGNuTnBiMjRpT2lJeElpd2lZM1Z6ZEc5dFpYSWlPaUpoZFhSb2VTSXNJbUZqZEdsMmFYUjVJam9pYlc5aWFXeGxYMnh2WjE5MGIydGxiaUo5LjdwSlJEeUNtdUFJcG50RkVPbml3bVRfV25uYzdmQkljRlRRV3VueENXTGciCiAgfSwKICAibGV2ZWwiOiAiaW5mbyIsCiAgIm1lc3NhZ2UiOiAiVXNlciBvcGVucyB0aGUgYXBwIiwKICAib2JqZWN0cyI6IHsKICAgICJkZXZpY2UiOiB7CiAgICAgICJzX29zX3ZlcnNpb24iOiAiMzAiLAogICAgICAic19hY2Nlc3NpYmlsaXR5X3NlcnZpY2UiOiAibm9uZSIsCiAgICAgICJzX2RldmljZV9hcHAiOiAiYXV0aHkiLAogICAgICAic19hcHBfdmVyc2lvbiI6ICIyNC4xMy40IiwKICAgICAgInNfcHJvY2Vzc29yX2FyY2hpdGVjdHVyZSI6ICJ4ODZfNjQiLAogICAgICAiaV9udW1iZXJfb2ZfYXV0aGVudGljYXRvcl90b2tlbnNfZW5jcnlwdGVkIjogMCwKICAgICAgImJfYmFja3Vwc19lbmFibGVkIjogZmFsc2UsCiAgICAgICJzX2J1aWxkX3ZlcnNpb24iOiAiMTAxMSIsCiAgICAgICJpX2RlY3J5cHRpb25fYXR0ZW1wdCI6IDAsCiAgICAgICJzX2Fub255bW91c19pZCI6ICI5YzU1YWI0Yi04NWEzLTQxYWEtODY2Yy1jNjAwZTg0Yjk1Y2UiLAogICAgICAic191dWlkIjogImF1dGh5OjoxY2QxM2VjM2Q4ZmIzOWM0IiwKICAgICAgInNfZW5hYmxlZF9mZWF0dXJlX2ZsYWdzIjogInJlcG9ydF9hdXRoeV9hcHBzLCB2YWxpZGF0ZV93aGF0c19hcHBfaW5zdGFsbGVkLCBtaWdyYXRlX3Bpbl9hbmRyb2lkLCBjYW1lcmF4X3NjYW5uZXJfYW5kcm9pZCwgbmV3X3Rva2Vuc19saXN0aW5nLCBpbl9hcHBfdXBkYXRlX2FuZHJvaWQsIGRldmljZV9pbnZhbGlkYXRpb25fYW5kcm9pZCwgYmFja3VwX3Bhc3N3b3JkX2Zsb3dfYW5kcm9pZCwgZW1haWxfdmFsaWRhdGlvbl9hbmRyb2lkIiwKICAgICAgInNfZmlyZWJhc2VfaW5zdGFuY2VfaWQiOiAiZXlKaGJHY2lPaUpGdXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SmhjaEJKWkNJNklqRTZPREV5TWpJM01UTXlPREl4T21GdVpISnZhV1E2WVRRM1pETTVOREZsWkdReE0yUTNPQ0lzSW1WNGNDSTZNVFk1TlRnNE16a3lNQ3dpWm1sa0lqb2laa0ZUVEhkVlZqTlRRbUUzVTBsTVFWbHJTMHd3V2lJc0luQnliMnBsWTNST2RXMWlaWElpb2pneE1qSXlOekV6TWpneU14MC5BQjJsUFY4d1JRSWdUaGtLeGxaVXE5WnRVakdNYXkzWDNYZXdsam5DTV9VSjlVSEpBUl91bHZjQ0lRRDFlUHAwRFdSM1JWMjNEMF9sZ3MxVThsQkR3Z21ObGNVRUwyazlwQmc4Y3ciLAogICAgICAiaV9nb29nbGVfcGxheV9zZXJ2aWNlc192ZXJzaW9uIjogMTI0NTEwMDAsCiAgICAgICJzX2lkIjogIjg3MDk4NjU5MCIsCiAgICAgICJiX2RhcmtfbW9kZSI6IHRydWUsCiAgICAgICJzX2RldmljZV9tYW51ZmFjdHVyZXIiOiAiV2F5ZHJvaWQiLAogICAgICAic19tb2RlbF9uYW1lIjogIldheURyb2lkIHg4Nl82NCBEZXZpY2UiLAogICAgICAiYl9tdWx0aWRldmljZSI6IHRydWUsCiAgICAgICJub3RpZmljYXRpb25fY2hhbm5lbHMiOiB7CiAgICAgICAgInNfcHJpb3JpdHlfYXBwcm92YWxfcmVxdWVzdCI6ICJIaWdoIiwKICAgICAgICAic19wcmlvcml0eV9kZXZpY2VzIjogIkhpZ2giLAogICAgICAgICJzX3ByaW9yaXR5X21lc3NhZ2UiOiAiSGlnaCIsCiAgICAgICAgInNfcHJpb3JpdHlfbmV3X2RldmljZV9yZXF1ZXN0IjogIkhpZ2giLAogICAgICAgICJzX3ByaW9yaXR5X3N1cHBvcnQiOiAiSGlnaCIsCiAgICAgICAgInNfcHJpb3JpdHlfdG9rZW5zIjogIkhpZ2giCiAgICAgIH0sCiAgICAgICJpX251bWJlcl9vZl9hdXRoZW50aWNhdG9yX2FjY291bnRzIjogNCwKICAgICAgImlfbnVtYmVyX29mX3Zpc2libGVfYWNjb3VudHMiOiAwLAogICAgICAic19vcGVyYXRpbmdfc3lzdGVtIjogIkFuZHJvaWQiLAogICAgICAic19kZXZpY2VfdHlwZSI6ICJhbmRyb2lkIiwKICAgICAgInNfdXNlcl9hZ2VudCI6ICI8YXV0aHktYW5kcm9pZD4gPGFwcF92ZXJzaW9uXzI0LjEzLjQ+IDxvc192ZXJzaW9uXzMwPiA8cHJvY2Vzc29yX2FyY2hpdGVjdHVyZV94ODZfNjQ+IgogICAgfSwKICAgICJ1c2VyIjogewogICAgICAic19hdXRoeV9pZCI6ICI4NzA5OTY1MDAiLAogICAgICAic19jb3VudHJ5X2NvZGUiOiAiMSIsCiAgICAgICJzX2xvY2FsZSI6ICJlbiIsCiAgICAgICJpX251bWJlcl9vZl9hY2NvdW50cyI6IDQsCiAgICAgICJpX251bWJlcl9vZl9hdXRoeV9hY2NvdW50cyI6IDAsCiAgICAgICJpX251bWJlcl9vZl9kZXZpY2VzIjogMQogICAgfQogIH0sCiAgInByb2R1Y3QiOiAiYXV0aHktYW5kcm9pZCIsCiAgInJlcXVlc3QiOiB7CiAgICAiaWQiOiAiMDRmZmE3NDEtMmMyZS00ZjI3LWI2MGQtMWYzNDQ5YWY1Y2JiIgogIH0sCiAgInRpbWUiOiAiMjAyMy0wOS0yMVQwNjo1MTo1OS45NThaIgp9Cgo=","PartitionKey":"97c1a917-cb2f-43a9-baa8-954786931fde"}],"StreamName":"authy-coresdk-production"}

The base64 in the Data section is a second JSON object containing the structured log entry:

{
  "event": "app_session_initialized",
  "extra": {
    "authentication_log_token": "eyJhbGciOiJIUzI1NiJ9.eyJhdXRoeV9pZCI6ODcwOTg2NDAwLCJleHAiOjE2OTUyODEwNTIsInZlcnNpb24iOiIxIiwiY3VzdG9tZXIiOiJhdXRoeSIsImFjdGl2aXR5IjoibW9iaWxlX2xvZ190b2tlbiJ9.7pJRDyCmuAIpntFEOniwmT_Wnnc7fBIcFTQWunxCWLg"
  },
  "level": "info",
  "message": "User opens the app",
  "objects": {
    "device": {
      "s_os_version": "30",
      "s_accessibility_service": "none",
      "s_device_app": "authy",
      "s_app_version": "24.13.4",
      "s_processor_architecture": "x86_64",
      "i_number_of_authenticator_tokens_encrypted": 0,
      "b_backups_enabled": false,
      "s_build_version": "1011",
      "i_decryption_attempt": 0,
      "s_anonymous_id": "9c55ab4b-85a3-41aa-866c-c600e84b95ce",
      "s_uuid": "authy::1cd13ec3d8fb39c4",
      "s_enabled_feature_flags": "report_authy_apps, validate_whats_app_installed, migrate_pin_android, camerax_scanner_android, new_tokens_listing, in_app_update_android, device_invalidation_android, backup_password_flow_android, email_validation_android",
      "s_firebase_instance_id": "eyJhbGciOiJFuzI1NiIsInR5cCI6IkpXVCJ9.eyJhchBJZCI6IjE6ODEyMjI3MTMyODIxOmFuZHJvaWQ6YTQ3ZDM5NDFlZGQxM2Q3OCIsImV4cCI6MTY5NTg4MzkyMCwiZmlkIjoiZkFTTHdVVjNTQmE3U0lMQVlrS0wwWiIsInByb2plY3ROdW1iZXIiojgxMjIyNzEzMjgyMx0.AB2lPV8wRQIgThkKxlZUq9ZtUjGMay3X3XewljnCM_UJ9UHJAR_ulvcCIQD1ePp0DWR3RV23D0_lgs1U8lBDwgmNlcUEL2k9pBg8cw",
      "i_google_play_services_version": 12451000,
      "s_id": "870986590",
      "b_dark_mode": true,
      "s_device_manufacturer": "Waydroid",
      "s_model_name": "WayDroid x86_64 Device",
      "b_multidevice": true,
      "notification_channels": {
        "s_priority_approval_request": "High",
        "s_priority_devices": "High",
        "s_priority_message": "High",
        "s_priority_new_device_request": "High",
        "s_priority_support": "High",
        "s_priority_tokens": "High"
      },
      "i_number_of_authenticator_accounts": 4,
      "i_number_of_visible_accounts": 0,
      "s_operating_system": "Android",
      "s_device_type": "android",
      "s_user_agent": "<authy-android> <app_version_24.13.4> <os_version_30> <processor_architecture_x86_64>"
    },
    "user": {
      "s_authy_id": "870996200",
      "s_country_code": "1",
      "s_locale": "en",
      "i_number_of_accounts": 4,
      "i_number_of_authy_accounts": 0,
      "i_number_of_devices": 1
    }
  },
  "product": "authy-android",
  "request": {
    "id": "04ffa741-2c2e-4f27-b60d-1f3449af5cbb"
  },
  "time": "2023-09-21T06:51:59.958Z"
}

Many events triggered logs. For instance when an account is added, a token log item is sent back to the server:

{
  "event": "account_added",
  "extra": {
    "authentication_log_token": "eyJhbGciOiJIUzI1NiJ9.eyJhdXRoeV9pZCI6ODcwOTg2NDAwLCJleHAiOjE2OTUyODEwNTIsInZlcnNpb24iOiIxIiwiY3VzdG9tZXIiOiJhdXRoeSIsImFjdGl2aXR5IjoibW9iaWxlX2xvZ190b2tlbiJ9.7pJRDyCmuAIpntFEOniwmT_Wnnc7fBIcFTQWunxCWLg"
  },
  "level": "info",
  "message": "When users add an account",
  "objects": {
    "app": {
      "i_account_add_time_in_seconds": 453,
      "s_account_type": "authenticator",
      "s_logo": "authenticator_blue",
      "s_logo_type": "authenticator",
      "s_token_id": "1695240000"
    },
    "device": {
      "s_os_version": "30",
      "s_accessibility_service": "none",
      "s_device_app": "authy",
      "s_app_version": "24.13.4",
      "s_processor_architecture": "x86_64",
      "i_number_of_authenticator_tokens_encrypted": 0,
      "b_backups_enabled": false,
      "s_build_version": "1011",
      "i_decryption_attempt": 0,
      "s_anonymous_id": "9c55ab4b-85a3-41aa-866c-c600e84b95ce",
      "s_uuid": "authy::1cd13ec3d8fb39c4",
      "s_enabled_feature_flags": "report_authy_apps, validate_whats_app_installed, migrate_pin_android, camerax_scanner_android, new_tokens_listing, in_app_update_android, device_invalidation_android, backup_password_flow_android, email_validation_android",
      "i_google_play_services_version": 12451000,
      "s_id": "870986493",
      "s_device_manufacturer": "Waydroid",
      "s_model_name": "WayDroid x86_64 Device",
      "b_multidevice": true,
      "notification_channels": {
        "s_priority_approval_request": "High",
        "s_priority_devices": "High",
        "s_priority_message": "High",
        "s_priority_new_device_request": "High",
        "s_priority_support": "High",
        "s_priority_tokens": "High"
      },
      "i_number_of_authenticator_accounts": 5,
      "i_number_of_visible_accounts": 1,
      "s_operating_system": "Android",
      "s_device_type": "android",
      "s_user_agent": "<authy-android> <app_version_24.13.4> <os_version_30> <processor_architecture_x86_64>"
    },
    "user": {
      "s_authy_id": "870986200",
      "s_country_code": "1",
      "s_locale": "en",
      "i_number_of_accounts": 5,
      "i_number_of_authy_accounts": 0,
      "i_number_of_devices": 1
    }
  },
  "product": "authy-android",
  "request": {
    "id": "04ffa741-2c2e-4f27-b60d-1f3449af5cbb"
  },
  "time": "2023-09-21T07:06:42.990Z"
}

This log entry contains a token_id. When an account is selected, they also send the token id back to the server along with the associated user:

{
  "event": "account_selected",
  "extra": {
    "authentication_log_token": "eyJhbGciOiJIUzI1NiJ9.eyJhdXRoeV9pZCI6ODcwOTg2NDAwLCJleHAiOjE2OTUyODEwNTIsInZlcnNpb24iOiIxIiwiY3VzdG9tZXIiOiJhdXRoeSIsImFjdGl2aXR5IjoibW9iaWxlX2xvZ190b2tlbiJ9.7pJRDyCmuAIpntFEOniwmT_Wnnc7fBIcFTQWunxCWLg"
  },
  "level": "info",
  "message": "Users selecting account from account list/grid in app",
  "objects": {
    "app": {
      "s_account_column": "0",
      "s_account_row": "0",
      "s_account_type": "authenticator",
      "s_logo": "authenticator_blue",
      "s_logo_type": "authenticator",
      "s_token_id": "1695240000",
      "s_view_mode": "list"
    },
    "device": {
      "s_os_version": "30",
      "s_accessibility_service": "none",
      "s_device_app": "authy",
      "s_app_version": "24.13.4",
      "s_processor_architecture": "x86_64",
      "i_number_of_authenticator_tokens_encrypted": 0,
      "b_backups_enabled": false,
      "s_build_version": "1011",
      "i_decryption_attempt": 0,
      "s_anonymous_id": "9c55ab4b-85a3-41aa-866c-c600e84b95ce",
      "s_uuid": "authy::1cd13ec3d8fb39c4",
      "s_enabled_feature_flags": "report_authy_apps, validate_whats_app_installed, migrate_pin_android, camerax_scanner_android, new_tokens_listing, in_app_update_android, device_invalidation_android, backup_password_flow_android, email_validation_android",
      "i_google_play_services_version": 12451000,
      "s_id": "870986493",
      "s_device_manufacturer": "Waydroid",
      "s_model_name": "WayDroid x86_64 Device",
      "b_multidevice": true,
      "notification_channels": {
        "s_priority_approval_request": "High",
        "s_priority_devices": "High",
        "s_priority_message": "High",
        "s_priority_new_device_request": "High",
        "s_priority_support": "High",
        "s_priority_tokens": "High"
      },
      "i_number_of_authenticator_accounts": 5,
      "i_number_of_visible_accounts": 1,
      "s_operating_system": "Android",
      "s_device_type": "android",
      "s_user_agent": "<authy-android> <app_version_24.13.4> <os_version_30> <processor_architecture_x86_64>"
    },
    "user": {
      "s_authy_id": "870986200",
      "s_country_code": "1",
      "s_locale": "en",
      "i_number_of_accounts": 5,
      "i_number_of_authy_accounts": 0,
      "i_number_of_devices": 1
    }
  },
  "product": "authy-android",
  "request": {
    "id": "04ffa741-2c2e-4f27-b60d-1f3449af5cbb"
  },
  "time": "2023-09-21T07:15:33.378Z"
}