Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

WebPush Notification Send Results in 403 #1

Open
iseec opened this issue Aug 19, 2019 · 6 comments
Open

WebPush Notification Send Results in 403 #1

iseec opened this issue Aug 19, 2019 · 6 comments

Comments

@iseec
Copy link

iseec commented Aug 19, 2019

Hello

I used your demo as a blueprint to implement the push subscriptions for our customers.

I can subscribe users, and also send notifications to them in my development environment.
So i pushed it up to staging, but now i get the 403 with the same code.
(with new subscriptions for the new environment).

Exception:
Received unexpected response code: 403 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() --- End of stack trace from previous location where exception was thrown --- at WebPush.WebPushClient.HandleResponse(HttpResponseMessage response, PushSubscription subscription) at WebPush.WebPushClient.<SendNotificationAsync>d__15.MoveNext() at WebPush.WebPushClient.<SendNotificationAsync>d__16.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Backend.Notifications.MessageHandler.NotificationBatchMessageHandler.<Handle>d__11.MoveNext() in /app/src/Backend/Notifications/MessageHandler/NotificationBatchMessageHandler.cs:line 93

For the Subscriptions, they are done via a website run in docker containers behind a Loadbalancer, the public endpoint of the Loadbalancer is served via Https, and the containers run on different machines in a private subnet.

The Communication between the Loadbalancers and Containers is established via HTTP.

Code to send Notifications:

    var notification = GenerateNotification(batch.Template, account);
    string notificationjson = string.Empty;
    try
    {
        if (await _repo.RecordNotificationSent(subscription.Id, batch.Template.Id, 
    notification.NotificationId.ToString()))
        {
            notificationjson = JsonConvert.SerializeObject(notification);
            _client = new WebPushClient();
            await _client.SendNotificationAsync(ToWebPushSubscription(subscription),
                     notificationjson, _vapidDetails);
        }
    
    }
    catch (WebPushException ex)
    {
    
        if(ex.Message == "Subscription no longer valid")
        {
            Logger?.LogInformation($"invalidate subscription {subscription.Id}");
            await _ar.UnsubscribePushAsync(subscription);
        }
        else
        {
            Logger?.LogCritical(ex.Message, ex);
        }
    }
    catch (Exception ex)
    {
        Logger?.LogCritical(ex.Message, ex);
    }
    ...
    private WebPush.PushSubscription ToWebPushSubscription(PushSubscription sub)
    {
        return new WebPush.PushSubscription(sub.Endpoint, sub.P256Dh, sub.Auth);
    }

Environment Settings:

  • dotnet core 1.1.1
  • webpush version: 1.0.11

Development Environment:

  • windows 10 Pro & VS Community 2019 16.2.2

Staging Environment:

  • containers based on microsoft/dotnet:1.1.1-sdk

WebServer: Kestrel

Any Ideas what could cause this issue, and how to fix it?

@mark-szabo
Copy link
Contributor

Hi @epandasa, have you generated new VAPID keys for your staging environment?

@iseec
Copy link
Author

iseec commented Aug 20, 2019

Hi @mark-szabo,

i just tested it and yes my Code automatically generates new VAPID keys for each Environment/Tenant, and writes them to our Database.

        private async Task<VapidDetails> CheckOrGenerateVapidDetails(string vapidSubject, string vapidPublicKey, string vapidPrivateKey, int tenantid)
        {
            if (string.IsNullOrEmpty(vapidSubject))
            {
                return null;
            }

            if (string.IsNullOrEmpty(vapidSubject) ||
                string.IsNullOrEmpty(vapidPublicKey) ||
                string.IsNullOrEmpty(vapidPrivateKey))
            {
                var vapidKeys = VapidHelper.GenerateVapidKeys();
                vapidPublicKey = vapidKeys.PublicKey;
                vapidPrivateKey = vapidKeys.PrivateKey;
                await _tr.UpdateVapidDetailsAsync(tenantid, vapidSubject, vapidPublicKey,vapidPrivateKey);
            }
            return new VapidDetails(vapidSubject, vapidPublicKey, vapidPrivateKey);
        }

This Code runs when no VAPID keys are given/generated on Startup in the current context, inside of my Push Controller.

    
        public async Task<IActionResult> VapidPublicKey()
        {

            if(_vapidDetails == null)
            {
                _vapidDetails = await CheckOrGenerateVapidDetails(Request.Host.Host, null, null, _tenant.Id);
            }

            return Json(_vapidDetails.PublicKey);
        }

......
        public async Task<IActionResult> Subscribe([FromBody] PushSubscriptionViewModel model)
        {
            if (_vapidDetails == null)
            {
                _vapidDetails = await CheckOrGenerateVapidDetails($"https://{Request.Host}", null, null, _tenant.Id);
            }
     .....
        }

@TASimpson
Copy link

TASimpson commented Oct 15, 2019

@mark-szabo

I too am having a 403 issue with every environment besides my own. I have followed the demo set up almost to a "T". Including the service: https://github.com/MicrosoftEdge/pushnotifications-demo-aspnetcore/blob/master/PushnotificationsDemo/Services/PushService.cs

For my public and private key I saved it as env variable so that everything who pulls latest or when we push it to dev and up. Will have those keys as well.

I to this day do not have any issues receiving the notifications.

But in co-workers and dev environments. I get the same exact exception above. Any help will be more than appreciated! I have been banging my head against the wall.

From certs to appsettings to env variables to keys....I do not see any differences. What am I missing?!

@gavrilyuc
Copy link

I have the same trouble. I didn't change the project I just downloaded and ran it.

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
WebPush.WebPushException: Received unexpected response code: 403
   at WebPush.WebPushClient.HandleResponse(HttpResponseMessage response, PushSubscription subscription)
   at WebPush.WebPushClient.SendNotification(PushSubscription subscription, String payload, Dictionary`2 options)
   at WebPush.WebPushClient.SendNotification(PushSubscription subscription, String payload, VapidDetails vapidDetails)
   at PushnotificationsDemo.Services.PushService.Send(String userId, Notification notification) in /Users/gavrilyuc/Downloads/pushnotifications-demo-aspnetcore-master 2/PushnotificationsDemo/Services/PushService.cs:line 96
   at PushnotificationsDemo.Services.PushService.Send(String userId, Notification notification) in /Users/gavrilyuc/Downloads/pushnotifications-demo-aspnetcore-master 2/PushnotificationsDemo/Services/PushService.cs:line 107
   at PushnotificationsDemo.Controllers.PushController.Send(String userId, Notification notification, Nullable`1 delay) in /Users/gavrilyuc/Downloads/pushnotifications-demo-aspnetcore-master 2/PushnotificationsDemo/Controllers/PushController.cs:line 105
   at lambda_method(Closure , Object )
   at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

@gavrilyuc
Copy link

Can you help me, anybody? @molant @mark-szabo @TASimpson

@pouyababaie
Copy link

any updates on this?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants