Crypto JS not encrypting properly in production mode - react-native

I've the following code to send a message:
function sendMessage(data) {
data.version = clientVersion;
var message = { data: CryptoJS.AES.encrypt(JSON.stringify(data), system.Authentication.SendAuth, { mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7, iv: system.Authentication.Sendiv }).toString() };
return JSON.stringify(message);
}
This works just fine on dev mode. Expo app sends the encrypted message and gets decrypted properly. However, in production mode, the encrypted code gets sent and received no problem, but when decrypted by the server we get a negative sigBytes number. So the decryption failed.
This happened when updation from SDK 27 to SDK 31 of expo.

Related

FCM - "messaging/registration-token-not-registered" - but the client is still using the token?

When sending a multicast message to FCM...
const message = {
notification: {
title: messageTitle,
body: messageBody,
},
tokens: tokenArray,
}
getMessaging().sendMulticast(message)
I'm receiving this error.
messaging/registration-token-not-registered - Requested entity was not
found
According to this post, I should then remove the token.
Here's what I'm confused about though. When I run getToken() on my client device, it's still showing this same token.
getToken(messaging, { vapidKey: "MY_VAPID_KEY"}).then(token => console.log(token))
Is there like a registration step that I'm missing? I don't understand why the client is using this as the current token but FCM thinks it's unregistered.
So my solution was I reset the browser cache and notification permissions. My browser then generated a new token which is working.
Kind of strange though is on the first call of getToken() after clearing and refreshing, it sent a request to delete the token after failing a check with isTokenValid(), and then the delete itself failed so my token remained registered and is now working. No idea what's going on there.

WalletConnect disable infura error message

I am currently developing a dapp and I am integrating walletconnect.
I use this code for connecting:
const chainId = ContractService.getPreferredChainId();
const rpc = ContractService.getRpcAddress();
provider = new WalletConnectProvider({
infuraId: undefined,
rpc: {
[chainId]: rpc,
},
});
await provider.enable();
chainId is dynamically chosen based on if the app is in development mode or not. while in development it runs on chain id 97.
RPC is the same story, it just gets the binance smart chain RPC JSON provider.
Connecting works well, but I get the following error:
Any idea on how I can fix this without making an infura account? Or is that required..
I found out what the problem was.
make sure to add a chainId to the object like this:
new WalletConnectProvider({
infuraId: undefined,
rpc: {
1: "https://RPC_URL",
},
chainId: 1
});
Then it should work without issues, you can even omit the infuraId field

Push Notifications don't work after deploying Expo app to Apple store's TestFlight

Push Notifications works perfectly side loaded to my iOS phone. I can fetch the token and successfully save it to and recall it from my Google Firestore db. Recalling it to send out notifications also work as expected. If I'm not in the App, I get a notification. If I am in the app, my Notification Listener works well.
After building to iOS and deploying the stand alone app to TestFlight on Apple's servers, Push Notifications no longer work.
This is my build.
Adrians-MBP:xxxxx abarthol$ expo build:ios -c
Checking if there is a build in progress...
Removed existing credentials from expo servers
Please enter your Apple Developer Program account credentials. These
credentials are needed to manage certificates, keys and provisioning profiles
in your Apple Developer account.
The password is only used to authenticate with Apple and never stored.
? Apple ID: xxxxx
? Password (for xxxxx): [hidden]
Trying to authenticate with Apple Developer Portal...
Authenticated with Apple Developer Portal successfully!
Only 1 team associated with your account, using Apple Team with ID: xxxxx
We do not have some credentials for you: Apple Distribution Certificate, Apple Push Notifications service key, Apple Provisioning Profile
? How would you like to upload your credentials? Expo handles all credentials, y
ou can still provide overrides
? Will you provide your own Apple Distribution Certificate? Let Expo handle the
process
✔ Didn't find any previously uploaded Apple Distribution Certificate
? Will you provide your own Apple Push Notifications service key? I want to uplo
ad my own file
Please provide your Apple Push Notifications service key:
? Path to P8 file: ~/Sites/certs/aps.cer
? Key ID: xxxxx
✔ App ID found on Apple Developer Portal.
We're going to generate:
- Apple Distribution Certificate
- Apple Provisioning Profile
✔ Generated Apple Distribution Certificate
✔ Generated Apple Provisioning Profile
Encrypted credentials and saved to the Expo servers
Publishing to channel 'default'...
Building iOS bundle
Building Android bundle
Analyzing assets
Uploading assets
No assets changed, skipped.
Processing asset bundle patterns:
- ~/Sites/Personal/xxxxx/**/*
Uploading JavaScript bundles
Published
Your URL is
https://exp.host/#xxxxx/xxxxx
Checking if this build already exists...
Build started, it may take a few minutes to complete.
You can check the queue length at https://expo.io/turtle-status
You can monitor the build at
https://expo.io/builds/xxxxx
Waiting for build to complete. You can press Ctrl+C to exit.
✔ Build finished.
Successfully built standalone app: https://expo.io/artifacts/xxxxx
Here is my component:
componentDidMount() {
this.registerForPushNotifications();
}
componentWillUnmount() {
if (!this.subscription) return;
this.subscription.remove();
}
registerForPushNotifications = async () => {
const PNToken = await this.props.MainStore.getLocal("PNToken");
if (!PNToken) {
try {
const { status } = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
let finalStatus = status;
if (status !== "granted") {
const { status } = await Permissions.askAsync(
Permissions.NOTIFICATIONS
);
finalStatus = status;
if (finalStatus !== "granted") {
throw "Notification permission not granted";
}
const token = await Notifications.getExpoPushTokenAsync();
this.props.MainStore.setPNToken(token);
this.subscription = Notifications.addListener(
this.handleNotification
);
}
} catch (err) {
console.warn("Permissions check error: ", err);
}
} else {
this.props.MainStore.setPNToken(PNToken);
this.subscription = Notifications.addListener(this.handleNotification);
}
};
handleNotification = notification => {
const store = this.props.NotificationStore;
const sortedNotifications = sortMessages([
...store.state.notifications,
{ ...notification, read: false }
]);
store.setState({
notifications: sortedNotifications
});
};
I had a lot of frustration with push finally solved the issue.
1) Enable Push notifications in Developer portal > Certificates, Identifiers & Profiles > Identifier (of your app)
2) Create your APNS key file as described here
https://fluffy.es/p8-push-notification/
3) Delete existing provisioning profile
4) expo build:ios --clear-credentials, upload your P8 file to expo
From the look of it you're providing the old APNS cert to Expo when it's asking for the new P8 format.
You should be able to generate a new P8 file from the Apple member center.
In addition to having the correct "Apple Distribution Certificate", "Apple Provisioning File" & "Apple Push Key" at expo.io, you also have to have the correct device token.
First, find experienceId of your app by executing expo credentials:manager
It is shown as
Experience: #user/slug, bundle identifier: com.xxx.xxx
Then get your token as below
const token = (
await Notifications.getExpoPushTokenAsync({
experienceId: '#user/slug', // <-- Experience shown above
})
).data;
console.log('EXPO TOKEN: ', token); // Store this in the backend
Put this device token in the expo test tool (https://expo.io/notifications) and see if you get the notification.

How to pass query parameters in react native WebSocket connection

I have a server where I can make a WebSocket connection. When a device makes a WebSocket connection (when the app starts/splash screen), the server looks for the query parameter in the URL, which has the auth token of the user and if the token is correct, the connection is approved, else connection is rejected.
This is how the code looks on the react native client side:
const socket = new WebSocket(`ws://${website}/?token=${value}`);
socket.onmessage = (messageEvent) => {
console.log('>>> socket on message:', messageEvent.data);
};
socket.onopen = function () {
socket.send("hello world connection");
};
socket.onclose = () => {
console.log('Socket disconnected');
};
This works fine in my iOS emulator, and the iOS emulator has a WebSocket connection to mine server. However, I have an android phone (testing via LAN), and when I open the app, I get an error saying:
Unable to set ws://192.xxx.xx.xx/token=aut sfiseft2sefsefs..... as default origin header
But, if I remove the query param from the URL
const socket = new WebSocket(`ws://${website}`);
This works fine, but since I cannot pass the token in the query params, I get an error from the server.
How can I pass query parameters to the WebSocket connection in android? What am I doing wrong?
I have the same issue. Solve the issue by using encodeURI() before passing the url to WebSocket.
const uri = encodeURI(`ws://${website}/?token=${value}`);
const socket = new WebSocket(uri);
This works for me.

Can't get GCM push messages being sent properly

So my GCM push message works if I use this test link
http://www.androidbegin.com/tutorial/gcm.html
Here's the response
{ "multicast_id":7724943165862866717,
"success":1,
"failure":0,
"canonical_ids":0,
"results":[{"message_id":"0:1418649384921891% 7fd2b314f9fd7ecd"}]}
However if I push using my own service using node push service using the toothlessgear/node-gcm lib
https://github.com/ToothlessGear/node-gcm I get a success message on the server but no msg makes it to the client
{ multicast_id: 5130374164465991000,
success: 1,
failure: 0,
canonical_ids: 0,
results: [ { message_id: '0:1418649238305331%7fd2b3145bca2e79' } ] }
I also tried the same message using pushwoosh and push woosh doesn't work either. How come I'm getting a success message on the server, but no push is received on the client on the latter two services. Is there some sort of ip configuration that I need to do, or some sort of certificate? I've used the same google api server key which is open to all ips on all 3 of these services.
Why does the response show success on the latter but no msg gets received on the client?
Node service server side code
var gcm = require('node-gcm');
// create a message with default values
var message = new gcm.Message();
// or with object values
var message = new gcm.Message({
collapseKey: 'demo',
delayWhileIdle: true,
timeToLive: 3,
data: {
key1: 'message1',
key2: 'message2'
}
});
var sender = new gcm.Sender('insert Google Server API Key here');
var registrationIds = ['regId1'];
/**
* Params: message-literal, registrationIds-array, No. of retries, callback-function
**/
sender.send(message, registrationIds, 4, function (err, result) {
console.log(result);
});
So the pushes were correctly being sent, my issue was with the cordova plugin on the client which requires that the android payload for "message" or "title" be set. The sample php just coincidentally was setting the message property and that's why it worked.
Updating the code to add the following to the data
data: {message:'test'}
works correctly