SendEmptyPushNotification to gateway.push.apple.com no longer working - apple-push-notifications

For at least the past couple of days (maybe longer), nothing seems to happen when I send an Empty Push Notification to at least 1 test device. I'm pretty much using the same SendEmptyPushNotification code as the article posted below.
https://medium.com/#yangzhoupostbox/part-2-push-notification-for-updating-apple-pass-in-asp-net-6020768d112
My test device is running iOS 14.4.1. I can manually update the Pass, so the WebServiceURL is working.
My cert expires later this year. I've rebooted my device. This all used to work and I haven't changed anything.
NOTE: It looks like the AppleDeviceLibraryIdentifier & ApplePushToken are changing over time. Should these change or remain the same over the life of the Apple device the passes are installed on? I'm wondering if the new PushToken could be the issue. This seems to be the expected behavior. Does the Device Library Identifier change with the Push Token?
Does anyone know what might be wrong? Is anyone else having an issue?

Me too man. Let's figure this out together like Apex Legends.
I have submitted a TSI to Apple. They sent out an email on feb 10 saying:
On March 29, 2021, token and certificate-based HTTP/2 connections to the Apple Push Notification service must incorporate the new root certificate (AAACertificateServices 5/12/2020) which replaces the old GeoTrust Global CA root certificate. To ensure a seamless transition and to avoid push notification delivery failures, verify that both the old and new root certificates for the HTTP/2 interface are included in the Trust Store of each of your notification servers before March 29.
Note that Apple Push Notification service SSL provider certificates issued to you by Apple do not need be to updated at this time.
Learn more about connecting to APNs.
If you have any questions, contact us.
Best regards,
Apple Developer Relations
Update - Mon May 3, after submitting a TSI to Apple Dev
Push notifications stopped working for developers on March 31, 2021 after Apple migrated to a new APNS provider API (http/2 protocol).
To continue using push, see this page: https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns/
On that page, these 3 items are of special interest to me:
Registering Your App with APNs
Establishing a Token-Based Connection to APNs
Generating a Remote Notification
What I learned?
Revoke all developer account certificates related to APNS
Make new certs and this time don't make any PEM files when installing them to your providing server. Also, make sure to stop using port 2195 when making a connection to APNS and use 443 or 2197.
The great news? The new APNS provider API is still compatible with Objective C!
🐆
<?php
// Put your device token here (without spaces):
$deviceToken = '09a0c8ff92b3621c5f5032c1fa031f2851d01dd99beaf1446c281c5458fe2ffd';
// Put your private key's passphrase here:
$passphrase = 'pushchat';
// Put your alert message here:
$message = 'Hello!';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n',
strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
Update: I was wrong about the PEM aspect. Creating a PEM file is still necessary for APNs connections using the new APNs Provider API.

To get this to work in a non .Net Core Solution, I had to upgrade from Asp.net 4.6.1 to 4.7.2. I then created a folder in my Project called AppleAPNS. I added all the files found here.
NOTE: I had to upgrade to 4.7.2 in order to get the Project to recognize CreateFromValue found in the AppleCryptoHelper file.
https://github.com/andrei-m-code/net-core-push-notifications/tree/master/CorePush/Apple
I then added the files found here to the AppleAPNS folder.
https://github.com/andrei-m-code/net-core-push-notifications/tree/master/CorePush/Utils
I then added the WinHttpHandler Project along with this helper to my AppleAPNS folder. This will ensure that you are calling APNS with an HTTP client capable of 2.0.
public class Http2CustomHandler : WinHttpHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
request.Version = new Version("2.0");
return base.SendAsync(request, cancellationToken);
}
}
Next, add the AppleNotification class found here and use the calling method in the program.cs file.
https://github.com/andrei-m-code/net-core-push-notifications/tree/master/CorePush.Tester
To use the Http2CustomHandler, make these changes.
ApnSender.cs
//private readonly HttpClient http;
private readonly HttpClient http = new HttpClient(new Http2CustomHandler());
In your calling method make this change.
//private static readonly HttpClient http = new HttpClient();
private static readonly HttpClient http = new HttpClient(new Http2CustomHandler());
Finally, make this change to send an empty push notification to update passes.
ApnSender.cs
//var json = JsonHelper.Serialize(notification);
var json = "{\"aps\":\"\"}";
NOTE: Copy the contents of the p8 file as string into the apnP8PrivateKey in your calling method. Do not open/read the file.
Hope this helps! I know this is not a detailed explanation, but hopefully it will help somebody.

