How to programmatically determine if NE Personal VPN start failed because of authentication failure?

I have a PersonalVPN app that configures and controls an IKEv2 Personal VPN connection. I need to be able to determine if a start connection fails because of invalid credentials so that I can present a dialog for the user to re-enter credentials.

I can see in the console app:
"Last disconnect error for <VPN_name> changed from "none" to "The VPN credentials are invalid."

How do I access this information programmatically?

Replies

I need to be able to determine if a start connection fails because of invalid credentials so that I can present a dialog for the user to re-enter credentials.

One way to do this would be to monitor the status NEVPNStatus before and if an error is caught while calling startVPNTunnel().

Code Block swift
do {
lastError = nil
postStatusChangedNotification()
try self.manager.connection.startVPNTunnel()
} catch {
lastError = error
/* After the status change is posted reason about the error that was caught.*/
postStatusChangedNotification()
}


Also, if you are authenticating with an identityReference or an passwordReference that is being accessed from the keychain, then there could be OSStatus errors that you catch too from the keychain before startVPNTunnel() is even called.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Thank you for your response Matt. From the NEVPN documentation, my understanding is that the error you are catching in the code snippet can be one of :
NEVPNErrorConfigurationDisabled
NEVPNErrorConfigurationInvalid
NEVPNErrorConnectionFailed
NEVPNErrorConfigurationStale
NEVPNErrorConfigurationReadWriteFailed
NEVPNErrorConfigurationUnknown

So, I won't be able to tell if there was an authentication failure, right?

I am using EAPExtendedAuthentication and have saved a VPN profile with a persistence reference from the keychain. I believe my startVPNTunnelAndReturnWithErrors (I'm using ObjectiveC) succeeds without generating an error. I only get a system alert pop-up telling me that the authentication failed.

I am not sure I understand why I would get an OSStatus error before calling startVpnTunnel since the authentication is done by the server?

I am not sure I understand why I would get an OSStatus error before calling startVpnTunnel since the authentication is done by the server?

An OSStatus error can be thrown for a query to SecItemCopyMatching, which would query a credential that is used for authentication. For example, an identityReference or an passwordReference. Getting one of these errors before startVPNTunnelAndReturnWithErrors is called would give you an indication of a preemptive authentication failure for an invalid credential.

As for the errors you have listed, yes, keying on an NEVPNErrorConnectionFailed and notifying the user to check their credentials on a NEVPNStatus disconnected state would be one option here. In this sequence you may see the NEVPNStatus go from NEVPNStatusConnecting -> NEVPNStatusDisconnecting -> NEVPNStatusDisconnected.

You could also try examining the localizedDescription of NSError that you are receiving from startVPNTunnelAndReturnWithErrors for more information. Digging into this a bit more VPN disconnect errors are attempting to be reasoned about and set here, so you may be able to see some useful information here on why the VPN transport when down in this property.

When debugging this on your own you will also see useful information with your device tethered to your macOS machine in the Console.app, that you did not see in the Xcode console. For example:
"Last disconnect error for 'name here' changed from 'none' to 'The VPN session failed because an internal error occurred.'"


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Hi Matt,

So startVPNTunnelAndReturnError does not return an error - it completes successfully. Checking the NEVPNStatus AFTER completion of the call does show that the connection status is Disconnected. However, this by itself is not enough for me to deduce it is an authentication failure. I do see the "last disconnect error for <vpn name> changed from "none" to "The VPN credentials are invalid" in the Console app. I was hoping to get access to the "last disconnect error" programmatically.

Also fyi, this app is targeted to MacOS and I am running it directly on my MacBook.


So startVPNTunnelAndReturnError does not return an error - it completes successfully. Checking the NEVPNStatus AFTER completion of the call does show that the connection status is Disconnected. However, this by itself is not enough for me to deduce it is an authentication failure.

Right. If you are unable to get the error here then it would be best to monitor the NEVPNStatus here and notify the user that something went wrong.

I also think that this is worth an Enhancement Request to consolidate what is being presented in the Console.app compared to what is available in the NSError, or what is not available.

Please follow up with the Feedback ID.



Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Thank you Matt. Here is the Feedback Id filed: FB8719651
Thank you! I see your Feedback internally and have copied myself on it for further updates.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com