how to reset password of users whose email is not verified in loopback? - 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.

Related

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

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');

Strapi - Update Additional Fields on User Model

Problem Statement: Able to register user but unable to update customFields on same model in single request. Detail explanation below.
I have added additional fields to UserModel on Strapi. UserModel Attached
I am building a front end using Nuxt, where admin user can create new users who can access the website. This is not Regular Signup, This is User getting created by admin of the site. I guess even a regular signup I would face this issue.
Admin has all the rights to crud users.
When I submit the form I am getting Forbidden error. Form Attached
Below is my code which handled the submit. I first register the user and based on the user id I try to update First Name and Last name.
handleSubmit() {
if (this.$refs.form.validate()) {
this.loading = true
// console.log(this.username, this.email, this.password)
strapi
.register(this.username, this.email, this.password)
.then(response => {
console.log(response)
strapi
.updateEntry('users', response.user.id, {
firstName: this.firstname,
lastname: this.lastname
})
.then(response => {
this.loading = false
this.$router.push('/users')
})
.catch(err => {
this.loading = false
// alert(err.message || 'An error occurred.')
this.errorMessage = true
this.errorMessageContent = err.message || 'An error occurred.'
})
})
.catch(err => {
this.loading = false
// alert(err.message || 'An error occurred.')
this.errorMessage = true
this.errorMessageContent = err.message || 'An error occurred.'
})
}
}
Below is the console message.
Do you want to update the additional user fields (using PUT method) or passing them to the back-end in the register process (using POST method) ?
If you want to update them, you have to do the following:
Adding fields to you user model (already done)
Make the /update endpoint available in the users-permissions configuration.
See screenshot:
Now you are able to use the PUT method on the endpoint users/:id, which you could do e.g. like this:

Facebook Login is returning 'Undefined' Fields in user profile and it doesn't return email. MEANJs + Passport-facebook

I am using Meanjs.org boilerplate and Facebook Signup returns me to the Signup page.
Following are the steps that I have taken so far.
1) Setting up the Facebook App Site URL
http://localhost:3000/
and the callback URI of OAuth
http://localhost:3000/auth/facebook/callback
2) Placing the APP_ID and APP_Secret in as Client_ID and Client_Secret
facebook: {
clientID: process.env.FACEBOOK_ID || '*****',
clientSecret: process.env.FACEBOOK_SECRET || '*****',
callbackURL: 'http://localhost:3000/auth/facebook/callback',
profileFields: ['id','emails', 'first_name', 'last_name', 'displayName', 'link', 'about_me', 'photos' ]
},
3) Code is as follows
--Routes
// Setting the facebook oauth routes
app.route('/auth/facebook').get(passport.authenticate('facebook', {
scope: ['email']
}));
app.route('/auth/facebook/callback').get(users.oauthCallback('facebook'));
-- The oauthCallback function,
exports.oauthCallback = function(strategy) {
return function(req, res, next) {
passport.authenticate(strategy, function(err, user, redirectURL) {
if (err || !user) {
console.log('1' + err);
//console.log(user);
return res.redirect('/#!/signin');
}
req.login(user, function(err) {
if (err) {
console.log('2' + err);
return res.redirect('/#!/signin');
}
return res.redirect(redirectURL || '/');
});
})(req, res, next);
};
};
-- Passport-Facebook Strategy
module.exports = function() {
// Use facebook strategy
passport.use(new FacebookStrategy({
clientID: config.facebook.clientID,
clientSecret: config.facebook.clientSecret,
callbackURL: config.facebook.callbackURL,
passReqToCallback: true
},
function(req, accessToken, refreshToken, profile, done) {
console.log('facebook Strategy Started');
// Set the provider data and include tokens
var providerData = profile._json;
providerData.accessToken = accessToken;
providerData.refreshToken = refreshToken;
// console.log(JSON.stringify(profile));
console.log(profile);
// console.log(JSON.stringify(profile.name.givenName));
// Create the user OAuth profile
var providerUserProfile = {
firstName: profile.name.givenName,
lastName: profile.name.familyName,
displayName: profile.displayName,
email: profile.emails[0].value,
username: profile.username,
provider: 'facebook',
providerIdentifierField: 'id',
providerData: providerData
};
//console.log('provider' + providerUserProfile);
// Save the user OAuth profile
users.saveOAuthUserProfile(req, providerUserProfile, done);
}
));
};
4) Debugging
Logging err under oauthCallback function returns the following,
1TypeError: Cannot read property '0' of undefined
What Facebook returns as profile in Passport-Facebook module is as follows,
{ id: 'Id_of_the_person',
username: undefined,
displayName: 'Full_name_of_person',
name:
{ familyName: undefined,
givenName: undefined,
middleName: undefined },
gender: undefined,
profileUrl: undefined,
provider: 'facebook',
_raw: '{"name":"Full_name_of_person","id":"Id_of_the_person"}',
_json:
{ name: 'Id_of_the_person',
id: 'Id_of_the_person',
accessToken: 'access_token_value',
refreshToken: undefined } }
Can anyone be kind to guide me about getting the correct user profile from Facebook including user email?
Thank you so much.
I have my profile fields set to the following
profileFields: ['email','id', 'first_name', 'gender', 'last_name', 'picture']
Even though you set email it might return emails if the user has multiple emails. So you need to check if email was returned profile.email or profile.emails[0].value. You must also check if it is undefined, because there is people that register with facebook that never verify their email account and there is people that sign up with a phone number, in both those cases their emails will always be undefined.
you want to check that any required fields have values.
var email = profile.email || profile.emails[0].value;
if (! email){
console.log('this user has no email in his FB');
var err = {message:'this user is missing an email'};
return done(err);
}
now i can do this if they have an email
newUser.facebook.email = email;
if they don't have an email you can set a session for profile and send them to a page that asks them to enter an email.
It sounds like a pain, but you can never trust information from a third party api to have values.
Most of the passport examples I've seen online are wrong. They all assume an email is present.
First, profileFields field does not obey to Portable Contacts convention - and you can find the convention for passportjs here.
Second, in your example, after removing removed 'about_me', the Facebook signup returns no error. Before removing 'about_me', I had a different error: Tried accessing nonexisting field (about_me) on node type (User)
If the error persist, see this serie of 5 tutorials which helps me when I was doing the sign up page to authenticate with social networks accounts.

