Use Firebase Cloud Function for Create User(Remove Automatically Login When register user) - ionic-framework

When user register from client side(mobile app) , user automatically login app i dont want auto login so, I did some research, I had to use a firebase cloud function to solve this.
But I get a few errors when calling the function , how can i fix these errors
First error :
Access to XMLHttpRequest at 'https://***.cloudfunctions.net/createUser' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
second error :
zone-evergreen.js:2845 POST https://****.cloudfunctions.net/createUser net::ERR_FAILED
Third Error
core.js:4197 ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "https://***.cloudfunctions.net/createUser", ok: false, …}
Firebase Console log
2:02:23.363 ÖS
createUser
Function execution started
2:02:23.390 ÖS
createUser
Function execution took 28 ms, finished with status: 'crash'
cloud function :
const functions = require('firebase-functions');
const cors = require('cors')({ origin: true });
const admin = require('firebase-admin')
admin.initializeApp();
exports.createUser = functions.https.onRequest((request, response) => {
return cors(req, res, () => {
if (request.method !== "POST") {
response.status(405).send("Method Not Allowed");
} else {
let body = request.body;
const email = body.email;
const password = body.password;
admin.auth().createUser({
email: email,
emailVerified: false,
password: password,
})
.then((userRecord) => {
return response.status(200).send("Successfully created new user: " +userRecord.uid);
})
.catch((error) => {
return response.status(400).send("Failed to create user: " + error);
});
}
})
});
client side :
signUp(email,password){
let body = {
email : email,
password : password
}
this.http.post(
'https://****.cloudfunctions.net/createUser',
body
).subscribe(a=>{console.log("Work")});
}
EDIT (new cloud function code) :
1st and 2nd bug fixed 3 still continues but I can create users.
exports.createUser = functions.https.onRequest((req, res) => {
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-Methods', ' POST, OPTIONS');
res.set('Access-Control-Allow-Headers', '*');
if (req.method === 'OPTIONS') {
res.end();
}
else {
let body = req.body;
console.log(body.email)
console.log("body.password")
const email = body.email;
const password = body.password;
admin.auth().createUser({
email: email,
emailVerified: false,
password: password,
})
.then((userRecord) => {
return res.status(200).send("Successfully created new user: " +userRecord.uid);
})
.catch((error) => {
return res.status(400).send("Failed to create user: " + error);
});
}
});

Cross origin error has many reason, first problem is your current url that probably like a ads url, please change the url pattern and clear browser cache. If you are using a VPN turn off it. The Chrome blocks url that contain ads url. This problem is not happen on production environment.
If your problem not fixed with top solution, use chrome in security disable mode.
Open start menu and type chrome.exe --disable-web-security and
make sure that this headers set in your backend
header('Access-Control-Allow-Origin: *');
header('Access-Control-Request-Method:*');
header('Access-Control-Allow-Headers: Origin,token, Authorization, X-Requested-With, Content-Type, Accept');
header('Access-Control-Allow-Credentials: true');

Related

How could i pass cookies in Axios

I am in a next-js app and my auth token is stored in cookies.
For some raisons i use Swr and Api route to fetch my secured api backend.
i am trying to find a way to put my auth token in all api request.
During login cookie is set
res.setHeader(
'Set-Cookie',
cookie.serialize('token', data.access_token, {
httpOnly: true,
secure: process.env.NODE_ENV !== 'development',
maxAge: data.expires_in, // 1 week
sameSite: 'strict',
path: '/',
}),
);
This is an example of a page using swr fetch
//page/test.ts - example of my test route
const { data, error } = useFetchContent(id);
if (error) {
showError('error');
replace('/');
}
return <DisplayContent content={data} />
This is a swrFetchHook
// fetchContentHook
function useFetchContent(id: string): ContentDetail {
return useSWR<any>(`/api/content/${id}`, fetcherApiRoute);
}
const fetcherApiRoute = (url: string): Promise<any> => {
return axios(url)
.then((r) => r.data)
.catch((err) => {
console.info('error is ', err)
throw err
});
};
export default useFetchContent;
inside api route
export default async (req, res): Promise<ContentDetail> => {
const { id } = req.query;
if (req.method === 'GET') {
const fetchRealApi = await apiAxios(url);
if(fetchRealApi) {
// here depending on result of fetchRealApi i add some other fetch ...
return res.status(200).json({ ...fetchRealApi, complement: comp1 });
}
return res.status(500)
}
return res.status(500).json({ message: 'Unsupported method only GET is allowed' });
};
and finally api axios configuration
const apiAxios = axios.create({
baseURL: '/myBase',
});
apiAxios.interceptors.request.use(
async (req) => {
// HERE i am trying to get token from cookies
// and also HERE if token is expired i am trying to refresh token
config.headers.Authorization = token;
req.headers['Content-type'] = 'application/x-www-form-urlencoded';
return req;
},
(error) => {
return Promise.reject(error);
},
);
export default apiAxios;
I am stuck here because i cant find token during apiAxios.interceptors.request.use...
Did you know what i am doing wrong, and am i on a correct way to handle this behavior ?
To allow sending server cookie to every subsequent request, you need to set withCredentials to true. here is the code.
const apiAxios = axios.create({
baseURL: '/myBase',
withCredentials: true,
});
Nilesh's answer is right if your API is able to authorize requests based on cookies. Also it needs the API to be in the same domain as your frontend app. If you need to send tokens to the API (the one which is in the cookie), then you will need a small backend component often called BFF or Token Handler. It can extract the token from the cookie and put in an Authorization header.
At Curity we've created a sample implementation of such a Token Handler, of which you can inspire: https://github.com/curityio/kong-bff-plugin/ You can also have a look at an overview article of the Token Handler pattern.

