AppCheck tokens are not recognised only when using mobile - javascript

I'm developing a webapp authentication system using Firebase. When I login and use the webapp from my computer everything works fine but when I use it on mobile appcheck does not work anymore and it gives me the following error in the console:
https://content-firebaseappcheck.googleapis.com/v1/projects/nameoftheproject/apps/1:784721317237:web:5db5892bc06253ab6b173c:exchangeRecaptchaEnterpriseToken?key=myKey
Failed to load resource: the server responded with a status of 403 ()
This is the code I'm using to create initialise appCheck in my webapp:
const appCheck = initializeAppCheck(app, {
provider: new ReCaptchaEnterpriseProvider(config[process.env.REACT_APP_ENV]['recaptcha-key']),
isTokenAutoRefreshEnabled: true
});
export const getAppCheckToken = async () => {
let appCheckTokenResponse;
try {
appCheckTokenResponse = await getToken(appCheck, false);
} catch(err) {
console.log(err);
}
return appCheckTokenResponse.token;
}
So a typical use case for that function is this:
//This is the code from one of my functions, it's just an example to show you how I use appcheck tokens
if (querySnapshot.docs.length === 0) {
headerAPI.headers['X-Firebase-AppCheck'] = await getAppCheckToken();
await axios.post(signupAPI, {
email: email,
username: displayName
}, headerAPI);
await sendEmailVerification(auth.currentUser, {
url: config[process.env.REACT_APP_ENV]['url-used-to-send-mail-auth-signup'],
handleCodeInApp: true
})
props.cookieAlert('Info', 'Cookies', 'Informations here...');
} else {
window.location.href = '/dashboard/home';
}
Now, I can't understand why it doesn't work on mobile...I hope my code is clear enough to let you understand my troubles, thank you in advance.

Related

NodeJS and Nginx - How to open url?

