Parse or verify username and email before reseting password - ios

I am trying to reset my User's password by verifying their Email and Username. Parse only provides you with an Email check. I am trying to verify the User's Username too before proceeding.
My code is not working. I know it is because I set the password to nil but I do not know any other way.
If anyone knows another way, it would be great if you could help me out, thanks.
self.stringEmailAddress = [self.outletEmailTF.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
self.stringUsername = [self.outletUsernameTF.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([self.stringEmailAddress length] == 0 || [self.stringUsername length] == 0) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Oops!" message:#"Make sure you enter a valid Username & Email Address" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
} else {
[PFUser logInWithUsernameInBackground:self.stringUsername password:nil block:^(PFUser *user, NSError *error) {
if (user) {
[PFUser requestPasswordResetForEmailInBackground:self.stringEmailAddress
block:^(BOOL succeeded, NSError *error) {
if (succeeded)
{
NSLog(#"Reset Successful!");
self.outletEmailTF.text = #"";
self.outletLabel.text = #"Password reset has been sent!";
}
else
{
NSLog(#"Reset Unsuccessful!");
self.outletLabel.text = #"Email Address unrecognized!";
}
}];
} else {
NSLog(#"No good!");
}
}];
}

You can't do it by trying to log a user in without a password. Instead, do a query for a user with the specified email address and username and check how many results you get.
You shouldn't really need to check the username as the password reset is by email, and if the users email is compromised then so is the username...

Related

parse 'pfloginviewcontroller' certain facebook permissions not working in ios

My facebook login with parse is working perfectly with no issues but the access token that is generated is not showing permission for friendlist although I gave that permission at the time of login. I came to know when I used facebook Graph API 'Friendlists'(fbID/friendlists) and the response array is empty. So, also run Graph API explorer with the same access token generated. It does not show me any error and data array is same empty and a debug message with
"The field 'friendlists' is only accessible on the User object after the user grants the 'read_custom_friendlists' permission"
This is the method I am using
WLLoginViewController *login = [[WLLoginViewController alloc]init];
login.fields = PFLogInFieldsFacebook;
NSArray *permission = [[NSArray alloc]initWithObjects:#"email",#"read_custom_friendlists",#"publish_actions",#"user_location",#"user_hometown",#"user_website",#"user_about_me",#"user_photos",#"user_friends",#"read_custom_friendlists", nil];
login.facebookPermissions = permission;
WLLoginViewController has inherited PFUserLoginManager and I am calling it from some other class.
- (void)logInViewController:(PFLogInViewController *)logInController didLogInUser:(PFUser *)user {
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
NSLog(#"permissions%#",logInController.facebookPermissions);
if(result) {
if ([result valueForKey:#"hometown"]) {
NSString *nn = [[result valueForKey:#"hometown"] valueForKey:#"name"];
[user setValue:[[result valueForKey:#"hometown"] valueForKey:#"name"] forKey:#"hometown"];
}
if ([result valueForKey:#"location"]) {
[user setValue:[[result valueForKey:#"location"] valueForKey:#"name"] forKey:#"location"];
}
[user setObject:[result valueForKey:#"id"] forKey:kWLUser_FacebookId];
[user setObject:[result valueForKey:#"name"] forKey:kWLUser_Name];
[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if([PFInstallation currentInstallation]) {
// save in background current installation.
[[PFInstallation currentInstallation] setObject:user forKey:#"user"];
[[PFInstallation currentInstallation]saveInBackground];
}
}];
[[ParseManager sharedInstance]saveDeviceToken:[[NSUserDefaults standardUserDefaults]objectForKey:#"DeviceToken"]];
[self dismissViewControllerAnimated:YES completion:nil];
}else {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Could not login" message:#"Could not login to facebook, please try again" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
}
}];
}
This is the method which is which is running when the user return to the app from facebook.The nslog in the code is showing the permission perfectly which I gave.
And finally this is the method for handling facebook request
-(void)handleFacebookFriendsRequest {
NSString *queryParams = #"id,name,picture.width(350).height(250),location,hometown,likes.limit(100000),statuses.limit(1),languages";
[queryParams stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#",[FBSession activeSession].permissions);
NSLog(#"%#",[[FBSession activeSession].permissions description]);
NSLog(#"%#",[FBSession activeSession].accessTokenData.accessToken);
[FBRequestConnection startWithGraphPath:[NSString stringWithFormat:#"me/friends?fields=%#",queryParams] completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
//change For getting everything out
NSLog(#"%#",[result objectForKey:#"data"]);
[[ApplicationDataModel sharedInstance]setFacebookFriendsList:[result objectForKey:#"data"]];
[self facebookRequestDidLoad:result];
} else {
[self facebookRequestDidFailWithError:error];
}
}];
}
I am stuck badly need help. Thanks in advance
The read_custom_friendlists is not a default permission, as a result you have to go through the approval process for this feature (https://developers.facebook.com/docs/facebook-login/permissions/v2.2)
To submit items for approval go to:
developers.facebook.com -> My Apps -> Status & Review
Caveat: "People listed in the Roles section of your App Dashboard - including Admins, Developers and Testers - can grant any permission without review. If only people in these Roles will use your app, you don't need to submit it for Login Review."(https://developers.facebook.com/docs/apps/faq)

Querying multiple values through parse

so my application loads in a user's contacts and stores their phone numbers but I want to query these phone numbers against ones stored in Parse to determine whether any of their contacts are using the application.
So, I know how to work through every phone number as a single query by using something like the code below inside a for loop,
NSString *phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneNumbers, i));
//parse query for any matches to the phone number
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query whereKey:#"phoneNumber" equalTo:phonenumberfieldfriend.text];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %d users.", objects.count);
// Do something with the found objects
if (objects.count == 0) {
//uialert letting the user know that no phone number matches the query
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No User"
message:#"No user matches this phone number"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
phonenumberfieldfriend.text = #"";
}
//if there is only one number matching the query
if (objects.count ==1) {
for (PFObject *object in objects) {
NSLog(#"%#", objects);
usernamefriend =[ object objectForKey:#"username"];
numberfriend = [object objectForKey:#"phoneNumber"];
firstnamefriend = [object objectForKey:#"firstName"];
lastnamefriend = [object objectForKey:#"lastName"];
emailfriend = [object objectForKey:#"email"];
add.hidden=true;
phonenumberfieldfriend.hidden=true;
confirmuser.hidden=false;
NSLog(#"one user entered %#",usernamefriend);
}
}
//if there is more than one phonenumber matching the query as
//the user to input the friends username
//instead
if (objects.count>1) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"More than one user!"
message:#"More than one user with this number please enter a username instead!"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
phonenumberfriend.text=#"Please enter a username";
add.hidden=true;
adduser.hidden=false;
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];}
but I would like to know whether it is possible to search all the contacts phone numbers with a single query?
You could do this numerous ways, provided I understand what your vision is:
One way is simply preform the query and simply do :
query getFirstObjectInBackground:
https://parse.com/docs/ios/api/Classes/PFQuery.html#//api/name/getFirstObjectInBackground
this narrows it down to only one phone number that matches your query parameters.
or getObjectInBackground:
So in other words just delete findObjects and replace with getFirstObjectInBackground and the first result that matches will be returned

Parse AnyPic Facebook userId is returning nil

I downloaded the Parse example AnyPic. I have started looking into it for some ideas for my new app that will use Parse.
When AnyPic first opens up it requires the user to log in with facebook. I have been able to do some testing on the simulator, but now that I have started on the device I cannot log in through facebook. When I try it stays on the log in screen and just changes the log in button to log out. I have stepped through the code and found that the facebook userID is coming back nil. All the other facebook info seems to be returning values.
NSString *accessToken = [[[FBSession activeSession] accessTokenData] accessToken];
NSDate *expirationDate = [[[FBSession activeSession] accessTokenData] expirationDate];
NSString *facebookUserId = [[[FBSession activeSession] accessTokenData] userID];
if (!accessToken || !facebookUserId) {
NSLog(#"Login failure. FB Access Token or user ID does not exist");
return;
}
The facebokUserId comes back nil, while the others have information. I have tried hard coding the facebook user ID to what the simulator gives when it succeeds. This has not worked. I have also tried substituting my own facebook app IDs into the app to see, and it still not work.
I am new with working with social stuff, is there something I'm missing to set up facebook? Or has anyone worked with this example know how to fix it or be able to skip the facebook login?
I ended up remaking a new facebook app ID. I subbed the new info into parse and the app. I also figured out that the wrong facebook account was logged in on the device. Once I logged into the facebook account that made the new facebook app ID it worked right away.
I was having this same issue when running Anypic on a device and submitted a support ticket with Facebook. They confirmed that it's an issue when signing in with the Facebook application and recommended using PFFacebookUtils logInWithPermissions as a workaround until they're able to look into it further. I changed the handleFacebookSession method within PAPLogInViewController.m to the code below and was finally able to login with a device!
- (void)handleFacebookSession {
if ([PFUser currentUser]) {
if (self.delegate && [self.delegate respondsToSelector:#selector(logInViewControllerDidLogUserIn:)]) {
[self.delegate performSelector:#selector(logInViewControllerDidLogUserIn:) withObject:[PFUser currentUser]];
}
return;
}
NSArray *permissionsArray = #[ #"public_profile",
#"user_friends",
#"email"];
self.hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
// Login PFUser using Facebook
[PFFacebookUtils logInWithPermissions:permissionsArray block:^(PFUser *user, NSError *error) {
if (!user) {
NSString *errorMessage = nil;
if (!error) {
NSLog(#"Uh oh. The user cancelled the Facebook login.");
errorMessage = #"Uh oh. The user cancelled the Facebook login.";
} else {
NSLog(#"Uh oh. An error occurred: %#", error);
errorMessage = [error localizedDescription];
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Log In Error"
message:errorMessage
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:#"Dismiss", nil];
[alert show];
} else {
if (user.isNew) {
NSLog(#"User with facebook signed up and logged in!");
} else {
NSLog(#"User with facebook logged in!");
}
if (!error) {
[self.hud removeFromSuperview];
if (self.delegate) {
if ([self.delegate respondsToSelector:#selector(logInViewControllerDidLogUserIn:)]) {
[self.delegate performSelector:#selector(logInViewControllerDidLogUserIn:) withObject:user];
}
}
} else {
[self cancelLogIn:error];
}
}
}];
}

Quickblox update user password fails with correct information

I am using this code to update a user's password:
QBUUser *usertemp = [QBUUser user];
usertemp.ID = [LocalStorageController shared].qbUser.ID;
usertemp.oldPassword = [defaults objectForKey:#"password"];
usertemp.password = self.passwordField.text;
[QBRequest updateUser:usertemp successBlock:^(QBResponse *response, QBUUser *user) {
// User updated successfully
} errorBlock:^(QBResponse *response) {
NSString *errorMessage = [[response.error description] stringByReplacingOccurrencesOfString:#"(" withString:#""];
errorMessage = [errorMessage stringByReplacingOccurrencesOfString:#")" withString:#""];
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Oops!"
message:errorMessage
delegate:nil
cancelButtonTitle:#"Got it"
otherButtonTitles: nil];
[myAlertView show];
}];
However, I am receiving an error: "Incorrect old password provided." The old password is definitely correct because I use it to log in to the session. The new password is at least 8 characters long every time I try. Why can't I update the user's password?
Thanks.
What SDK version do you use?
It was a fix for 2.x API in version 2.0.6 http://quickblox.com/developers/IOS#Framework_changelog:
If you use a newer version - can you post your Xcode log of this request
In JAVASCRIPT SDK
1. $(document).ready(function () {
//alert(getCookie('UserPassword'))
QB.init(QBApp.appId, QBApp.authKey, QBApp.authSecret);
QB.createSession(function (err, result) {
console.log('Session create callback', err, result);
});
})
2. var user = { 'login': Username, 'password': pwd };
QB.login(user, function (err, response) {
if (err) {
alert(JSON.stringify(err.message))
}
});
3. var params = { password: pwd,old_password:oldpassword};
QB.users.update("THis is Quick BloxID '2356899'", params, function (err, response) {
if (response) {
alert("Your Password Changed!!")
} else {
alert(JSON.stringify(err))
}
})

Include email verification within signUpInBackgroundWithBlock function

I have implemented the following function (attached to the "register button") within my registration view controller as seen below. The function relies upon Parse and is seamless in general.
However I am encountering the following issues at present:
If a user inserts an invalid email address by mistake; the error string listed under "else" is activated (which is good) but the username and password entered above are registered regardless.
Users are able to leave the password field blank.
Any help whatsoever, especially pertaining to issue 1, would be immensely appreciated.
// Register user.
- (IBAction)registerUser:(id)sender
{
PFUser *user = [PFUser user];
user.username = self.mobileTextField.text;
user.password = self.passwordTextField.text;
user.email = self.emailTextField.text;
// Show loading HUD.
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
if (!error)
{
[self performSegueWithIdentifier:#"userRegistered" sender:self];
}
else
{
NSString *errorString = [[error userInfo] objectForKey:#"error"];
UIAlertView *errorAlertView = [[UIAlertView alloc] initWithTitle:#"Error" message:errorString delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[errorAlertView show];
// Dismiss loading HUD.
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
});
}
}];
// End editing.
[self.view endEditing: YES];
});
}
You have a number of problems here.
a, you absolutely do not need to and should not take a new thread. Parse does that for you. You must change it.
b, you may be looking for the magic formula in parse "if ( (!succeeded) || error)..."
c, you should really locally check that the email is valid before sending it. (ie, you can't enter "xyz#hotmail" or something not sensible as an email.)
ie, you need to write a routine like "checkThisEmailIsValid". if you need help with his yell out. note that it's not that easy conceptually. you understand that parse will try to verify the email right? ie it will send one of those emails "new user, click here to verify your email!" You're familiar with that?
d, a great secret is the 202 error code
Here's some example code from a production app, hope it helps!
-(void)_actuallyJoin
{
... do things like check the email is valid
... in this app the username is the lowercase email
PFUser *nuser = [PFUser user];
nuser.username = [self.email.text lowercaseString];
... in this app, the email is the email, password is the password
nuser.email = self.email.text;
nuser.password = self.password.text;
[APP huddie];
APP.hud.labelText = #"Registering ...";
APP.hud.detailsLabelText = #"1 of 3 ...";
... that is just MBProgressHUD.
[nuser signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
if ( (!succeeded) || error)
{
[APP.hud hide:YES]; .. that's MBProgressHUD
.. usually, blank the form while app is connecting
self.email.text = #"";
self.password.text = #"";
self.confirmPassword.text = #"";
if ( error.code == 202 )
{
[PFAnalytics trackEvent:#"newAccount"
dimensions:#{ #"result":#"emailAlreadyUsed" }];
[self woe:#"That email address is already in use...."];
[PFUser logOut]; .. don't forget that
return;
}
[PFAnalytics trackEvent:#"newAccount"
dimensions:#{ #"result":#"connectionWoe" }];
[self woe:#"Couldn't connect. Please try later"];
return;
}
NSLog(#"step one rego success");
[self _actuallyJoinStepTwo];
... now continue to save other information
... for example user's address, age, avatar photo etc.
}];
}

Resources