alexalok / dotAPNS

dotAPNS is a library used to send push notifications to Apple devices using Apple Push Notification service via HTTP/2 API.
Apache License 2.0
114 stars 34 forks source link

Using Voip Services Certificate.p12 Getting "Authentication Failed - The credentials supplied to the package were not recognized #106

Closed NebulaSleuth closed 2 years ago

NebulaSleuth commented 2 years ago

I created a Voip Services Cert on developer.apple.com. Downloaded it, loaded it into Keychain Access and exported as a .p12 file. I Converted the .p12 file to Base64 string and include that as a secret in my application (Azure App Service) In my back end I do this:

` var key = Environment.GetEnvironmentVariable("APNS_VOIP");

            var pw = Environment.GetEnvironmentVariable("APNS_VOIP_PW");

            var bytes = Convert.FromBase64String(key);

            X509Certificate2 cert = new X509Certificate2(bytes, pw);

            var client = ApnsClient.CreateUsingCert(cert);

`

Looking at the resulting cert it looks like it decoded properly: {[Subject] C=US, O=Extrastrength Software LLC, OU=XQB4K82SMZ, CN=VoIP Services: com.extrastrength.MFEAssist, OID.0.9.2342.19200300.100.1.1=com.extrastrength.MFEAssist.voip [Issuer] C=US, O=Apple Inc., OU=G4, CN=Apple Worldwide Developer Relations Certification Authority [Serial Number] 93F8518C6FAAE44E30BEDA7499FFA6EB [Not Before] 9/11/2022 2:35:17 PM [Not After] 10/11/2023 2:35:16 PM [Thumbprint] 25305E20FDFE44C01E1A0F5A89DCC986BC2F520B }

I attempt to send the push:

`
var push = new ApplePush(ApplePushType.Voip) .AddVoipToken(deviceNotificationId);

            try
            {

                push.SendToDevelopmentServer(); // Tried with and without this

                await client.SendAsync(push);

            }
            catch (Exception ex)
            {

                Debug.WriteLine(ex.Message);

            }`

I Receive the following exception: System.Net.Http.HttpRequestException HResult=0x80131501 Message=The SSL connection could not be established, see inner exception. Source=System.Net.Http StackTrace: at System.Net.Http.ConnectHelper.<EstablishSslConnectionAsync>d__2.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Threading.Tasks.ValueTask1.get_Result() at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable1.ConfiguredValueTaskAwaiter.GetResult() at System.Net.Http.HttpConnectionPool.<ConnectAsync>d__96.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Threading.Tasks.ValueTask1.get_Result() at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable1.ConfiguredValueTaskAwaiter.GetResult() at System.Net.Http.HttpConnectionPool.<AddHttp2ConnectionAsync>d__77.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at System.Threading.Tasks.TaskCompletionSourceWithCancellation1.<WaitWithCancellationAsync>d__1.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Threading.Tasks.ValueTask1.get_Result() at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable1.ConfiguredValueTaskAwaiter.GetResult() at System.Net.Http.HttpConnectionPool.<GetHttp2ConnectionAsync>d__79.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Threading.Tasks.ValueTask1.get_Result() at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable1.ConfiguredValueTaskAwaiter.GetResult() at System.Net.Http.HttpConnectionPool.<SendWithVersionDetectionAndRetryAsync>d__83.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at System.Net.Http.DiagnosticsHandler.d8.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Threading.Tasks.ValueTask1.get_Result() at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable1.ConfiguredValueTaskAwaiter.GetResult() at System.Net.Http.RedirectHandler.d4.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at System.Net.Http.HttpClient.<gCore|83_0>d.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() at dotAPNS.ApnsClient.d17.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at MFEWebAPI.Services.NotificationService.d__2.MoveNext() in D:\repos\MFE\MFEWebAPI\MFEWebAPI\Services\NotificationService.cs:line 134

This exception was originally thrown at this call stack: [External Code]

Inner Exception 1: AuthenticationException: Authentication failed, see inner exception.

Inner Exception 2: Win32Exception: The credentials supplied to the package were not recognized `

alexalok commented 2 years ago

Which version of .NET and OS are you using?

NebulaSleuth commented 2 years ago

DotNet 6.0. Also note that this is happening on a deployed Azure App Service (on Windows), not locally. Because of other factors, it does not run locally. I plan on building a locally runnable test this evening to see if it related to that.

Since its an Azure App Service, I don't know exactly what version of windows it is running on, but I would expect pretty recent.

NebulaSleuth commented 2 years ago

I found this article: https://docs.microsoft.com/en-us/azure/app-service/configure-ssl-certificate-in-code I will try it tonight as well...

[EDIT] - This was the answer. It requires a Basic tier (No Free or Dev/Test tier support) Upload the .P12 file (rename to .pfx) and then follow the instructions to make it available to the app. Then the HTTP2 SSL/TLS connection will succeed. I tried just upgrading the tier and using my previous method of creating the cert, and it still failed. Seems it NEEDS to be in the keystore to the App Service.

NebulaSleuth commented 2 years ago

As per my edit, I was able to get past the exception. You can close this issue

alexalok commented 2 years ago

Thanks for taking your time to share the solution! I'm now closing the issue as per your request.