diff --git a/Source/ZoomNet.UnitTests/Extensions/InternalTests.cs b/Source/ZoomNet.UnitTests/Extensions/InternalTests.cs index 52bc49d6..3cbeba08 100644 --- a/Source/ZoomNet.UnitTests/Extensions/InternalTests.cs +++ b/Source/ZoomNet.UnitTests/Extensions/InternalTests.cs @@ -178,11 +178,11 @@ public async Task ThrowsExceptionWhenExpectedRecordsAreMissing() { // Arrange var responseContent = @"{ - ""next_page_token"": """", - ""page_number"": 1, - ""page_size"": 100, - ""total_records"": 5 - }"; + ""next_page_token"": """", + ""page_number"": 1, + ""page_size"": 100, + ""total_records"": 5 + }"; var message = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(responseContent) diff --git a/Source/ZoomNet.UnitTests/Utils.cs b/Source/ZoomNet.UnitTests/Utils.cs index 8b038da0..8d1f25b7 100644 --- a/Source/ZoomNet.UnitTests/Utils.cs +++ b/Source/ZoomNet.UnitTests/Utils.cs @@ -13,11 +13,12 @@ public static class Utils { private const string ZOOM_V2_BASE_URI = "https://api.zoom.us/v2"; - public static Pathoschild.Http.Client.IClient GetFluentClient(MockHttpMessageHandler httpMessageHandler) + public static Pathoschild.Http.Client.IClient GetFluentClient(MockHttpMessageHandler httpMessageHandler, MockHttpMessageHandler tokenMessageHandler = null) { - var httpClient = httpMessageHandler.ToHttpClient(); - var client = new FluentClient(new Uri(ZOOM_V2_BASE_URI), httpClient); - client.SetRequestCoordinator(new ZoomRetryCoordinator(new Http429RetryStrategy(), null)); + var client = new FluentClient(new Uri(ZOOM_V2_BASE_URI), httpMessageHandler.ToHttpClient()); + var tokenHandler = tokenMessageHandler == null ? null : new OAuthTokenHandler(OAuthConnectionInfo.ForServerToServer("bogus clientId", "bogus secret", "bogus accountId"), tokenMessageHandler.ToHttpClient(), null); + + client.SetRequestCoordinator(new ZoomRetryCoordinator(new Http429RetryStrategy(), tokenHandler)); client.Filters.Remove(); // Remove all the built-in formatters and replace them with our custom JSON formatter diff --git a/Source/ZoomNet.UnitTests/WebhookParserTests.cs b/Source/ZoomNet.UnitTests/WebhookParserTests.cs index 59936bcb..f831657f 100644 --- a/Source/ZoomNet.UnitTests/WebhookParserTests.cs +++ b/Source/ZoomNet.UnitTests/WebhookParserTests.cs @@ -502,5 +502,44 @@ public void WebinarEnded() parsedEvent.Webinar.Password.ShouldBeNull(); parsedEvent.Webinar.Settings.ShouldBeNull(); } + + public class VerifySignature + { + [Fact] + public void Simple() + { + // Arange + var requestBody = "{\"payload\":{\"plainToken\":\"xys8n8PGS7mAU0m5-YJjRA\"},\"event_ts\":1720705455858,\"event\":\"endpoint.url_validation\"}"; + var secretToken = "4fv1RkqGQUq5sWbEz6hA5A"; + var signature = "v0=93a1a675965ceb9c5a50c5dfb31f20e50f763be37a54ef74cd2d16a1a8e5c0d6"; + var timestamp = "1720705455"; + + var parser = new WebhookParser(); + + // Act + var result = parser.VerifySignature(requestBody, secretToken, signature, timestamp); + + //Assert + result.ShouldBeTrue(); + } + + [Fact] + public void Topic_contains_non_ASCII_characters() + { + // Arange + var requestBody = "{\"event\":\"meeting.started\",\"payload\":{\"account_id\":\"VjZoEArIT5y-HlWxkV-tVA\",\"object\":{\"duration\":60,\"start_time\":\"2024-07-11T14:12:55Z\",\"timezone\":\"America/New_York\",\"topic\":\"Test \\uD83D\\uDE92\\uD83D\\uDE92 ? - ’ - – \\uD83D\\uDE97 HOLA\",\"id\":\"85393847045\",\"type\":2,\"uuid\":\"jUh5o3dKQIytvcsfTtKBlg==\",\"host_id\":\"8lzIwvZTSOqjndWPbPqzuA\"}},\"event_ts\":1720707175904}"; + var secretToken = "4fv1RkqGQUq5sWbEz6hA5A"; + var signature = "v0=1a14e79349318fa1bead50ebbd3c185ae078e182d3bbd30ab8010fcb7f4357c7"; + var timestamp = "1720707175"; + + var parser = new WebhookParser(); + + // Act + var result = parser.VerifySignature(requestBody, secretToken, signature, timestamp); + + //Assert + result.ShouldBeTrue(); + } + } } } diff --git a/Source/ZoomNet.UnitTests/ZoomNet.UnitTests.csproj b/Source/ZoomNet.UnitTests/ZoomNet.UnitTests.csproj index fb2e98c7..136ecd88 100644 --- a/Source/ZoomNet.UnitTests/ZoomNet.UnitTests.csproj +++ b/Source/ZoomNet.UnitTests/ZoomNet.UnitTests.csproj @@ -20,8 +20,8 @@ - - + + all runtime; build; native; contentfiles; analyzers diff --git a/Source/ZoomNet/WebhookParser.cs b/Source/ZoomNet/WebhookParser.cs index 76d4d3b0..d80293c2 100644 --- a/Source/ZoomNet/WebhookParser.cs +++ b/Source/ZoomNet/WebhookParser.cs @@ -33,8 +33,9 @@ public bool VerifySignature(string requestBody, string secretToken, string signa var message = $"v0:{timestamp}:{requestBody}"; // Hash the message - var hmac = new HMACSHA256(Encoding.ASCII.GetBytes(secretToken)); - var hashAsBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(message)); + var hashingEncoding = Encoding.UTF8; // Switched from ASCII to UTF8 in July 2024. See https://github.com/Jericho/ZoomNet/issues/349 for more information. + var hmac = new HMACSHA256(hashingEncoding.GetBytes(secretToken)); + var hashAsBytes = hmac.ComputeHash(hashingEncoding.GetBytes(message)); var hashAsHex = hashAsBytes.ToHexString(); // Create the signature diff --git a/Source/ZoomNet/ZoomNet.csproj b/Source/ZoomNet/ZoomNet.csproj index ead76ed5..2a9015d3 100644 --- a/Source/ZoomNet/ZoomNet.csproj +++ b/Source/ZoomNet/ZoomNet.csproj @@ -42,7 +42,7 @@ - + diff --git a/build.cake b/build.cake index cc5b3bc8..3befc266 100644 --- a/build.cake +++ b/build.cake @@ -1,13 +1,13 @@ // Install tools. #tool dotnet:?package=GitVersion.Tool&version=5.12.0 #tool dotnet:?package=coveralls.net&version=4.0.1 -#tool nuget:https://f.feedz.io/jericho/jericho/nuget/?package=GitReleaseManager&version=0.17.0-collaborators0004 -#tool nuget:?package=ReportGenerator&version=5.3.5 -#tool nuget:?package=xunit.runner.console&version=2.8.1 +#tool nuget:https://f.feedz.io/jericho/jericho/nuget/?package=GitReleaseManager&version=0.17.0-collaborators0007 +#tool nuget:?package=ReportGenerator&version=5.3.7 +#tool nuget:?package=xunit.runner.console&version=2.9.0 #tool nuget:?package=CodecovUploader&version=0.7.3 // Install addins. -#addin nuget:?package=Cake.Coveralls&version=1.1.0 +#addin nuget:?package=Cake.Coveralls&version=4.0.0 #addin nuget:?package=Cake.Git&version=4.0.0 #addin nuget:?package=Cake.Codecov&version=3.0.0 @@ -86,6 +86,8 @@ var isTagged = BuildSystem.AppVeyor.Environment.Repository.Tag.IsTag && !string. var isIntegrationTestsProjectPresent = FileExists(integrationTestsProject); var isUnitTestsProjectPresent = FileExists(unitTestsProject); var isBenchmarkProjectPresent = FileExists(benchmarkProject); +var removeIntegrationTests = isIntegrationTestsProjectPresent && (!isLocalBuild || target == "coverage"); +var removeBenchmarks = isBenchmarkProjectPresent && (!isLocalBuild || target == "coverage"); var publishingError = false; @@ -162,7 +164,7 @@ Setup(context => // Integration tests are intended to be used for debugging purposes and not intended to be executed in CI environment. // Also, the runner for these tests contains windows-specific code (such as resizing window, moving window to center of screen, etc.) // which can cause problems when attempting to run unit tests on an Ubuntu image on AppVeyor. - if (!isLocalBuild && isIntegrationTestsProjectPresent) + if (removeIntegrationTests) { Information(""); Information("Removing integration tests"); @@ -172,7 +174,7 @@ Setup(context => // Similarly, benchmarking can causes problems similar to this one: // error NETSDK1005: Assets file '/home/appveyor/projects/stronggrid/Source/StrongGrid.Benchmark/obj/project.assets.json' doesn't have a target for 'net5.0'. // Ensure that restore has run and that you have included 'net5.0' in the TargetFrameworks for your project. - if (!isLocalBuild && isBenchmarkProjectPresent) + if (removeBenchmarks) { Information(""); Information("Removing benchmark project"); @@ -182,7 +184,7 @@ Setup(context => Teardown(context => { - if (!isLocalBuild) + if (removeIntegrationTests || removeBenchmarks) { Information("Restoring projects that may have been removed during build script setup"); GitCheckout(".", new FilePath[] { solutionFile }); @@ -352,7 +354,7 @@ Task("Generate-Code-Coverage-Report") new FilePath(coverageFile), codeCoverageDir, new ReportGeneratorSettings() { - ClassFilters = new[] { "*.UnitTests*" } + ClassFilters = new[] { "+*" } } ); }); diff --git a/global.json b/global.json index d3edfcb3..175f404f 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.301", + "version": "8.0.303", "rollForward": "patch", "allowPrerelease": false }