Skip to content

Commit

Permalink
Merge pull request #88 from pusher/user_authentication
Browse files Browse the repository at this point in the history
Introduce user authentication
  • Loading branch information
MeenaAlfons authored Jan 5, 2023
2 parents b4dcc70 + 413cf1a commit b4da785
Show file tree
Hide file tree
Showing 23 changed files with 683 additions and 74 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ jobs:
- name: Prepare package
run: |
sed -i 's/<Version>[^<]*<\/Version>/<Version>${{ env.VERSION }}<\/Version>/' Root.Build.props
sed -i 's/<AssemblyVersion>[^<]*<\/AssemblyVersion>/<AssemblyVersion>${{ env.VERSION }}.0<\/AssemblyVersion>/' Root.Build.props
sed -i 's/<FileVersion>[^<]*<\/FileVersion>/<FileVersion>${{ env.VERSION }}.0<\/FileVersion>/' Root.Build.props
- name: Prepare CHANGELOG
run: |
echo "${{ github.event.pull_request.body }}" | csplit -s - "/##/"
Expand Down
16 changes: 11 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
# Changelog

## 4.7.0-beta
* [ADDED] AuthenticateUser
* [ADDED] AuthorizeChannel
* [DEPRECATED] Authenticate
* [CHANGED] Bump Newtonsoft.Json to version 13.0.2

## 4.6.1
* [FIXED] PusherClient test integration to 2.1.0.

## 4.6.0
* [ADDED] Strong name to the PusherServer assembly.

## 4.5.0
* [ADDED] End-to-end encryption using NaCl.Net.
* [ADDED] EncryptionMasterKey and RestClientTimeout properties to IPusherOptions.
* [ADDED] Cluster property to test application settings.
* [ADDED] End-to-end encryption using NaCl.Net.
* [ADDED] EncryptionMasterKey and RestClientTimeout properties to IPusherOptions.
* [ADDED] Cluster property to test application settings.
* [CHANGED] Default timeout from 100 to 30 seconds.

## 4.4.0
* [REMOVED] PusherServer.Core project
* [REMOVED] PusherServer.Core project
* [FIXED] Use .ConfigureAwait(false) on every await

## 4.3.2
* [CHANGED] Make the GH release task depend tag creation
* [CHANGED] Make the GH release task depend tag creation

## 4.3.1
* [CHANGED] PusherServer.Core should not be packed
Expand Down
40 changes: 40 additions & 0 deletions PusherServer.Tests/AcceptanceTests/AuthenticateUser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Threading.Tasks;
using NUnit.Framework;
using PusherServer.Tests.Helpers;

