Quicklox token required - ios

I am using quickblox in my app. I did my user signup, user login and chat. Everything works fine when i log in for the first time. if I press home and enter the app again, I come to my viewController page. The user is logged out automatically. And when I try to log in it says, token is required.
I have put the session authentication in appdelegate
[QBAuth createSessionWithDelegate:self]
-(void)viewDidAppear:(BOOL)animated
{
if([LocalStorageService shared].currentUser == nil)// check if user is logged in
{
NSCharacterSet *nonalphanumericSet = [[ NSCharacterSet alphanumericCharacterSet] invertedSet];
[QBUsers logInWithUserLogin:[[[PFUser currentUser].username componentsSeparatedByCharactersInSet:nonalphanumericSet ] componentsJoinedByString:#"1"] password:#"password" delegate:self];
}
}
- (void)completedWithResult:(Result *)result
{
if(result.success && [result isKindOfClass:QBUUserLogInResult.class])
{
// Success, do something
QBUUserLogInResult *userResult = (QBUUserLogInResult *)result;
NSLog(#"Logged In user=%#", userResult.user);
userResult.user.password =#"password";
// Save current user
//
[[LocalStorageService shared] setCurrentUser: userResult.user];
// Login to QuickBlox Chat
//
[[ChatService instance] loginWithUser:[LocalStorageService shared].currentUser completionBlock:^{
NSLog(#"chat logged successfully");
}];
// Errors
}
else
{
NSString *errorMessage = [[result.errors description] stringByReplacingOccurrencesOfString:#"(" withString:#""];
errorMessage = [errorMessage stringByReplacingOccurrencesOfString:#")" withString:#""];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Errors"
message:errorMessage
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}
}

token is required means that you are trying to perform request, but you didn't create a session still
You can reproduce this issue just perform 2 requests one by one:
[QBAuth createSessionWithDelegate:self];
[QBUsers logInWithUserLogin:... delegate:self];
After this sequence you will got 'token is required'
To get rid of this you should wait when create session requests will be finished and perform next request:
[QBAuth createSessionWithDelegate:self];
...
- (void)completedWithResult:(Result *)result{
if(result.success && [result isKindOfClass:QBAAuthSessionCreationResult.class]){
// you got token here - perform any other requests after this
[QBUsers logInWithUserLogin:... delegate:self];
}
}
It's not a solution for your issue, but it's an explanation hy it happenes and how to resolve it

It seems socket get closed. Try to log out from QBChat instance when app goes to background, and log in to QBChat when app will enter foreground. And if you don't send presence messages to QBChat, socket will be closed in 90 seconds

Related

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.
}];
}

iOS Facebook integration with signin does not work when Setting is signed in

Ok, this is probably something very common, but I cannot find the solution anywhere. When using the Facebook SDK to handle logging in as a SSO, it works great in the iOS simulator. However, on the actual device, it fails in one very specific instance: If the iPhone/iPad is signed into Facebook via the Settings in iOS, it comes back with "Session Closed: User cancelled login" (this message is generated when the error received is of the FBErrorCategoryUserCancelled type). I have tried every instance of this:
Facebook iOS app installed and Signed In with Settings logged in [FAIL]
Facebook iOS app installed and not signed In with Settings logged in [FAIL]
Facebook iOS app not installed and Settings logged in [FAIL]
Facebook OS app Installed and signed In with Settings not logged in [SUCCESS]
Facebook iOS app Installed but not logged in and Settings not logged in [SUCCESS]
Facebook iOS app not installed and Settings no logged in [SUCCESS]
This all has to do with the Settings being logged in to Facebook. Now I know others have their apps able to have Facebook integration with Settings being signed in, so what am I missing? Here is my sign in code:
- (IBAction)loginWithFacebook:(id)sender {
if (FBSession.activeSession.state == FBSessionStateOpen || FBSession.activeSession.state == FBSessionStateOpenTokenExtended) {
[FBSession.activeSession closeAndClearTokenInformation];
}
[FBSession openActiveSessionWithReadPermissions:#[#"basic_info",#"public_profile",#"email"]
allowLoginUI:YES
completionHandler: ^(FBSession *session, FBSessionState state, NSError *error) {
// Retrieve the app delegate
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
// Call the app delegate's sessionStateChanged:state:error method to handle session state changes
[appDelegate sessionStateChanged:session state:state error:error];
}];
}
Here is my code that handles all of this from the AppDelegate:
- (void)sessionStateChanged:(FBSession *)session state:(FBSessionState) state error:(NSError *)error {
// If the session was opened successfully
if (!error && state == FBSessionStateOpen){
NSLog(#"Session opened");
[[FBRequest requestForMe] startWithCompletionHandler:
^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *error) {
if (!error) {
NSString *firstName = user.first_name;
NSString *lastName = user.last_name;
NSString *facebookId = user.id;
NSString *email = [user objectForKey:#"email"];
[Data facebookLogin:facebookId email:email firstName:firstName lastName:lastName];
}
}];
return;
}
if (state == FBSessionStateClosed || state == FBSessionStateClosedLoginFailed){
// If the session is closed
NSLog(#"Session closed");
}
// Handle errors
if (error){
NSLog(#"Error");
NSString *alertText;
NSString *alertTitle;
// If the error requires people using an app to make an action outside of the app in order to recover
if ([FBErrorUtility shouldNotifyUserForError:error] == YES){
alertTitle = #"Something went wrong";
alertText = [FBErrorUtility userMessageForError:error];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Notice" message: alertText delegate: nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
} else {
// If the user cancelled login, do nothing
if ([FBErrorUtility errorCategoryForError:error] == FBErrorCategoryUserCancelled) {
// This is the part that gets called, right here!
NSLog(#"User cancelled login");
// Handle session closures that happen outside of the app
} else if ([FBErrorUtility errorCategoryForError:error] == FBErrorCategoryAuthenticationReopenSession){
alertTitle = #"Session Error";
alertText = #"Your current session is no longer valid. Please log in again.";
NSLog(#"%#",alertText);
// Here we will handle all other errors with a generic error message.
// We recommend you check our Handling Errors guide for more information
// https://developers.facebook.com/docs/ios/errors/
} else {
//Get more error information from the error
NSDictionary *errorInformation = [[[error.userInfo objectForKey:#"com.facebook.sdk:ParsedJSONResponseKey"] objectForKey:#"body"] objectForKey:#"error"];
// Show the user an error message
alertTitle = #"Something went wrong";
alertText = [NSString stringWithFormat:#"Please retry. \n\n If the problem persists contact us and mention this error code: %#", [errorInformation objectForKey:#"message"]];
NSLog(#"%#",alertText);
}
}
// Clear this token
[FBSession.activeSession closeAndClearTokenInformation];
// Show the user the logged-out UI
}
}
I understand this is a long post, but I figured it would be more beneficial to have all of the information available when talking about this.
I had a similar problem. I think what is happening is that the native iOS login machinery chokes on the #"public_profile" permission (or more likely the server response to it that it is getting from Facebook). To verify, try to remove this permission from your permissions array.
This is an annoying problem, since the Facebook docs state that this permission is now obligatory.

Authenticate Anonymously using XMPP framework in iOS

I want to connect to openfire server anonymously using xmpp framework in iOS. I can connect to open fire by providing the JID and PW. However when I tried to connect anonymously it says "The server doesn't support anonymous authentication".
I'm using a button in xib file. When its clicked below code executes:
- (IBAction)login:(id)sender {
[[self appDelegate]connect];
NSError *authenticationError = nil;
[self.xmppStream authenticateAnonymously:&authenticationError];
}
and below is the code for connect method:
- (BOOL)connect {
[self setupStream];
xmppStream.hostName = #"abc.xyz.com";
//xmppStream.hostName = #"Virtuals-MacBook-Pro.local ";
NSString *jabberID = [[NSUserDefaults standardUserDefaults] stringForKey:#"userID"];
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:#"userPassword"];
if (![xmppStream isDisconnected]) {
return YES;
}
if (jabberID == nil || myPassword == nil) {
return NO;
}
[xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
password = myPassword;
NSError *error = nil;
if (![xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
//[alertView release];
return NO;
}
return YES;
}
Steps for anonymous authentication:
1- First of all connect the xmpp-stream, then authenticate anonymously.
[[self xmppStream] authenticateAnonymously:&error];
then you will be authenticated anonymously. but a very important thing. before authenticating, get the username and password of a registered user and connect to the xmpp-stream
The accepted answer is almost right but is mixing things (connection and authentication)
What you are facing is probably a server side configuration problem, if your server does not allow you to log in anonymously you cannot, period.
Anyway you can still try to connect anonymously and handle the fact that you are not allow, for that you need to:
1) Set your JabberID to anonymous#domain (were domain is your server domain)
[self.xmppStream setMyJID:[XMPPJID jidWithString:#"anonymous#domain"]];
2) With that in place you can connect to the server (you do not need a valid user as the accepted answer pointed out)
[self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]
3) Once you get response from the sever your XMPP delegate method didConnect will be called, in there you check if the server configuration supports anonymous authentication and if so try to authenticate anonymously
- (void)xmppStreamDidConnect:(XMPPStream*)sender
{
self.isXmppConnected = YES;
if ([self.xmppStream supportsAnonymousAuthentication]) {
NSError* error = nil;
//the server does support anonymous auth
[self.xmppStream authenticateAnonymously:&error];
}
else {
NSLog(#"The server does not support anonymous authentication");
}
}
4) You handle however you want the situations were the server does not support anonymous auth (maybe trie with a well know user or display a warning to the user) or you get an error authenticating (network issues)

Unable to login on loading FBLoginView

I am using facebook SDK for the first time in iOS. I have tried to follow Facebook Documentations for logging in the user: Login Tutorial and Getting Started.
I am adding FBLoginView to new view controller on a button press to prompt user for login. Issue I am facing is that after FBLoginView is created, I am immediately taken to two FBLoginViewDelegate Methods: loginViewShowingLoggedOutUser: and loginView:handleError:
loginView:handleError: states error as FBErrorCategoryUserCancelled while I never cancelled any request! Modal popup for login appears for 2 seconds, then dismisses automatically with cancel status.
I am really unable to understand that why it is happening. I am testing it on simulator. I have all 3 keys required in .plist file for Facebook SDK integration. Why request is cancelled automatically? Please help me with this issue.. Thanks.
Code:
#import "FBLoginViewController.h"
#interface FBLoginViewController ()
#end
#implementation FBLoginViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
FBLoginView *loginview = [[FBLoginView alloc] initWithReadPermissions:[NSArray arrayWithObjects:#"basic_info",#"user_photos",#"friend_photos", nil]];
loginview.frame = CGRectOffset(loginview.frame, (self.view.center.x - (loginview.frame.size.width / 2)), 5);
loginview.delegate = self;
[self.view addSubview:loginview];
}
#pragma mark - FBLoginDelegate
-(void) loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user
{
NSLog(#"user info: %#",user);
}
-(void) loginViewShowingLoggedInUser:(FBLoginView *)loginView
{
NSLog(#"User logged in");
}
-(void) loginViewShowingLoggedOutUser:(FBLoginView *)loginView
{
NSLog(#"User logged out");//Logs on console
}
-(void) loginView:(FBLoginView *)loginView handleError:(NSError *)error
{
NSString *alertMessage, *alertTitle;
// If the user should perform an action outside of you app to recover,
// the SDK will provide a message for the user, you just need to surface it.
// This conveniently handles cases like Facebook password change or unverified Facebook accounts.
if ([FBErrorUtility shouldNotifyUserForError:error]) {
alertTitle = #"Facebook error";
alertMessage = [FBErrorUtility userMessageForError:error];
// This code will handle session closures that happen outside of the app
// You can take a look at our error handling guide to know more about it
// https://developers.facebook.com/docs/ios/errors
} else if ([FBErrorUtility errorCategoryForError:error] == FBErrorCategoryAuthenticationReopenSession) {
alertTitle = #"Session Error";
alertMessage = #"Your current session is no longer valid. Please log in again.";
// If the user has cancelled a login, we will do nothing.
// You can also choose to show the user a message if cancelling login will result in
// the user not being able to complete a task they had initiated in your app
// (like accessing FB-stored information or posting to Facebook)
} else if ([FBErrorUtility errorCategoryForError:error] == FBErrorCategoryUserCancelled) {
NSLog(#"user cancelled login");
// For simplicity, this sample handles other errors with a generic message
// You can checkout our error handling guide for more detailed information
// https://developers.facebook.com/docs/ios/errors
} else {
alertTitle = #"Something went wrong";
alertMessage = #"Please try again later.";
NSLog(#"Unexpected error:%#", error);
}
if (alertMessage) {
[[[UIAlertView alloc] initWithTitle:alertTitle
message:alertMessage
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
}
}
#end
Strange, but it worked for me. In viewDidLoad, I changed initialization of FBLoginView from:
FBLoginView *loginview = [[FBLoginView alloc] initWithReadPermissions:[NSArray arrayWithObjects:#"basic_info",#"user_photos",#"friend_photos", nil]];
to:
FBLoginView *loginview = [[FBLoginView alloc] init];
Initializing without permissions is bringing up the modal popup for login now.
The problem could have been that you had a nil as the last item in the list.

how to check bool value before going for fast app switch using FBLoginView

Here is a simple scenario, I am using FBLoginView which show a login button and on click application go for fast switching but i want to check a bool value of terms and conditions before app go for fast switch. There is not way i am able to find to achieve this scenario.
- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView {
// Upon login, transition to the main UI by pushing it onto the navigation stack.
LGAppDelegate *appDelegate = (LGAppDelegate *)[UIApplication sharedApplication].delegate;
[self.navigationController pushViewController:((UIViewController *)appDelegate.mainViewController) animated:YES];
}
- (void)acceptTermsAndConditions {
if (!_checkboxButton.checked) {
NSString *alertMessage, *alertTitle;
alertTitle = #"Terms to Use";
alertMessage = #"Please accept the terms & condition to use this application.";
UIAlertView* av = [[UIAlertView alloc] initWithTitle:alertTitle
message:alertMessage
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[av show];
[av release];
}
}
- (void)loginView:(FBLoginView *)loginView
handleError:(NSError *)error{
NSString *alertMessage, *alertTitle;
// Facebook SDK * error handling *
// Error handling is an important part of providing a good user experience.
// Since this sample uses the FBLoginView, this delegate will respond to
// login failures, or other failures that have closed the session (such
// as a token becoming invalid). Please see the [- postOpenGraphAction:]
// and [- requestPermissionAndPost] on `SCViewController` for further
// error handling on other operations.
if (error.fberrorShouldNotifyUser) {
// If the SDK has a message for the user, surface it. This conveniently
// handles cases like password change or iOS6 app slider state.
alertTitle = #"Something Went Wrong";
alertMessage = error.fberrorUserMessage;
} else if (error.fberrorCategory == FBErrorCategoryAuthenticationReopenSession) {
// It is important to handle session closures as mentioned. You can inspect
// the error for more context but this sample generically notifies the user.
alertTitle = #"Session Error";
alertMessage = #"Your current session is no longer valid. Please log in again.";
} else if (error.fberrorCategory == FBErrorCategoryUserCancelled) {
// The user has cancelled a login. You can inspect the error
// for more context. For this sample, we will simply ignore it.
NSLog(#"user cancelled login");
} else {
// For simplicity, this sample treats other errors blindly, but you should
// refer to https://developers.facebook.com/docs/technical-guides/iossdk/errors/ for more information.
alertTitle = #"Unknown Error";
alertMessage = #"Error. Please try again later.";
NSLog(#"Unexpected error:%#", error);
}
if (alertMessage) {
[[[UIAlertView alloc] initWithTitle:alertTitle
message:alertMessage
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
}
}
- (void)loginViewShowingLoggedOutUser:(FBLoginView *)loginView {
// Facebook SDK * login flow *
// It is important to always handle session closure because it can happen
// externally; for example, if the current session's access token becomes
// invalid. For this sample, we simply pop back to the landing page.
LGAppDelegate *appDelegate = (LGAppDelegate *)[UIApplication sharedApplication].delegate;
if (appDelegate.isNavigating) {
// The delay is for the edge case where a session is immediately closed after
// logging in and our navigation controller is still animating a push.
[self performSelector:#selector(logOut) withObject:nil afterDelay:.5];
} else {
[self logOut];
}
}
- (void)logOut {
[self.navigationController popToRootViewControllerAnimated:YES];
}

Resources