Skip to content

fix the controllers#12506

Open
Saif0933 wants to merge 1 commit into
appwrite:1.9.xfrom
Saif0933:fix-jwt
Open

fix the controllers#12506
Saif0933 wants to merge 1 commit into
appwrite:1.9.xfrom
Saif0933:fix-jwt

Conversation

@Saif0933

@Saif0933 Saif0933 commented Jun 6, 2026

Copy link
Copy Markdown

What does this PR do?

(Provide a description of what this PR does and why it's needed.)

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)

Related PRs and Issues

  • (Related PR or issue)

Checklist

  • Have you read the Contributing Guidelines on issues?
  • If the PR includes a change to an API's metadata (desc, label, params, etc.), does it also include updated API specs and example docs?

@greptile-apps

greptile-apps Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds session expiry enforcement to JWT-based authentication in three code paths — console cookie auth (general.php), realtime WebSocket connections (connection.php), and HTTP request auth (request.php) — so that sessions whose expire timestamp has passed are now rejected rather than treated as valid.

  • general.php: refactors the $sessionExists check to store the found session document and adds an expire >= now guard; sessions without an expire attribute remain valid.
  • connection.php & request.php: apply the same pattern in the inverse form (clear $user when session not found or when expire is set and already passed), using DatabaseDateTime (same Utopia\\Database\\DateTime class, different alias).
  • The expiry comparisons in all three files pass the stored attribute value through a redundant new \\DateTime()format()formatTz() round-trip; a direct formatTz($expire) call would be cleaner and avoids the silent "now" fallback if the attribute value is ever null.

Confidence Score: 4/5

The core logic is correct and the three changed paths are consistent with each other; the main concern is a minor implementation choice in how the expiry timestamp is normalized before comparison.

The expiry-check logic is equivalent across all three files and the auth flow correctly rejects expired sessions. The only findings are the unnecessary round-trips through new \DateTime() and format() before formatTz(), which add noise and carry a subtle null-fallback risk, but are unlikely to cause a real defect given that Appwrite stores well-formed datetime strings.

All three changed files contain the same redundant date-normalisation pattern; no single file needs special attention beyond the others.

Important Files Changed

Filename Overview
app/controllers/general.php Adds session expiry validation to console cookie-based JWT auth; logic is correct but uses a redundant round-trip date normalisation.
app/init/realtime/connection.php Adds session expiry check to realtime WebSocket auth; consistent logic with request.php, using DatabaseDateTime alias correctly.
app/init/resources/request.php Adds session expiry check to HTTP request JWT auth; same pattern as connection.php, correctly rejects expired sessions.

Reviews (1): Last reviewed commit: "fix the controllers" | Re-trigger Greptile

Comment on lines +261 to +266
if (!empty($session) &&
(
!$session->isSet('expire') ||
DateTime::formatTz(DateTime::format(new \DateTime($session->getAttribute('expire')))) >= DateTime::formatTz(DateTime::now())
)
) {

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.

P2 The stored expire value from the DB is already in Appwrite's Utopia\Database\DateTime string format, so round-tripping it through new \DateTime() and DateTime::format() before passing to DateTime::formatTz() is redundant. More importantly, if $session->getAttribute('expire') ever returns a malformed or null string, new \DateTime(...) will silently create a "now" timestamp instead of throwing, making the session appear perpetually non-expired (if null produces "now", now >= now is true). Passing the raw stored string directly to DateTime::formatTz() avoids this ambiguity.

Suggested change
if (!empty($session) &&
(
!$session->isSet('expire') ||
DateTime::formatTz(DateTime::format(new \DateTime($session->getAttribute('expire')))) >= DateTime::formatTz(DateTime::now())
)
) {
if (!empty($session) &&
(
!$session->isSet('expire') ||
DateTime::formatTz($session->getAttribute('expire')) >= DateTime::formatTz(DateTime::now())
)
) {

Comment on lines +301 to +304
(
$session->isSet('expire') &&
DatabaseDateTime::formatTz(DatabaseDateTime::format(new \DateTime($session->getAttribute('expire')))) < DatabaseDateTime::formatTz(DatabaseDateTime::now())
)

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.

P2 Same redundant round-trip via new \DateTime() and DatabaseDateTime::format() before DatabaseDateTime::formatTz(). The value returned by $session->getAttribute('expire') should already be in Appwrite's stored datetime format, so DatabaseDateTime::formatTz($expire) is sufficient and avoids the silent "now" fallback if the value is ever null.

Suggested change
(
$session->isSet('expire') &&
DatabaseDateTime::formatTz(DatabaseDateTime::format(new \DateTime($session->getAttribute('expire')))) < DatabaseDateTime::formatTz(DatabaseDateTime::now())
)
(
$session->isSet('expire') &&
DatabaseDateTime::formatTz($session->getAttribute('expire')) < DatabaseDateTime::formatTz(DatabaseDateTime::now())
)

Comment on lines +460 to +463
(
$session->isSet('expire') &&
DatabaseDateTime::formatTz(DatabaseDateTime::format(new \DateTime($session->getAttribute('expire')))) < DatabaseDateTime::formatTz(DatabaseDateTime::now())
)

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.

P2 Same redundant round-trip via new \DateTime() and DatabaseDateTime::format() before DatabaseDateTime::formatTz(). The stored expire string is already in Appwrite's datetime format; passing it directly to DatabaseDateTime::formatTz() is cleaner and avoids the silent "now" fallback if the value is ever null.

Suggested change
(
$session->isSet('expire') &&
DatabaseDateTime::formatTz(DatabaseDateTime::format(new \DateTime($session->getAttribute('expire')))) < DatabaseDateTime::formatTz(DatabaseDateTime::now())
)
(
$session->isSet('expire') &&
DatabaseDateTime::formatTz($session->getAttribute('expire')) < DatabaseDateTime::formatTz(DatabaseDateTime::now())
)

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.

1 participant