Skip to content

Commit bcc252d

Browse files
Merge pull request #1612 from appwrite/realtime-jwt-support
added realtime jwt support
2 parents 5966a34 + c96b002 commit bcc252d

8 files changed

Lines changed: 59 additions & 9 deletions

File tree

templates/android/library/src/main/java/io/package/services/Realtime.kt.twig

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@ class Realtime(client: Client) : Service(client), CoroutineScope {
7373
val encodedProject = java.net.URLEncoder.encode(client.config["project"].toString(), "UTF-8")
7474
val queryParams = "project=$encodedProject"
7575
val url = "${client.endpointRealtime}/realtime?$queryParams"
76-
val request = Request.Builder().url(url).build()
76+
val requestBuilder = Request.Builder().url(url)
77+
val jwt = client.config["jwt"]
78+
if (!jwt.isNullOrEmpty()) {
79+
requestBuilder.addHeader("x-{{ spec.title | caseLower }}-jwt", jwt)
80+
}
81+
val request = requestBuilder.build()
7782

7883
val generation = socketGeneration.incrementAndGet()
7984
socket = client.http.newWebSocket(request, {{ spec.title | caseUcfirst }}WebSocketListener(generation))

templates/apple/Sources/Services/Realtime.swift.twig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,15 @@ open class Realtime : Service {
135135
return
136136
}
137137

138+
var headers = HTTPHeaders()
139+
if let jwt = client.config["jwt"], !jwt.isEmpty {
140+
headers.add(name: "x-{{ spec.title | caseLower }}-jwt", value: jwt)
141+
}
142+
138143
socketClient = WebSocketClient(
139144
url,
140145
tlsEnabled: !client.selfSigned,
146+
headers: headers,
141147
delegate: self
142148
)
143149

templates/flutter/lib/src/realtime_browser.dart.twig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ class RealtimeBrowser extends RealtimeBase with RealtimeMixin {
2222

2323
Future<WebSocketChannel> _getWebSocket(Uri uri) async {
2424
await (client as ClientBrowser).init();
25+
26+
final jwt = client.config['jwt'];
27+
if (jwt != null && jwt.isNotEmpty) {
28+
uri = uri.replace(queryParameters: {
29+
...uri.queryParameters,
30+
'jwt': jwt,
31+
});
32+
}
33+
2534
return HtmlWebSocketChannel.connect(uri);
2635
}
2736

templates/flutter/lib/src/realtime_io.dart.twig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ class RealtimeIO extends RealtimeBase with RealtimeMixin {
3232
final cookies = await (client as ClientIO).cookieJar.loadForRequest(uri);
3333
headers = {HttpHeaders.cookieHeader: CookieManager.getCookies(cookies)};
3434

35+
final jwt = client.config['jwt'];
36+
if (jwt != null && jwt.isNotEmpty) {
37+
headers['x-{{ spec.title | caseLower }}-jwt'] = jwt;
38+
}
39+
3540
final websok = IOWebSocketChannel((client as ClientIO).selfSigned
3641
? await _connectForSelfSignedCert(uri, headers)
3742
: await WebSocket.connect(uri.toString(), headers: headers));

templates/react-native/src/client.ts.twig

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,11 @@ class Client {
328328
const channels = new URLSearchParams();
329329
channels.set('project', this.config.project);
330330

331+
const jwt = this.config.jwt;
332+
if (jwt && Platform.OS === 'web') {
333+
channels.set('jwt', jwt);
334+
}
335+
331336
const url = this.config.endpointRealtime + '/realtime?' + channels.toString();
332337

333338
if (
@@ -347,7 +352,8 @@ class Client {
347352
// @ts-ignore
348353
this.realtime.socket = new WebSocket(url, undefined, {
349354
headers: {
350-
Origin: `{{ spec.title | caseLower }}-${Platform.OS}://${this.config.platform}`
355+
Origin: `{{ spec.title | caseLower }}-${Platform.OS}://${this.config.platform}`,
356+
...(jwt && Platform.OS !== 'web' ? { 'x-{{ spec.title | caseLower }}-jwt': jwt } : {})
351357
}
352358
});
353359
this.realtime.socket.addEventListener('message', this.realtime.onMessage);

templates/unity/Assets/Runtime/Realtime.cs.twig

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -523,17 +523,24 @@ namespace {{ spec.title | caseUcfirst }}
523523
{
524524
var uri = PrepareUri();
525525
Debug.Log($"[Realtime] Connecting to URI: {uri}");
526-
526+
527+
var headers = new Dictionary<string, string>();
528+
var jwt = _client.Config.GetValueOrDefault("jwt");
529+
if (!string.IsNullOrEmpty(jwt))
530+
{
531+
headers["x-{{ spec.title | caseLower }}-jwt"] = jwt;
532+
}
533+
527534
if (_webSocket == null || _webSocket.State == WebSocketState.Closed)
528535
{
529-
_webSocket = new WebSocket(uri);
536+
_webSocket = new WebSocket(uri, headers);
530537
_lastUrl = uri;
531538
SetupWebSocketEvents();
532539
}
533540
else if (_lastUrl != uri && _webSocket.State != WebSocketState.Closed)
534541
{
535542
await CloseConnection();
536-
_webSocket = new WebSocket(uri);
543+
_webSocket = new WebSocket(uri, headers);
537544
_lastUrl = uri;
538545
SetupWebSocketEvents();
539546
}

templates/web/src/client.ts.twig

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,11 @@ class Client {
564564

565565
const encodedProject = encodeURIComponent((this.config.project as string) ?? '');
566566
// URL carries only the project; channels/queries are sent via subscribe message.
567-
const queryParams = 'project=' + encodedProject;
567+
let queryParams = 'project=' + encodedProject;
568+
569+
if (this.config.jwt) {
570+
queryParams += '&jwt=' + encodeURIComponent(this.config.jwt as string);
571+
}
568572

569573
const url = this.config.endpointRealtime + '/realtime?' + queryParams;
570574

templates/web/src/services/realtime.ts.twig

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,14 @@ export class Realtime {
208208
}
209209

210210
// URL carries only the project; channels/queries are sent via the subscribe message.
211-
const queryParams = `project=${projectId}`;
211+
let queryParams = `project=${projectId}`;
212+
213+
const jwt = this.client.config.jwt;
214+
{% if language.name != 'ReactNative' %}
215+
if (jwt) {
216+
queryParams += `&jwt=${encodeURIComponent(jwt)}`;
217+
}
218+
{% endif %}
212219

213220
const endpoint =
214221
this.client.config.endpointRealtime !== ''
@@ -243,10 +250,11 @@ export class Realtime {
243250
{% if language.name == 'ReactNative' %}
244251
const WebSocketCtor: any = WebSocket;
245252
const socket = (this.socket = Platform.OS === 'web'
246-
? new WebSocketCtor(url)
253+
? new WebSocketCtor(jwt ? `${url}&jwt=${encodeURIComponent(jwt)}` : url)
247254
: new WebSocketCtor(url, undefined, {
248255
headers: {
249-
Origin: `{{ spec.title | caseLower }}-${Platform.OS}://${this.client.config.platform}`
256+
Origin: `{{ spec.title | caseLower }}-${Platform.OS}://${this.client.config.platform}`,
257+
...(jwt ? { 'x-{{ spec.title | caseLower }}-jwt': jwt } : {})
250258
}
251259
}));
252260
{% else %}

0 commit comments

Comments
 (0)