Error trying to get authenticated user email with googleapis and node.js

I'm implementing auth on my website using googleapis. The function plus.people.get doesn't work. I have seen it is deprecated on some forums but it's still documented at google which has me confused. The error I get is "Legacy People API has not been used in project 328985958128 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/legacypeople.googleapis.com then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry." The webpage doesn't even load. My code is
if (!req.body.token) return res.status(500).json({ type: 'error', message: 'No access token provided.' })
const OAuth2 = google.auth.OAuth2
const oauth2Client = new google.auth.OAuth2(keys.client_id, keys.client_secret)
google.options({ auth: oauth2Client });
const plus = google.plus('v1')
oauth2Client.setCredentials({
access_token: req.body.token
})
plus.people.get({
userId: 'me',
auth: oauth2Client
}, (error, response) => {
if (error)
console.log(error)
return res.status(500).json({ type: 'error',error })
const emails = (response.data || {}).emails
You are using google.plus('v1'), which has been deprecated
Instead you should use
const service = google.people({version: 'v1', auth: oauth2Client})
to create a service object.
To perform a request an additional auhtorization is not required anymore, so:
service.people.get({
userId: 'me'
}, (error, response) => {
...
})
Further information:
Creating a service account client with node.js
People API quide for node.js

how to reset password of users whose email is not verified in loopback?

So I ran into this issue.
I have a user who has emailedVerified as false.
So, when I try to reset password for that user as follows it gives me user unverified error.
Person.resetPassword({
email: email
}, function (err) {
if (err) return res.status(422).send(err);
});
So if user has emailVerified as false I created a token for the user with token data as follows:
const tokenData = {
ttl: 900,
scopes: ['reset-password'],
};
user.createAccessToken(tokenData, req, function (err, token) {
//email link with token
});
Now when I try to change password with following request.
/api/people/reset-password?access_token=generated-token and data message as {newPassword: “newPassword”}
I’m getting Access Denied for POST /api/people/reset-password?access_token=token
--Context scopes of Person.setPassword()
This happening only for generated token (either for verified user or non-verified user). If verified user request for password-change its successful which is done by following code.
Person.resetPassword({
email: email
}, function (err) {
if (err) return res.status(422).send(err);
});
I have following settings in person model, which i removed, but still it says access denied.
"restrictResetPasswordTokenScope": true,
"emailVerificationRequired": true,
I found this code in loopback/common/models/user.js:
User.resetPassword = function(options, cb) {
...
if (UserModel.settings.emailVerificationRequired && !user.emailVerified) {
err = new Error(g.f('Email has not been verified'));
err.statusCode = 401;
err.code = 'RESET_FAILED_EMAIL_NOT_VERIFIED';
return cb(err);
}
...
}
Looks like email verification validation only depends on the emailVerificationRequired setting. The value should be false if you want to enable reset password for not verified users:
"emailVerificationRequired": false, // The deletion of this property should also work as I don't see a default value in user.json
If it will not help, I suggest just debug the method above. I think it should be easy to find the problem, when you know the place to search.

facebook messenger bot encoding error

I have written sample echo message bot using facebook messenger api and wit.ai actions.
My message from facebook page is received and the proper action function defined using wit api's is also getting called. However
while returning the response, i am getting followin error as -
Oops! An error occurred while forwarding the response to : Error: (#100) Param message[text] must be a UTF-8 encoded string
at fetch.then.then.json (/app/index.js:106:13)
at process._tickCallback (internal/process/next_tick.js:103:7)
Here is the function which is used to return the response -
const fbMessage = (id, text) => {
const body = JSON.stringify({
recipient: { id },
message: { text },
});
const qs = 'access_token=' + encodeURIComponent(FB_PAGE_ACCESS_TOKEN);
return fetch('https://graph.facebook.com/v2.6/me/messages?' + qs, {
method: 'POST',
headers: {'Content-Type': 'application/json; charset=UTF-8'},
body
})
.then(rsp => rsp.json())
.then(json => {
if (json.error && json.error.message) {
throw new Error(json.error.message);`enter code here`
}
return json;
});
};
I have copied this function from the messenger.js file from the documentation since i am just trying the POC.
I checked the values for text and id in this function and verified using console.log statements and those are coming properly.
Can some experts help me to solve this error?
Note - I tried encoding the text using text.toString("utf8"); but it returns the encoding string as [object object] and thats the
response i get from bot. so it doesnt work.
Get the latest code from node-wit, there is a change in facebook id usage,
According to Facebook:
On Tue May 17 format of user and page ids delivered via webhooks will
change from an int to a string to better support default json encoder
in js (that trims long ints). Please make sure your app works with
string ids returned from webhooks as well as with ints.
Still you are getting issue with the api try to add if(event.message && !event.message.is_echo) condition as shown in below code.
// Message handler
app.post('/webhook', (req, res) => {
const data = req.body;
if (data.object === 'page') {
data.entry.forEach(entry => {
entry.messaging.forEach(event => {
if (event.message && !event.message.is_echo) {
const sender = event.sender.id;
const sessionId = findOrCreateSession(sender);
const {text, attachments} = event.message;
if (attachments) {
fbMessage(sender, 'Sorry I can only process text messages for now.')
.catch(console.error);
} else if (text) {
wit.runActions(
sessionId, // the user's current session
text, // the user's message
sessions[sessionId].context // the user's current session state
).then((context) => {
console.log('Waiting for next user messages');
sessions[sessionId].context = context;
})
.catch((err) => {
console.error('Oops! Got an error from Wit: ', err.stack || err);
})
}
} else {
console.log('received event', JSON.stringify(event));
}
});
});
}
res.sendStatus(200);
});
Reference:
no matching user bug
no matching user fix

Getting and "Error, wrong validation token" when trying to create a Facebook Chatbot

I'm trying to create a Facebook chatbot with NodeJS, Express, and a Heroku server.
I created my webhook on heroku and had it verified and saved by facebook. I then started adding code that would reply to the incoming messages and I can't seem to get it connected. It keeps saying "Error, wrong validation token" when I try to load my webhook in my browser. And when I try to send my bot a message I get no response. Even though I already had it verified and didn't change the code.
Here is my code:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var port = process.env.PORT || 3000;
// body parser middleware
app.use(bodyParser.urlencoded({ extended: true }));
// test route
//app.get('/', function (req, res) { res.status(200).send('Hello world!') });
app.get('/', function (req, res) {
if (req.query['hub.verify_token'] === '8FKU9XWeSjnZN4ae') {
res.send(req.query['hub.challenge']);
}
res.send('Error, wrong validation token');
})
app.post('/', function (req, res) {
messaging_events = req.body.entry[0].messaging;
for (i = 0; i < messaging_events.length; i++) {
event = req.body.entry[0].messaging[i];
sender = event.sender.id;
if (event.message && event.message.text) {
text = event.message.text;
sendTextMessage(sender, "Text received, echo: "+ text.substring(0, 200));
}
}
res.sendStatus(200);
});
// error handler
app.use(function (err, req, res, next) {
console.error(err.stack);
res.status(400).send(err.message);
});
app.listen(port, function () {
console.log('Listening on port ' + port);
});
var token = <myToken>;
function sendTextMessage(sender, text) {
messageData = {
text:text
}
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token:token},
method: 'POST',
json: {
recipient: {id:sender},
message: messageData,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
});
}
So I'm confused as to why nothing is happening and why I'm getting that error. I feel like I'm missing a whole step. I am following this tutorial by the way: https://developers.facebook.com/docs/messenger-platform/quickstart
Any help is appreciated. Thanks!
Edit: Here are my heroku logs
Do not post your full access tokens here!
Have you tested the output of the challenge? Since it's just a GET and you know all values you can try it yourself: your-app-domain.com/your-callback-url?hub_mode=subscribe&hub_verify_token=the_token_you_set_in_your_app_config&hub_challenge=ping which sould print 'ping' if everything work fine.
Make sure you add sendStatus(200) to the hub challenge response, too.
You need to subscribe your page to the app first. To do so make a POST request to /your-page-id/subscribed_apps which should return "success". You can make a GET request to the same endpoint afterwards to double check your app is subscribed to your page
You did not mention which events you subscribed to (needs to be message_deliveries, messages, messaging_optins, messaging_postbacks)
Make sure the webhooks tab in your app dashboard now says "complete"
Test again
You are actually using "request" but you are never importing it anywhere. Here's how to fix it:
var request = require("request")
Once you have added that to your index.js or app.js file (basically whatever this file is), make sure you do:
npm install request --save
This should fix it. Unfortunately, Heroku doesn't error out and say that it does not know what "request" is and that's why it was so hard to figure this out in the first place!