helper function
below is my helper function which do two things.
1.generateotp function will send otp to mobile from req.body(here i pass two parametr mobile number and channel. channel is mode of sending otp means sms or otp here it is sms)
2.secon function will verify the otp which user recived. here also we take 2 parameter mobile number and otp
var db = require('../config/connection');
const config= require('../config/config');
const collection = require('../config/connection');
const client = require("twilio")(config.accountSID,config.authToken)
module.exports={
generateOtp:(userNumber,channel) => {
client
.verify
.services(config.serviceID)
.verifications
.create({
to:`+91${userNumber}`,
channel:channel
})
.then((data) => {
console.log(data)
// return callback(null, 'success');
})
.catch((error) => {
console.log(error);
});
},
verifyOtp:(userNumber,userOtp) => {
client
.verify
.services(config.serviceID)
.verificationChecks
.create({
to:`+91$${userNumber}`,
code:userOtp
})
.then((data) => {
console.log(data);
})
.catch((error) => {
console.llog(error);
})
}
}
Route
/Generate Otp
router.post('/signup',(req,res) => {
const {userNumber, channel} = req.body;
userhelper.generateOtp(userNumber,channel)
return res.redirect('/verify');
});
//Verify Otp
router.post('/verify',(req,res) => {
const {userNumber,userOtp} = req.body;
console.log(req.body);
// userhelper.verifyOtp(userNumber,userOtp)
})
I am using twilio verify api for mobile number verification the above code worked perfectly till yesterday now when is test code i am getting an error.
RestException [Error]: Too many requests
at success (C:\Users\Alfas Ahmed\Desktop\whatsapp-ecom\node_modules\twilio\lib\base\Version.js:135:15)
at Promise_then_fulfilled (C:\Users\Alfas Ahmed\Desktop\whatsapp-ecom\node_modules\q\q.js:766:44)
at Promise_done_fulfilled (C:\Users\Alfas Ahmed\Desktop\whatsapp-ecom\node_modules\q\q.js:835:31)
at Fulfilled_dispatch [as dispatch] (C:\Users\Alfas Ahmed\Desktop\whatsapp-ecom\node_modules\q\q.js:1229:9)
at Pending_become_eachMessage_task (C:\Users\Alfas Ahmed\Desktop\whatsapp-ecom\node_modules\q\q.js:1369:30)
at RawTask.call (C:\Users\Alfas Ahmed\Desktop\whatsapp-ecom\node_modules\asap\asap.js:40:19)
at flush (C:\Users\Alfas Ahmed\Desktop\whatsapp-ecom\node_modules\asap\raw.js:50:29)
at processTicksAndRejections (internal/process/task_queues.js:75:11) {
status: 429,
code: 20429,
moreInfo: 'https://www.twilio.com/docs/errors/20429',
details: undefined
}
How to test Twilio Verify without getting rate limited
https://www.twilio.com/blog/test-verify-no-rate-limits
Above what happened is, in development time I just tested many time with same mobile number. Twilio just blocked service. So I just created new Service id , now the code working perfectly fine.
Related
Phone Auth is working locally but when the app is deployed the phone auth isnt working. When i enter my number and click to receive otp , i run into a error.
POST https://identitytoolkit.googleapis.com/v1/accounts:sendVerificationCode?key=AIzaSyDAcA6ooS6Rzg0jlAItTbWxM3ADJqCX2lE 400
this is my code:
getOTP(){
this.recaptchaVerifier = new RecaptchaVerifier('phone-verify',
{size: 'invisible'}, this.local_auth)
let vnumber = this.verify.value.number.slice(1)
vnumber = '+27' + vnumber
console.log(vnumber)
signInWithPhoneNumber(this.local_auth, vnumber, this.recaptchaVerifier)
.then((confirmation) => {
localStorage.setItem('verificationId',JSON.stringify(confirmation.verificationId))
}).then((response) => {
console.log(response)
})
.catch((err) => {
console.log(err.messge)
setTimeout(() => {
window.location.reload()}, 5000)
})
}
any ideas or advice or solutions would be welcomed...
I've made a firebase function which every time I pass data to it and try to use the data, it returns that the data is undefined. This is the function I made:
const functions = require('firebase-functions');
// The Firebase Admin SDK to access Cloud Firestore.
const admin = require('firebase-admin');
// CORS Express middleware to enable CORS Requests.
const cors = require('cors')({origin: true});
admin.initializeApp();
exports.addUser = functions.https.onRequest((req, res) => {
const handleError = (error) => {
console.log('Error creating new user:', error);
//sends back that we've been unable to add the user with error
return res.status(500).json({
error: err,
});
}
try {
return cors(req, res, async () => {
console.log(req);
const uid = req.uid;
const dob = req.dob;
const postcode = req.postcode;
const sex = req.sex;
const username = req.username;
admin.firestore().collection('users').doc(uid).set({
dob:dob,
postcode:postcode,
sex:sex,
username:username,
})
.then(function(userRecord) {
console.log('Successfully created new user:', userRecord.username);
// Send back a message that we've succesfully added a user
return res.status(201).json({
message: 'User stored',
id: req.body.uid,
});
})
.catch(function(error) {
return handleError(error);
});
});
} catch (error) {
return handleError(error);
}
});
This is how I call it within react:
const addUserFunc = firebase.functions().httpsCallable('addUser');
console.log("Calling user func " + user.uid)
addUserFunc({
uid:user.uid,
dob:dob,
postcode:postcode,
sex:sex,
username:username,
}).then(function(result) {
console.log(result);
}).catch(err => {
console.log(err)
setErrors(prev => ([...prev, err.message]))
});
I've printed the data before sending the request and it definitely exists. I've also tried getting it within the function using req.body and req.query but this just returns the same.
This is the error I get in the firebase function logs:
Error: Value for argument "document path" is not a valid resource path. The path must be a non-empty string.
at Object.validateResourcePath (/srv/node_modules/#google-cloud/firestore/build/src/path.js:406:15)
at CollectionReference.doc (/srv/node_modules/#google-cloud/firestore/build/src/reference.js:1982:20)
at cors (/srv/index.js:44:51)
at cors (/srv/node_modules/cors/lib/index.js:188:7)
at /srv/node_modules/cors/lib/index.js:224:17
at originCallback (/srv/node_modules/cors/lib/index.js:214:15)
at /srv/node_modules/cors/lib/index.js:219:13
at optionsCallback (/srv/node_modules/cors/lib/index.js:199:9)
at corsMiddleware (/srv/node_modules/cors/lib/index.js:204:7)
at exports.addUser.functions.https.onRequest (/srv/index.js:31:16)
This is the error return in the web console for the react app:
Access to fetch at 'https://***/addUser' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I tested the function within using the emulator and passing the values using the link which works there but just not when deployed.
Any help would be great.
Your Cloud Function is defined as a HTTPS Function, which means that you can access it over a URL, but then you're calling it from your code as a Callable Function. The two types are different and not interchangeable.
If you want to use the firebase.functions().httpsCallable('addUser'); in your client code, you'll have to modify your Cloud Function to be a Callable Function too. This mostly means that you get the parameters from data instead of res, and return responses instead of sending them through res.
exports.addUser = functions.https.onCall((data, context) => {
...
const uid = context.auth.uid; // automatically passed to Callable Functions
return admin.firestore().collection('users').doc(uid).set({
dob: data.dob,
postcode: data.postcode,
sex: data.sex,
username: data.username,
})
.then(function(userRecord) {
return {
message: 'User stored',
id: req.body.uid,
};
}).catch(err => {
throw new functions.https.HttpsError('dabase-error', error);
})
});
Alternatively, you can leave your Cloud Function as is and instead modify the calling code to use something like fetch().
I'm developing an authentication system for my React app with Firebase Auth. When the user signs up, firebase auth registers the user (createUserWithEmailAndPassword) and returns a promise with auth.uid and auth.emailVerified set to "false". This is fine.
I then use sendEmailVerification() method so the email address can be verified. I've tested the code and it works ok for a "valid" and "existing" email address. "catch" does give error for duplicate email address as expected. The problem is, it does not send the NON-EXISTING email (which I suppose is the correct bahaviour) but its should then give an error (so I can display to the user) which it does not.
Can someone explain why I'm not getting error for NON EXISTENT email address?
export const unpSignUp = (newUser) => {
console.log("newUser", newUser);
return (dispatch, getState, { getFirebase, getFirestore }) => {
const firebase = getFirebase();
const firestore = getFirestore();
firebase.auth().createUserWithEmailAndPassword(
newUser.unp_a05_email,
newUser.unp_a10_password
)
.then((response) => {
return firestore
.collection("unps")
.doc(response.user.uid)
.set({
unp_a02_surname: newUser.unp_a02_surname,
unp_a03_name: newUser.unp_a03_name,
unp_a06_verify_email_sent_datetime: null,
unp_a07_email_verified_on_datetime: null,
unp_a18_acc_created_on_datetime: moment().format("YYYY MM DD HH:mm:ss"),
});
})
.then((response) => {
console.log("SIGNUP SUCCESS ", response);
// user has been signed up, next step is to send verification email
dispatch({ type: SIGNUP_SUCCESS })
})
.then(() => {
// user has been signed up, next step is to send verification email
console.log('send email adr verification')
return firebase.auth().currentUser.sendEmailVerification()
})
.then( (response) => {
console.log("Verification email sent", response);
const user = firebase.auth().currentUser
console.log('current user', user)
const unp = firestore.collection("unps").doc(user.uid);
return unp.update({
unp_a06_verify_email_sent_datetime: moment().format("YYYY MM DD HH:mm:ss"),
})
})
.then( () => {
console.log(`unp_a06_verify_email_sent_datetime update to ${moment().format("YYYY MM DD HH:mm:ss")} `)
})
.catch((error) => {
console.log("SIGNUP ERROR", error);
console.log("SIGNUP ERROR CODE", error.code);
console.log("SIGNUP ERROR MESAGE", error.message);
dispatch({ type: SIGNUP_ERROR, error });
});
};
};
From firebase reference,
the return type of sendEmailVerification is Promise<void> - and it does not tell about any error codes that are sent in case of wrong email or failed/bounce mails. The error code it mentions is with respect to actionCodeSettings
If the actionCodeSettings is not specified, no URL is appended to the action URL. The state URL provided must belong to a domain that is whitelisted by the developer in the console. Otherwise an error will be thrown.
Thus it can not be checked if it is a valid email id. (This is expected behaviour as receiving mail servers may be down at times and hence there is a concept of retrying bounce mails)
I'm trying to use the Spotify wrapper to use my app, I manage to hit Spotify's Account Service and the page to authorize the app to use a users spotify account information but I get an internal 500 server error:
index.js:6 POST https://accounts.spotify.com/en/authorize/accept 500 (Internal Server Error)
// Set up Spotify API wrapper
const scopes = ['user-read-private', 'user-read-email'];
const STATE_KEY = 'spotify_auth_state';
app.get('/login', (req, res) => {
const state = generateRandomString(16);
res.cookie(STATE_KEY, state);
res.redirect(spotifyApi.createAuthorizeURL(scopes, state));
});
app.get('/callback', (req, res) => {
const { code, state } = req.query;
const storedState = req.cookies ? req.cookies[STATE_KEY] : null;
if (state === null || state !== storedState) {
res.redirect('/#/error/state mismatch');
} else {
res.clearCookie(STATE_KEY);
spotifyApi
.authorizationCodeGrant(code)
.then(data => {
const { expires_in, access_token, refresh_token } = data.body;
// Set the access token on the API object to use it in later calls
spotifyApi.setAccessToken(access_token);
spotifyApi.setRefreshToken(refresh_token);
spotifyApi.getMe().then(({ body }) => {
console.log(body);
});
res.redirect('/search');
})
.catch(err => {
res.redirect('/#/error/invalid token');
});
}
});
This is my endpoint on that page:
https://accounts.spotify.com/en/authorize?client_id=CLIENT_ID&response_type=code&redirect_uri=http:%2F%2Flocalhost:8888%2Fcallback%2F&scope=user-read-private%20user-read-email&state=k4ogwe4h53i00000
Not entirely sure what's happening. I thought it was initially a state mismatch but the state generated is fine. Having trouble pinpointing where the error is. Anyone have any suggestions?
You need to set your redirect URI in the developer dashboard, ensuring that it's exactly the same as the one you're using in your app.
We're aware of the poor error handling for the invalid redirect URI error and it's being fixed.
I've got a trouble when trying to implement backend firebase Authorization.
After I had read carefully the docs (https://firebase.google.com/docs/auth/web/phone-auth), I figured out that Authorization need to be proceded by two steps:
send phone
send code
I divided Google's example on two promises, but can't understand how to store current user and whether or not I've done everything in an appropriate way.
app.post("/appSignInByPhone", (req, res) => {
let {phoneNumber, applicationVerifier} = req.body;
firebase.auth().signInWithPhoneNumber(phoneNumber, applicationVerifier)
.then(() => res.end("Waiting for code"))
.catch(
error => res.json(error)
);
});
app.post("/appSignInPhoneVerify", (req, res) => {
let {verificationCode} = req.body;
firebase.auth.ConfirmationResult.confirm(verificationCode)
.then( user => res.json(user))
.catch(
error => res.json(error)
);
});
Maybe there are some ways of merging these to request to one...
Try the following:
In step #1 either store or send back the confirmationResult you get from the fulfillment handler:
firebase.auth().signInWithPhoneNumber(phoneNumber, applicationVerifier)
.then((confirmationResult) => {
// either store confirmationResult
// or send it to the client and ask for it in step #2)
}).catch(
error => res.json(error)
);
then in step #2:
// get the confirmationResult from the client or from some storage
// in the server
// for example let { verificationCode, confirmationResult } = req.body;
confirmationResult.confirm(verificationCode)
.then( user => res.json(user))
.catch(
error => res.json(error)
);