Meteor Facebook login (Meteor.loginWithFacebook) issue extracting public profile, email and user_friends

Trying to get Meteor Facebook login to work. It functions fully in that it uses Facebook API and requests the correct permissions from the users account and then logs in successfully.
The problem is it doesn't save the permission requested information even though its been approved and only the basic name and ID are available in Meteor.user().services.facebook. Is this code not working because it's not saving the users details on login? I can't find a resource that details how to save or extract the other data.
Simply trying to console log the data to see that it's been extracted out of the Facebook user account on log in.
Within Meteor.isClient code:
Template.login.events({
'click #facebook-login': function(event) {
Meteor.loginWithFacebook({ requestPermissions: ['email', 'public_profile', 'user_friends', 'user_likes']}, function(err){
if (err) {
throw new Meteor.Error("Facebook login failed");
}
console.log(Meteor.user().services.facebook.name);
console.log(Meteor.user().services.facebook.id);
console.log(Meteor.user().services.facebook.email);
console.log(Meteor.user().services.facebook.gender);
});
},
'click #logout': function(event) {
Meteor.logout(function(err){
if (err) {
throw new Meteor.Error("Logout failed");
}
});
}
The config code:
ServiceConfiguration.configurations.remove({
service: 'facebook'
});
ServiceConfiguration.configurations.insert({
service: 'facebook',
appId: 'correctAppID',
secret: 'CorrectSecret'
});
For Facebook v2.4 API after you have requested for certain permissions you can then access them by making a graph API call and requesting them with a valid auth token. The code is as follows:
if (user.hasOwnProperty('services') && user.services.hasOwnProperty('facebook') ) {
var result = Meteor.http.get('https://graph.facebook.com/v2.4/' + user.services.facebook.id + '?access_token=' + user.services.facebook.accessToken + '&fields=first_name, last_name, birthday, email, gender, location, link, friends');
console.log(result.data.first_name);
console.log(result.data.last_name);
console.log(result.data.birthday);
console.log(result.data.email);
console.log(result.data.gender);
console.log(result.data.location);
console.log(result.data.link);
console.log(result.data.friends);
}

Passport and SailsJS, how to get isAuthenticated() test to pass

My code keeps failing here when the user tries to login:
isAuthenticated: function (req, res) {
if (req.isAuthenticated()) { return res.json(req.user); }
else { return res.send(401); }
},
It FAILS and I get GET http://localhost:1337/user/authenticated 401 (Unauthorized) in the console, even though the user has entered in a correct email and password.
Where in the code makes that test pass?
I have the related StackOverflow question with more info HERE.
The problem was that my frontend application has a different origin than my backend application, so the AJAX requests will not include the session cookie and req.isAuthenticated() will never return true.
Use the withCredentials options to force it.
$http({ withCredentials: true, ... })