react-native loginwithpermissions promise not resolved on android - javascript

After upgrading a react-native from 0.56 to 0.59.8 (using FBSDK 0.10.1), the facebook login don't work anymore on android.
when I fill the Fb login form and continue, LoginManager.logInWithPermissions promise does not resolve and never goes to .then() after logInWithPermissions()
here is my code:
loginWithFBSDKLoginManager() {
LoginManager.logOut();
const self = this;
return new Promise((resolve, reject) => {
LoginManager.logInWithPermissions(['public_profile', 'email']).then(function (result) {
if (result.isCancelled) {
return;
}
AccessToken.getCurrentAccessToken().then((data) => {
const accessToken = data.accessToken.toString();
const userID = data.userID.toString();
self
.getUserInfos(accessToken)
.then((response) => {
resolve({ ...response, accessToken, userID });
})
.catch(
function (error) {
reject(error);
}
);
});
});
});
}
I tried to put breakpoint almost everywhere but nothing help.
To most strange thing is that work perfrectly on iOS, this issue only occurs on Android.
I tried to debug my app using Android Studio and the only error found in the console is
I/chromium: [INFO:CONSOLE(0)] "Refused to display
'https://m.facebook.com/intern/common/referer_frame.php' in a frame
because it set 'X-Frame-Options' to 'deny'.", source:
https://m.facebook.com/v3.3/dialog/oauth?client_id=2129868160675609&e2e=%7B%22init%22%3A1562743341374%7D&sdk=android-5.0.3&scope=public_profile%2Cemail&state=%7B%220_auth_logger_id%22%3A%22edb48b96-de45-47e6-8331-f3db300e4eb2%22%2C%223_method%22%3A%22web_view%22%7D&default_audience=friends&redirect_uri=fbconnect%3A%2F%2Fsuccess&auth_type=rerequest&display=touch&response_type=token%2Csigned_request&return_scopes=true&ret=login&fbapp_pres=0&logger_id=edb48b96-de45-47e6-8331-f3db300e4eb2#= (0) I/chromium: [INFO:CONSOLE(53)] "ErrorUtils caught an error:
"Script error.". Subsequent errors won't be logged; see
https://fburl.com/debugjs.", source:
https://static.xx.fbcdn.net/rsrc.php/v3iEpX4/ys/l/fr_FR/LDgA15LzuMu.js
(53) I/chromium: [INFO:CONSOLE(262)] "Uncaught SecurityError: Blocked
a frame with origin "https://m.facebook.com" from accessing a frame
with origin "null". The frame requesting access has a protocol of
"https", the frame being accessed has a protocol of "data". Protocols
must match.
", source: https://static.xx.fbcdn.net/rsrc.php/v3iEpX4/ys/l/fr_FR/LDgA15LzuMu.js
(262)
Could somebody help me solving this? or guide me to find the root cause.
Thanks

I manageed to solve it by upgrading from v0.10.1 to v1.0.1. Remember to remove all the CallbackManager stuff in MainApplication.java

Related

PushManager subscription fails on Firefox for Android

