React native Apple login stuck in enter password screen in IOS? - ios

In IOS after entering the password it shows loading and nothing happens after that.There are no console logs?It's working fine in android.
I have implemented V2 of react native apple authentication
https://github.com/invertase/react-native-apple-authentication
Tried 2 codes below same issue.
Code 1
const IOSAppleLogin = async () => {
try {
// performs login request
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: appleAuth.Operation.LOGIN,
requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME]
});
const credentialState = await appleAuth.getCredentialStateForUser(
appleAuthRequestResponse.user
);
if (credentialState === appleAuth.State.AUTHORIZED) {
console.log('appleAuthRequestResponse', appleAuthRequestResponse);
const response = appleAuthRequestResponse;
console.log('apple-response', response);
// you may also want to send the device's ID to your server to link a device with the account
// identityToken generated
if (response) {
if (response.identityToken) {
let device_identifier = DeviceInfo.getUniqueId();
let details = {
'identity_token': response.identityToken,
'first_name': response.fullName ? response.fullName.givenName : '-',
'last_name': response.fullName ? response.fullName.familyName : '-',
'device_identifier': device_identifier,
device: Platform.OS
};
props.appleLogin({ values: details });
}
}
// user is authenticated
}
} catch (error) {
if (appleAuth.Error.CANCELED === error.code) {
console.log('apple-error-CANCELED', JSON.stringify(error));
} else if (appleAuth.Error.FAILED === error.code) {
console.log('apple-error-FAILED', error);
} else if (appleAuth.Error.NOT_HANDLED === error.code) {
console.log('apple-error-NOT_HANDLED', error);
} else {
console.log('apple-error', error);
}
}
}
Code 2
const IOSAppleLogin = async () => {
try {
// performs login request
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: appleAuth.Operation.LOGIN,
requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME]
});
console.log('appleAuthRequestResponse', appleAuthRequestResponse);
const response = appleAuthRequestResponse;
console.log('apple-response', response);
// you may also want to send the device's ID to your server to link a device with the account
// identityToken generated
if (response) {
if (response.identityToken) {
let device_identifier = DeviceInfo.getUniqueId();
let details = {
'identity_token': response.identityToken,
'first_name': response.fullName ? response.fullName.givenName : '-',
'last_name': response.fullName ? response.fullName.familyName : '-',
'device_identifier': device_identifier,
device: Platform.OS
};
props.appleLogin({ values: details });
}
}
// user is authenticated
} catch (error) {
if (appleAuth.Error.CANCELED === error.code) {
console.log('apple-error-CANCELED', JSON.stringify(error));
} else if (appleAuth.Error.FAILED === error.code) {
console.log('apple-error-FAILED', error);
} else if (appleAuth.Error.NOT_HANDLED === error.code) {
console.log('apple-error-NOT_HANDLED', error);
} else {
console.log('apple-error', error);
}
}
}

Had this happen to me as well. Found the solution here https://github.com/invertase/react-native-apple-authentication/issues/162#issuecomment-723502035.
Basically, just use iOS 13 if you are on an emulator or iOS 14 on a real device.

This also happened with me when I am trying to run the code on simulator, Try this on real device it will work.
Don't forgot to add Sign In with Apple for both release and debug App in Signing & Capabilities .For this you should have an ADP Account.
Thank you.

Related

Capacitor iOS Geolocation watchPostion kCLErrorDomain error 1 while permission granted

