Skip to content

[core, sql, auth] Trust Tokens - Remember this computer for X days 2FA#9418

Merged
WinterSolstice8 merged 1 commit into
LandSandBoat:basefrom
9001-Solutions:9001/trust-tokens
Feb 11, 2026
Merged

[core, sql, auth] Trust Tokens - Remember this computer for X days 2FA#9418
WinterSolstice8 merged 1 commit into
LandSandBoat:basefrom
9001-Solutions:9001/trust-tokens

Conversation

@9001-Sols

@9001-Sols 9001-Sols commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

I affirm:

  • I understand that if I do not agree to the following points by completing the checkboxes my PR will be ignored.
  • I understand I should leave resolving conversations to the LandSandBoat team so that reviewers won't miss what was said.
  • I have read and understood the Contributing Guide and the Code of Conduct.
  • I have tested my code and the things my code has changed since the last commit in the PR and will test after any later commits.

What does this pull request do?

Summary

When a user has TOTP enabled, they currently have to enter a one-time code on every login. This adds trust tokens so a client can send "trust_this_computer": true along with a valid OTP login, receive back a trust_token in the response, and use that token on future logins to skip the OTP prompt for 30 days (server configurable).

What changed

sql/accounts_trust_tokens.sql - New table storing hashed trust tokens per account with an expiration timestamp. Foreign key on accid with ON DELETE CASCADE.

src/login/otp_helpers.h - New helper functions:

  • generateTrustToken() - 32 random bytes via OpenSSL RAND_bytes, returned as hex
  • hashTrustToken() - SHA-256 hash before storing (raw token never hits the DB)
  • saveTrustToken() - cleans expired tokens for the account, inserts new one with 30-day expiry
  • validateTrustToken() - cleans expired tokens, checks if hashed token exists for the account
  • removeAllTrustTokens() - wipes all tokens for an account (called on password change and TOTP removal)
  • New doesAccountNeedOTP(uint32 accid, ...) overload that takes an account ID directly instead of looking it up by username again

src/login/auth_session.cpp - Login flow changes:

  • validatePassword() now returns std::optional<std::pair<uint32, uint32>> (account ID + status) instead of bool, eliminating a redundant second DB query that fetched the same info
  • Login attempt reads trust_token and trust_this_computer from the JSON payload
  • OTP check tries the trust token first; falls back to the actual TOTP code if the token is missing or invalid
  • On successful login with trust_this_computer == true and a verified OTP, a new trust token is generated and returned in the response JSON
  • Password change and TOTP removal both call removeAllTrustTokens() to invalidate all trusted devices
  • sendLoginResult no longer takes an unused len parameter

src/login/auth_session.h - Signature change for validatePassword.

Security notes

  • Tokens are 256-bit random, stored as SHA-256 hashes (the raw token only lives client-side)
  • Expired tokens are cleaned up on every validate/save call
  • All tokens are revoked when the password changes or TOTP is removed
  • 30-day expiry

Dependencies

LandSandBoat/xiloader#46

Steps to test these changes

Prerequisites: A running LSB server with the accounts_trust_tokens table created, and an account with TOTP enabled.

  • Normal TOTP login still works - Log in with username, password, and a valid TOTP code without sending trust_this_computer. Login succeeds and no trust_token is in the response.
  • Trust token generation - Log in with username, password, valid TOTP code, and "trust_this_computer": true. Login succeeds and response JSON contains a trust_token (64 hex chars). A row exists in accounts_trust_tokens with expires ~30 days out.
  • Trust token login (skip OTP) - Log in with username, password, and the trust_token from above, no OTP code. Login succeeds.
  • Invalid trust token failure - Bogus trust_token fails.
  • Expired trust token - when trust token expires the normal untrusted flow is shown
  • Password change revokes all trust tokens - Generate and verify a trust token works, then change the password. Old trust token should no longer work (row gone from DB).
  • TOTP removal revokes all trust tokens - Generate and verify a trust token works, then remove TOTP (via OTP or recovery code). accounts_trust_tokens should be empty for that account.
  • Account without TOTP unaffected - Log in with an account that has no TOTP. Works as before, no trust token logic involved.
  • Satchel upgrade works with trust token login - otpVerified is set true when the account requires OTP regardless of whether the user authenticated via trust token or direct TOTP code. Confirm satchel size query still runs.

Screenshots of xiloader

New [ ] Trust this computer option

image

Successful login with trust, shows message specifying how long it is trusted for (server specific, falls back to 30 days)

image

Example of a trusted computer (Dynamically updates when username changes)

image

Bogus token auto revoke

image

Revoke Trust option

image

@github-actions

github-actions Bot commented Feb 9, 2026

Copy link
Copy Markdown

✨ Hello and thanks for the PR! ✨

🤖: This is a friendly automated reminder that the maintainers won't look at your PR until you've properly completed all of the checkboxes in the pre-filled template.

@9001-Sols 9001-Sols changed the title Trust Tokens [core] [sql] [security] Trust Tokens Feb 9, 2026
@9001-Sols 9001-Sols changed the title [core] [sql] [security] Trust Tokens [core] [sql] [security] Trust Tokens - Remember this computer for 30 days 2FA Feb 9, 2026
@9001-Sols 9001-Sols force-pushed the 9001/trust-tokens branch 2 times, most recently from 970bbba to fea46b5 Compare February 9, 2026 23:25
@9001-Sols 9001-Sols changed the title [core] [sql] [security] Trust Tokens - Remember this computer for 30 days 2FA [core] [sql] [auth] Trust Tokens - Remember this computer for 30 days 2FA Feb 9, 2026
@9001-Sols 9001-Sols changed the title [core] [sql] [auth] Trust Tokens - Remember this computer for 30 days 2FA [core, sql, auth] Trust Tokens - Remember this computer for 30 days 2FA Feb 10, 2026
@9001-Sols 9001-Sols marked this pull request as ready for review February 10, 2026 00:08
@9001-Sols 9001-Sols changed the title [core, sql, auth] Trust Tokens - Remember this computer for 30 days 2FA [core, sql, auth] Trust Tokens - Remember this computer for X days 2FA Feb 10, 2026
Comment thread src/login/auth_session.h
LOGIN_ERROR_TRUST_TOKEN_INVALID = 0x13,
};

constexpr std::array<uint8, 3> SupportedXiloaderVersion = { 2, 0, 0 };

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine this will need to be bumped in tandem with the xiloader PR, but I wanted to get direction from everyone on whether it should be a major, minor, or patch bump

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, if the server end updates we don't need to force support the new xiloader version. But the client may be mismatched, but that's a server distribution problem. I'll have to think about this a bit

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested old xiloader and it's forwards compatible with this build of xi_map, so no need to change this

@Xaver-DaRed Xaver-DaRed left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving out of "I am not opposed to this functionality"

However, WinterSolstice And Zach should review this properly

@WinterSolstice8

Copy link
Copy Markdown
Contributor

I have pulled this down and tested it. xiloader 2.0.1 is forwards compatible with this

@WinterSolstice8 WinterSolstice8 merged commit cf1e08b into LandSandBoat:base Feb 11, 2026
10 checks passed
@9001-Sols 9001-Sols deleted the 9001/trust-tokens branch February 11, 2026 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants