-[SFOAuthCoordinator setAuthInfo:]: message sent to deallocated instance crash - ios

I'm receiving this crash in my iOS app using Salesforce after user taps on 'Deny' button in app permission screen after login.
I have referred sample app given by SF for & it’s displaying an error alert for same scenario.
Don’t know what I’m missing
Error:
Error Domain=com.salesforce.OAuth.ErrorDomain Code=669 "end-user denied authorization" UserInfo=0x1d8ab880 {NSLocalizedDescription=end-user denied authorization, error=access_denied}
-[SFOAuthCoordinator setAuthInfo:]: message sent to deallocated instance 0x189b1370
Below is the code I’m using:
Appdelegate:
init method
[SFLogger setLogLevel:SFLogLevelDebug];
[SalesforceSDKManager sharedManager].connectedAppId = RemoteAccessConsumerKey;
[SalesforceSDKManager sharedManager].connectedAppCallbackUri = OAuthRedirectURI;
[SalesforceSDKManager sharedManager].authScopes = #[ #"web", #"api" ];
__weak AppDelegate *weakSelf = self;
[SalesforceSDKManager sharedManager].postLaunchAction = ^(SFSDKLaunchAction launchActionList) {
[weakSelf setupRootViewController];
};
[SalesforceSDKManager sharedManager].launchErrorAction = ^(NSError *error, SFSDKLaunchAction launchActionList) {
[weakSelf initializeAppViewState];
[[SalesforceSDKManager sharedManager] launch];
};
[SalesforceSDKManager sharedManager].postLogoutAction = ^{
[weakSelf handleSdkManagerLogout];
};
[SalesforceSDKManager sharedManager].switchUserAction = ^(SFUserAccount *fromUser, SFUserAccount *toUser) {
[weakSelf handleUserSwitch:fromUser toUser:toUser];
didFinishLaunchingWithOptions:
[[SalesforceSDKManager sharedManager] launch];
ViewController: (deferred login)
[[SFAuthenticationManager sharedManager] loginWithCompletion:^(SFOAuthInfo *sfOAuthInfo) {
NSLog(#"authentication successful!!!");
}
failure:^(SFOAuthInfo *sfOAuthInfo, NSError *error) {
NSLog(#"Authentication failure!!!");
}];

Related

QuickBlox - QBChatDialogTypePublicGroup : Dialog have to be in memory cache

Hello Friends i have create an application with QuickBlox. i am to create an 10 QBChatDialogTypePublicGroup from admin panel. it is static.
i want to create static public group from quickblox admin panel and chat any user in this group.
i am get this all group in viewController and display it. then user can choose any group to chat publicly.
i am using quickblox framework to chat with user. i am done QBChatDialogTypePrivate one to one user cheating.
Login :
- (void)loginWithQuickBlox{
NSString *emaiAddress = [[NSUserDefaults standardUserDefaults] objectForKey:#"UserLogin"];
NSString *password = [[NSUserDefaults standardUserDefaults] objectForKey:#"UserPassword"];
[QBRequest logInWithUserLogin:emaiAddress password:password successBlock:^(QBResponse *response, QBUUser *user)
{
[[NSUserDefaults standardUserDefaults]setObject:[NSString stringWithFormat:#"%ld",(unsigned long)user.ID] forKey:#"USerLoginID"];
[self loginWithQuickBloxChat:user];
} errorBlock:^(QBResponse *response)
{
// error handling
NSLog(#"errorsssss : %#", response.error);
}];
}
Login with QuickBloxChat
- (void)loginWithQuickBloxChat:(QBUUser *)selectedUser {
QBUUser *selectedUserx = [QBUUser user];
selectedUserx.login = [[NSUserDefaults standardUserDefaults] objectForKey:#"UserLogin"];
selectedUserx.password = [[NSUserDefaults standardUserDefaults] objectForKey:#"UserPassword"];
selectedUserx.ID = [[[NSUserDefaults standardUserDefaults] objectForKey:#"USerLoginID"] integerValue];
NSLog(#"Currunt User : %#", [QBSession currentSession].currentUser);
[ServicesManager.instance logInWithUser:selectedUserx completion:^(BOOL success, NSString *errorMessage)
{
[[QBChat instance] connectWithUser:selectedUserx completion:^(NSError * _Nullable error) {
}];
if (success)
{
NSLog(#"Login in Quickblox : %#",selectedUser);
[self getPublicGroup];
}
else
{
NSLog(#"Error in QuickBlox : %#",errorMessage);
}
}];
}
Get Public Group
- (void)getPublicGroup {
NSMutableDictionary *extendedRequest = #{#"type" : #(1)}.mutableCopy;
QBResponsePage *page = [QBResponsePage responsePageWithLimit:100 skip:0];
[QBRequest dialogsForPage:page extendedRequest:extendedRequest successBlock:^(QBResponse *response, NSArray *dialogObjects, NSSet *dialogsUsersIDs, QBResponsePage *page) {
publicGroupArray = dialogObjects.mutableCopy;
NSLog(#"Public Group : %#",publicGroupArray);
[self.groupCollectionview reloadData];
} errorBlock:^(QBResponse *response) {
}];
}
Select Any one Group and Chat With ChatViewcontroller
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
QBChatDialog *groupChatDialog = [publicGroupArray objectAtIndex:indexPath.row];
ChatViewController *chatViewController = [[ChatViewController alloc] init];
chatViewController.dialog = groupChatDialog;
chatViewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:chatViewController animated:YES];
}
This all procedure are working perfectly but when i send message from ChatViewController it will give me error
Assertion failure in -[QMChatService
sendMessage:toDialogID:saveToHistory:saveToStorage:completion:],
All/September/21/ChatApp/Pods/QMServices/QMChatService/QMChatService/QMChatService.m:1338
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Dialog have to be in
memory cache!'
*** First throw call stack:
You are trying to combine core SDK methods with QMServices' methods.
QBRequest is part of the Quickblox SDK, QMServices are high-level API for Chat features including:
Authentication service for logging to Quickblox REST and XMPP.
Inbox persistent and memory storage for messages, dialogs and users.
If you want to get dialog using QMServices try the method below:
- (void)loadDialogWithID:(NSString *)dialogID completion:(nullable void (^)(QBChatDialog * _Nullable loadedDialog))completion;
Example:
[ServicesManager.instance.chatService loadDialogWithID:dialogID
completion:^(QBChatDialog * _Nullable loadedDialog)
{
}];
This method will load dialog from the server, join it(if dialog's type is group) and store in memory and CoreDate.
If you want to fetch dialog using core method of the SDK you should implement all described actions by yourself.

Custom UI on Auth0

I need your help about auth0 social login. I have following ios code
- (IBAction)linkedin:(id)sender {
A0Lock *lock = [MyApplication sharedInstance].lock;
A0APIClient *client = [lock apiClient];
A0APIClientAuthenticationSuccess success = ^(A0UserProfile *profile, A0Token *token) {
NSLog(#"We did it!. Logged in with Auth0.");
};
A0APIClientError failure = ^(NSError *error){
NSLog(#"Oops something went wrong: %#", error);
};
A0AuthParameters *params = [A0AuthParameters newDefaultParams];
params[A0ParameterConnection] = #"linkedin"; // Or your configured DB connection
[client authenticateWithSocialConnectionName:#"linkedin"credentials:#"token" parameters:nil success:success failure:failure];
My aim is simple, i try to create social login connection via using auth0. In the quickstart documentation of auth0 there is a sample which is using controller, and i also add custom connections.
- (IBAction)signUp:(id)sender {
A0Lock *lock = [[MyApplication sharedInstance] lock];
A0LockViewController *controller = [lock newLockViewController];
controller.connections=#[#"facebook", #"linkedin"];
controller.useWebView=YES;
controller.onAuthenticationBlock = ^(A0UserProfile *profile, A0Token *token) {
// Do something with token & profile. e.g.: save them.
// And dismiss the ViewController
[self dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:controller animated:YES completion:nil];}}
But i cant use this because i need custom UI, i want to do this without controller. Can you please help me, what i m doing wrong in "authenticateWithSocialConnectionName" part. Thank you very much.

Using AWSS3TransferUtility to upload data on iOS

I've managed to successfully upload data using the AWS 2.0 SDK, however I'm having some trouble understanding the "re-wiring" of completion handlers that is meant to take place on resuming of the app.
What I believe I should be doing, is at comment 6, saving the upload task. Then if it reaches the completionHandler block, deleting it. However, if the app is terminated before this, I can look at my saved upload tasks in the block at comment 4. Any saved tasks would be "re-wired" to the completion handler.
For reference, imagine this code happening in an "Upload" class, and in a block, which is the "uploadSuccess()" code you see in the completionHandler.
For reference here is the blog that introduced the AWSS3TransferUtility, and here is its documentation.
Hopefully someone can guide me on this.
// 1. Get/Setup credentials
AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:#"IdentityPoolId"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
// 2. Create AWSS3 Transfer blocks
AWSS3TransferUtilityUploadExpression *expression = [AWSS3TransferUtilityUploadExpression new];
expression.uploadProgress = ^(AWSS3TransferUtilityTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Update a progress bar.
});
};
AWSS3TransferUtilityUploadCompletionHandlerBlock completionHandler = ^(AWSS3TransferUtilityUploadTask *task, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
// Do something e.g. Alert a user for transfer completion.
// On failed uploads, `error` contains the error object.
if (error) {
uploadSuccess(NO);
} else {
uploadSuccess(YES);
}
});
};
// 3. Create Transfer Utility
AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility];
// 4. Rewire Transfer Utility blocks
[transferUtility
enumerateToAssignBlocksForUploadTask:^(AWSS3TransferUtilityUploadTask *uploadTask, __autoreleasing AWSS3TransferUtilityUploadProgressBlock *uploadProgressBlockReference, __autoreleasing AWSS3TransferUtilityUploadCompletionHandlerBlock *completionHandlerReference) {
NSLog(#"Upload task identifier = %lu", (unsigned long)uploadTask.taskIdentifier);
// Use `uploadTask.taskIdentifier` to determine what blocks to assign.
//*uploadProgressBlockReference = // Reassign your progress feedback block.
*completionHandlerReference = completionHandler;// Reassign your completion handler.
}
downloadTask:^(AWSS3TransferUtilityDownloadTask *downloadTask, __autoreleasing AWSS3TransferUtilityDownloadProgressBlock *downloadProgressBlockReference, __autoreleasing AWSS3TransferUtilityDownloadCompletionHandlerBlock *completionHandlerReference) {
}];
// 5. Upload data using Transfer Utility
[[transferUtility uploadData:myNSDataObject
bucket:#"bucketName"
key:#"keyName"
contentType:#"text/plain"
expression:expression
completionHander:completionHandler] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(#"Error: %#", task.error);
}
if (task.exception) {
NSLog(#"Exception: %#", task.exception);
}
if (task.result) {
AWSS3TransferUtilityUploadTask *uploadTask = task.result;
// 6. Should i be saving uploadTasks here?
}
return nil;
}];

Parse Query not returning when iOS app is in background, triggered by Background Fetch

Using a Background Fetch we trigger a method
- (void)sendPush:(SPUserInfo *)userInfo {
PFQuery *findUserQuery = [PFUser query];
[findUserQuery whereKey:#"objectId" equalTo:userInfo.userID];
[findUserQuery findObjectsInBackgroundWithBlock:^(NSArray* arr, NSError* err) {
if (err) {
MLog(#"Error Finding User to Spark: %#", err.description);
}
else {
if (arr.count) {
MLog(#"User found");
PFObject *spark = [PFObject objectWithClassName:kSparkClassName];
[...]
[spark saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
//save
// send push through Parse
[...]
PFPush *push = [PFPush push];
NSString *channel = [NSString stringWithFormat:#"u_%#", receiver.objectId];
[push setChannels:#[channel]];
[push setData:data];
[push sendPushInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (nil == error) {
MLog(#"Push success");
//do the stuff
[self.queueSendingSpark removeObject:userInfo];
[self saveSendingSparkQueue];
}
else {
MLog(#"Push Error : %#", error.description);
}
}];
}
else {
MLog(#"Spark is not saved on parse | %#", error);
}}];
}
else {
MLog(#"ZERO Users");
}
}
}];
}
This is all fine and dandy if the app is running in the foreground or if the phone is awake. But when the iPhone is locked/asleep, the findObjectsInBackgroundWithBlock never returns any data.
Is this expected behaviour? Is there a way to ensure this query, and others, are returning as normal when a device is asleep?
So theres a property that you can use to handle this...
#property (nonatomic, assign) UIBackgroundTaskIdentifier fileUploadBackgroundTaskId;
Within your init method set the property like so:
self.fileUploadBackgroundTaskId = UIBackgroundTaskInvalid;
Set the value when needed
// Request a background execution task to allow us to finish uploading the photo even if the app is backgrounded
self.fileUploadBackgroundTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:self.fileUploadBackgroundTaskId];
}];
Run your query, then when the query is finished...
[[UIApplication sharedApplication] endBackgroundTask:self.fileUploadBackgroundTaskId];

Expired access token after openActiveSession for Facebook iOS SDK

I'm using the 3.1 Facebook SDK with iOS 6 Facebook set up in Settings and my app authorized.
This executes flawlessly:
[FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:YES completionHandler:^(FBSession *fbSession, FBSessionState fbState, NSError *error) { ... }
However now when I try to get 'me' information I'm getting an error:
com.facebook.sdk:ParsedJSONResponseKey = {
body = {
error = {
code = 190;
"error_subcode" = 463;
message = "Error validating access token: Session has expired at unix time 1348704000. The current unix time is 1348706984.";
type = OAuthException;
};
};
code = 400;
}
If I look at [error code] it's equal to 5. Shouldn't I have a valid access token after just logging in? Do I need to call reauthorize?
UPDATE: Reauthorizing doesn't help. Oddly the accessToken for my activeSession is always coming back the same. This despite calling closeAndClearToken.
UPDATE:
This issue has been addressed in Facebook iOS SDK 3.1.1.
I synched the code off of github and found that they weren't calling accountStore renewCredentialsForAccount:completion: anywhere. I changed the following code in authorizeUsingSystemAccountStore and it seems to have resolved the issue.
// we will attempt an iOS integrated facebook login
[accountStore requestAccessToAccountsWithType:accountType
options:options
completion:^(BOOL granted, NSError *error) {
// this means the user has not signed-on to Facebook via the OS
BOOL isUntosedDevice = (!granted && error.code == ACErrorAccountNotFound);
dispatch_block_t postReauthorizeBlock = ^{
NSString *oauthToken = nil;
if (granted) {
NSArray *fbAccounts = [accountStore accountsWithAccountType:accountType];
id account = [fbAccounts objectAtIndex:0];
id credential = [account credential];
oauthToken = [credential oauthToken];
}
// initial auth case
if (!isReauthorize) {
if (oauthToken) {
_isFacebookLoginToken = YES;
_isOSIntegratedFacebookLoginToken = YES;
// we received a token just now
self.refreshDate = [NSDate date];
// set token and date, state transition, and call the handler if there is one
[self transitionAndCallHandlerWithState:FBSessionStateOpen
error:nil
token:oauthToken
// BUG: we need a means for fetching the expiration date of the token
expirationDate:[NSDate distantFuture]
shouldCache:YES
loginType:FBSessionLoginTypeSystemAccount];
} else if (isUntosedDevice) {
// even when OS integrated auth is possible we use native-app/safari
// login if the user has not signed on to Facebook via the OS
[self authorizeWithPermissions:permissions
defaultAudience:defaultAudience
integratedAuth:NO
FBAppAuth:YES
safariAuth:YES
fallback:YES
isReauthorize:NO];
} else {
// create an error object with additional info regarding failed login
NSError *err = [FBSession errorLoginFailedWithReason:nil
errorCode:nil
innerError:error];
// state transition, and call the handler if there is one
[self transitionAndCallHandlerWithState:FBSessionStateClosedLoginFailed
error:err
token:nil
expirationDate:nil
shouldCache:NO
loginType:FBSessionLoginTypeNone];
}
} else { // reauth case
if (oauthToken) {
// union the requested permissions with the already granted permissions
NSMutableSet *set = [NSMutableSet setWithArray:self.permissions];
[set addObjectsFromArray:permissions];
// complete the operation: success
[self completeReauthorizeWithAccessToken:oauthToken
expirationDate:[NSDate distantFuture]
permissions:[set allObjects]];
} else {
// no token in this case implies that the user cancelled the permissions upgrade
NSError *error = [FBSession errorLoginFailedWithReason:FBErrorReauthorizeFailedReasonUserCancelled
errorCode:nil
innerError:nil];
// complete the operation: failed
[self callReauthorizeHandlerAndClearState:error];
// if we made it this far into the reauth case with an untosed device, then
// it is time to invalidate the session
if (isUntosedDevice) {
[self closeAndClearTokenInformation];
}
}
}
};
if (granted) {
[accountStore renewCredentialsForAccount:[[accountStore accountsWithAccountType:accountType] lastObject] completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) {
dispatch_async(dispatch_get_main_queue(), postReauthorizeBlock);
}];
} else {
// requestAccessToAccountsWithType:options:completion: completes on an
// arbitrary thread; let's process this back on our main thread
dispatch_async(dispatch_get_main_queue(), postReauthorizeBlock);
}
}];
}
So it's addressed, but I've been calling /me from our backend to verify since you can't trust the device.
So I make a call to FBSession's + (void)renewSystemAuthorization when the backend comes back with an authorization error.

Resources