I am trying to open url using using this package. It works locally, but if I try to use the same thing on my deployed app, it is not working, it just skip that part, or it looks like that because it returns a message, but it is not opening url. Is there something that should be configured on server for this?
For example, I am trying to do this
const authorizeUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: scopes,
});
try {
opn(authorizeUrl, { wait: true }).then(cp => {
console.log('cp', cp)
const server = http
.createServer(async (req, res) => {
try {
if (req.url.indexOf('/callback') > -1) {
const qs = new url.URL(req.url, `${process.env.SERVER_API_URL}`)
.searchParams;
res.end(
'Authentication successful! Please return to the console.'
);
server.destroy();
const { tokens } = await oauth2Client.getToken(qs.get('code'));
oauth2Client.credentials = tokens;
resolve(oAuth2Client);
}
} catch (e) {
reject(e);
}
})
});
return res.send({ msg: 'okay' })
and it works locally, but on deployed app it just returns 'ok'. If I use callback or something else to return message, it just block and causes timeout.

JS await throws an error in a browser console

I'm using nuxt to develop a client for my laravel project.
In the login.vue component I have the following JS code
import Form from 'vform'
export default {
head () {
return { title: this.$t('login') }
},
data: () => ({
form: new Form({
email: '',
password: ''
}),
remember: false
}),
methods: {
async login () {
let data;
// Submit the form.
try {
const response = await this.form.post('/api/login');
data = response.data;
} catch (e) {
return;
}
// Save the token.
this.$store.dispatch('auth/saveToken', {
token: data.token,
remember: this.remember
});
// Fetch the user.
await this.$store.dispatch('auth/fetchUser');
// Redirect home.
this.$router.push({ name: 'home' })
}
}
}
If I try to submit the login form with wrong email and password values I see an error message in a browser console.
For example:
POST http://laravel.local/api/login 422 (Unprocessable Entity)
Please note that I'm using try catch that catches all errors on the following call.
const response = await this.form.post('/api/login');
Is this really issue with async/await usage?
How can I get rid of that error in the browser console?
If you need some more info from me do not hesitate to ask it.

How to integrate getAccessToken with fetch function to load data from DRF backend to React Frontend?

React newbie here, but proficient in Django.I have a simple fetch function which worked perfectly but then my project had no login authentication involved. Now that I have configured the login system, my backend refuses to serve requests with any access tokens. My login authentication is very new to me and was more or less copied from somewhere. I am trying to understand it but am not able to. I just need to know how to convert my simple fetch function to include the getAccessToken along the request in it's headers so my backend serves that request.
Here is my previously working simple fetch function :
class all_orders extends Component {
state = {
todos: []
};
async componentDidMount() {
try {
const res = await fetch('http://127.0.0.1:8000/api/allorders/'); // fetching the data from api, before the page loaded
const todos = await res.json();
console.log(todos);
this.setState({
todos
});
} catch (e) {
console.log(e);
}
}
My new login JWT authentication system works perfectly, but my previous code is not working and I keep getting error
"detail": "Authentication credentials were not provided."
This is is the accesstoken I am not able to 'combine' with my preivous fetch function:
const getAccessToken = () => {
return new Promise(async (resolve, reject) => {
const data = reactLocalStorage.getObject(API_TOKENS);
if (!data)
return resolve('No User found');
let access_token = '';
const expires = new Date(data.expires * 1000);
const currentTime = new Date();
if (expires > currentTime) {
access_token = data.tokens.access;
} else {
try {
const new_token = await loadOpenUrl(REFRESH_ACCESS_TOKEN, {
method: 'post',
data: {
refresh: data.tokens.refresh,
}
});
access_token = new_token.access;
const expires = new_token.expires;
reactLocalStorage.setObject(API_TOKENS, {
tokens: {
...data.tokens,
access: access_token
},
expires: expires
});
} catch (e) {
try {
if (e.data.code === "token_not_valid")
signINAgainNotification();
else
errorGettingUserInfoNotification();
} catch (e) {
// pass
}
return reject('Error refreshing token', e);
}
}
return resolve(access_token);
});
};
If you're looking for a way how to pass headers in fetch request, it's pretty straight forward:
await fetch('http://127.0.0.1:8000/api/allorders/', {
headers: {
// your headers there as pair key-value, matching what your API is expecting, for example:
'details': getAccessToken()
}
})
Just don't forget to import your getAccessToken const, if that's put it another file, and I believe that would be it. Some reading on Fetch method

ReCaptcha 2 working only once

I'm trying to implement a ReCaptcha but I can only get a valid g-recaptcha-response once when I'm testing it. If I'm trying to validate the captcha a second time, I check the box "I'm not a robot" then resolve the challenge but I'm getting the exact same g-recaptcha-response as the first time and I get a "timeout-or-duplicate" error from the webservice https://www.google.com/recaptcha/api/siteverify.
The only way I can get it to work again is to empty my local storage and my cookies.
Do you have any idea of why I have to do this ?
My code look like this :
HTML:
<div class="g-recaptcha"></div>
JS:
class CaptchaProtectedForm {
onSubmit() {
const captchaContainer = document.querySelector('.g-recaptcha');
this.captchaWidgetId = global.grecaptcha.render(capContainer, {
sitekey: '{site key}',
callback: this.doSubmit.bind(this),
});
}
doSubmit() {
const response = global.grecaptcha.getResponse(this.captchaWidgetId);
this.callBackend(parameters, response);
global.grecaptcha.reset();
}
}
Backend code (express router) :
router.route('/captchaProtectedEndpoint').post((req, res) => {
const {
headers: {
'x-captcha-token': captchaToken,
'x-forwarded-for': forwardedIp,
},
} = req;
const requestData = {
secret: conf.captchaSecretKey,
response: captchaToken,
remoteip: forwardedIp || req.connection.remoteAddress,
};
const requestConfig = {
uri: 'https://www.google.com/recaptcha/api/siteverify',
method: 'POST',
form: requestData,
};
request(requestConfig)
.then((captchaResponse) => {
if (captchaResponse.success) {
console.log('success', captchaResponse);
res.status(200).send();
} else {
console.log('failure', captchaResponse);
res.status(403).send();
}
})
.catch((err) => {
res.status(500).send();
});
});
Late edit:
The code works as expected, it was not working because of another module that was messing up with the local storage of our app.
This happens because, the g-recaptcha prevents duplicate entries. If you refresh the page and try to validate it, it will start the validation from the beginning. Also, if the data is stored in your cookies, the recaptcha will not start a fresh validation.

Facebook login in React Native

I am developing an app in React Native and I want to implement logging in with Facebook.
I have an API in Node.js where I handle the logic for users to log in, etc.
I use passport.js to let users log in with either Facebook or traditional Email.
I am opening an URL in my API with SafariView which is just a regular "WebView" directly in my app.
I have tried using the following code:
class FacebookButton extends Component {
componentDidMount() {
// Add event listener to handle OAuthLogin:// URLs
Linking.addEventListener('url', this.handleOpenURL);
// Launched from an external URL
Linking.getInitialURL().then((url) => {
if (url) {
this.handleOpenURL({ url });
}
});
}
componentWillUnmount() {
Linking.removeEventListener('url', this.handleOpenURL);
}
handleOpenURL({ url }) {
// Extract stringified user string out of the URL
const [, user_string] = url.match(/user=([^#]+)/);
this.setState({
// Decode the user string and parse it into JSON
user: JSON.parse(decodeURI(user_string))
});
if (Platform.OS === 'ios') {
SafariView.dismiss();
}
}
openURL(url) {
if (Platform.OS === 'ios') {
SafariView.show({
url: url,
fromBottom: true,
});
} else {
Linking.openURL(url);
}
}
render() {
return (
<Button
onPress={() => this.openURL('https://mywebsite.com/api/auth/facebook')}
title='Continue with Facebook'
...
so I guess I will have to do the authentication on URL https://mywebsite.com/api/auth/facebook and then send the user to an url that looks something like OAuthLogin://..., but I am not entirely sure how to use it.
Can anyone help me move in the right direction?
import { LoginManager, AccessToken } from 'react-native-fbsdk'; // add this file using npm i react-native-fbsdk
Create function
const onFacebookButtonPress = async () => {
// Attempt login with permissions
const result = await LoginManager.logInWithPermissions(['public_profile', 'email']);
if (result.isCancelled) {
throw 'User cancelled the login process';
}
// Once signed in, get the users AccesToken
const userInfo = await AccessToken.getCurrentAccessToken();
if (!userInfo) {
throw 'Something went wrong obtaining access token';
}
console.log('user info login', userInfo)
// Create a Firebase credential with the AccessToken
const facebookCredential = auth.FacebookAuthProvider.credential(userInfo.accessToken);
setGoogleToken(userInfo.accessToken)
// Sign-in the user with the credential
return auth().signInWithCredential(facebookCredential)
.then(() => {
//Once the user creation has happened successfully, we can add the currentUser into firestore
//with the appropriate details.
console.log('current User ####', auth().currentUser);
var name = auth().currentUser.displayName
var mSplit = name.split(' ');
console.log("mSplit ",mSplit);
let mUserDataFacebook = {
user_registration_email: auth().currentUser.email,
user_registration_first_name: mSplit[0],
user_registration_last_name: mSplit[1],
registration_type: 'facebook',
user_registration_role: "Transporter",
token: userInfo.accessToken,
user_image : auth().currentUser.photoURL,
};
console.log('mUserDataFacebook',mUserDataFacebook)
LoginWithGoogleFacebook(mUserDataFacebook) /// Call here your API
firestore().collection('users').doc(auth().currentUser.uid) //// here you can add facebook login details to your firebase authentication.
.set({
fname: mSplit[0],
lname: mSplit[1],
email: auth().currentUser.email,
createdAt: firestore.Timestamp.fromDate(new Date()),
userImg: auth().currentUser.photoURL,
})
//ensure we catch any errors at this stage to advise us if something does go wrong
.catch(error => {
console.log('Something went wrong with added user to firestore: ', error);
})
})
}
Call this function on button press onFacebookButtonPress()
For android need to setup and add facebook id in
android/app/src/main/res/values/strings.xml file
add these two lines.
YOUR_FACEBOOK_ID
fbYOUR_FACEBOOK_ID //Don't remove fb in this string value
/////////////add this code in AndroidMainfest.xml file
//////////This code add in MainApplication.java file
import com.facebook.FacebookSdk;
import com.facebook.appevents.AppEventsLogger;
/////////add code build.gradle file
implementation 'com.facebook.android:facebook-android-sdk:[5,6)'

Categories