How to make User logout from twitter fabric ios - ios

I have made a basic app using Twitter's fabric that allows user to tweet within my app and Provide Login With Twitter.Every things works a I Wanted.
How my app Works
If the user doesn't logged in to twitter my app allows him to login and if he is login then directly allows him to tweet.
Now the Big Part Comes
As I saw in many Apps I Can Remove my signed account from the app.And I am not able to get any method that help me to achieve this. I want to allow user to logout from twitter within my app whenever he/She wants.
I googled but i doesn't find anything
Here Is my Code:
- (IBAction)LogOut:(id)sender
{
[[Twitter sharedInstance]logOut];
}
- (IBAction)LogMeIn:(id)sender
{
[[Twitter sharedInstance] logInWithCompletion:^
(TWTRSession *session, NSError *error) {
if (session) {
NSLog(#"signed in as %#", [session userName]);
[LoginButton setTitle:#"LogOut" forState:normal];
} else {
NSLog(#"error: %#", [error localizedDescription]);
}
}];
}

this was a problem with NSCookie from Foundation framework And i slove this issues with help of below code
NSURL *url = [NSURL URLWithString:#"https://api.twitter.com"];
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:url];
for (NSHTTPCookie *cookie in cookies)
{
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}

You need to use below code
[[[Twitter sharedInstance] sessionStore] logOutUserID:USERID];
Provide user id of the user you want to logout.

UPDATE: May 2016 - Framework has changed so this answer is no longer relevant.
See this answer:
https://stackoverflow.com/a/35765833/940709
and this answer:
https://stackoverflow.com/a/30916904/940709 instead.
[[[Twitter sharedInstance] sessionStore] logOutUserID:USERID];

This is the best simple answer for Swift 3:
let store = Twitter.sharedInstance().sessionStore
if let userID = store.session()?.userID {
store.logOutUserID(userID)
}
or you can use Naeem's answer but add () after store.session

Logout Code From Twitter Docs:
Objective-C
TWTRSessionStore *store = [[Twitter sharedInstance] sessionStore];
NSString *userID = store.session.userID;
[store logOutUserID:userID];
Swift
let store = Twitter.sharedInstance().sessionStore
if let userID = store.session()?.userID {
store.logOutUserID(userID)
}

For Swift try this,
/**
* Deletes the local Twitter user session from this app. This will not remove the system Twitter account nor make a network request to invalidate the session.
*
* #param userID ID of the user to log out
*/
Twitter.sharedInstance().sessionStore.logOutUserID(userId)

First make sure some user is signed in, then perform logout.
NSString *signedInUserID = [TWTRAPIClient clientWithCurrentUser].userID;
if (signedInUserID) {
[[Twitter sharedInstance].sessionStore logoutUserID:signedInUserID];
}

While login mention method as webBasedForceLogin, so that it will not create entry into Safari Cache.
private func twitterLogin() {
Twitter.sharedInstance().logIn(withMethods: .webBasedForceLogin, completion: { (session, error) in
if let error = error {
print(error.localizedDescription)
}
guard let session = session else {
return
}
print("success! Welcome \(session.userName).")
self.twitterButton.setTitle("TWITTER LOGOUT", for: .normal)
})
}
private func twitterLogout() {
let sessionStore = Twitter.sharedInstance().sessionStore
if let userID = sessionStore.session()?.userID {
sessionStore.logOutUserID(userID)
}
twitterButton.setTitle("TWITTER LOGIN", for: .normal)
}

Use below:
[TWTRSessionStore logout]
Deprecated:
[Twitter logOut]
is deprecated.
Users are encouraged to call - [TWTRSessionStore logout] instead of calling this method on the Twitter instance directly.

Related

Fabric Twitter Login issue when account is not setup?

I am using Twitter's fabric too login via twitter & to get user's detail. I am using below code for that.
[[Twitter sharedInstance] logInWithCompletion:^
(TWTRSession *session, NSError *error) {
if (session) {
NSLog(#"signed in as %#", [session userID]);
} else {
NSLog(#"error: %#", [error localizedDescription]);
}
}];
It is working fine when I have configured twitter account in settings of iPhone i.e. added user name & password in twitter app of iPhone.
But if that is blank & no twitter account is configured I can not login & will get the error Request failed: unauthorized (401)
Is there any way in which I can ask user to enter his/her username & password ?
Thanks in advance.
-Aakil
Okay so I figured this out for anyone that happens to find this.
Go to you developer.twitter app (their website).
Add a callback URL in the apps settings. (doesn't matter what it is)
The button will work now.
You can check like this :
if (![TWTweetComposeViewController canSendTweet]) {
NSLog(#"No Twitter Accounts");
}
if you want without going settings you need to use fabric way login. In documentation they use button, I don't know your application's lifecycle but at this point you can show this button somewhere and ask them to login maybe. here is some code from documentation :
TWTRLogInButton* logInButton = [TWTRLogInButton
buttonWithLogInCompletion:
^(TWTRSession* session, NSError* error) {
if (session) {
NSLog(#"signed in as %#", [session userName]);
} else {
NSLog(#"error: %#", [error localizedDescription]);
}
}];
logInButton.center = self.view.center;
[self.view addSubview:logInButton];
hope it helps.

Logout of Active Twitter Session Using Fabric

I have read through the forums and suggestions about how to logout of Twitter in Xcode for IOS using Fabric, but I can't get the logOut method to call and logout the user from the current session. Here is my current code for the login view controller:
- (IBAction)TESTT:(id)sender {
[[Twitter sharedInstance] logInWithCompletion:^
(TWTRSession *session, NSError *error) {
if (session != nil) {
NSLog(#"signed in as %#", [session userName]);
} else {
NSLog(#"error: %#", [error localizedDescription]);
}
}];
}
- (IBAction)LOGOUT:(id)sender {
[self logOut];
}
- (void)logOut{
[[Twitter sharedInstance] logOut];
}
I have imported and have the login functionality working well from the Fabric tutorial.
I just can't get the button that I made which is using the LOGOUT action to logout the user from the current Twitter session. I have even tried to clear the cookies to see if that could wipe the Twitter session from the memory and reset it - but nothing. If anyone could help me out I would really appreciate it - thanks!
FYI: PLEASE do not suggest only [[Twitter sharedInstance] logOut]; . This method does not do what I am asking by itself. If someone can tell me how to successfully logout using this method along with the rest of the procedure that would be fine.
After a long extensive series of methods, clearing of cookies, data, almost everything you could think of, I discovered it is actually quite simple.
The easiest way to sign out and clear the previous user session is as follows:
Go to settings
Go to your Twitter and Disallow Twitter access to your app (it should appear here)
Go back to the app and call the following method:
- (void)twitterLogout:(id)sender {
NSUserDefaults *twitterSession = [NSUserDefaults standardUserDefaults];
[twitterSession setObject:0 forKey:#"TwitterSession"];
[twitterSession synchronize];
NSLog(#"Twitter session = %#", twitterSession);
[[Twitter sharedInstance] logOut];
[self.view insertSubview:_logoutTwitter atIndex:16];
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies])
{
NSString* domainName = [cookie domain];
NSRange domainRange = [domainName rangeOfString:#"Twitter"];
if(domainRange.length > 0)
{
[storage deleteCookie:cookie];
}
}
NSURL *url = [NSURL URLWithString:#"https://api.twitter.com"];
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:url];
for (NSHTTPCookie *cookie in cookies)
{
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}
}
There is quite a lot in this method, and to be honest some of it is probably extraneous and not even needed, but anyone who needs this can mess around with what should and shouldn't stay. Either way hopefully this helps people - it certainly helped me!
You can use this simple code for Swift 3:
let store = Twitter.sharedInstance().sessionStore
if let userID = store.session()?.userID {
store.logOutUserID(userID)
}

Get user profile details (especially email address) from Twitter in iOS

I am aiming to get a user's details based on his/her Twitter account. Now first of all, let me explain what I want to do.
In my case, user will be presented an option to Sign-up with Twitter account. So, based on user's Twitter account, I want to be able to get user details (e.g. email-id, name, profile picture, birth date, gender etc..) and save those details in database. Now, many people will probably suggest me to use ACAccount and ACAccountStore, a class that provides an interface for accessing, manipulating, and storing accounts. But in my case, I want to sign up user, even if user has not configured an account for Twitter in iOS Settings App. I want user to navigate to login screen of Twitter (in Safari or in App itself, or using any other alternative).
I have also referred the documentation of Twitter having API list here. But I am a lot confused how user should be presented a login screen to log into the Twitter account and how I will get profile information. Should I use UIWebView, or redirect user to Safari or adopt another way for that ?
Finally, after having a long conversation with sdk-feedback#twitter.com, I got my App whitelisted. Here is the story:
Send mail to sdk-feedback#twitter.com with some details about your App like Consumer key, App Store link of an App, Link to privacy policy, Metadata, Instructions on how to log into our App. Mention in mail that you want to access user email address inside your App.
They will review your App and reply to you within 2-3 business days.
Once they say that your App is whitelisted, update your App's settings in Twitter Developer portal. Sign in to apps.twitter.com and:
On the 'Settings' tab, add a terms of service and privacy policy URL
On the 'Permissions' tab, change your token's scope to request email. This option will only been seen, once your App gets whitelisted.
Put your hands on code:
Agree with statement of Vizllx: "Twitter has provided a beautiful framework for that, you just have to integrate it in your app."
Get user email address
-(void)requestUserEmail
{
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];
} else {
// Handle user not signed in (e.g. attempt to log in or show an alert)
}
}
Get user profile
-(void)usersShow:(NSString *)userID
{
NSString *statusesShowEndpoint = #"https://api.twitter.com/1.1/users/show.json";
NSDictionary *params = #{#"user_id": userID};
NSError *clientError;
NSURLRequest *request = [[[Twitter sharedInstance] APIClient]
URLRequestWithMethod:#"GET"
URL:statusesShowEndpoint
parameters:params
error:&clientError];
if (request) {
[[[Twitter sharedInstance] APIClient]
sendTwitterRequest:request
completion:^(NSURLResponse *response,
NSData *data,
NSError *connectionError) {
if (data) {
// handle the response data e.g.
NSError *jsonError;
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:data
options:0
error:&jsonError];
NSLog(#"%#",[json description]);
}
else {
NSLog(#"Error code: %ld | Error description: %#", (long)[connectionError code], [connectionError localizedDescription]);
}
}];
}
else {
NSLog(#"Error: %#", clientError);
}
}
Hope it helps !!!
How to get email id in twitter ?
Step 1 : got to https://apps.twitter.com/app/
Step 2 : click on ur app > click on permission tab .
Step 3 : here check the email box
Twitter has provided a beautiful framework for that, you just have to integrate it in your app.
https://dev.twitter.com/twitter-kit/ios
It has a simple Login Method:-
// Objective-C
TWTRLogInButton* logInButton = [TWTRLogInButton
buttonWithLogInCompletion:
^(TWTRSession* session, NSError* error) {
if (session) {
NSLog(#"signed in as %#", [session userName]);
} else {
NSLog(#"error: %#", [error localizedDescription]);
}
}];
logInButton.center = self.view.center;
[self.view addSubview:logInButton];
This is the process to get user profile information:-
/* Get user info */
[[[Twitter sharedInstance] APIClient] loadUserWithID:[session userID]
completion:^(TWTRUser *user,
NSError *error)
{
// handle the response or error
if (![error isEqual:nil]) {
NSLog(#"Twitter info -> user = %# ",user);
NSString *urlString = [[NSString alloc]initWithString:user.profileImageLargeURL];
NSURL *url = [[NSURL alloc]initWithString:urlString];
NSData *pullTwitterPP = [[NSData alloc]initWithContentsOfURL:url];
UIImage *profImage = [UIImage imageWithData:pullTwitterPP];
} else {
NSLog(#"Twitter error getting profile : %#", [error localizedDescription]);
}
}];
I think rest you can find from Twitter Kit Tutorial, it also allows to request a user’s email, by calling the TwitterAuthClient#requestEmail method, passing in a valid TwitterSession and Callback.
In Twitter you can get user_name and user_id only. It is that much secure that you can't fetch email id, birth date, gender etc.., compare to Facebook, Twitter is very confidential for supplying the data.
need ref: link1.
In Swift 4.2 and Xcode 10.1
It's getting email also.
import TwitterKit
#IBAction func onClickTwitterSignin(_ sender: UIButton) {
TWTRTwitter.sharedInstance().logIn { (session, error) in
if (session != nil) {
let name = session?.userName ?? ""
print(name)
print(session?.userID ?? "")
print(session?.authToken ?? "")
print(session?.authTokenSecret ?? "")
let client = TWTRAPIClient.withCurrentUser()
client.requestEmail { email, error in
if (email != nil) {
let recivedEmailID = email ?? ""
print(recivedEmailID)
}else {
print("error--: \(String(describing: error?.localizedDescription))");
}
}
//To get profile image url and screen name
let twitterClient = TWTRAPIClient(userID: session?.userID)
twitterClient.loadUser(withID: session?.userID ?? "") {(user, error) in
print(user?.profileImageURL ?? "")
print(user?.profileImageLargeURL ?? "")
print(user?.screenName ?? "")
}
let storyboard = self.storyboard?.instantiateViewController(withIdentifier: "SVC") as! SecondViewController
self.navigationController?.pushViewController(storyboard, animated: true)
}else {
print("error: \(String(describing: error?.localizedDescription))");
}
}
}
Follow the Harshil Kotecha answer.
Step 1 : got to https://apps.twitter.com/app/
Step 2 : click on ur app > click on permission tab .
Step 3 : here check the email box
If you want to logout
let store = TWTRTwitter.sharedInstance().sessionStore
if let userID = store.session()?.userID {
print(store.session()?.userID ?? "")
store.logOutUserID(userID)
print(store.session()?.userID ?? "")
self.navigationController?.popToRootViewController(animated: true)
}

Post as a fan page on iOS Facebook SDK 3.0

I'm trying to post to a fan page as the fan page, not as the user.
On the old SDK, I simply asked for "me/accounts" and received the access token. Now I can do the same, but I have no way to use that Token, since FBRequest takes its access token from the active session (also, it's a readonly property).
Does anyone knows how to create another session or simply FBRequests with the page token?
Thanks!
Found a solution, it's not the cleanest, but it's working:
Note: Updated for Facebook SDK 3.2+
- (void)postAsFanPageWithToken:(NSString *)aFanPageToken {
if (self.selectedFanPage == nil) {
self.userAccessToken = [FBSession activeSession].accessTokenData.accessToken;
}
//Using KVC, since it is a readonly property
[[FBSession activeSession].accessTokenData setValue:aFanPageToken forKey:#"accessToken"];
}
- (void)postAsMe {
if (self.userAccessToken == nil) {
return; //Already posting as me
}
[[FBSession activeSession].accessTokenData setValue:self.userAccessToken forKey:#"accessToken"];
self.userAccessToken = nil;
}
// Make sure you cleanup on logout
- (void)logout {
self.userAccessToken = nil;
[[FBSession activeSession] closeAndClearTokenInformation];
}

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