When do we use saveAccount:(ACAccount *)account of ACAccountStore class? - ios

Please clarify me when do we use this method ?
- (void)saveAccount:(ACAccount *)account withCompletionHandler:(ACAccountStoreSaveCompletionHandler)completionHandler
As I know we get access to the account through OAuth and we do not get user's credentials. So how do we create an account? I've found that ACAccount has the only one creation method:
- (id)initWithAccountType:(ACAccountType *)type
What actually happens when we create account this way? And can we save it now ?

Ok, finally I've found the information about it.
Consider this scenario:
Our app have already been authorized by the user and we've got both access token and secret. Now we want to support new iOS 6 features and create twitter (for example) account in Settings. To do this we need to migrate these tokens to the central account store.
Here's how:
- (void)storeAccountWithAccessToken:(NSString *)token secret:(NSString *)secret {
//We start creating an account by creating the credentials object
ACAccountCredential *credential = [[ACAccountCredential alloc] initWithOAuthToken:token tokenSecret:secret];
ACAccountType *twitterAcctType =[self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
ACAccount *newAccount = [[ACAccount alloc] initWithAccountType:twitterAcctType];
//Here we assign credentials and now can save account
newAccount.credential = credential;
[self.accountStore saveAccount:newAccount withCompletionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"the account was saved!");
}
else {
//Handle error here
}
}];
}
For more information about it read here how to migrate tokens

Related

How to save facebook account to ACAccountStore from facebookSDK

