Displaying notifications from NEPacketTunnelProvider

Hi there,


Been writing a NEPacketTunnelProvider implementation, and currently trying to handle the case where a user calls the VPN directly from the system settings but there is an error in estabilishing the connection. The rationale here is to either provide a quick link back to the application for the user, or simply give them some feedback as to why a connection has failed should they choose to use the system preferences instead of the application. Looking around the documentation and developer forums have lead to different trains of thought and deprecated methods.


The first and most obvious method was the use of displayMessage(_:completionHandler:). This works for a simple error messsage but is now deprecated as of iOS 12.0 and macOS 10.14. Thus, this is not ideal.


Searching further, the closest post I could find was this one where the poster was recommended to make use of the UserNotifications framework. However when requesting authorization with requestAuthorization(options:completionHandler:) from the tunnel provider I am returned notificationNotAllowed- "Notifications are not allowed for this application".


Is this expected behaviour? The only indication from a comment from Apple Staff user "eskimo" in the post linked above (sorry I don't know of a way to directly link to that comment) was that they were "pretty sure they work from a packet tunnel provider", so I'm not sure if this is in fact not allowed or if I am simply doing something wrong?


Alternatively if a better/more conventional modern approach exists for notifying the user of an error, I'd be grateful for it to be pointed out.


Thanks!

Replies

Back in the day, at the time of that thread in fact, I tested using UserNotification framework to post a notification from an NE provider, and it worked for me. Lots of things have changed since then, so it’s possible that that’s broken.

My recommendation is that you first try posting the notification from the container app. Once you get that working, your NE provider should be able to post notifications as well, that is, the authorisation to post a notification applies to the container app and all the app extensions embedded within that container.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Glad you could chip in! 🙂


I believe I did try that, but as per your recommendations I tried again, and unfortunately had the same result. Here is a minimal snippet of what I tried..


In AppDelegate.swift's applicationDidFinishLaunching(_:)


let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert]) { (granted, _) in
     if granted {
          print("Got authorization for notifications")
     } else {
          print("Failed to get authorization for notifications")
     }
}


This indeed prints "Got authorization for notifications". Then in the initialiser for my PacketTunnelProvider:


override init() {
    super.init()
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options: [.alert]) { (granted, _) in
        if granted {
            self.displayMessage("Granted", completionHandler: { _ in })
        } else {
            self.displayMessage("Not granted", completionHandler: { _ in})
        }
    }
}


This displays a modal saying "Not granted" (after the main app has been granted permissions).


Do you still think this should work, or can you point me in the right direction to submit a bug report/feature request?


NB: I am using displayMessage(_:completionHandler:) in the PacketTunnelProvider as I cannot seem to attach the debugger in such a way that I can get print statements to appear in the Xcode debugger console - I assume the output stream is being redirected somewhere else by the system? If anyone knows of a way to capture print/NSLog statements from the tunnel provider in the debugger, then this that would be appreciated, however I understand that is a different issue altogether!

Do you still think this should work … ?

Yes. What OS release are you testing this on?

If anyone knows of a way to capture print/NSLog statements from the tunnel provider in the debugger …

It’s currently not possible to do that, but it’s not something I miss a lot because, IMO, your packet tunnel provider should be logging to the system log. During development you can view these log entries in real time using the Console app on the Mac. And when you deploy to end user devices these log entries can be captured using various tools, including a sysdiagnose log, which helps when debugging problems that only show up in the field.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

> Yes. What OS release are you testing this on?


macOS Mojave 10.14.6, with Xcode 11 - *Currently bringing my iOS project up inline with my macOS project so in a few days I'll be able to test on iOS 13 as well.)


> It’s currently not possible to do that, but it’s not something I miss a lot because, IMO, your packet tunnel provider should be logging to the system log.


Ahh fantastic, I'll look into this. Unless I missed it I did not see any recommendations to do this in the documentation and am less familiar with development on Apple Platforms. Thanks for the heads up.

I'm having the same problem -

I'm calling requestAuthorization at the containing app, and the user approves notifications.

Then at the Extension, I'm calling getNotificationSettings, but the authorizationStatus is notDetermined, and the error is "Notifications are not allowed for this application". Trying to post notifications from the containing app is working fine, but I want to send the notifications from the extension, because the app might be in background mode.

Also, looking at the Mac's Notifications Settings, I see that the "Allow Notifications from myApp" is enabled.


I tried to test it on several devices - iphone with iOS 13, Mac with macOS 10.14.5 and Mac with macOS 10.15.2.

I am also having same problem in FilterControlProvider extension on IOS.

Calling requestAuthorization in main app, and I could approve notification.

Then at the Network Extension ( FilterControlProvider ), getNotificationSettings, but the authorizationStatus is notDetermined, and the error is "Notifications are not allowed for this application".


iPhone X IOS 13.2