Two-factor Plugin - "trust device" feature for TOTP only works for one login #1239

Closed
opened 2026-03-13 08:29:37 -05:00 by GiteaMirror · 6 comments
Owner

Originally created by @ErikPetersenDev on GitHub (May 21, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Set up project using the two-factor plugin w/ TOTP.

  1. When entering the TOTP, send along the trustDevice property as true.
  2. The user will be logged in and the trust_device cookie will be set with an expiration 30 days from now.
  3. Log out.
  4. Log in.
  5. User will NOT be asked for TOTP (correct!).
  6. Check the trust_device cookie. It is set, but now the expiration is "session".
  7. Log out.
  8. Log in.
  9. TOTP is requested (bad!).

Current vs. Expected behavior

Current behavior: when "trust device" is true, the user is not required to enter the TOTP on the very next login, but then is required to enter the TOTP on the following login. So basically it only works for one login (the next one after entering it).

Expected behavior: all logins for at least 30 days should not require the TOTP (potentially indefinite if the cookie is refreshed on every login).

What version of Better Auth are you using?

1.2.7

Provide environment information

- OS: MacOS
- Browser: Brave, Safari, Chrome

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)


Additional context

The bug may be related to how the trust_device cookie is refreshed. In any case, when the "trust device" option is used it only works for the next login. The following login will require the TOTP again, which is not how it's supposed to work.

One theory is that the way the cookie is originally set here uses a maxAge:

https://github.com/better-auth/better-auth/blob/87b2ffa5620fc1ca534e8d3d2f3859b629b365ce/packages/better-auth/src/plugins/two-factor/verify-two-factor.ts#L59-L64

But here it does not when it's being refreshed (no maxAge so maybe defaults to session?).

https://github.com/better-auth/better-auth/blob/87b2ffa5620fc1ca534e8d3d2f3859b629b365ce/packages/better-auth/src/plugins/two-factor/index.ts#L264-L266


Related note: the docs for 2FA state that the device will be trusted for 60 days, while the code actually sets it to 30. Also, if the cookie is refreshed on every login, it's not exactly "30 days" either ... it's at least 30 days, refreshed each time the user signs in (so it could be indefinite from a user perspective if they log in at least once every 30 days on that device!). https://www.better-auth.com/docs/plugins/2fa#trusted-devices