Related

Problem with Adafruit IO/Adafruit_MQTT_Subscribe/Arduino

I have problem with Adafruit_MQTT_Subscribe.
This is some of my code:
mqtt = Adafruit_MQTT_Client(&client, AIO_SERVER2, AIO_SERVERPORT2, aioUsername.getValue(), aioKey.getValue()); trigger = Adafruit_MQTT_Subscribe(&mqtt, feed);
When my feed = "username/feeds/trigger"
aioKey.getValue()); trigger = Adafruit_MQTT_Subscribe(&mqtt, "username/feeds/trigger");
everything is fine, but i want to change the username dynamically. I want to get it from wifiManager parameter.
String topic = String(aioUsername.getValue()) + "/feeds/trigger"; const char* feed = topic.c_str();
If i do that I see "MQTT ERROR: rejected, not a valid topic format" on AdafruitIO dashboard.
Please help.
You can try and use the example ConfigOnDRD_FS_MQTT_Ptr of my ESP_WiFiManager
/****************************************************************************************************************************
This example will open a Config Portal when there is no stored WiFi Credentials or when a DRD is detected.
You can reconfigure to use another pin, such as the convenience FLASH / BOOT button # PIN_D0;.
A password is required to connect to the Config Portal so that only who know the password can access the Config Portal.
The Credentials, being input via Config Portal, will then be saved into LittleFS / SPIFFS file, and be used to connect to
Adafruit MQTT Server at "io.adafruit.com" and publish a Temperature Topic
Based on original sketch posted by "Marko"(https://github.com/wackoo-arduino) on https://forum.arduino.cc/index.php?topic=692108
*****************************************************************************************************************************/

Link between SharePoint and Oracle server might be broken but can't find out

