OTPCredential Webapi throws "DOMException: OTP retrieval was cancelled." - reactjs

The following is my useEffect
useEffect(() => {
//#ts-ignore
if ("OTPCredential" in window) {
const ac = new AbortController();
setTimeout(() => {
ac.abort();
}, 1 * 60 * 1000);
navigator.credentials
.get({
otp: { transport: ["sms"] },
signal: ac.signal,
})
.then((otp) => {
console.log("otp",otp);
//ac.abort();
})
.catch((err) => {
//ac.abort();
console.log(err);
});
}
}, []);
I am following the typescript solutions given on other similar questions:-
I have copied type script definitions given here
Web OTP API Typescript Typings issue - Missing Types in TypeScript
I have also styled the sms as per the standard.
Your OTP is :1234
#domainname #1234.
The android browser version is 106 and there is default popup which seeks permission to input the OTP.
But in console log I can see the error "DOMException: OTP retrieval was cancelled."
Any help would be appreciated.

Related

How to login with Microsoft SSO in Cypress test when getting cookies blocked error

I'm trying to login to microsoft SSO account in my cypress test and I'm getting "Your browser is currently set to block cookies." error. I am using Cypress version 10+. I've seen posts about using Cypress.Cookies.preserveOnce() but it is deprecated in the 10+ version. This is the error I'm seeing in my cypress test:
This is how I'm trying to login.
cy.session(args, () => {
cy.origin(`https://login.microsoftonline.com/`, {args}, ({ email, password}) => {
cy.visit('/')
cy.get('[name="loginfmt"]').type(email);
cy.get('[name="passwd"]').type(password);
cy.get('[type="submit"]').type('{enter}');
})
});
Any help will be appreciated!
// cypress.config.js
experimentalSessionAndOrigin: true,
pageLoadTimeout: 180000,
experimentalModifyObstructiveThirdPartyCode: true,
chromeWebSecurity: false,
experimentalInteractiveRunEvents: true,
// commands.js
Cypress.Commands.add("jwtlogin", (name, password, token, path) => {
const args = {
name,
password,
token,
path
}
cy.visit(Cypress.config('apiLoginURL'))
cy.on('uncaught:exception', (err, runnable) => {
return false
})
cy.wait(7000)
cy.get('.microsoft').click()
cy.origin('https://login.microsoftonline.com', {
args
}, ({
name,
password,
token,
path
}) => {
cy.wait(17000)
cy.get('body').then((body) => {
if (body.find('#otherTileText').length > 0) {
cy.contains('Use another account').click()
cy.get('#i0116').type(name)
} else {
cy.get('#i0116').type(name)
}
})
cy.get('#idSIButton9').click()
cy.wait(3000)
cy.get('#i0118').type(password)
cy.contains('Sign in').click()
cy.get('div.tile:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(2)').click()
cy.task("generateOTP", token).then(token => {
cy.get("#idTxtBx_SAOTCC_OTC").type(token);
cy.get('#idSubmit_SAOTCC_Continue').click()
cy.wait(3000)
})
cy.on('uncaught:exception', (err, runnable) => {
return false
})
})
cy.wait(5000)
cy.get('body').then((body1) => {
cy.wait(5000)
if (body1.find('#idBtn_Back').is(":visible")) {
cy.wait(5000)
cy.get('#idBtn_Back').click()
}
cy.wait(16000)
})
})
//hooks file
before(() => {
cy.origin('https://login.microsoftonline.com', () => {
cy.visit('https://login.windows.net/common/oauth2/logout')
})
cy.on('uncaught:exception', (err, runnable) => {
return false
})
cy.jwtlogin('testaccount.com', 'Derersr1', 'dfdfd', 'jeet.txt')
cy.window().then(win => win.sessionStorage.clear());
cy.clearCookies();
cy.clearLocalStorage()
cy.wait(11000)
})
Sometimes when logging into Microsoft SSO in Cypress, the error message that appears is 'Your browser is currently set to block cookies,' even in cases where the actual reason for the error is something else. For instance, my account has been suspended and locked. In Cypress, the error message shows "Your browser is currently set to block cookies," but in my system's browser, it shows a different message.
This can be confusing, so it's important to keep in mind that the error message may not always accurately reflect the issue at hand.

socket.io not working in production mode for IOS?