I'm working on integrating web-push notifications in my web-application. Everything works fine for Chrome and Firefox on desktop and Chrome on Android, but not for Firefox for Android. This question seems to discuss the same issue but has no responses.
I used this tutorial as a base for the service worker registration script. I have added some more prints/checks but it is mostly the same.
So, when calling the registerServiceWorker method from a button press on FF Android, the serviceWorker is installed, the subscribeUser function is called, but the pushManager.subscribe method will fail with the following error message:
DOMException: User denied permission to use the Push API.
This is not correct, even while paused on the error print line Notification.permission will return "granted".
Doing the same thing on the nightly build results in slightly different, but still incorrect behaviour. The pushManager.subscribe method does not throw an error. Instead the callback is ran but with a null value for the subscription argument. Therefore, the process still fails.
Service worker registration script:
'use strict';
function updateSubscriptionOnServer(subscription, apiEndpoint) {
return fetch(apiEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
subscription_json: JSON.stringify(subscription)
})
});
}
function subscribeUser(swRegistration, applicationServerPublicKey, apiEndpoint) {
// It seems browsers can take the base64 string directly.
// const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
console.log(`Subscribing pushManager with appkey ${applicationServerPublicKey}`);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerPublicKey
})
.then(function(subscription) {
console.log('User is subscribed.');
console.log(`Sending subscription data to server (${apiEndpoint})`, subscription);
return updateSubscriptionOnServer(subscription, apiEndpoint);
})
.then(function(response) {
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function(responseData) {
console.log(responseData);
if (responseData.status!=="success") {
throw new Error('Bad response from server.');
}
})
.catch(function(err) {
// FF Android says "User denied permission to use the Push API."
console.log('Failed to subscribe the user: ', err);
console.log(err.stack);
});
}
function registerServiceWorker(serviceWorkerUrl, applicationServerPublicKey, apiEndpoint){
let swRegistration = null;
if ('serviceWorker' in navigator && 'PushManager' in window) {
console.log('Service Worker and Push is supported');
console.log(`Current Notification.permission = ${Notification.permission}`);
swRegistration = navigator.serviceWorker.register(serviceWorkerUrl)
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
console.log(`Current Notification.permission = ${Notification.permission}`); // Will give "granted"
subscribeUser(swReg, applicationServerPublicKey, apiEndpoint);
})
.catch(function(error) {
console.error('Service Worker Error', error);
});
} else {
console.warn('Push messaging is not supported');
return false;
}
return swRegistration;
}
I cannot figure out how to get a working push-subscription. As said before, all other browsers that I have tried work fine. I hope someone can point me in the right direction. Is this a bug in Firefox Android or in my code?
Showing notifications manually using
new Notification("Hi there!");
does work, proving in principle that permissions are not the issue.
UPDATE:
FF Fenix team confirmed a bug while displaying the notifications
Feel free to track it here
Got curious regarding service worker support for Firefox mobile browser.
Tried hard to find a debug tool for Mobile Firefox as plugin or a 3rd party tool with no luck.
However, I've tested my web push application on Mobile Firefox and may totally confirm there is an issue with Service Worker Registration state.
In order to discard any issues within my code, I've used Matt Gaunt's Webpush Book
And I can tell Matt's service worker returns registration as simply as that:
async function registerSW() {
await navigator.serviceWorker.register('/demos/notification-examples/service-worker.js');
}
function getSW() {
return navigator.serviceWorker.getRegistration('/demos/notification-examples/service-worker.js');
}
Firefox for Android successfully requests permission for notification, but it doesn't display push whenever you launch the .showNotification function.
Here's an example of showNotification method within the Badge example in Matt's website:
async function onBadgeClick() {
const reg = await getSW();
/**** START badgeNotification ****/
const title = 'Badge Notification';
const options = {
badge: '/demos/notification-examples/images/badge-128x128.png'
};
reg.showNotification(title, options);
/**** END badgeNotification ****/
}
Looks fine and should be working fine, but for Firefox Mobile it doesn't work at all.
I guess this issue should be escalated to Mozilla.
UPDATE
New bug report was created on Github:

How to fix 'Uncaught (in promise) TypeError: Cannot read property 'method' of undefined' in Cloudflare worker?

