Error - Insufficient credentials while making the connection for push notification - ios

I am trying to deliver push notification in my ios app and i user node.js. So I am followint the tutorial from the link: https://blog.engineyard.com/2013/developing-ios-push-notifications-nodejs.
In this tutorial they are keeping the passphrase for the private key as empty. But I am setting a password for my private key and I dont know how to include my password in the coding. I know there has been many angles of answer to this. But am not getting anything works. I tried :
.set('cert file', join(__dirname, '../_cert/apn-dev-cert.pem'))
.set('key file', join(__dirname, '../_cert/apn-dev-key.pem'))
//or this works too:
// .set('pfx file', join(__dirname, '../_cert/Certificates.p12'))
// .set('passphrase', 'your passphrase')
.enable('sandbox')
agent.on('message:error', function (err, msg) {
connect.log('error1');
switch (err.name) {
// This error occurs when Apple reports an issue parsing the message.
case 'GatewayNotificationError':
console.log('[message:error] GatewayNotificationError: %s', err.message);
// The err.code is the number that Apple reports.
// Example: 8 means the token supplied is invalid or not subscribed
// to notifications for your application.
if (err.code === 8) {
console.log(' > %s', msg.device().toString());
// In production you should flag this token as invalid and not
// send any futher messages to it until you confirm validity
}
break;
// This happens when apnagent has a problem encoding the message for transfer
case 'SerializationError':
console.log('[message:error] SerializationError: %s', err.message);
break;
// unlikely, but could occur if trying to send over a dead socket
default:
console.log('[message:error] other error: %s', err.message);
break;
}
});
/*!
* Make the connection
*/
agent.connect(function (err) {
// gracefully handle auth problems
if (err && err.name === 'GatewayAuthorizationError') {
console.log('Authentication Error: %s', err.message);
process.exit(1);
}
// handle any other err (not likely)
else if (err) {
console.log('error1');
throw err;
}
// it worked!
var env = agent.enabled('sandbox')
? 'sandbox'
: 'production';
console.log('apnagent [%s] gateway connected', env);
});
I also tried concatenating the certificate and the key and use it as a single file, nothing works.

Related

Only Receiving Part of Apple Subscription Notification in Google Cloud Function

