How to do login in Twitter using STTwitter for OSX? - objective-c

Hello,
I am developing a Twitter client for OSX using STTwitter library.
I use this code to do login:
- (void) loginWithUser:(NSString*) user
password:(NSString*) password {
twitter = [STTwitterAPI twitterAPIWithOAuthConsumerKey:kOAuthConsumerKey
consumerSecret:kOAuthConsumerSecret
username:user
password:password];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *username) {
_status = [NSString stringWithFormat:#"Access granted for %#", username];
_isConnected = YES;
} errorBlock:^(NSError *error) {
_isConnected = NO;
_status = [error localizedDescription];
NSLog(#"Status: %#",_status);
}];
}
I can read direct messages using my personal Twitter account and other development Twitter account but if I try to use other Twitter account from my beta testers I can not read the direct messages.
The error message is:
This application is not allowed to access or delete your direct messages.
I tried to use an OSX system account to do login using this code:
- (void) loginWithSystemAccount {
twitter = [STTwitterAPI twitterAPIOSWithFirstAccount];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *username) {
_status = [NSString stringWithFormat:#"Access granted for %#", username];
_isConnected = YES;
} errorBlock:^(NSError *error) {
_isConnected = NO;
_status = [error localizedDescription];
NSLog(#"Status: %#",_status);
}];
}
But I can read direct messages using a system account.
I checked the OSX Demo in STTwitter git repository but I could not find a solution.
How can I do a right login in Twitter for all users to read direct messages?
Thanks in advance

At first, you should find out if it's a weird behaviour of Twitter API, or a bug in STTwitter.
To do so, I suggest that you try reading direct messages with twurl.
If you're not sure which endpoints you're calling, enable STTwitter networks logs with the STHTTPRequestShowCurlDescription argument.

Related

Not getting the email from twitter using Fabric Twitter SDK