I am using an older version of the capacitor geolocation, v1.3.1, and recently switched to the watchPosition implementation but occasionally that created a situation where the position is null or undefined even when the device is showing the location icon being active for the app. I tried to solve that by falling back to the slower getCurrentPosition function but still persists. Has anyone run into this issue before? Here is a gist of the hook.
https://gist.github.com/billpull/8bc6e49872cfee29aa5cef193b59c835
useCurrentPosition.ts
const useCurrentPosition = (): GeoWatchPositionResult => {
const [position, setPosition] = useState<Position>();
const [watchId, setWatchId] = useState("");
const [error, setError] = useState();
const clearWatch = () => {
if (watchId) {
clearPosition({ id: watchId });
setWatchId("");
}
};
const startWatch = async () => {
if (!watchId) {
const id = await watchPosition(async (pos: Position | null, err) => {
if (err) {
setError(err);
}
if (pos) {
setPosition(pos);
} else {
const newPosition = await getCurrentPosition();
setPosition(newPosition);
}
});
setWatchId(id);
}
};
useEffect(() => {
startWatch();
return () => clearWatch();
}, []);
return { currentPosition: position, error };
};
Even though the watchPosition is still returning location data on the interval I am getting a kCLErrorDomain error 1. which online says it means the permission was denied but thats not the case the phone was just in sleep mode. Is there a way to catch this error specifically? Should I clear the watch and restart it on this error?
Edit:
One attempt I made was to use a try catch in the watch, but I still have encountered this issue.
const useCurrentPosition = (): GeoWatchPositionResult => {
const [position, setPosition] = useState<Position>();
const [watchId, setWatchId] = useState("");
const [error, setError] = useState();
const clearWatch = () => {
if (watchId) {
clearPosition({ id: watchId });
setWatchId("");
}
};
const startWatch = async () => {
if (!watchId) {
const id = await watchPosition(async (pos: Position | null, err) => {
try {
if (err) {
setError(err);
}
if (pos) {
setPosition(pos);
} else {
const newPosition = await getCurrentPosition();
setPosition(newPosition);
}
} catch (ex) {
await requestPermission();
clearWatch();
await startWatch();
}
});
setWatchId(id);
}
};
useEffect(() => {
startWatch();
return () => clearWatch();
}, []);
return { currentPosition: position, error };
};
I think you should use this code snippet to check the current position.
import { Geolocation, Geoposition } from '#ionic-native/geolocation/ngx';
constructor(private geolocation: Geolocation) { }
...
let watch = this.geolocation.watchPosition();
watch.subscribe((data) => {
// data can be a set of coordinates, or an error (if an error occurred).
// data.coords.latitude
// data.coords.longitude
});
You can also use the following code snippet to get the current position.
this.geolocation.getCurrentPosition().then((resp) => {
// resp.coords.latitude
// resp.coords.longitude
}).catch((error) => {
console.log('Error getting location', error);
});
If you want to handle the permission denied error, the best way to handle the permission denied error is to check the permission status of the app first before trying to access any location data. This can be done by using the Capacitor Permissions API. If the permission has been granted, you can then proceed to use the watchPosition or getCurrentPosition APIs. If the permission has been denied, you can present a prompt to the user to request permission again.
setState is an asynchronous function, so please pass to it an anonymous function:
if (pos) {
setPosition(pos);
} else {
const newPosition = await getCurrentPosition();
setPosition(() => newPosition);
}

Data sharing between Safari and standalone iPhone 12 iOS 14.3

I tried to share data between Safari browser and standalone PWA on iPhone12 with iOS 14.3.
The information, that this should work are here: https://firt.dev/ios-14/
I#ve tried this: https://www.netguru.com/codestories/how-to-share-session-cookie-or-state-between-pwa-in-standalone-mode-and-safari-on-ios
Without success.
Are there any suggestions to running this? Or is it not possible ...
This is the code
const CACHE_NAME = "auth";
const TOKEN_KEY = "token";
const FAKE_TOKEN = "sRKWQu6hCJgR25lslcf5s12FFVau0ugi";
// Cache Storage was designed for caching
// network requests with service workers,
// mainly to make PWAs work offline.
// You can give it any value you want in this case.
const FAKE_ENDPOINT = "/fake-endpoint";
const saveToken = async (token: string) => {
try {
const cache = await caches.open(CACHE_NAME);
const responseBody = JSON.stringify({
[TOKEN_KEY]: token
});
const response = new Response(responseBody);
await cache.put(FAKE_ENDPOINT, response);
console.log("Token saved! 🎉");
} catch (error) {
// It's up to you how you resolve the error
console.log("saveToken error:", { error });
}
};
const getToken = async () => {
try {
const cache = await caches.open(CACHE_NAME);
const response = await cache.match(FAKE_ENDPOINT);
if (!response) {
return null;
}
const responseBody = await response.json();
return responseBody[TOKEN_KEY];
} catch (error) {
// Gotta catch 'em all
console.log("getToken error:", { error });
}
};
const displayCachedToken = async () => {
const cachedToken = await getToken();
console.log({ cachedToken });
};
// Uncomment the line below to save the fake token
// saveToken(FAKE_TOKEN);
displayCachedToken();
Without success means no result, i've tried to set data in safari and get them in standalone pwa

Cordova iOS app crashes after second launch on device

after a lot of investigation i have no clue of what could be the problem here. I have an iOS app developed with cordova and using Firebase (cordova-plugin-firebase) for notifications.
When i run my app on my device with Xcode for the first time everything works fine, the notifications arrive and the app works great. The problem starts when i stop the app on Xcode and try to open it on my device without using Xcode, the app crashes on the splash screen. If i send any notification, it arrives with no issue, but when i open one notification the app just crashes on the splash screen again.
I have created all certificates and the development, production and ad-hoc provisioning profiles on my apple developer account, created and APNs Key to store on my Firebase Account, I have the file GoogleService-Info.plist on my Resources folders (platforms/ios/AppName/Resources & platforms/ios/AppName/Resources/Resources).
The only error that i can see on my log is this one
Unable to connect to FCM. Error Domain=com.google.fcm Code=2001 "FIRMessaging is already connected"
and this one
The object does not respond to -messaging:didReceiveRegistrationToken:, nor -messaging:didRefreshRegistrationToken:. Please implement -messaging:didReceiveRegistrationToken: to be provided with an FCM token.
This errors are shown when i accept the notification permission bubble.
Here is my JS for handling notifications:
function firebasePUSH() {
if (device.platform === "iOS") {
window.FirebasePlugin.hasPermission(function (data) {
if (!data.isEnabled) {
window.FirebasePlugin.grantPermission();
}
});
}
window.FirebasePlugin.onNotificationOpen(function (notification) {
console.log("tipo de notificacion " + notification.tipo);
console.log(notification);
if (notification.tipo === "alerta") {
var parametros = {
id: notification.numero,
categoria: "rescato"
};
myApp.request.post("http://190.98.210.41/comuna/app/contactos.php", parametros, function (data) {
var json = JSON.parse(data);
console.log(json);
if (json.error === false) {
mostrarSOS(json.alerta);
}
});
} else if (notification.tipo === "chat" || notification.tipo === "salud" || notification.tipo === "seguridad" || notification.tipo === "contacto" || notification.tipo === "oficina") {
aceptarLlamada();
} else if (notification.tipo === "publicidad") {
mostrarPublicidad(notification.numero);
} else if (notification.tipo === "sondeo") {
mostrarSondeo(notification.numero);
}
}, function (error) {
console.error("onResume>>" + error);
});
window.FirebasePlugin.getToken(function (token) {
try {
var jsonToken = JSON.parse(token);
token = jsonToken.token;
console.warn("venia json: " + jsonToken.token);
}
catch (err) {
console.warn("viene json limpio: " + token);
}
console.log("getToken js: " + token);
localStorage.setItem('registrationId', token);
/*PEGRUNTA SI YA ESTA LOGEADO*/
if (localStorage.getItem("correo") !== null && localStorage.getItem("clave") !== null) {
//pasa a la pantalla principal
var parametros = {
"id": localStorage.getItem("id"),
"token": localStorage.getItem('registrationId'),
"categoria": "token",
format: "json",
callback: function () {
return true;
}
};
myApp.request.json("http://190.98.210.41/comuna/app/usuario_get.php", parametros, function (data) {
console.log(data);
}, function (error) {
console.log(error);
});
}
}, function (error) {
console.error("getToken error: " + error);
});
window.FirebasePlugin.onTokenRefresh(function (token) {
try {
var jsonToken = JSON.parse(token);
token = jsonToken.token;
console.warn("token json: " + jsonToken.token);
}
catch (err) {
console.warn("token limpio: " + token);
}
console.log("onTokenRefresh js: " + token);
localStorage.setItem('registrationId', token);
/*PEGRUNTA SI YA ESTA LOGEADO*/
if (localStorage.getItem("correo") != null && localStorage.getItem("clave") != null) {
//pasa a la pantalla principal
var parametros = {
"id": localStorage.getItem("id"),
"token": localStorage.getItem('registrationId'),
"categoria": "token",
format: "json",
callback: function () {
return true;
}
};
myApp.request.json("http://190.98.210.41/comuna/app/usuario_get.php", parametros, function (data) {
console.log(data);
}, function (error) {
console.log(error);
});
}
}, function (error) {
console.error(error);
});
}
I could use some help on this issue because i have been on this for weeks and i'm getting so frustrated. Thank you very much guys.
EDIT:
I spotted a third error when i launch the app.
[Firebase/Messaging][I-FCM002023] The object does not respond to -messaging:didReceiveRegistrationToken:, nor -messaging:didRefreshRegistrationToken:. Please implement -messaging:didReceiveRegistrationToken: to be provided with an FCM token.
I had a problem very similar..
and I discovered that the problem was when i called window.FirebasePlugin.grantPermission() in second time.
do one test without asking permission more than once..

