Skip to content

fix: session refresh works as intended now#5330

Open
isXander wants to merge 3 commits intomodrinth:mainfrom
isXander:fix/5324
Open

fix: session refresh works as intended now#5330
isXander wants to merge 3 commits intomodrinth:mainfrom
isXander:fix/5324

Conversation

@isXander
Copy link
Contributor

@isXander isXander commented Feb 8, 2026

Fixes #5324

What's fixed

  1. The /session/refresh failed with expired sessions given, but the frontend only attempted to refresh after a failed fetch. The route fails because it attempts to get the current user from the auth token, but this fails because the session has expired.
  2. If a session was refreshed successfully, the refresh_expires DB column would be reset to 60 days, not retain the timestamp from the original session, making this functionality completely useless.
  3. /session/refresh accepted any authorization token, not just mra_ session tokens, and would issue a new session.

How's it fixed

  • struct SessionBuilder has two new fields, expires: Option<DateTime<Utc>> and refresh_expires.
    • When None, database defaults are used
  • Add param to get_user_record_from_bearer_token to ignore session expiry
    • Any usages have been set to false
  • New get_user_from_bearer_token function that transforms DBUser -> User
  • routes/internal/session.rs/issue_session function now accepts refresh_expires: Option<DateTime<Utc>> as a new parameter, feeds it into the SessionBuilder
  • session/refresh route now feeds in the expired session's refresh_expires
  • Prevented session/refresh route from accepting Authorization tokens that are not mra_

Questions to you

In an attempt to not duplicate the defaults set by the database table migration
(https://github.com/modrinth/code/blob/main/apps/labrinth/migrations/20230628180115_kill-ory.sql#L32-L33), a slightly over-complicated match expression was used to only insert those values when they are Some.
https://github.com/isXander/modrinth/blob/76c63148152b7591b7c93688175bed8e8da4b8aa/apps/labrinth/src/database/models/session_item.rs#L66-L111

If instead you do not mind some duplication, this would make this function significantly simpler.

@isXander isXander marked this pull request as draft February 8, 2026 14:16
@IMB11 IMB11 added the backend Involves work from the backend team label Feb 8, 2026
@IMB11 IMB11 requested a review from a team February 8, 2026 14:18
@IMB11 IMB11 added the 📂 Under review [Triage] Is being reviewed by Modrinth Staff for future roadmap consideration. label Feb 8, 2026
@isXander
Copy link
Contributor Author

isXander commented Feb 8, 2026

Just confirmed locally that this fix does indeed work!

@isXander isXander marked this pull request as ready for review February 8, 2026 14:34
Copy link
Contributor

@aecsocket aecsocket left a comment

Choose a reason for hiding this comment

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

Keeping the defaults in the database makes sense to me, so I'm fine with the match expression. Code LGTM.

.await?;
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Would try to remove the UPDATE statements and create the session with just a single INSERT to avoid table bloat - can remove the database default & just define the default in code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm getting mixed signals here!! @aecsocket said to leave the db defaults?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry for the confusion here - we discussed this in further detail, and came to the conclusion that the default shouldn't be specified in the DB, but in the code itself, since it's more important to combine the INSERT and UPDATE here.

My thought here is that SessionBuilder's insert and update operations should default to Utc::now() + (14 days) for expires, and + 60 days for refresh expires, like the DB already does, but in the Rust logic rather than in the DB. And that SessionBuilder will never omit inserting an expires or refresh_expires value - it will always be set to a value, or the default if not explicitly set.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should I add a database migration to remove the defaults from the table on the db-level as to not cause unexpected behaviour or hide bugs?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Involves work from the backend team 📂 Under review [Triage] Is being reviewed by Modrinth Staff for future roadmap consideration.

Development

Successfully merging this pull request may close these issues.

session/refresh fails when session has expired

4 participants

Comments