fix: align session TTL with refresh token lifetime and prevent silent…#947
Merged
RUKAYAT-CODER merged 1 commit intoJun 29, 2026
Merged
Conversation
… role fallback - SessionService now validates that session TTL >= JWT refresh token lifetime at startup, logging a warning when misaligned. Added parseDurationToSeconds utility to interpret JWT_REFRESH_EXPIRES_IN formats (e.g. '7d', '1h'). - User.role getter now throws when the roles relation is not loaded, preventing silent STUDENT fallback. Added unit tests for both loaded and unloaded scenarios. - Updated auth.controller.ts and auth.service.ts to load the roles relation when querying users for login and refresh token operations. - Updated courses.service.ts and enrollments.service.ts to check user.roles (string array from JWT) instead of relying on the entity role getter, fixing role checks for JWT-authenticated users. - Documented the SESSION_TTL / JWT_REFRESH_EXPIRES_IN alignment requirement in .env.example.
|
@anumukul Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
RUKAYAT-CODER
approved these changes
Jun 29, 2026
RUKAYAT-CODER
left a comment
Contributor
There was a problem hiding this comment.
Thank you for contributing to the project.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes #819
closes #823
Summary
Two fixes addressing authentication state inconsistencies and a silent permissions downgrade bug.
Issue 1: Session TTL vs Refresh Token Lifetime Alignment
Problem:
src/session/session.service.tsdefaults session TTL to 604800s (7 days) fromAUTH_SESSION_TTL_SECONDS, while the JWT refresh token expires based onJWT_REFRESH_EXPIRES_IN. These values were configured independently with no enforcement of their relationship, allowing sessions to outlive refresh tokens or vice versa.Fix:
SessionServiceconstructor now parsesJWT_REFRESH_EXPIRES_INand compares it againstsessionTtlSecondsSessionService.parseDurationToSeconds()utility supporting7d,1h,60m,3600s, and numeric formats.env.exampleforSESSION_TTL_SECONDS,AUTH_SESSION_TTL_SECONDS, andJWT_REFRESH_EXPIRES_INAcceptance Criteria:
.env.examplewith a note about alignmentIssue 2: User Role Getter Silent STUDENT Fallback
Problem:
User.rolegetter insrc/users/entities/user.entity.tsreturnedUserRole.STUDENTwhenthis.roleswas undefined or empty. TypeORM does not eagerly load relations, so any query withoutrelations: ['roles']silently granted incorrect (downgraded) permissions.Fix:
get role()now throwsError('User.roles relation not loaded. Include relations: ["roles"] in the query.')whenthis.roles === undefinedrelations: ['roles']:auth.controller.ts: login user lookupauth.service.ts: refresh token user lookupcourses.service.tsandenrollments.service.tsrole checks to useuser.roles(string array from JWT payload) instead of relying on the entity getter, fixing role resolution for JWT-authenticated contextsuser.entity.spec.tscovering:undefinednullroles gracefullyAcceptance Criteria:
user.roleon an entity loaded without the relation throws an errorFiles Changed
src/session/session.service.tsparseDurationToSeconds().env.examplesrc/users/entities/user.entity.tsget role()throws whenrolesis undefinedsrc/auth/auth.controller.tsrelations: ['roles']src/auth/auth.service.tsrelations: ['roles']src/courses/courses.service.tsuser.rolesarray instead of entity gettersrc/courses/enrollments.service.tsuser.rolesarray instead of entity gettersrc/users/entities/user.entity.spec.tssrc/session/session.service.spec.tsparseDurationToSeconds()and constructor validationsrc/auth/auth.service.spec.tsfindOnewith relations