Store access_token in the AsyncStorage

After user enters ID and password, I am passing access_token from Rails.
I am using
itzikbenh/Rails-React-Auth and
itzikbenh/React-Native-on-Rails as reference.
But I am unable to save the access_token. Here is the code:
let res = await response.text();
if (response.status >= 200 && response.status < 300) {
//Handle success
let accessToken = res;
console.log(accessToken);
//On success we will store the access_token in the AsyncStorage
this.storeToken(accessToken);
//this.redirect('home');
alert(ACCESS_TOKEN )
} else {
//Handle error
let error = res;
throw error;
}
You can use AsyncStorage.setItem to store single items:
import { ... AsyncStorage } from 'react-native'
try {
await AsyncStorage.setItem('access_token', access_token);
} catch (error) { // Error saving data }
Then to retrieve it use AsyncStorage.getItem:
try {
const value = await AsyncStorage.getItem('access_token');
if (value !== null) console.log(value)
} catch (error) { // Error retrieving data }
For storing and retrieving multiple items you can see AsyncStorage.multiSet and AsyncStorage.multiGet.

Titanium Appcelerator unable to send push notification to a specified user

I'm making an app using appcelerator alloy framework which needs push notifications. I'm using push notifications for the first time, so bear with me and help me out here.
I've followed the push notification wiki tutorial here https://wiki.appcelerator.org/display/guides2/Push+Notifications
This is my code here :
var deviceToken = null;
// Check if the device is running iOS 8 or later
if (Ti.Platform.name == "iPhone OS" && parseInt(Ti.Platform.version.split(".")[0]) >= 8) {
// Wait for user settings to be registered before registering for push notifications
Ti.App.iOS.addEventListener('usernotificationsettings', function registerForPush() {
// Remove event listener once registered for push notifications
Ti.App.iOS.removeEventListener('usernotificationsettings', registerForPush);
Ti.Network.registerForPushNotifications({
success: deviceTokenSuccess,
error: deviceTokenError,
callback: receivePush
});
});
// Register notification types to use
Ti.App.iOS.registerUserNotificationSettings({
types: [
Ti.App.iOS.USER_NOTIFICATION_TYPE_ALERT,
Ti.App.iOS.USER_NOTIFICATION_TYPE_SOUND,
Ti.App.iOS.USER_NOTIFICATION_TYPE_BADGE
]
});
}
// For iOS 7 and earlier
else {
Ti.Network.registerForPushNotifications({
// Specifies which notifications to receive
types: [
Ti.Network.NOTIFICATION_TYPE_BADGE,
Ti.Network.NOTIFICATION_TYPE_ALERT,
Ti.Network.NOTIFICATION_TYPE_SOUND
],
success: deviceTokenSuccess,
error: deviceTokenError,
callback: receivePush
});
}
// Process incoming push notifications
function receivePush(e) {
alert('Received push: ' + JSON.stringify(e));
}
// Save the device token for subsequent API calls
function deviceTokenSuccess(e) {
deviceToken = e.deviceToken;
}
function deviceTokenError(e) {
alert('Failed to register for push notifications! ' + e.error);
}
// Require the Cloud module
var Cloud = require("ti.cloud");
function subscribeToChannel () {
// Subscribes the device to the 'chats' channel
// Specify the push type as either 'android' for Android or 'ios' for iOS
Cloud.PushNotifications.subscribeToken({
device_token: deviceToken,
channel:'test',
type: Ti.Platform.name == 'android' ? 'android' : 'ios'
}, function (e) {
if (e.success) {
alert('Subscribed');
} else {
alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
}
});
}
function unsubscribeToChannel () {
// Unsubscribes the device from the 'test' channel
Cloud.PushNotifications.unsubscribeToken({
device_token: deviceToken,
channel:'test',
}, function (e) {
if (e.success) {
alert('Unsubscribed');
} else {
alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
}
});
}
function loginUser(username, password){
// Log in to Arrow
Cloud.Users.login({
login: username,
password: password
}, function (e) {
if (e.success) {
subscribeToChannel ();
alert('Login successful with device token' + deviceToken);
// Store the authentication details in the local filesystem
Ti.App.Properties.setString('usernameSave',username);
Ti.App.Properties.setString('passwordSave',password);
// user_id = jsonPost.SuccessResult.user_id;
} else {
alert('Error:\n' +
((e.error && e.message) || JSON.stringify(e)));
}
});
}
var savedUserName = Ti.App.Properties.getString('usernameSave','');
var savedPassword = Ti.App.Properties.getString('passwordSave','');
if(savedUserName != ''){
$.userNameField.value = savedUserName;
$.passwordField.value = savedPassword;
}
function login(){
var username = $.userNameField.value;
var password = $.passwordField.value;
loginUser(username, password);
}
The Login() function is called when a button named login is clicked.
I get the Login Successful and Subscribed alerts as expected on login.
Whenever I tried sending a push notification to all the users, it worked. But if I try to send it to a specified user it gives me a failure on the Push Logs in the dashboard.
What am I missing here? Please help me out.
Thanks.
Ok I found the problem that was causing this.
Yeah it was my fault as in the subscription method I'm using token subscription instead of channel subscription. As I'm using the session based method.
Here is the difference, if anyone needs it in future.
Check the second line...
Previous Code
function subscribeToChannel () {
Cloud.PushNotifications.subscribeToken({
device_token: deviceToken,
channel:'test',
type: Ti.Platform.name == 'android' ? 'android' : 'ios'
}, function (e) {
if (e.success) {
alert('Subscribed');
} else {
alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
}
});
}
New Code
function subscribeToChannel(){
Cloud.PushNotifications.subscribe({
device_token: deviceToken,
channel: 'test',
type: Ti.Platform.name == 'android' ? 'android' : 'ios'
}, function (e) {
if (e.success) {
alert('Subscribed');
} else {
alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
}
});
}
Thank you.
Cheers.

Resources