I want to save the facebook account to ACAccountStore in iOS,
I will get accessTocken from facebookSDK but how to obtain tocken and secret
How to save it to ACAccountStore
Thanks in Advance.
------ Edit--------
I have an application that uses facebook to login and after with login information need to share photos that he selected.
My use cases are,
If account already in settings app then I can use it for login and share.
User using safari or webview for login then how I can proceed for sharing.
a. facebook SDK says If the user need to use OS integrated share controller then, login method used to authenticate the user must be native iOS 6.0 authentication..
b. If I need to share option that provided by facebook SDK uses facebook App I don't want this option because I want to avoid App switching as much as possible.
How to solve this..
to do it you should have an accesstoken and secret,
if (self.accountStore == nil) {
self.accountStore = [[ACAccountStore alloc] init];
}
//make credentials to assign to ACAccount
ACAccountCredential *credential = [[ACAccountCredential alloc] initWithOAuthToken:accesstoken tokenSecret:secret];
ACAccountType *acctType =[self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
ACAccount *newAccount = [[ACAccount alloc] initWithAccountType:acctType];
newAccount.credential = credential;
NSDictionary *options = [[NSDictionary alloc] initWithObjectsAndKeys:
"xXXXXXX", (NSString *)ACFacebookAppIdKey,
[NSArray arrayWithObject:#"basic_info"], (NSString *)ACFacebookPermissionsKey,
ACFacebookAudienceEveryone, (NSString *)ACFacebookAudienceKey,
nil];
[_accountStore requestAccessToAccountsWithType:acctType options:options completion:^(BOOL granted, NSError *error) {
if (granted == YES) {
[self.accountStore saveAccount:newAccount withCompletionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"the account was saved!");
}
else {
if ([error code] == ACErrorPermissionDenied) {
NSLog(#"Got a ACErrorPermissionDenied, the account was not saved!");
}
NSLog(#"%#",error);
}
}];
}
else {
NSLog(#"%# ",error);
}
}];

Save Facebook account using ACAccountStore

I'm trying to use iOS Social.framework to share to Facebook. However, most users will not have Facebook setup in Settings>Facebook so therefore Facebook doesn't show up when you bring up a UIActivityViewController, it just isn't listed. (See UIActivity with no settings for Facebook or just google "facebook doesn't show in UIActivityViewController," there's plenty of people trying to solve this problem.)
Our app already uses the Facebook SDK so I can get at the Facebook account info, so I thought I would just get the info and then save the info in Settings>Facebook. Here's my code. (Which I got from When do we use saveAccount:(ACAccount *)account of ACAccountStore class? and iOS requestAccessToAccountsWithType is Not Showing Permission Prompt / NSAlert)
- (void)storeAccountWithAccessToken:(NSString *)token secret:(NSString *)secret {
if (self.accountStore == nil) {
self.accountStore = [[ACAccountStore alloc] init];
}
//We start creating an account by creating the credentials object
ACAccountCredential *credential = [[ACAccountCredential alloc] initWithOAuthToken:token tokenSecret:secret];
ACAccountType *acctType =[self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
ACAccount *newAccount = [[ACAccount alloc] initWithAccountType:acctType];
//Here we assign credentials and now can save account
newAccount.credential = credential;
NSDictionary *options = [[NSDictionary alloc] initWithObjectsAndKeys:
[VVEnvironment stringForKey:kVVEnvironmentKeyFacebookAppID], (NSString *)ACFacebookAppIdKey,
[NSArray arrayWithObject:#"basic_info"], (NSString *)ACFacebookPermissionsKey,
ACFacebookAudienceEveryone, (NSString *)ACFacebookAudienceKey,
nil];
[_accountStore requestAccessToAccountsWithType:acctType options:options completion:^(BOOL granted, NSError *error) {
if (granted == YES) {
[self.accountStore saveAccount:newAccount withCompletionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"the account was saved!");
}
else {
if ([error code] == ACErrorPermissionDenied) {
NSLog(#"Got a ACErrorPermissionDenied, the account was not saved!");
}
NSLog(#"the account was not saved! %d, %#", [error code], error);
}
}];
}
else {
NSLog(#"ERR: %# ",error);
}
}];
}
I added the call to requestAccessToAccountsWithType there because without I was getting a ACErrorPermissionDenied back from saveAccount. When I run this I do see my app slide briefly aside for the Facebook dialog (if I delete my app on Facebook's website it does bring up the full dialog asking me for permissions which I grant.)
The problem is that granted is always NO, so I never get a chance to save the account. What am I missing here?
I am running this on a real device that has the Facebook App installed and setup.
I'd appreciate any help on this, thanks!
There is no solution available for this. iOS native facebook applications are not allowed to write or save account to ACAccountStore. It only allow to access account from the ACAccountStore. iOS only allow to store 1 facebook account at a time. Try to do these steps you will understand this easily,
Add a facebook account to settings App and try to get permission to access it. It will grand permission.
Remove account and try to get the permission it will deny access.
Add a facebook account and get access and try to save new account to ACAccountStore, It will say that Native applications are not allowed to save account to ACAccountStore.
The proposed solution is, Add the account to settings App and login with it and Share using Social framework or presentOSIntegratedDialog.

ACAccountCredential returns null for oauthToken

I am getting access to user's facebook via:
[accStore requestAccessToAccountsWithType:fbAccountType
options:options
completion:^(BOOL granted, NSError *error) {
if (granted) {
// If access granted, then get the Facebook account info
NSArray *accounts = [accStore
accountsWithAccountType:fbAccountType];
ACAccount *acc = [accounts lastObject];
// Get the access token, could be used in other scenarios
ACAccountCredential *fbCredential = [acc credential];
NSString *accessToken = [fbCredential oauthToken];
NSLog(#"Facebook Access Token: %#", accessToken);
// Add code here to make an API request using the SLRequest class
} else {
NSLog(#"Access not granted");
}
}];
This prints out:
Facebook Access Token: (null)
I am granted access, but the token is null. What am I doing wrong?
Thanks
I've solved the problem by renewing the credentials. That is, after access to FB has been granted, but in the case where ACAccountCredential's oauthToken returns nil, we just call ACAccountStore's renewCredentialsForAccount. Credentials are renewed, and after that the token is valid!
Here's some info from Apple doc:
#property(nonatomic, retain) ACAccountCredential *credential
Discussion This property is required and must be set before the
account is saved. For privacy reasons, this property is inaccessible
after the account is saved.
As in your code, [acc credential] will return null
For reference, http://developer.apple.com/library/ios/#documentation/Accounts/Reference/ACAccountClassRef/Reference/Reference.html#//apple_ref/doc/uid/TP40011019
Found a similar post here: Get Facebook access token from Social.framework(iOS6)
Hope this can help.

How do I get the oauth token after logging into Twitter?

After logging into Twitter, I am able to print out some useful data such as the username and user ID. However, the OAuth token is always null. How do I get it? I need to send OAuth token to my server so it can verify that the user is indeed who he says he is.
ACAccountStore* accountStore = [[ACAccountStore alloc] init];
ACAccountType* twitterType = [self.context.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore
requestAccessToAccountsWithType:twitterType
withCompletionHandler:^(BOOL isAllowed, NSError* error) {
dispatch_sync(dispatch_get_main_queue(), ^(void) {
if (isAllowed) {
ACAccount* account = [[self.context.accountStore accountsWithAccountType:[self.context.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter]] lastObject];
NSLog(#"username = %#", account.username);
NSLog(#"user_id = %#", [[account valueForKey:#"properties"] valueForKey:#"user_id"]);
// ouath token is always null
NSLog(#"oauth token = %#", account.credential.oauthToken);
}
});
}
];
I "think" I need Reverse Auth, but that tutorial mysteriously left out the code for "step 1".
You will indeed need to use Reverse Auth.
I recently used Sean Cook's TWReverseAuth and it worked very well. Just be careful to turn off ARC for the individual files in the Vendor directory.

Using a Hidden Twitter Account

Not sure if any one has tried this. I want to access twitter with an account that the user of the phone doesn't have access to.
The way I have looked at it is by adding a twitter account using the OAth (token/secret)
I can add an account using the following code.
NSString *token = #"blahblahblah";
NSString *secret = #"blahblahblah";
ACAccountStore *store = [[ACAccountStore alloc] init];
ACAccountCredential *credential = [[ACAccountCredential alloc] initWithOAuthToken:token tokenSecret:secret];
ACAccountType *twitterAcctType = [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
ACAccount *newAccount = [[ACAccount alloc] initWithAccountType:twitterAcctType];
newAccount.credential = credential;
[store saveAccount:<#(ACAccount *)#> withCompletionHandler:<#^(BOOL success, NSError *error)completionHandler#>
[store saveAccount:newAccount withCompletionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"Account was saved!");
} else {
//something went wrong, check value of error
}
}];
But this code stores the user id associataed with the secret in the iphones account store. The problem being that if the phone user then uses twitter the account privilages are still there for him to use...
There doesn't seem to be a store deleteAccount method implemented
For my second attempt i tried using just the user that was created without adding it to the account store but I think the SaveAccount method is what verifies the token and secret and gets the user name...
Any tips???
Just a friendly reminder that this will most likely have your app banned from the app store, as this can easily be classified as spying on the user/device, if you can pull it off which I doubt.
Also, beware of having thousands/millions of users twitting from the same account.
Finally, there does not seem to be a way to remove the account, as you said, plus in order to use it you'd need to use requestAccessToAccountsWithType:withCompletionHandler: which would trigger a notice to the user and would make them think you were requesting access to his tweeter account, rather than yours...

Resources