Ok, this is a bit of a doozy. I've been saddled with a SharePoint 2013 on prem site and a few web parts are having issues getting information from an Oracle server. I'm trying to troubleshoot the connection, but I can't even access the Secure Store Service to find out if the connection is working or where the connection is going. When I try to get in there, I get "Sorry, this site hasn't been shared with you." When I check the ULS logs, it has a couple errors: EventID 8311 (SSL policy errors have been encountered) and EventID 7557 (Secure Store Service Proxy is not accessible). What's extra weird, is the server it's trying to communicate with is the same server, just on port 32844. I'm using an account that can access most sites and features.
To make matters more interesting, the Central Admin site isn't accessible in https, only http. I'm really at a loss as to where to go.
I've tried the following code, but it says "cannot update the secure store master key. Exception calling 'Invoke' with '2' arguments"
$sa = Get-SPServiceApplication 9ebf067e-2161-42b5-87ac-9c6f0a3eaf66;
$proxy = Get-SPServiceApplicationProxy 4d13d637-d6e5-41d4-a7ea-0c9aef3d7769;
$sp_secure_store_passpharse_new = "micro8845";
try{
##BUG with Update-SPSecureStoreMasterKey => Didn't work properly
#HotFix: Reverse engineering on classes:
#-> Microsoft.Office.SecureStoreService.Server.SecureStoreServiceApplication
#-> Microsoft.Office.SecureStoreService.Server.SecureStoreServiceApplicationProxy
#-> Microsoft.Office.SecureStoreService.Server.KeyManagement.KeyManager
#-> Microsoft.Office.SecureStoreService.Server.CryptoHelper
$ass = $sa.GetType().Assembly
$CryptoHelperType = $ass.GetType("Microsoft.Office.SecureStoreService.Server.CryptoHelper")
$GetPassPhraseHashMethod=$CryptoHelperType.GetMethod("GetPassPhraseHash");
$proxyType = $proxy.GetType();
$IsMasterSecretKeyPopulated = $proxyType.GetMethod("IsMasterSecretKeyPopulated",[Reflection.BindingFlags]"NonPublic,Instance")
$SetChangeKeyPassphrase = $proxyType.GetMethod("SetChangeKeyPassphrase",[Reflection.BindingFlags]"NonPublic,Instance")
$SetKey = $proxyType.GetMethod("SetKey",[Reflection.BindingFlags]"NonPublic,Instance", $null, [type[]]#([string]), $null)
if(-not $IsMasterSecretKeyPopulated.invoke($proxy,$null)){
#ChangeKey with the proxy is buggy
#$proxy.ChangeKey( $proxy.GetChangeKeyToken(), $sp_secure_store_passpharse_new );
#Fallback by using the service application directly
$token = $sa.GetChangeMasterSecretKeyToken();
$sa.ChangeMasterSecretKey($token, $GetPassPhraseHashMethod.Invoke($null, $sp_secure_store_passpharse_new) );
$c=0;
while(-not $IsMasterSecretKeyPopulated.invoke($proxy,$null)){
$c++;
if($c -ge 20){
Write-Error $("The master key cannot be populated!");
}
sleep 1;
}
}
$SetChangeKeyPassphrase.invoke($proxy, #($sp_secure_store_passpharse_new));
$SetKey.invoke($proxy,$sp_secure_store_passpharse_new);
}catch{
Write-Error $("Cannot update the secure store master key.`n{0}" -f $_.Exception.Message);
}
The browser had to be started as an administrator. Now, I am able to do everything I need to do.

iOS Httpclient cannot connect: {System.Threading.Tasks.TaskCanceledException}

I'm building an app with Xamarin Forms. I have no issues with Android, but when I attempt to simulate or deploy the iOS app, my HttpClient can't seem to connect to the server. After the timeout expires, I get a TaskCanceledException.
The HttpClient is actually used in a separate project that is referenced by the iOS app, if that matters. Here's my usage:
string serviceUri = service + methodName;
HttpRequestMessage request = new HttpRequestMessage(methodRequestType, serviceUri)
{
Content = new StringContent(content, Encoding.UTF8, "application/json")
};
HttpResponseMessage response = await _client.SendAsync(request).ConfigureAwait(false);
string returnString = await response.Content.ReadAsStringAsync();
return returnString;
I'm not using any waits or accessing .Result, as I've seen many people try that don't understand async operations.
I've seen older posts (circa 2013) where the wrong HttpClient is used. Is this still an issue in current releases? I've also tried changing the HttpClient implementation in the iOS project settings, to no avail.
Thanks in advance!
The issue was an invalid Deployment Target - It was set to "80" instead of "8.0
In come cases, the build server does not communicate this invalidity back to your machine - hence why it took so long to notice it!

Send sms using twilio and codeigniter

I'm developing a web app using codeigniter,and i'm trying to send sms notifications using Twilio api,i tried using the twilio-ci library i found in github but it keep getting an error
Curl failed with error Could not resolve host: api.twilio.com
anyone has an idea on how to send sms using codeigniter and twilio?
I attempted to use the ci library when I was working on a Twilio project and it just never worked out.
While someone else pointed you to another answer, I do not believe it will work. Even when I was doing this last year the ci-library was badly out of date and I am not sure it has ever been updated
I would suggest using the standard Twilio Library. The only trick is you need to create a Helper file.
I will describe.
under the helper folder create a file my-twilio_helper.php
<?php
if (!class_exists('Services_Twilio')) {
include_once(APPPATH.'/libraries/Services/Twilio.php');
}
function get_twilio_service() {
static $twilio_service;
if (!($twilio_service instanceof Services_Twilio)) {
$twilio_service = new Services_Twilio("sid", "auth");
}
return $twilio_service;
}
Then download the twilio Library into your libraries folder. You will just have a folder that says Services with all of the Twilio library inside.
After this I go into autoload.php and add it into my helper array like such
$autoload['helper'] = array("my-twilio", 'file');
Then in the controller files you call it
//Calling the twilio help function to get the service
$twilio = get_twilio_service();
$sms = $twilio->account->messages->sendMessage(
'from', //from number
$to, //To
'Message')
);

Phonegap Android app ajax requests to HTTPS fail with status 0

Ajax HTTPS requests from my PhoneGap/Cordova app on Android inexplicably fail with status=0. It appears only when signing the app with the release key (i.e., exporting from ADT), but doesn't appear when signing with debug key (running directly in emulator or phone).
request = new XMLHttpRequest()
request.open "GET", "https://some.domain/", true
request.onreadystatechange = ->
console.log "** state = " + request.readyState
if request.readyState is 4
console.log "** status = " + request.status
request.send()
always outputs
** state = 4
** status = 0
It doesn't matter if i install the app from Play Store or with adb utility. I presume it could be connected with the certificate, since not all HTTPS domains fail this way.
I was having the same problem but my solution was a little different.
In only the Android App build of my Cordova app, AJAX calls to my server via HTTPS were being blocked. Not in iOS, not in desktop browsers. Most confusingly, in the actual Android Browser the HTTPS AJAX calls would work no problem.
I verified that I could make HTTPS AJAX calls to well known and trusted URLs such as https://google.com as well as regular HTTP calls to any URL I cared to try.
This led me to believe that my SSL cert was either NOT installed 100% correctly OR the cheap (~$10 usd) cert from PositveSSL was not universally trusted OR both.
My cert was installed on my AWS Load Balancer so I looked around about how I may have messed this up and also how PositiveSSL was not the best cert to be using in terms of trustworthiness. Lucky me found an article covering AWS ELB installation of certs AND they happened to be using a PositiveSSL cert! Contained within was this little gem:
"...Don’t be fooled by the AWS dialog, the certificate chain isn’t really optional when your ELB is talking directly to a browser..."
http://www.nczonline.net/blog/2012/08/15/setting-up-ssl-on-an-amazon-elastic-load-balancer/
Drumroll....
I reinstalled the cert with the "optional" Certificate Chain info and voilĂ !, the HTTPS AJAX calls to my server started working.
So it appears that the Android Webview is more conservative than the Android Browser in terms of cert trust. This is not totally intuitive since they are supposed to be basically the same tech.
It happens when the requested URL responds with an erroneous or self-signed certificate. While testing or distributing the app to friends, setting <application android:debuggable="true"...> in AndroidManifest.xml is enough — it automatically bypasses certificate errors.
But Google Play Store will not accept an APK with android:debuggable="true". First of all, the certificates, of course, need to be fixed. But while that happens, here is a workaround for PhoneGap/Cordova 3:
In your app package create a subclass for CordovaWebViewClient:
public class SSLAcceptingCordovaWebViewClient extends CordovaWebViewClient {
public SSLAcceptingCordovaWebViewClient(CordovaInterface cordova, CordovaWebView view) {
super(cordova, view);
}
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
}
Same for IceCreamCordovaWebViewClient:
public class SSLAcceptingIceCreamCordovaWebViewClient extends IceCreamCordovaWebViewClient {
public SSLAcceptingIceCreamCordovaWebViewClient(CordovaInterface cordova, CordovaWebView view) {
super(cordova, view);
}
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
}
in <Your App Name>.java add an override for makeWebViewClient:
#Override
protected CordovaWebViewClient makeWebViewClient(CordovaWebView webView) {
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
return new SSLAcceptingCordovaWebViewClient(this, webView);
} else {
return new SSLAcceptingIceCreamCordovaWebViewClient(this, webView);
}
}
Et voilĂ ! SSL errors will be disregarded. However, never use erroneous certificates. Try to fix them first and use this dirty workaround only when you run out of other solutions.
The other option that works as well is to recompile the underlying cordova.jar file so that the test is removed completely thus no reason to worry about your cert being valid or not. I ran in the issue due to the fact that Android would not recognize the GoDaddy cert that was on the server. The cert shows valid on iOS but even when browsing from Android complained about the cert. This is from the 2.9.x branch as this is what I was working with.
cordova-android / framework / src / org / apache / cordova / CordovaWebViewClient.java
#TargetApi(8)
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
final String packageName = this.cordova.getActivity().getPackageName();
final PackageManager pm = this.cordova.getActivity().getPackageManager();
ApplicationInfo appInfo;
try {
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
handler.proceed();
return;
/* REMOVED TO BY PASS INVALID CERT CHAIN ****
if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// debug = true
handler.proceed();
return;
} else {
// debug = false
super.onReceivedSslError(view, handler, error);
}*/
} catch (NameNotFoundException e) {
// When it doubt, lock it out!
super.onReceivedSslError(view, handler, error);
}
}
NOTE: I understand this is not safe but when all else fails this solved the issue that has been on going for over 2 months including reinstalling the cert following the cert chain install guide and beside it is a site that is our own not 3rd party so no matter if valid or not it is only connecting to this server.
In my case it has been a missing intermediate certificate, which I had to install on my webserver. You have to keep it in mind especially when you use cheap certificates.
You can check it easily online if your certificate chain is proper, you will find a lot on google, e.g. https://www.sslshopper.com/ssl-checker.html
At the Apache2 it's part of the VirtualHost 443 directive, you have three rules in your directive, it looks like that:
SSLCertificateFile /etc/apache2/ssl/mycert.crt
SSLCertificateKeyFile /etc/apache2/ssl/mykey.key
SSLCertificateChainFile /etc/apache2/ssl/certification_auth_intermediate.crt
You can't use relese-ready (phonegap) apks with self-signed certificates. Look at this answer to get further information.
lg
fastrde

Resources