This seems to be age old question with no specific answers or solutions for it. I had my application whitelisted from twitter. Done all the things. Checked the request email from user box and used the following code
[[Twitter sharedInstance] startWithConsumerKey:#"FabricKey" consumerSecret:#"FabricSecretKey"];
if ([[Twitter sharedInstance] session]) {
TWTRShareEmailViewController *shareEmailViewController =
[[TWTRShareEmailViewController alloc]
initWithCompletion:^(NSString *email, NSError *error) {
NSLog(#"Email %# | Error: %#", email, error);
}];
[self presentViewController:shareEmailViewController
animated:YES
completion:nil];
But still it is returning null. Why is this?? I even created the application in twitter developer portal. Please help me. Is twitter trying to be more over secure?? It is just pissing me out......

OSX ACAccountStore requestAccessToAccountsWithType... returning 'granted=No' and error=nil after denying permissions

I am trying to request access to my facebook account. The first time I ran this it went well and I saw the popup requesting permissions. The popup asked me to allow or deny. I chose to deny because I wanted to test that use case. Now I cannot figure out how to get it to allow access again. I have deleted the app from my facebook account and deleted my facebook account from my mac. I've also tried adding the property
#"auth_type": #"rerequest"
to the options dictionary. I get the same result no matter what.
As mentioned in the title, the error is nil and granted is False.
Thanks in advance.
ACAccountType* accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSDictionary* options = #{
ACFacebookAppIdKey: [[NSBundle mainBundle] objectForInfoDictionaryKey:#"FacebookAppID"],
ACFacebookPermissionsKey: #[#"public_profile", #"email", #"user_friends"],
};
[accountStore requestAccessToAccountsWithType:accountType options:options completion:^(BOOL granted, NSError* error)
{
if (granted)
{
ACAccount* account = [[accountStore accountsWithAccountType:accountType] lastObject];
macFacebookAccount = account;
}
else
{
NSLog(#"%#", error);
}
}];
I solved this: Facebook permission settings for an app are located under System Preferences > Security and Privacy. From there just click facebook and check the box next to your app

openActiveSessionWithPublishPermissions show login form twice

I'm trying to implement post wall using objective-c but when i do request new permission to 'publish_actions' with action session, the FB SDK login form is show again.
I'm looking for this tutorial: https://developers.facebook.com/docs/ios/publish-to-feed-ios-sdk/
In my application flow is basically this:
void (^completionHandler)(FBSession*, NSError*) = ^(FBSession*session, NSError*error){
if (session.isOpen && !error)
{
[FBWebDialogs presentFeedDialogModallyWithSession:session
parameters:params
handler:handler];
}
};
// abrie o dialog
BOOL isFBIntegration = [SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook];
if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound)
{
if(isFBIntegration)
{
[[FBSession activeSession] requestNewPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:completionHandler];
}
else
{
[FBSession openActiveSessionWithPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceEveryone
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
completionHandler(session, error);
}];
}
}
else
{
completionHandler(FBSession.activeSession, nil);
}
The user is already logged in because I do ask him to log when it enters the application:
HOME
[FBSession openActiveSessionWithReadPermissions:#[#"basic_info, user_friends, friends_interests"]
allowLoginUI:YES
completionHandler:nil];
When Facebook is native integration, all right, but when no, openActiveSessionWithPublishPermissions show login form again.
thank you.
Facebook iOS SDK 3.1 has now disabled openActiveSessionWithPublishPermissions. You will need to first establish a read only session, then additionally request write permissions. You can read more details about the upgrade process at iOS SDK Upgrade Guide.

Twitter OAuth and accessToken to GET statuses/user_timeline in Objective-C

I'm trying to acquire the accessToken value from Twitter for using it in my app (I need to use API v1.1's Authentication Model for GET statuses/user_timeline); I have registered my app on api.twitter.com, imported the AFOAuth1Client classes in the project, and this is the simple code:
- (void)viewDidLoad
{
self.twitterClient = [[AFOAuth1Client alloc] initWithBaseURL:
[NSURL URLWithString:#"https://api.twitter.com/"] key:#"MYKEY" secret:#"MYSECRETKEY"];
AFOAuth1Token *accessToken;
[self.twitterClient acquireOAuthAccessTokenWithPath:#"oauth/request_token" requestToken:accessToken accessMethod:#"GET" success:^(AFOAuth1Token *accessToken) { // I have tried also accessMethod: #"POST"
NSLog(#"Success: %#", accessToken);
} failure:^(NSError *error) {
NSLog(#"Error: %#", error);
}];
}
Unluckly XCode give me this error:
Error: Error Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code in (200-299), got 401" UserInfo=0x79a14f0 {NSLocalizedRecoverySuggestion=Failed to validate oauth signature and token, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x7956390>
What is wrong here? DO i need to REGISTER app on api.twitter.com? Is it the right way, or, what is the simpler way to Get statuses/user_timeline using API v1.1's Twitter Authentication Model in iOS? Thank you!
EDIT: possible waypoint?
1) register a new app on dev.twitter.com
2) in OAuth settings, read Consumer key and Consumer secret
3) set default app access type to read? or read/write? ask for access tokens? use this values in.... ?
It's been a few days since Twitter added an application only mode. In this mode, you can access specific API endpoints without user's context, ie. your users don't have to authenticate. Only the application does authenticate once in a while to get a "bearer token" which is then sent in every request.
The following code gets a bearer token and then retrieves the public timeline for #barackobama.
STTwitterAPI *twitter = [STTwitterAPI twitterAPIApplicationOnlyWithConsumerKey:#""
consumerSecret:#""];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *bearerToken) {
NSLog(#"Access granted with %#", bearerToken);
[twitter getUserTimelineWithScreenName:#"barackobama" successBlock:^(NSArray *statuses) {
NSLog(#"-- statuses: %#", statuses);
} errorBlock:^(NSError *error) {
NSLog(#"-- error: %#", error);
}];
} errorBlock:^(NSError *error) {
NSLog(#"-- error %#", error);
}];
See STTwitter iOS demo project for a working example (use you own consumer key / secret).
If you have your own consumer tokens, you can use the STTwitter library I wrote.
STTwitterAPI *twitter =
[STTwitterAPI twitterAPIWithOAuthConsumerName:#""
consumerKey:#"your_key"
consumerSecret:#"your_secret"
username:#"username"
password:#"password"];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *username) {
NSLog(#"Access granted for %#", username);
[twitter getUserTimelineWithScreenName:#"barackobama"
successBlock:^(NSArray *statuses) {
NSLog(#"-- statuses: %#", statuses);
} errorBlock:^(NSError *error) {
NSLog(#"-- error: %#", error);
}];
} errorBlock:^(NSError *error) {
NSLog(#"-- error %#", error);
}];
If your tokens are not 'xAuth' enabled, you'll have to use a PIN. STTwitter provides simple asynchronous block-based methods to ask the user. You can also choose to automate the PIN retrieval, see STTwitterDemo -[AppDelegate guessPIN:] for an automated process.
STTwitter is simple for use . Also I added example that you can get public twitter timeline

Access Facebook Accounts on OS X Mountain Lion

As Mountain Lion now officialy has Facebook integrated I wanted to play a little bit with Accounts.framework and Social.framework of OS X.
I set up an App in the Facebook Developer App and used the following code to request access to the Facebook Accounts of the logged in user:
ACAccountStore *acStore = [[ACAccountStore alloc] init];
ACAccountType *accType = [acStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:FB_APP_ID, ACFacebookAppIdKey, #"read_stream, publish_stream", ACFacebookPermissionsKey, ACFacebookAudienceFriends, ACFacebookAudienceKey, nil];
[acStore requestAccessToAccountsWithType:accType options:options completion:^(BOOL granted, NSError *error) {
if (granted) {
NSLog(#"Accounts: %#", acStore.accounts);
NSLog(#"Access granted");
} else {
NSLog(#"Access denied");
}
}];
Now I always get the error Error Domain=XPCObjectsErrorDomain Code=2 "The operation couldn’t be completed. (XPCObjectsErrorDomain error 2.)"
When I launched the App from Xcode the first 2-3 times, OS X displayed the confirmation dialog "XYZ wants to access your Facebook Accounts", I clicked ok and I got an error saying something like "The Application is not yet installed". This error now "disappeared" and I'm getting the error noted above.
My question is: Do I have to configure something special in my Xcode Project (Info.plist) or in the Facebook Developer App to make it work with OS X? Or am I missing something in the code? Samples and Tutorials regarding this seem to be very rare :-/
I already watched the WWDC 2012 Video about the Twitter/Facebook Integration but it uses almost exactly the code I used.
Any help is appreciated :-)
Cheers,
Björn
Update
I solved the issue, I just did not read the docs carefully enough ;-) I have to pass the permissions as an NSArray and not as a string. I've modified the options dictionary to look like this:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
FB_APP_ID, ACFacebookAppIdKey,
[NSArray arrayWithObjects:#"read_stream", #"publish_stream", #"email", #"user_likes", nil], ACFacebookPermissionsKey,
ACFacebookAudienceFriends, ACFacebookAudienceKey, nil];
Now OS X shows an alert that asks me if I want to allow the App to post to Facebook on my behalf, I click OK and a new error appears resulting in no access to the Facebook accounts:
Error Domain=com.apple.accounts Code=7 "The Facebook server could not fulfill this access request: The app must ask for a basic read permission at install time."
I already modified the permissions to be just email or just user_likes but it all resulted in the same error. If I only request access to read_stream the access gets granted but results in the OAuth error 190 with the message Error validating access token: User XXXXXX has not authorized application XXXXXX.
Update 2:
I now solved all my problems, see my answer below.
Alright, I finally solved it :-)
When you first request access to a users Facebook accounts, you may only request permissions from the user listed under "User and Friend permissions" in Facebook's Permission Reference.
Once the user granted access and with that also installed the application on Facebook, you may request any additional permissions required by your App. It's important that you may not ask for read and write permissions at the same time, one after the other! So requesting the permission read_stream and publish_stream in the same request will not work.
This is the basically the code I used:
self.store = [[ACAccountStore alloc] init];
ACAccountType *accType = [self.store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSMutableDictionary *options = [NSMutableDictionary dictionaryWithObjectsAndKeys:
FB_APP_ID, ACFacebookAppIdKey,
[NSArray arrayWithObjects:#"email", #"user_about_me", #"user_likes", nil], ACFacebookPermissionsKey, ACFacebookAudienceFriends, ACFacebookAudienceKey, nil];
[self.store requestAccessToAccountsWithType:accType options:options completion:^(BOOL granted, NSError *error) {
if (granted && error == nil) {
self.accounts = self.store.accounts;
[options setObject:[NSArray arrayWithObjects:#"read_stream, read_mailbox, read_requests", nil] forKey:ACFacebookPermissionsKey];
[self.store requestAccessToAccountsWithType:accType options:options completion:^(BOOL granted, NSError *error) {
if (granted && error == nil) {
completionHandler(granted, error);
} else {
NSLog(#"Access denied 2");
NSLog(#"%#", [error description]);
}
}];
} else {
NSLog(#"Error: %#", [error description]);
NSLog(#"Access denied");
}
}];
Hope this will help somebody :-)
I would like to add that there is an additional caveat in the Facebook docs:
// if a user has *never* logged into your app, you MUST include one of
// "email", "user_location", or "user_birthday". Other read
// permissions can also be included here.
Failure to do this leads to the same error.