namespace PusherServer.Tests.AcceptanceTests
{
[TestFixture]
public class When_authenticating_a_user
{
[Test]
public async Task the_auth_token_for_a_user_should_be_accepted_by_Pusher()
{
PusherServer.Pusher pusherServer = new Pusher(Config.AppId, Config.AppKey, Config.AppSecret, new PusherOptions()
{
HostName = Config.HttpHost
});
PusherClient.Pusher pusherClient = new PusherClient.Pusher(Config.AppKey, new PusherClient.PusherOptions
{
UserAuthenticator = new InMemoryUserAuthenticator(
pusherServer,
new UserData()
{
id = "leggetter",
watchlist = new string[] { "user_1", "user_2" },
user_info = new { twitter_id = "@leggetter" }
}),
Cluster = Config.Cluster,
TraceLogger = new PusherClient.TraceLogger(),
});

await pusherClient.ConnectAsync().ConfigureAwait(false);
pusherClient.User.Signin();

await pusherClient.User.SigninDoneAsync().ConfigureAwait(false);

// No assertions for now. If the above code executes without error then the test passes.
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
namespace PusherServer.Tests.AcceptanceTests
{
[TestFixture]
public class When_authenticating_a_private_subscription
public class When_authorizing_a_private_subscription
{
[Test]
public async Task the_authentication_token_for_a_private_channel_should_be_accepted_by_Pusher()
public async Task the_auth_token_for_a_private_channel_should_be_accepted_by_Pusher()
{
PusherServer.Pusher pusherServer = new Pusher(Config.AppId, Config.AppKey, Config.AppSecret, new PusherOptions()
{
HostName = Config.HttpHost
});
PusherClient.Pusher pusherClient = new PusherClient.Pusher(Config.AppKey, new PusherClient.PusherOptions
{
Authorizer = new InMemoryAuthorizer(pusherServer),
ChannelAuthorizer = new InMemoryChannelAuthorizer(pusherServer),
Cluster = Config.Cluster,
TraceLogger = new PusherClient.TraceLogger(),
});
Expand All @@ -31,7 +31,7 @@ public async Task the_authentication_token_for_a_private_channel_should_be_accep
}

[Test]
public async Task the_authentication_token_for_a_private_encrypted_channel_should_be_accepted_by_Pusher()
public async Task the_auth_token_for_a_private_encrypted_channel_should_be_accepted_by_Pusher()
{
PusherServer.Pusher pusherServer = new Pusher(Config.AppId, Config.AppKey, Config.AppSecret, new PusherOptions()
{
Expand All @@ -41,7 +41,7 @@ public async Task the_authentication_token_for_a_private_encrypted_channel_shoul

PusherClient.Pusher pusherClient = new PusherClient.Pusher(Config.AppKey, new PusherClient.PusherOptions
{
Authorizer = new InMemoryAuthorizer(pusherServer),
ChannelAuthorizer = new InMemoryChannelAuthorizer(pusherServer),
Cluster = Config.Cluster,
TraceLogger = new PusherClient.TraceLogger(),
});
Expand All @@ -56,15 +56,15 @@ public async Task the_authentication_token_for_a_private_encrypted_channel_shoul
}

[Test]
public async Task the_authentication_token_for_a_presence_channel_should_be_accepted_by_Pusher()
public async Task the_auth_token_for_a_presence_channel_should_be_accepted_by_Pusher()
{
Pusher pusherServer = new Pusher(Config.AppId, Config.AppKey, Config.AppSecret, new PusherOptions
{
HostName = Config.HttpHost,
});
PusherClient.Pusher pusherClient = new PusherClient.Pusher(Config.AppKey, new PusherClient.PusherOptions
{
Authorizer = new InMemoryAuthorizer(
ChannelAuthorizer = new InMemoryChannelAuthorizer(
pusherServer,
new PresenceChannelData()
{
Expand Down
2 changes: 1 addition & 1 deletion PusherServer.Tests/AcceptanceTests/Trigger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public async Task It_should_be_received_by_a_client_async()
{
Cluster = Config.Cluster,
TraceLogger = new PusherClient.TraceLogger(),
Authorizer = new InMemoryAuthorizer(_pusher as Pusher),
ChannelAuthorizer = new InMemoryChannelAuthorizer(_pusher as Pusher),
});

await client.ConnectAsync().ConfigureAwait(false);
Expand Down
11 changes: 0 additions & 11 deletions PusherServer.Tests/App.config

This file was deleted.

2 changes: 1 addition & 1 deletion PusherServer.Tests/Helpers/ClientServerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static async Task CreateClientAsync(Pusher pusherServer, string channelNa
{
PusherClient.Pusher pusherClient = new PusherClient.Pusher(Config.AppKey, new PusherClient.PusherOptions
{
Authorizer = new InMemoryAuthorizer(
ChannelAuthorizer = new InMemoryChannelAuthorizer(
pusherServer,
new PresenceChannelData()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

namespace PusherServer.Tests.Helpers
{
internal class InMemoryAuthorizer: IAuthorizer
internal class InMemoryChannelAuthorizer: IChannelAuthorizer
{
private readonly PusherServer.Pusher _pusher;
private readonly PresenceChannelData _presenceData;

public InMemoryAuthorizer(PusherServer.Pusher pusher):
public InMemoryChannelAuthorizer(PusherServer.Pusher pusher):
this(pusher, null)
{
}

public InMemoryAuthorizer(PusherServer.Pusher pusher, PresenceChannelData presenceData)
public InMemoryChannelAuthorizer(PusherServer.Pusher pusher, PresenceChannelData presenceData)
{
_pusher = pusher;
_presenceData = presenceData;
Expand Down
23 changes: 23 additions & 0 deletions PusherServer.Tests/Helpers/InMemoryUserAuthenticator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using PusherClient;

namespace PusherServer.Tests.Helpers
{
internal class InMemoryUserAuthenticator: IUserAuthenticator
{
private readonly PusherServer.Pusher _pusher;
private readonly UserData _userData;

public InMemoryUserAuthenticator(PusherServer.Pusher pusher, UserData userData)
{
_pusher = pusher;
_userData = userData;
}

public string Authenticate(string socketId)
{
IUserAuthenticationResponse authResponse;
authResponse = _pusher.AuthenticateUser(socketId, _userData);
return authResponse.ToJson();
}
}
}
4 changes: 3 additions & 1 deletion PusherServer.Tests/PusherServer.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

<PropertyGroup>
<TargetFrameworks>net45</TargetFrameworks>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<IsPackable>false</IsPackable>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
Expand All @@ -25,10 +26,11 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="nunit" Version="3.13.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="NSubstitute" Version="1.10.0.0" />
<PackageReference Include="PusherClient" Version="2.1.0" />
<PackageReference Include="PusherClient" Version="2.3.0-beta" />
<PackageReference Include="WebSocket4Net" Version="0.15.2" />
</ItemGroup>

Expand Down
16 changes: 10 additions & 6 deletions PusherServer.Tests/UnitTests/Authenticate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
using PusherServer.Exceptions;
using PusherServer.Tests.Helpers;

////
// This file tests the deprecated PusherServer.IPusher.Authenticate method.
////

namespace PusherServer.Tests.UnitTests
{
[TestFixture]
Expand Down Expand Up @@ -134,9 +138,9 @@ public class When_authenticating_a_private_encrypted_channel
public void the_auth_response_is_valid()
{
string channelName = "private-encrypted-channel";
Pusher pusher = new Pusher(Config.AppId, Config.AppKey, Config.AppSecret, new PusherOptions
{
EncryptionMasterKey = DataHelper.GenerateEncryptionMasterKey(),
Pusher pusher = new Pusher(Config.AppId, Config.AppKey, Config.AppSecret, new PusherOptions
{
EncryptionMasterKey = DataHelper.GenerateEncryptionMasterKey(),
});

IAuthenticationData result = pusher.Authenticate(channelName, "123.456");
Expand All @@ -161,9 +165,9 @@ public void encryption_master_key_should_be_defined()
public void encryption_master_key_should_be_well_defined()
{
string channelName = "private-encrypted-channel";
Pusher pusher = new Pusher(Config.AppId, Config.AppKey, Config.AppSecret, new PusherOptions
{
EncryptionMasterKey = new byte[] { 1, 2 },
Pusher pusher = new Pusher(Config.AppId, Config.AppKey, Config.AppSecret, new PusherOptions
{
EncryptionMasterKey = new byte[] { 1, 2 },
});
pusher.Authenticate(channelName, "123.456");
}
Expand Down
112 changes: 112 additions & 0 deletions PusherServer.Tests/UnitTests/AuthenticateUser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System;
using Newtonsoft.Json;
using NUnit.Framework;
using PusherServer.Exceptions;
using PusherServer.Tests.Helpers;

namespace PusherServer.Tests.UnitTests
{
[TestFixture]
public class When_authenticating_a_user
{
private IPusher _pusher;

[OneTimeSetUp]
public void Setup()
{
_pusher = new Pusher(Config.AppId, Config.AppKey, Config.AppSecret);
}

[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void null_user_data_throw_Exception()
{
string socketId = "some_socket_id";

_pusher.AuthenticateUser(socketId, null);
}

[Test]
public void the_auth_response_is_valid()
{
string socketId = "123.456";

UserData userData = new UserData()
{
id = "unique_user_id",
};
string userDataJson = DefaultSerializer.Default.Serialize(userData);

string expectedAuthString = Config.AppKey + ":" + CreateSignedString(socketId, userDataJson);

IUserAuthenticationResponse result = _pusher.AuthenticateUser(socketId, userData);
Assert.AreEqual(expectedAuthString, result.auth);
Assert.AreEqual(userDataJson, result.user_data);
}

[Test]
public void with_watchlist_the_auth_response_is_valid()
{
string socketId = "123.456";

UserData userData = new UserData()
{
id = "unique_user_id",
watchlist = new string[] { "user1", "user2" },
user_info = new { twitter_id = "@leggetter" }
};
string userDataJson = DefaultSerializer.Default.Serialize(userData);

string expectedAuthString = Config.AppKey + ":" + CreateSignedString(socketId, userDataJson);

IUserAuthenticationResponse result = _pusher.AuthenticateUser(socketId, userData);
Assert.AreEqual(expectedAuthString, result.auth);
Assert.AreEqual(userDataJson, result.user_data);
}

[Test]
public void with_userinfo_the_auth_response_is_valid()
{
string socketId = "123.456";

UserData userData = new UserData()
{
id = "unique_user_id",
user_info = new { twitter_id = "@leggetter" }
};
string userDataJson = DefaultSerializer.Default.Serialize(userData);

string expectedAuthString = Config.AppKey + ":" + CreateSignedString(socketId, userDataJson);

IUserAuthenticationResponse result = _pusher.AuthenticateUser(socketId, userData);
Assert.AreEqual(expectedAuthString, result.auth);
Assert.AreEqual(userDataJson, result.user_data);
}

[Test]
public void with_userinfo_and_watchlist_the_auth_response_is_valid()
{
string socketId = "123.456";

UserData userData = new UserData()
{
id = "unique_user_id",
watchlist = new string[] { "user1", "user2" },
user_info = new { twitter_id = "@leggetter" }
};
string userDataJson = DefaultSerializer.Default.Serialize(userData);

string expectedAuthString = Config.AppKey + ":" + CreateSignedString(socketId, userDataJson);

IUserAuthenticationResponse result = _pusher.AuthenticateUser(socketId, userData);
Assert.AreEqual(expectedAuthString, result.auth);
Assert.AreEqual(userDataJson, result.user_data);
}

private string CreateSignedString(string socketId, string userDataJson)
{
var stringToSign = socketId + "::user::" + userDataJson;
return CryptoHelper.GetHmac256(Config.AppSecret, stringToSign);
}
}
}
Loading

0 comments on commit b4da785

Please sign in to comment.