I am trying to set up a Google Cloud Function (GCF) to handle Subscription Notifications from Apple. I am familiar with GCF, but not very familiar with writing my own REST API and the Nodejs methods of handling the data Apple sends with the notification. I am receiving the Apple notification, but only a "chunk" of it. Here's my code (using express and body-parser frameworks). I put my whole function here to help people since there is absolutely nothing about how to use GCF for Subscription Notifications anywhere I could find on the web (note this code is very much a work in progress and I am new to Nodejs):
// Set up express object
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
exports.iosNotification = functions.https.onRequest((req, res) => {
console.log("We are receiving a request from Apple.");
app.use(bodyParser.json());
let receipt = req.body.latest_receipt;
console.log(req.body);
const chunks = [];
req.on('data', chunk => {
chunks.push(chunk);
console.log('A chunk of data has arrived:', chunk);
});
req.on('end', () => {
const data = Buffer.concat(chunks);
console.log('Data: ', data);
console.log('No more data');
});
const type = req.body.notification_type;
console.log("Notification type: ", type);
const lri = req.body.latest_receipt_info;
console.log(lri, receipt);
// Verify the receipt.
validateAppleReceipt(receipt)
.then((appleResponse) => {
console.log("Receipt from App Store server validated.", appleResponse);
res.sendStatus(200);
const oTxId = appleResponse.latest_receipt_info[0].original_transaction_id;
// Receipt is valid and we let Apple know. Let's process the notification.
switch (type) {
case 'CANCEL':
// User canceled the subscription (like on accidental purchase).
console.log("User canceled a subscription.");
break;
case 'DID_CHANGE_RENEWAL_PREF':
console.log("The subscriber downgraded. Effective on next renewal. Handle.");
break;
case 'DID_CHANGE_RENEWAL_STATUS':
console.log("The subscriber downgraded or upgraded. Effective on next renewal. Handle.");
break;
case 'DID_FAIL_TO_RENEW':
console.log("Subscription has a billing issue. Check if in billing retry period.");
break;
case 'DID_RECOVER':
console.log("Renewal of expired subscription that failed to renew.");
break;
case 'INITIAL_BUY':
console.log("Initial purchase. Ignored because we already handled with another function.");
break;
case 'INTERACTIVE_RENEWAL':
console.log("Interactive renewal. Not sure if we'll ever see this.");
break;
case 'RENEWAL':
console.log("Renewal after failure. Same as DID_RECOVER. Handle there.");
break;
default:
console.log("Hit default.");
break;
};
})
.catch((error) => {
console.log("Error validating receipt from App Store server.", error);
});
});
This is the output I'm getting (which is only a portion of the notification Apple says it is sending). I don't get notification_type or any of the other parts of the JSON file the Apple docs say I should be receiving:
{ latest_receipt: 'ewoJInNpZ25hdHVyZSIgPSAiQTNVM0FjaDJpbXRPMG53cEtrQW9 <<shortened for this post>>
I never see the console.log for any chunks.
What can I do to make sure I receive all the "chunks" and put them together into the complete JSON file that Apple is sending me so I can work with it?
I solved it. It was so simple. I just had to use req.body instead of req. Here's the code for anyone who is trying to use Google Cloud Functions to handle Server to Server Notifications for subscriptions from Apple.
exports.iosNotification = functions.https.onRequest((req, res) => {
console.log("We are receiving a request from Apple.");
let receipt = req.body.latest_receipt;
const type = req.body.notification_type;
console.log("Notification type: ", type);
const lri = req.body.latest_receipt_info;
console.log(type, lri, receipt);
// Verify the receipt.
validateAppleReceipt(receipt)
See code above for how to handle the types Apple sends...

http.Post() from a gRPC server to an http server returns EOF error on a docker-compose setup

I have a gRPC server (server) written in Go that a Python gRPC client (client) talks to. The server occasionally sends http post requests to a Go based http server (sigsvc). All of these instances run as docker instances spun up through docker-compose sharing the same docker network.
This is the section of code on server that creates and sends the http request:
b := new(bytes.Buffer)
txbytes, err := json.Marshal(tx)
if err != nil {
log.WithError(err).Error("failed to marshal transaction")
return nil, err
}
b.Write(txbytes)
resp, err := http.Post(sigsvc.signerURL, "application/json; charset=utf-8", b)
if err != nil {
log.WithError(err).Errorf("error signing transaction with signer %s", sigsvc.signerURL)
return nil, err
}
defer resp.Body.Close()
var signedTx types.Transaction
err = json.NewDecoder(resp.Body).Decode(&signedTx)
if err != nil {
log.WithError(err).Error("couldn't decode signed transaction")
return nil, err
}
sigsvc.signerURL maps to something like http://signer:6666/sign which is the endpoint on the http signer service that handles the request.
signer refers to the service name listed on a docker-compose.yml specification.
This is how the handler looks like on sigsvc:
func (sv *SignerSv) handleSignTx() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Info("request received to sign transaction")
dump, err := httputil.DumpRequest(r, true)
if err != nil {
http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
}
log.Debugf("%q", dump)
if r.Body == nil {
log.Error("request body missing")
http.Error(w, "Please send a request body", 400)
return
}
log.Debugf("request body: %v", r.Body)
var tx types.Transaction
err = json.NewDecoder(r.Body).Decode(&tx)
if err != nil {
log.WithError(err).Error("failed to unmarshal transaction")
http.Error(w, err.Error(), 400)
return
}
log.WithFields(log.Fields{
"txhash": tx.Hash().Hex(),
"nonce": tx.Nonce(),
"to": tx.To().Hex(),
"data": tx.Data(),
"gasLimit": tx.Gas(),
"gasPrice": tx.GasPrice(),
"value": tx.Value(),
}).Debug("Decoded transaction from request body")
Both the request and request body are dumped successfully by the debug logs. However, apparently the line decoding the request body to the transaction type is never executed, since no error or decoded transaction logs are logged.
On server, I keep getting the following error:
error="Post http://signer:6666/sign: EOF"
This is how the request is logged on sigsvc:
msg="\"POST /sign HTTP/1.1\\r\\nHost: signer:6666\\r\\nConnection: close\\r\\nAccept-Encoding: gzip\\r\\nConnection: close\\r\\nContent-Length: 10708\\r\\nUser-Agent: Go-http-client/1.1\\r\\n\\r\\n{\\\"nonce\\\":\\\"0x0\\\",\\\"gasPrice\\\":\\\"0x2540be400\\\",\\\"gas\\\":\\\"0x15c285\\\",\\\"to\\\":null,\\\"value\\\":\\\"0x0\\\",\\\"input\\\":\\\"0x6080604055",\\\"v\\\":\\\"0x0\\\",\\\"r\\\":\\\"0x0\\\",\\\"s\\\":\\\"0x0\\\",\\\"hash\\\":\\\"0xab55920fb3d490fc55ccd76a29dfb380f4f8a9e5d0bda4155a3b114fca26da0a\\\"}\"
I have tried reproducing this error on similar but simplified docker setups, but I have failed at that.
I'm trying to understand the following:
If there is anything wrong with this code that is being exposed due
to a particular setup on docker?
Or, do I need to look at some docker setup specifics to debug the instances.
The problem was in the way the http handler code was logging the to field in this logrus call.
log.WithFields(log.Fields{
"txhash": tx.Hash().Hex(),
"nonce": tx.Nonce(),
"to": tx.To().Hex(),
"data": tx.Data(),
"gasLimit": tx.Gas(),
"gasPrice": tx.GasPrice(),
"value": tx.Value(),
}).Debug("Decoded transaction from request body")
Under specific circumstances, the tx.To() call returns nil, which implies calling tx.To().Hex() would lead to an error on account of trying to make a method call on a nil pointer. On the face of it, one would expect the log.WithFields() call to error out or panic, but instead the handler silently closes connection with the client side getting an EOF response.

How to handle cloudboost errors in Ionic2?

The error I get when the user fails to log in is "Error: Request failed with status code 401". This error is logged here:
static login(username : string, password : string){
return new Promise(resolve =>{
let user = new CB.CloudUser();
user.set('username', username);
user.set('password', password);
user.logIn({
success: function(user) {
console.log("user");
resolve();
},
error: function(error) {
console.log(error);
resolve(error);
}
});
});
}
But what I need is the error that actually says what went wrong e.g. "invalid username" or "User is not authenticated".
How do I get these?
Error: Request failed with status code 401
This error generally means that the login request you made to the server was not authenticated/ you were not authorized to make the login request. This can mean that the CB instance is not properly initialized. Please check the appId and the master/client key you are using to initialize the CB instance.

react-native error RCTJSONStringify() encountered the following error: Invalid type in JSON write (NSURL)

I am trying to use react-native-fbsdk in my react-native app. It was working fine untill yesterday. But, today it gives a weird error stating RCTJSONStringify() encountered the following error: Invalid type in JSON write (NSURL).
RN v0.42.0
Here is my code:
_fbAuth(error, result) {
if (error) {
console.log("error");
alert("login has error: " + result.error);
} else if (result.isCancelled) {
console.log("login cancelled");
alert("login is cancelled.");
} else {
AccessToken.getCurrentAccessToken().then((data) => {
console.log("login success");
console.log(data.accessToken.toString());
let accessToken = data.accessToken;
alert(data.accessToken.toString());
const responseInfoCallback = (error, result) => {
if (error) {
console.log(error);
} else {
console.log(result);
}
}
const infoRequest = new GraphRequest(
'/me',
{
accessToken: accessToken,
parameters: {
fields: {
string: 'email,name,first_name,middle_name,last_name'
}
}
},
responseInfoCallback
);
// Start the graph request.
new GraphRequestManager().addRequest(infoRequest).start();
});
}
}
render() {
console.log("in new render");
return (
<View style={styles.container}>
<LoginButton
publishPermissions={["publish_actions"]}
onLoginFinished={this._fbAuth}
onLogoutFinished={() => alert("logout.")}/>
</View>
);
}
The error information printed in debugger:
I get the above error while calling the graphAPI in the function responseInfoCallback. Any ideas what is happening ?
Update 1:
This error happens only when remote debugger is turned on!! Else it is not happening. But without remote debugger, I cannot proceed with developing the app. Are there any other methods to see log statements of react-native app other than remote debugger ?
Update 2:
The RCTJSONStringify() error happens only behind proxy. And also https fetch calls does not work under proxy. I tested in an open network, it works fine. I guess, it is to add some proxy information to RN app. I think it is related to APP transport security
If you turn the debugger off, you can see the proper error in the XCode console. Access it from Xcode menu View/Debug Area/Activate console, if it's not enabled automatically.

Push notification missing messages

I am following the tutorial from this website:
https://blog.engineyard.com/2013/developing-ios-push-notifications-nodejs
to deliver push Notification in my app.
I have successfully created the certificate and other files so far. In the server side, I couldn't pass through the Making the Connection step.
I can get my device token in console while running the app. In the tutorial it is said that, after making the connection the Terminal console should give a output as "gateway connected".
But I am not getting this message. The worst case is I am not getting any error message either. I wonder what went wrong. Even though I got some errors in making the connection first like insufficient credentials, mac verify error, I solved those. Now am neither getting any error nor the correct message.
I also add my Terminal console here
SIVAs-MacBook-Air:~ AAA$ cd Desktop/
SIVAs-MacBook-Air:Desktop AAA$ cd poservices/
SIVAs-MacBook-Air:poservices AAA$ node agent/_header.js
SIVAs-MacBook-Air:poservices AAA$ node agent/_header.js
SIVAs-MacBook-Air:poservices AAA$`
var join = require('path').join
, pfx = join(__dirname, '../_certs/pfx.p12');
/*!
* Create a new gateway agent
*/
var apnagent = require('apnagent')
, agent = module.exports = new apnagent.Agent();
/*!
* Configure agent
*/
agent
.set('pfx file', pfx)
.enable('sandbox');
/*!
* Error Mitigation
*/
agent.on('message:error', function (err, msg) {
connect.log('error1');
switch (err.name) {
// This error occurs when Apple reports an issue parsing the message.
case 'GatewayNotificationError':
console.log('[message:error] GatewayNotificationError: %s', err.message);
// The err.code is the number that Apple reports.
// Example: 8 means the token supplied is invalid or not subscribed
// to notifications for your application.
if (err.code === 8) {
console.log(' > %s', msg.device().toString());
// In production you should flag this token as invalid and not
// send any futher messages to it until you confirm validity
}
break;
// This happens when apnagent has a problem encoding the message for transfer
case 'SerializationError':
console.log('[message:error] SerializationError: %s', err.message);
break;
// unlikely, but could occur if trying to send over a dead socket
default:
console.log('[message:error] other error: %s', err.message);
break;
}
});
/*!
* Make the connection
*/
agent.connect(function (err) {
// gracefully handle auth problems
if (err && err.name === 'GatewayAuthorizationError') {
console.log('Authentication Error: %s', err.message);
process.exit(1);
}
// handle any other err (not likely)
else if (err) {
console.log('error1');
throw err;
}
// it worked!
var env = agent.enabled('sandbox')
? 'sandbox'
: 'production';
console.log('apnagent [%s] gateway connected', env);
});
You need to add
agent.set('passphrase', '<YOUR_PASSWORD>');
after
agent.set('pfx file', pfx).enable('sandbox');

Resources