Originally created by @ErikPetersenDev on GitHub (May 21, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Set up project using the two-factor plugin w/ TOTP. 1. When entering the TOTP, send along the trustDevice property as `true`. 2. The user will be logged in and the `trust_device` cookie will be set with an expiration 30 days from now. 3. Log out. 4. Log in. 5. User will NOT be asked for TOTP (correct!). 6. Check the `trust_device` cookie. It is set, but now the expiration is "session". 7. Log out. 8. Log in. 9. TOTP is requested (bad!). ### Current vs. Expected behavior Current behavior: when "trust device" is true, the user is not required to enter the TOTP on the very next login, but then is required to enter the TOTP on the following login. So basically it only works for one login (the next one after entering it). Expected behavior: all logins for at least 30 days should not require the TOTP (potentially indefinite if the cookie is refreshed on every login). ### What version of Better Auth are you using? 1.2.7 ### Provide environment information ```bash - OS: MacOS - Browser: Brave, Safari, Chrome ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript ``` ### Additional context The bug may be related to how the trust_device cookie is refreshed. In any case, when the "trust device" option is used it only works for the next login. The following login will require the TOTP again, which is not how it's supposed to work. One theory is that the way the cookie is originally set here uses a maxAge: https://github.com/better-auth/better-auth/blob/87b2ffa5620fc1ca534e8d3d2f3859b629b365ce/packages/better-auth/src/plugins/two-factor/verify-two-factor.ts#L59-L64 But here it does not when it's being refreshed (no maxAge so maybe defaults to session?). https://github.com/better-auth/better-auth/blob/87b2ffa5620fc1ca534e8d3d2f3859b629b365ce/packages/better-auth/src/plugins/two-factor/index.ts#L264-L266 ------------- Related note: the docs for 2FA state that the device will be trusted for 60 days, while the code actually sets it to 30. Also, if the cookie is refreshed on every login, it's not exactly "30 days" either ... it's at least 30 days, refreshed each time the user signs in (so it could be indefinite from a user perspective if they log in at least once every 30 days on that device!). https://www.better-auth.com/docs/plugins/2fa#trusted-devices
Author
Owner

@waagdev commented on GitHub (Jun 10, 2025):

I can confirm this bug still exists in version 1.2.8.

The trusted device feature only works for one login cycle - after the first successful login without TOTP, the next login requires TOTP verification again, which breaks the expected user experience.

This significantly impacts usability since users expect trusted devices to remain trusted for the documented duration (30 days according to the code, 60 days according to the docs), not just for a single login session.

Additional consideration: Currently trusted devices are stored as cookies only. Would it make sense to also store them in the database? This would enable:

  • Admin management (viewing/revoking trusted devices)
  • Cross-browser device management
  • Better audit trails
  • More robust security controls

Is there any update on when this might be addressed? Happy to test any potential fixes.

@waagdev commented on GitHub (Jun 10, 2025): I can confirm this bug still exists in version 1.2.8. The trusted device feature only works for one login cycle - after the first successful login without TOTP, the next login requires TOTP verification again, which breaks the expected user experience. This significantly impacts usability since users expect trusted devices to remain trusted for the documented duration (30 days according to the code, 60 days according to the docs), not just for a single login session. **Additional consideration:** Currently trusted devices are stored as cookies only. Would it make sense to also store them in the database? This would enable: - Admin management (viewing/revoking trusted devices) - Cross-browser device management - Better audit trails - More robust security controls Is there any update on when this might be addressed? Happy to test any potential fixes.
Author
Owner

@milanpanin commented on GitHub (Jun 18, 2025):

I have the same problem. Can we expect a fix soon? Also, it would be good to integrate the possibility of setting the cookie expiration to a certain period, not fixed to 30 days.

@milanpanin commented on GitHub (Jun 18, 2025): I have the same problem. Can we expect a fix soon? Also, it would be good to integrate the possibility of setting the cookie expiration to a certain period, not fixed to 30 days.
Author
Owner

@milanpanin commented on GitHub (Jun 26, 2025):

@Bekacru Any update on this topic? Thank you.

@milanpanin commented on GitHub (Jun 26, 2025): @Bekacru Any update on this topic? Thank you.
Author
Owner

@dosubot[bot] commented on GitHub (Sep 25, 2025):

Hi, @ErikPetersenDev. I'm Dosu, and I'm helping the better-auth team manage their backlog and am marking this issue as stale.

Issue Summary:

  • The "trust device" feature in the TOTP two-factor plugin currently only persists for one login session instead of the intended 30 days.
  • This is caused by the trust_device cookie being refreshed without a maxAge, leading to usability issues.
  • Users including you, waagdev, and milanpanin have confirmed the problem persists in version 1.2.8.
  • Suggestions include storing trusted devices in the database for improved management and security.
  • No updates or fixes have been provided by maintainers so far.

Next Steps:

  • Please let me know if this issue is still relevant with the latest version of better-auth by commenting here to keep the discussion open.
  • If I don’t hear back within 7 days, I will automatically close this issue.

Thank you for your understanding and contribution!

@dosubot[bot] commented on GitHub (Sep 25, 2025): Hi, @ErikPetersenDev. I'm [Dosu](https://dosu.dev), and I'm helping the better-auth team manage their backlog and am marking this issue as stale. **Issue Summary:** - The "trust device" feature in the TOTP two-factor plugin currently only persists for one login session instead of the intended 30 days. - This is caused by the trust_device cookie being refreshed without a maxAge, leading to usability issues. - Users including you, waagdev, and milanpanin have confirmed the problem persists in version 1.2.8. - Suggestions include storing trusted devices in the database for improved management and security. - No updates or fixes have been provided by maintainers so far. **Next Steps:** - Please let me know if this issue is still relevant with the latest version of better-auth by commenting here to keep the discussion open. - If I don’t hear back within 7 days, I will automatically close this issue. Thank you for your understanding and contribution!
Author
Owner

@ErikPetersenDev commented on GitHub (Sep 25, 2025):

This is still open. The referenced PR is being actively worked with a commit as recently as 21 hours ago.

@ErikPetersenDev commented on GitHub (Sep 25, 2025): This is still open. The referenced PR is being actively worked with a commit as recently as 21 hours ago.
Author
Owner

@BobbaruK commented on GitHub (Nov 4, 2025):

have the same issue in 1.3.8

@BobbaruK commented on GitHub (Nov 4, 2025): have the same issue in 1.3.8
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1239