I am trying to cache images that will be called by a KML layer in React Google Maps in order to reduce latency in displaying images and reduce calls to AWS S3 at scale using Cloudflare Worker .
I have followed the Cloudflare tutorial that can be found through this link : https://workers.cloudflare.com/docs/tutorials/configure-your-cdn/
The Cloudflare worker project has been compiled into a script and the console is indicating the following errors.
Uncaught (in promise) TypeError: Cannot read property 'method' of undefined
Uncaught (in response) TypeError: Cannot read property 'method' of undefined
I have checked the minified file of the script generated by Cloudflare but I am not being able to figure out what is going wrong although I followed the tutorial diligently.
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
const BUCKET_NAME = 'nightskybrightness'
const BUCKET_URL = `https://${BUCKET_NAME}.s3.eu-west-3.amazonaws.com`
async function serveAsset(event) {
const url = new URL(event.request.url)
const cache = caches.default
let response = await cache.match(event.request)
if (!response) {
response = await fetch(`${BUCKET_URL}${url.pathname}`)
const headers = { 'cache-control': 'public, max-age=15638400' }
response = new Response(response.body, { ...response, headers })
event.waitUntil(cache.put(event.request, response.clone()))
}
return response
}
async function handleRequest(event) {
if (event.request.method === 'GET') {
let response = await serveAsset(event)
if (response.status > 399) {
response = new Response(response.statusText, { status: response.status })
}
return response
} else {
return new Response('Method not allowed', { status: 405 })
}
}
Expected result : Cloudflare will cache the images on it's CDN and serve them when called by final users with reduced latency and also reduce calls to AWS S3.
cf-cache-status in network/headers section should indicate a HIT or MISS. The cached images will be positioned by the KML layer on top of Google Maps in the users' browser.
Actual result : Cloudflare worker script is throwing an error thus no image caching is taking place as intended.
cf-cache-status in network/headers section doesn't even show up in Response Headers section.
The problem is that on this line:
event.respondWith(handleRequest(event.request))
you are passing event.request as the parameter to handleRequest(). But on this line:
async function handleRequest(event) {
handleRequest() is defined to take just event, not event.request. So on this line:
if (event.request.method === 'GET') {
you are actually accessing event.request.request.method. But event.request.request is undefined, therefore you get an exception about trying to access undefined.method.
I would suggest changing the event.respondWith line to:
event.respondWith(handleRequest(event))
This is how it looks in the example code that you linked to.
I think the root of the issue is in CloudFlare's Worker Editor Preview implementation. I found the clue in a "chore" issue in Udacity's code.
which mentions ...
WARNING: Request Attributes do not currently work in the Worker Editor
Preview, resulting in an error: "Uncaught (in response) TypeError: Cannot read property 'country' of undefined."
So, just the error in the preview. "Save & Deploy" and test the *.worker.dev URL in a real browser if it works.

Fetch() request immediately failing in service worker running through Android Webview

I have a service worker that I use to enable an offline version of my website. This works great. I also have an Android app that is basically just a wrapper around a webview that loads my website.
All was fine and dandy until about 2-3 weeks ago when the Fetch() request started immediately failing. It is only failing when running through the Android webview. Running through a browser works fine. If the resource is cached already (i.e. via the install event) then it works great, it's only when I get a page that is not cached.
The code in my service worker:
self.addEventListener("fetch", function (event) {
if (event.request.method !== 'GET'
|| event.request.url.toLowerCase().indexOf('//ws') > -1
|| event.request.url.toLowerCase().indexOf('localws') > -1) {
// Don't intercept requests made to the web service
// If we don't block the event as shown below, then the request will go to
// the network as usual.
return;
}
event.respondWith(async function () {
// override the default behavior
var oCache = await caches.open('cp_' + version);
var cached = await oCache.match(event.request.url);
if (cached && cached.status < 300) {
return cached;
}
// Need to make a call to the network
try {
var oResp = await fetch(event.request); // THIS LINE CAUSES THE PROBLEM!!!
return oResp;
} catch (oError) {
console.log('SW WORKER: fetch request to network failed.', event.request);
return new Response('<h1>Offline_sw.js: An error has occured. Please try again.</h1><br><h2>Could not load URL: ' + event.request.url + '</h2>', {
status: 503,
statusText: 'Service Unavailable',
headers: new Headers({
'Content-Type': 'text/html'
})
});
}
}()); // event.respondwith
}); // fetch
The line:
var oResp = await fetch(event.request);
is called once I've determined it is not cached and seems to be the culprit. When it errors out I get the following error in my catch(): 'Failed to fetch'
This seems pretty generic and not helpful. Again, this works when going through a browser and so I know it's not a CORS issue, service worker in the wrong directory, etc. Again, it worked until about 3 weeks ago and now I'm getting reports from customers that it's not working.
Here's a screen shot of the actual event.request that I'm sending off:
In the chrome developer tools (used to debug the webview) I see the following:
Am I doing something wrong or is this a bug in the webview / chrome that was released recently? (I say that as chrome powers the webview)
Looks like it was a bug in chromium. See bugs.chromium.org/p/chromium/issues/detail?id=977784. Should be fixed in v 76.
As a work around (as the link mentioned), you can add the following to your android code:
ServiceWorkerController oSWController = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
oSWController = ServiceWorkerController.getInstance();
oSWController.setServiceWorkerClient(new ServiceWorkerClient(){
#Nullable
#Override
public WebResourceResponse shouldInterceptRequest(WebResourceRequest request){
return super.shouldInterceptRequest(request);
}
});
}

Using MSAL with React, acquireTokenSilent causes app refresh and fails

I am having problems getting MSAL(x) working - The login popup succeeds, but when I try to retrieve and access token from the id token using acquireTokenSilent, it causes the app to reload (all resources, per dev tools network tab), and throws an error 'Token renewal operation failed due to timeout: null'. I've searched for relevant SO questions / google, but have had no luck finding similar issues. The crazy thing is, it WORKED the other day and just stopped - even reverting to the same code does not resolve the issue.
Using acquireTokenPopup in the silent's error handler displays a popup, but won't allow login with the same user ('We don't recognize this domain name') but shows the correct MS App name. This is driving me crazy.
Relevant code (in a React component click handler):
onMSLogin() {
const { msLoginFailure } = this.props;
const userAgentApplication = this.userAgentApplication;
userAgentApplication.loginPopup(['user.read'])
.then(function () {
console.log('User login success');
const scopes = ['User.Read'];
userAgentApplication.acquireTokenSilent(scopes).then((accessToken) => {
console.log('Access token acquired (silent): ', accessToken);
this.getGraphData(accessToken);
}, (error) => {
console.error('Silent token fail: ', error);
userAgentApplication.acquireTokenPopup(scopes).then((accessToken) => {
console.log('Access token acquired (popup): ', accessToken);
});
})
}, function (error) {
// handle error
console.log('MS Login Failure: ', error);
if (msLoginFailure) msLoginFailure(error);
});
}
I believe your issue is related to MSAL.js Issue #106, and is patched within the 'dev' branch. I've been working with Microsoft the past few weeks on this library, and I've been told that an official release is due to be cut this week.

Error bubbles to console even though it is handled

I am using isomorphic-fetch to perform AJAX requests from my react-redux application. In my api middleware I have the following function which calls the external resource:
import fetch from 'isomorphic-fetch';
function callApi({ endpoint, method, body, params = {} }) {
let route = generateRoute(endpoint, params);
return fetch(route, generateFetchOptions(method, body))
.then(response => {
if (!response.ok) {
return Promise.reject(response);
}
return response.json();
});
}
The above function is called by the following piece of code:
return callApi(callAPI).then(
response => next(actionWith({
response,
type: successType,
statusCode: 200
})),
error => error.json().then(errorObject => {
return next(actionWith({
type: failureType,
statusCode: errorObject.statusCode,
error: errorObject.message || 'Something bad happened'
}));
})
);
If I reject with Promise.reject(response) the error is being handled by the error handler, but for some reason the error also bubbles to the browser console (in my case Chrome).
Here is a screenshot from the console which shows what is happening (api.js:34 is the second line of the callApi method):
This is the usual behavior (in probably every browser?) when hitting an error during an HTTP request (no matter whether a linked image cannot be found, or an XHR fails). No matter if and how you handle those errors, they will always be logged to the console. There is no way to suppress this behavior.
References:
Provide a way not to display 404 XHR errors in console
How can I stop jQuery.ajax() from logging failures to the console?

Categories