Skip to content

Commit

Permalink
Add support for WALRUS AccessToken Pushes on every heartbeat see [#12
Browse files Browse the repository at this point in the history
  • Loading branch information
acupofjose committed Nov 29, 2021
1 parent 2b59f88 commit 163f2e1
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 2 deletions.
8 changes: 7 additions & 1 deletion Realtime/Channel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ public enum ChannelState
/// </summary>
public string Topic { get => Utils.GenerateChannelTopic(database, schema, table, col, value); }

/// <summary>
/// Flag stating whether a channel has been joined once or not.
/// </summary>
public bool HasJoinedOnce { get; private set; }

private string database;
private string schema;
private string table;
Expand All @@ -108,7 +113,7 @@ public enum ChannelState

private bool canPush => IsJoined && Socket.IsConnected;
private bool hasJoinedOnce = false;
private List<Push> buffer = new List<Push>();
internal List<Push> buffer = new List<Push>();
private Timer rejoinTimer;
private bool isRejoining = false;

Expand Down Expand Up @@ -166,6 +171,7 @@ public Task<Channel> Subscribe(int timeoutMs = Constants.DEFAULT_TIMEOUT)
{
// Success!
case ChannelState.Joined:
HasJoinedOnce = true;
StateChanged -= channelCallback;
JoinPush.OnTimeout -= joinPushTimeoutCallback;
Expand Down
44 changes: 43 additions & 1 deletion Realtime/Client.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading.Tasks;
using Newtonsoft.Json;
Expand All @@ -24,7 +25,12 @@ public class Client
/// Keys are of encoded value: `{database}{:schema?}{:table?}{:col.eq.:value?}`
/// Values are of type `Channel<T> where T : BaseModel, new()`;
/// </summary>
private Dictionary<string, Channel> subscriptions { get; set; }
public Dictionary<string, Channel> subscriptions { get; set; }

/// <summary>
/// Exposes all Realtime Channel Subscriptions for R/O public consumption
/// </summary>
public ReadOnlyDictionary<string, Channel> Subscriptions => new ReadOnlyDictionary<string, Channel>(subscriptions);

/// <summary>
/// The backing Socket class.
Expand Down Expand Up @@ -106,6 +112,11 @@ public JsonSerializerSettings SerializerSettings

private string realtimeUrl;

/// <summary>
/// JWT Access token for WALRUS security
/// </summary>
internal string AccessToken { get; private set; }

/// <summary>
/// Initializes a Client instance, this method should be called prior to any other method.
/// </summary>
Expand Down Expand Up @@ -242,6 +253,34 @@ public Client Disconnect(CloseStatusCode code = WebSocketSharp.CloseStatusCode.N
return this;
}

/// <summary>
/// Sets the JWT access token used for channel subscription authorization and Realtime RLS.
/// Ref: https://github.com/supabase/realtime-js/pull/117 | https://github.com/supabase/realtime-js/pull/117
/// </summary>
/// <param name="jwt"></param>
public void SetAuth(string jwt)
{
AccessToken = jwt;

try
{
foreach (var channel in subscriptions.Values)
{
if (channel.HasJoinedOnce && channel.IsJoined)
{
channel.Push(Constants.CHANNEL_ACCESS_TOKEN, new Dictionary<string, string>
{
{ "access_token", AccessToken }
});
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}

/// <summary>
/// Adds a Channel subscription - if a subscription exists with the same signature, the existing subscription will be returned.
/// </summary>
Expand Down Expand Up @@ -295,6 +334,9 @@ private void HandleSocketStateChanged(object sender, SocketStateChangedEventArgs
switch (args.State)
{
case SocketStateChangedEventArgs.ConnectionState.Open:
// Ref: https://github.com/supabase/realtime-js/pull/116/files
SetAuth(AccessToken);

OnOpen?.Invoke(this, args);
break;
case SocketStateChangedEventArgs.ConnectionState.Close:
Expand Down
2 changes: 2 additions & 0 deletions Realtime/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,7 @@ public enum EventType
public static string PHEONIX_STATUS_ERROR = "error";

public static string TRANSPORT_WEBSOCKET = "websocket";

public static string CHANNEL_ACCESS_TOKEN = "access_token";
}
}
6 changes: 6 additions & 0 deletions Realtime/Socket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ private void SendHeartbeat()
pendingHeartbeatRef = MakeMsgRef();

Push(new SocketRequest { Topic = "phoenix", Event = "heartbeat", Ref = pendingHeartbeatRef.ToString() });

// Ref: https://github.com/supabase/realtime-js/pull/116
if (!string.IsNullOrEmpty(Client.Instance.AccessToken))
{
Client.Instance.SetAuth(Client.Instance.AccessToken);
}
}

/// <summary>
Expand Down

0 comments on commit 163f2e1

Please sign in to comment.