I'm having a very difficult time making Web Push notifications work via Azure Notification Hubs.
Browser notifications support has been announced in March 2024, but it looks like any kind of proper availability is still missing, despite this and this pull requests waiting for several months to be merged.
I spent a decent amount of time trying some esoteric suggestions like this one, but I'm constantly failing at creating a new Installation for a Browser-based push notification target.
The error is:
Microsoft.Azure.NotificationHubs.Messaging.BadRequestException: The provided request body is invalid. Error: The JSON value could not be converted to Microsoft.NotificationHubs.Contracts.LegacyModels.BrowserPushSubscription. Path: $.pushChannel | LineNumber: 0 | BytePositionInLine: 487.. TrackingId:dacca0ce-6af8-45b5-9ab5-ea1d1f78a57e,TimeStamp:9/21/2024 6:02:33 PM +00:00
at Microsoft.Azure.NotificationHubs.NotificationHubClient.SendRequestAsync(HttpRequestMessage request, String trackingId, HttpStatusCode[] successfulResponseStatuses, CancellationToken cancellationToken)
at Microsoft.Azure.NotificationHubs.NotificationHubClient.SendRequestAsync(HttpRequestMessage request, String trackingId, HttpStatusCode successfulResponseStatus, CancellationToken cancellationToken)
at Microsoft.Azure.NotificationHubs.NotificationHubClient.<>c__DisplayClass91_0.<<CreateOrUpdateInstallationAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.Azure.NotificationHubs.NotificationHubRetryPolicy.RunOperation[T](Func`2 operation, CancellationToken cancellationToken)
at Microsoft.Azure.NotificationHubs.NotificationHubRetryPolicy.RunOperation[T](Func`2 operation, CancellationToken cancellationToken)
at Microsoft.Azure.NotificationHubs.NotificationHubClient.CreateOrUpdateInstallationAsync(Installation installation, CancellationToken cancellationToken)
It looks like under the hood the Notification Hubs SDK is Serializing the BrowserPushSubscription
instance a JSON string to be then saved into the PushChannel
property.
Unfortunately, the Notification Hubs endpoint doesn't like it at all, because it's not capable of properly de-serializing it.
I tried to manually serialize it into different formats (IE: a common way to represent the browser subscription JSON is by grouping P256DH
and Auth
properties into a Keys
subproperty), with no luck.
Is there anybody that got it working? Thanks
Construct a manual JSON payload by yourself and send it via the Notification Hub REST API, bypassing the SDK.
JSON Payload :
{
"installationId": "your-installation-id",
"platform": "browser",
"pushChannel": {
"endpoint": "https://your-endpoint-url.com",
"keys": {
"p256dh": "your-p256dh-key",
"auth": "your-auth-key"
}
},
"tags": ["your-tag"]
}
Use REST API Directly:
curl -X PUT \
https://<your-notification-hub-namespace>.servicebus.windows.net/<your-hub-name>/installations/<your-installation-id>?api-version=2020-06 \
-H "Content-Type: application/json" \
-H "Authorization: SharedAccessSignature sr=<resource-uri>&sig=<signature>&se=<expiry>&skn=<policy-name>" \
-d '{
"installationId": "your-installation-id",
"platform": "browser",
"pushChannel": {
"endpoint": "https://your-endpoint-url.com",
"keys": {
"p256dh": "your-p256dh-key",
"auth": "your-auth-key"
}
},
"tags": ["your-tag"]
}'
Generate the Shared Access Signature (SAS), you can use Azure Portal or a script like this in C#
Code:
string resourceUri = "<namespace>.servicebus.windows.net";
string keyName = "<your-key-name>";
string key = "<your-primary-or-secondary-key>";
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
int expiry = Convert.ToInt32(sinceEpoch.TotalSeconds) + 3600; // 1 hour expiration
string stringToSign = WebUtility.UrlEncode(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
string sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
WebUtility.UrlEncode(resourceUri), WebUtility.UrlEncode(signature), expiry, keyName);
Console.WriteLine(sasToken);
Response (Success):
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2024 14:02:33 GMT
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
TrackingId: 3429bafa-212b-44ab-9b7e-caa3f217b7f5
x-ms-request-id: 7db24283-22c7-4e93-b865-9f6f063d5c7f
x-ms-version: 2020-02-09