I'm currently using socket.io for real time alerts in my app. I'm developing it using React Native with Expo.
I import this instance of the socket into required components:
socketInstance.js
import io from 'socket.io-client';
import { url } from './url';
const socket = io(url, { secure: true });
export default socket;
And then use it to emit data to the server, for example, when the payment for an order has been completed:
OrderPurchaseScreen.js
const openPaymentSheet = async () => {
const { error } = await presentPaymentSheet();
if (error) {
Alert.alert(`Error code: ${error.code}`, error.message, [
{
text: "Try Again",
onPress: () => openPaymentSheet(),
},
{
text: "Cancel Order",
onPress: () => handleExit(),
style: "cancel",
},
]);
} else {
Alert.alert(
"Payment Successful",
"Your payment has successfully been processed."
);
socket.emit("order-purchase-complete", Store.getState().orderReducer.orderTicket.restaurantId);
setActive(false);
navigation.navigate('OrderCompleteScreen');
}
In the node server
server.js
io.on('connection', (socket) => {
socket.on("logIn", (userId) => {
console.log("new user logged in. - " + userId.toString());
socket.join(userId.toString());
socket.on("order-cancelled", (userId) => {
console.log("order cancelled");
io.to(userId.toString()).emit("order-cancelled", createNotificationObject("Order Cancelled", "The restaurant has cancelled your order. Your money will be refunded."));
});
socket.on("new-order-completed", (userId) => {
console.log("order completed");
io.to(userId.toString()).emit("new-order-completed", createNotificationObject("Order Completed", "Your order has been completed."));
});
});
socket.on("restaurantLogin", (restaurantId) => {
console.log("new restaurant logging in...");
socket.join(restaurantId.toString());
socket.on("new-order-for-approval", (restaurantId) => {
console.log("New Order For Approval!");
io.to(restaurantId.toString()).emit("new-order-for-approval", createNotificationObject("Order Awaiting Approval", "There is a new order awaiting approval. View it in the Restaurant Manager."));
});
socket.on("order-purchase-complete", (restaurantId) => {
console.log("new order purchase completed");
io.to(restaurantId.toString()).emit("order-purchase-complete", createNotificationObject("Order Completed", "A new order has been placed. View it in the Restaurant Manager."));
});
});
}
I have found that in dev mode, everything works fine and as expected. However when I switch to prod mode for IOS (have not tested Android), it only seems to be able to handle the user logging in. When it comes to emitting data after the order being completed for example, nothing gets emitted. Anyone know what I can do to debug this to help me find out the problem or have a potential solution?
Found the answer while browsing the socket.io documentation:
https://socket.io/blog/socket-io-on-ios/
"A Note About Multitasking in iOS
As you probably know, iOS is very picky about what you can do in the background. As such, dont expect that your socket connection will survive in the background! Youll probably stop receiving events within seconds of the app going into the background. So its better to create a task that will gracefully close the connection when it enters the background (via AppDelegate), and then reconnect the socket when the app comes back into the foreground."
So all I did was use AppState to get the state of the app, and depending on if it was in the foreground or background I would re connect to the socket or disconnect:
App.js
useEffect(async () => {
const subscription = AppState.addEventListener(
"change",
async (nextAppState) => {
if (
appState.current.match(/inactive|background/) &&
nextAppState === "active"
) {
if (_userToken !== null && email !== null && password !== null) {
socket.connect();
socket.emit("logIn", Store.getState().userReducer._id);
}
appState.current = nextAppState;
setAppStateVisible(appState.current);
if (appState.current === "background") {
socket.disconnect();
}
//console.log("AppState", appState.current);
}
);

React JS Detect Close Button PiP ( Picture in picture)

I'm having trouble trying to detect an onClick or some type of event listener for the PIP feature in most browsers - specifically on Chrome.
Reading MDN docs and implementing their suggestions proved unsuccessful
https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement/leavepictureinpicture_event
Here is my code so far which gives me a Cannot read properties of null error as there is no addEventListener for pipButton:
const video = document.getElementById('video');
const pipButton = document.getElementById('pipButton');
pipButton.addEventListener('click', () => {
if (document.pictureInPictureElement) {
document
.exitPictureInPicture()
.catch(error => {
// Error handling
})
} else {
// Request Picture-in-Picture
console.log('CLOSED PIP')
}
});
pipButton.addEventListener('leavepictureinpicture', function(event: any) {
console.log('Left PiP');
if (document.pictureInPictureElement) {
document.exitPictureInPicture().catch((error: any) => {
// Error handling
console.log('error :>> ', error);
});
}
});

How to reset recaptcha when using react-redux-firebase

I am working with React-Redux-Firebase. I implemented signing in with phone number. Now I am trying to implement error handling. When number is invalid I display window alert with error message. The only thing left to do is to reset recaptcha. Without it, I am getting error:
reCAPTCHA has already been rendered in this element
I was trying to do according to Firebase documentation
grecaptcha.reset(window.recaptchaWidgetId);
// Or, if you haven't stored the widget ID:
window.recaptchaVerifier.render().then(function(widgetId) {
grecaptcha.reset(widgetId);
}
but it does not work in my code. I dont have grecaptcha implemented. I tried to add it with react-grecaptcha, but it did not work.
Could someone give me a hint how to reset recaptcha after each error, please?
state = {
phone: "",
confirmationResult: {},
};
handleClick = () => {
const recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
"sign-in-button",
{
size: "invisible",
}
);
firebase
.signInWithPhoneNumber(`+${this.state.phone}`, recaptchaVerifier)
.then((confirmationResult) => {
this.setState({ confirmationResult });
})
.catch((error) => {
// Error; SMS not sent
// Handle Errors Here
window.alert(`${error.code}, ${error.message}`);
recaptchaVerifier.reset(); // How can I do that?
});
};
I've been struggling with this problem for several days, maybe my answer will help someone.
export const requestRecaptchVerifier = () => {
window.recaptchaVerifier = new RecaptchaVerifier(
"recapcha-container",
{
size: "invisible",
},
auth
);
};
I then call signInWithPhone from another function and handle the error like this:
await signInWithPhone(formik.values.phone)
.then(() => {
// ... my code
})
.catch(() => {
window.recaptchaVerifier.recaptcha.reset();
window.recaptchaVerifier.clear();
});
All the difference in
window.recaptchaVerifier.recaptcha.reset()
And
window.recaptchaVerifier.clear()
I'm no expert but from the documentation and by talking with you in the comment section I think you need to pass a callback. Like this:
const recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
'size': 'invisible',
'callback': function(response) {
// reCAPTCHA solved, allow signInWithPhoneNumber.
firebase
.signInWithPhoneNumber(`+${this.state.phone}`, recaptchaVerifier)
.then((confirmationResult) => {
this.setState({ confirmationResult });
})
.catch((error) => {
// Error; SMS not sent
// Handle Errors Here
window.alert(`${error.code}, ${error.message}`);
recaptchaVerifier.reset();
});
}
});
Reference: https://firebase.google.com/docs/auth/web/phone-auth#use-invisible-recaptcha
Hope this helps!

Public API call working on Mozilla but not on Chrome (react-app)

I recently tried to deploy my first react-app on to the web. The website is about looking up details for a certain pokemon and making your own card if you like.
I use Mozilla as my main browser and everything works pretty good. But when I ask for a pokemon request (GET) on chrome I don't get any results. If I have a look at the network console I get a 301 Error (from disk cache). What does this mean? You can look at my website at:
https://daan.boschmans.mtantwerp.eu/
I deployed my app using the npm run build command.
I added the .htaccess file in the public folder with the proper lines.
GET REQUEST:
export const getPokemonSprites = (name) => {
return fetch(`https://pokeapi.co/api/v2/pokemon-form/${name}`).then((response) => {
if(response.statusText === 'OK') {
return response.json();
}
throw new Error('Network response was not ok.');
})
}
export const getPokemonMoves = (name) => {
return fetch(`https://pokeapi.co/api/v2/pokemon/${name}`).then((response) => {
if(response.statusText === 'OK') {
return response.json();
}
throw new Error('Network response was not ok.');
})
}
This I how I handle the GET call:
getPokeData() {
if (this.state.searchValue && this.state.name !== this.state.searchValue) {
this.setState({ isLoading: true, hasError: false, name: "", sprites: [], moves: [], height: "", weight:"", specials: [], base_experience: "", type: [], stats:[], items: [], });
Promise.all([ getPokemonSprites(this.state.searchValue),getPokemonMoves(this.state.searchValue)])
.then( ([spriteList, pokeDetails]) => {
const sprites = Object.values(spriteList.sprites);
const moves = Object.entries(pokeDetails.moves);
const abilities = Object.entries(pokeDetails.abilities);
const types = Object.entries(pokeDetails.types);
const stats = Object.entries(pokeDetails.stats);
for (const [ , value] of Object.entries(moves)) {
this.state.moves.push(value[1].move.name);
}
for (const [, value] of Object.entries(types)) {
this.state.type.push(value[1].type.name);
}
for (const [, value] of Object.entries(abilities)) {
this.state.specials.push(value[1].ability.name);
}
for (const [, value] of Object.entries(stats)) {
let statsValue = `${value[1].stat.name}: ${value[1].base_stat}`;
this.state.stats.push(statsValue);
}
this.setState({sprites, name: spriteList.name, height: pokeDetails.height, weight: pokeDetails.weight, base_experience: pokeDetails.base_experience })
}).then(() => { this.setState({isLoading: false, searchValue: ""})})
.catch(() => { this.setState({isLoading: false, searchValue: "", hasError: true}) })
}
}
Any tips would be really appreciated
Thanks
Firstly, nice site. Looks like a fun little project.
I tried the website on Chrome and it works fine for me.
Looks as though you have a service worker that is caching content. If you used create-react-app, it comes with a service worker built it and looks as though it is caching the content of your API calls in your browser.
I suspect there is an issue with your Chrome's cache. You could try clearing the cache by following this suggestion here or alternatively it may be worth trying to reinstall chrome.

Resources