Skip to content

added realtime jwt support#1612

Merged
ArnabChatterjee20k merged 3 commits into
mainfrom
realtime-jwt-support
Jun 24, 2026
Merged

added realtime jwt support#1612
ArnabChatterjee20k merged 3 commits into
mainfrom
realtime-jwt-support

Conversation

@ArnabChatterjee20k

Copy link
Copy Markdown
Member

What does this PR do?

(Provide a description of what this PR does.)

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.)

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

(Write your answer here.)

@greptile-apps

greptile-apps Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds JWT support to Realtime WebSocket connections across generated SDK templates. The main changes are:

  • Adds JWT headers for native Realtime WebSocket clients.
  • Adds JWT query parameters for browser WebSocket clients.
  • Updates legacy web and React Native Realtime connection setup.
  • Removes tracked SwiftPM checkout artifacts from the Apple SDK test build directory.

Confidence Score: 5/5

The realtime JWT support changes appear safe to merge.

No blocking correctness or security issues were identified in the changed SDK templates.

T-Rex T-Rex Logs

What T-Rex did

  • The baseline run completed (trex-artifacts/realtime-web-rn-jwt-01-before.txt) with exit code 0, capturing webClientUrl:false, rnWebUrl:false, and rnNativeHeader:false.
  • The head run completed (trex-artifacts/realtime-web-rn-jwt-02-after.txt) with exit code 0, capturing webClientUrl:true, rnWebUrl:true, rnNativeHeader:true, with x-appwrite-jwt: jwt token/with+chars for native.
  • The Flutter WebSocket URL and native header values were updated: before, the browser URL remained .../realtime?project=abc+project and native headers were {}; after, the URL became .../realtime?project=abc+project&jwt=trex.jwt and native paths include {'x-appwrite-jwt': 'trex.jwt'}.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (2): Last reviewed commit: "removed comments" | Re-trigger Greptile

Comment on lines 252 to 263
{% if language.name == 'ReactNative' %}
const WebSocketCtor: any = WebSocket;
// On web the JWT must ride in the query string (no handshake headers);
// on native it goes in the `x-{{ spec.title | caseLower }}-jwt` header.
const socket = (this.socket = Platform.OS === 'web'
? new WebSocketCtor(url)
? new WebSocketCtor(jwt ? `${url}&jwt=${encodeURIComponent(jwt)}` : url)
: new WebSocketCtor(url, undefined, {
headers: {
Origin: `{{ spec.title | caseLower }}-${Platform.OS}://${this.client.config.platform}`
Origin: `{{ spec.title | caseLower }}-${Platform.OS}://${this.client.config.platform}`,
...(jwt ? { 'x-{{ spec.title | caseLower }}-jwt': jwt } : {})
}
}));

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.

P1 Stale JWT after rotation in new Realtime class

The new Realtime class (this file) reads this.client.config.jwt once inside createSocketLocked() and embeds it in the URL (web) or header (native) only at socket-creation time. Unlike the legacy client.ts.twig path — which caches this.realtime.url and compares it on every createSocket() call so that a JWT change causes a reconnect on the next subscribe() — this class has no URL-change detection. If the caller invokes client.setJwt(newToken) while an active subscription exists, the WebSocket continues using the old JWT until the connection naturally drops and reconnects. On native platforms the new JWT won't appear even after reconnect unless createSocketLocked() is re-entered, which requires all subscriptions to be torn down and re-created.

Consider either: (a) storing the JWT used at connection time and forcing a reconnect in createSocket() when it changes, or (b) documenting that callers must disconnect() and resubscribe after a JWT rotation.

Comment on lines +213 to +219
const jwt = this.client.config.jwt;
{% if language.name != 'ReactNative' %}
// Browsers cannot set headers on the WebSocket handshake, so the JWT
// travels in the `jwt` query string instead (the server accepts both).
if (jwt) {
queryParams += `&jwt=${encodeURIComponent(jwt)}`;
}

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 security JWT exposed in WebSocket URL and server access logs

For all non-ReactNative (browser) targets the JWT is appended to the WebSocket upgrade URL as ?jwt=<token>. Because the HTTP Upgrade request is a standard HTTP GET, the full URL — including the JWT — will appear in server-side access logs, reverse-proxy logs, and load-balancer logs. Anyone with read access to those logs can extract a valid bearer token.

The same limitation applies to the browser and flutter-browser templates. If log-based token exposure is a concern, consider rotating short-lived JWTs and ensuring log-scrubbing is in place on the server side.

@ArnabChatterjee20k ArnabChatterjee20k merged commit bcc252d into main Jun 24, 2026
59 checks passed
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.

2 participants