Twitter SLRequest Authentication Error - ios

I have been trying to retrieve twitter user data utilizing the built in iOS Accounts and Twitter frameworks.
I am getting access to the user account on the phone successfully. However, when making the SLRequest to twitter I receive an non authenticated error. I was under the impression that assigning the user ACCount to the twitter SLRequest.account fulfilled the OAuth parts necessary.
Code is from test project I have set up
Any feedback is greatly appreciated!
var accountsArray = AnyObject
var account = ACAccount()
override func viewDidLoad() {
super.viewDidLoad()
let accountStore: ACAccountStore = ACAccountStore()
let twitterAccountType: ACAccountType = accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)
let url = NSURL(string: "https://api.twitter.com/1.1/users/show.json")
let params: NSDictionary = ["field": "user_id, screen_name"]
accountStore.requestAccessToAccountsWithType(twitterAccountType, options: nil, completion: { (success, error) -> Void in
if success {
let account = accountStore.accountsWithAccountType(twitterAccountType)
if let userAccount = account.first as? ACAccount {
self.accountsArray.append(userAccount)
let twitterRequest = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: SLRequestMethod.GET, URL: url, parameters: params as [NSObject : AnyObject])
From what i have found i thought the line below covered the OAuth requirement for twitter api version 1.1
twitterRequest.account = userAccount
twitterRequest.performRequestWithHandler({ (responseData : NSData?, urlResponse : NSHTTPURLResponse?, error : NSError?) -> Void in
print("data : \(responseData)")
if let response = responseData {
var dict = NSDictionary()
do {
dict = try! NSJSONSerialization.JSONObjectWithData(response, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
}
print(dict)
} else if error != nil {
print("Error : \(error)")
}
})
}
} else if (error != nil) {
print("nooope")
}
})
}
}
Whats returned from the dictionary:
{
errors = (
{
code = 50;
message = "User not found.";
}
);
}

params dictionary should be:
["screen_name": "username"]

Related

Can't make multiple FBSDKGraphRequests

I'm trying to read the posts from a Facebook page using the following code:
class FacebookGraphAPI {
class func getPosts(fromPageWithID pageId: String, parameters: [String: AnyObject]?, completion: #escaping ([FacebookPost]?, Error?) -> Void) {
self.getAccessToken { (accessToken, error) in
if error != nil {
completion(nil, error)
return
}
let params = ["access_token": accessToken, "fields": "created_time,message,story"]
if let request = FBSDKGraphRequest(graphPath: "\(pageId)/posts", parameters: params) {
request.start { (connection, result, error) in
if error != nil {
completion(nil, error)
return
}
guard let resultDict = result as? [String: AnyObject],
let data = resultDict["data"] as? NSArray
else {
completion(nil, nil)
return
}
var posts = [FacebookPost]()
for item in data {
posts.append(FacebookPost(dict: item as! NSDictionary))
}
completion(posts, nil)
}
}
completion(nil, nil)
}
}
class func getAccessToken(completion: #escaping (String?, Error?) -> Void) {
let clientId = Bundle.main.object(forInfoDictionaryKey: "FacebookAppID") as! String
let clientSecret = Bundle.main.object(forInfoDictionaryKey: "FacebookAppSecret") as! String
let params = ["client_id": clientId, "client_secret": clientSecret, "grant_type": "client_credentials", "fields": "access_token"]
if let request = FBSDKGraphRequest(graphPath: "oauth/access_token", parameters: params) {
request.start(completionHandler: { (connection, result, error) in
if error != nil {
completion(nil, error)
return
}
guard let resultDict = result as? [String: AnyObject] else {
completion(nil, nil)
return
}
let accessToken = resultDict["access_token"] as! String
completion(accessToken, nil)
})
}
}
}
Which I then call using e.g. the following:
FacebookGraphAPI.getPosts(fromPageWithID: "{page-id}", parameters: ["limit": 5 as AnyObject]) { (posts, error) in
guard error == nil else { return }
...
}
The error I'm getting is: -[_SwiftValue length]: unrecognized selector sent to instance on the second FBSDKGraphRequest start.
I tried removing the first FBSDKGraphRequest and then I at least get a response in the completionHandler. It almost seams as if I can't make more than one FBSDKGraphRequest.
Any help is greatly appreciated.
Thanks in advance!
I finally managed to find the issue, when thinking about the error and remembering that the FBSDKCoreKit framework was written in Objective-C.
All I needed to do was cast accessToken inside the parameters array to an NSString.
I changed the following:
let params = ["access_token": accessToken, "fields": "created_time,message,story"]
To:
let params = ["access_token": accessToken! as NSString, "fields": "created_time,message,story"]

Twitter OAuth on iOS

I need to register on our server via twitter. I made registration with help of OAuth. When we make any request on our server we check our token is active, if our token is expired we make resign on our server and I need to resign in Twitter session, I do logout, but session is active. Android team do it with help
TwitterCore.getInstance().getSessionManager().clearActiveSession();
TwitterCore.getInstance().logOut();
. How can I do it on iOS? I use Swift Please, help me.
My code
func auth(userEmail: String?, successLoginCallback: ((usr : User) -> Void)?, failLoginCallback: ( (message: String) -> Void )?) {
Twitter.sharedInstance().sessionStore.reloadSessionStore()
Twitter.sharedInstance().startWithConsumerKey(twitterKey, consumerSecret: twitterSecret)
Twitter.sharedInstance().logInWithCompletion { (session, error) in
if session != nil {
TWTRAPIClient.clientWithCurrentUser().requestEmailForCurrentUser({ (twitterEmail, error) in
// oauth parameters
let oauthSession = TWTRSession(authToken: session!.authToken, authTokenSecret: session!.authTokenSecret, userName: session!.userName, userID: session!.userID)
let oauthSigning = TWTROAuthSigning(authConfig: Twitter.sharedInstance().authConfig, authSession: oauthSession)
let headers = oauthSigning.OAuthEchoHeadersToVerifyCredentials()
guard let authHeaders = headers as? [String : AnyObject] else {
return
}
var passEmail: String?
if userEmail != nil {
passEmail = userEmail
}
UserManager.sharedManager.logInViaTwitter(passEmail, parameters: authHeaders, success: { (user) in
self.userIsLogginedViaTwitter = true
self.twitterSuccessLogin(user)
print("user token", user.token?.expr)
successLoginCallback?(usr: user)
}, fail: { (errorMessage) in
if errorMessage != nil {
self.twitterFailsLogin(errorMessage!)
failLoginCallback?(message: errorMessage!)
}
})
})
}
if error != nil {
print(error?.localizedDescription)
}
}
}
func logOut(success: (() -> ())?) {
Twitter.sharedInstance().startWithConsumerKey(twitterKey, consumerSecret: twitterSecret)
guard let userID = Twitter.sharedInstance().sessionStore.session()?.userID else { return }
Twitter.sharedInstance().sessionStore.logOutUserID(userID)
userIsLogginedViaTwitter = false
let cookieStorage: NSHTTPCookieStorage = NSHTTPCookieStorage.sharedHTTPCookieStorage()
cookieStorage.cookies?.forEach({ (cook) in
cookieStorage.deleteCookie(cook)
})
success?()
}
// MARK: - Twitter functions
func logInViaTwitter(email: String?, parameters: [String : AnyObject], success: ((user: User) -> ())?, fail: ((errorMessage: String?) -> ())?) {
let url = "\(Networking.baseUrl)/auth/login/tw"
guard let oauth_url = parameters["X-Auth-Service-Provider"] as? String else { return }
guard let oauth_params = parameters["X-Verify-Credentials-Authorization"] as? String else { return }
var passParameters = [String : AnyObject]()
if email != nil {
passParameters = ["email" : email!, "oauth_url" : oauth_url, "oauth_params": oauth_params]
} else {
passParameters = ["oauth_url" : oauth_url, "oauth_params": oauth_params]
}
print("Twitter manager passParameters", passParameters, "Twitter manager passParameters")
Networking.manager.request(.POST, url, parameters: passParameters, encoding: .JSON, headers: nil).responseObject { (response: Response<RegisterResponse, NSError>) in
guard let result = response.result.value else {
fail?(errorMessage: nil)
return
}
if result.meta?.errors.count == 0 {
print(result.response)
guard let user = Mapper<User>().map(result.response) else {
fail?(errorMessage: nil)
return
}
// Save state in Twitter manager
TwitterManager.sharedManager.userIsLogginedViaTwitter = true
self.saveCurrentUser(user)
success?(user: user)
} else {
fail?(errorMessage: result.meta?.errors.first?.message)
}
}
}
We have changed the query logic, so that with every request we did not request information from the Twitter framework.

can not get twitter user details in swift

I am trying to load twitter user details using this code
#IBAction func twitterLogin(sender: UIButton) {
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter) {
let accountType = self.accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)
accountStore.requestAccessToAccountsWithType(accountType, options: nil, completion: { (granted : Bool, error : NSError?) -> Void in
if error != nil {
print("Error in getting permission : \(error)")
} else {
if granted {
let accounts : NSArray = self.accountStore.accountsWithAccountType(accountType)
if accounts.count > 0 {
self.twitterAccount = accounts.lastObject as? ACAccount
let url = NSURL(string: "https://api.twitter.com/1.1/users/show.json")
let parameters : NSDictionary = ["fields": "user_id,screen_name"]
let twitterRequest : SLRequest = SLRequest(forServiceType: SLServiceTypeFacebook, requestMethod: SLRequestMethod.GET, URL: url, parameters: parameters as [NSObject : AnyObject])
twitterRequest.account = self.facebookAccount
twitterRequest.performRequestWithHandler({ (responseData : NSData?, urlResponse : NSHTTPURLResponse?, error : NSError?) -> Void in
if error != nil {
print("Error : \(error)")
} else {
// print("data : \(responseData)")
if let response = responseData {
var dict = NSDictionary()
do {
dict = try! NSJSONSerialization.JSONObjectWithData(response, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
} catch let error as NSError {
print("Error : \(error)")
}
print(dict)
}
}
})
}
} else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.showAlert(nil, message: "Permission not granted")
})
}
}
})
} else {
self.askForSettingsChange("No Twitter Account", message: "There are no Twitter accounts configured. You can add or create Twitter account in Settings")
}
}
output
{
errors = (
{
code = 215;
message = "Bad Authentication data.";
}
);
}
Get many examples but cannot get proper solution.
I think that may be problem in api call or may be parameters.
Try to correct but no success
Fabric is sdk which is providing twitter login with easy authentication via either guest or user login.
Twitter login using Fabric
Sample Code written in Swift https://docs.fabric.io/ios/twitter/index.html
If you want to use raw REST calls against the API, follow the OAuth details in developer documentation
https://dev.twitter.com/oauth

Get ACAccount after login with Twitter SDK from Fabric Swift

I need a way to get ACAccount which is created, or taken by Twitter SDK provided by Fabric while login with:
Twitter.sharedInstance().logInWithCompletion { (session: TWTRSession?, error: NSError?) -> Void in
if let userSession = session {
}
else {
}
}
I need this account, to use while posting in background with SLRequest. Without account is not working.
If you are already using Twitter SDK, no need to deal with ACAccount anymore.
Just follow their instructions, and you can build a request manually:
Build TW Request manually
Here is that code updated for Swift 2:
if let userID = Twitter.sharedInstance().sessionStore.session()?.userID {
let client = TWTRAPIClient(userID: userID)
let statusesShowEndpoint = "https://api.twitter.com/1.1/statuses/update.json"
var clientError : NSError?
let request = client.URLRequestWithMethod("POST", URL: statusesShowEndpoint, parameters: dictMessage, error: &clientError)
if let err = clientError {
print("Error: \(err)")
}
else {
client.sendTwitterRequest(request) { (response, data, connectionError) -> Void in
if (connectionError == nil) {
do {
if let dictTWData = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as? [String: AnyObject] {
print("\(dictTWData)")
}
}
catch _ as NSError {
}
catch {
fatalError()
}
}
else {
print("Error: \(connectionError)")
}
}
}
}

how to get posts from facebook page using GraphAPI in swift

My app had a functionality which is : get posts from Facebook page and show it in the app.
i searched and i found that i should use Facebook GraphAPI :
https://developers.facebook.com/docs/graph-api/using-graph-api/v2.3#reading
i follow the previous link, but i get error :
"An access token is required to request this resource."
i have the access token for the page, but i really don't know how to assign it in my request.
any help please?
thanks a lot!
1. Using Facebook SDK.
LOGIN FACEBOOK BUTTON
#IBAction func click_Facebook(sender: AnyObject)
{
let loginView : FBSDKLoginManager = FBSDKLoginManager()
loginView.loginBehavior = FBSDKLoginBehavior.Browser
loginView.logInWithReadPermissions(["public_profile","user_friends","user_photos","user_location","user_education_history","user_birthday","user_posts"], handler: { (result : FBSDKLoginManagerLoginResult!, error : NSError!) -> Void in
if ((error) != nil)
{
// Process error
self.alertWithMessaage(error.localizedDescription)
}
else if result.isCancelled {
// Handle cancellations
}
else {
self.returnUserData()
}
})
}
After login calling the below function.
var Requset : FBSDKGraphRequest
println("\(FBSDKAccessToken.currentAccessToken())")
var acessToken = String(format:"%#", FBSDKAccessToken.currentAccessToken().tokenString) as String
println("\(acessToken)")
var parameters1 = ["access_token":FBSDKAccessToken.currentAccessToken().tokenString]
Requset = FBSDKGraphRequest(graphPath:"me/posts", parameters:parameters1, HTTPMethod:"GET")
Requset.startWithCompletionHandler({ (connection, result, error) -> Void in
MBProgressHUD.hideHUDForView(appDelegate.window, animated: true)
if ((error) != nil)
{
println("Error: \(error)")
}
else
{
println("fetched user: \(result)")
var dataDict: AnyObject = result!.objectForKey("data")!
}
})
}
2. Using Default Facebook App.
// Get Access TOKEN
var _accountStore: ACAccountStore = ACAccountStore()
var accountType : ACAccountType = _accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook)!
var accounts : NSArray = _accountStore.accountsWithAccountType(accountType)!
var facebookAccount1: ACAccount = accounts.lastObject! as ACAccount
println("== \(facebookAccount1.credential.oauthToken)")
// Pass AccessToken To Parameter
var acessToken = String(format:"%#", facebookAccount1.credential.oauthToken) as String
var parameters = ["access_token":acessToken] as NSDictionary
//SLRequset
var imageURL : NSURL = NSURL(string: "Your graph URL")!
println("=== TOKEN : \(LoginService().currentAccount?.credential.oauthToken)")
var Requset = SLRequest(forServiceType: SLServiceTypeFacebook, requestMethod: SLRequestMethod.GET, URL: imageURL, parameters: parameters)
Requset.account = account
Requset.performRequestWithHandler { (responseData : NSData!, urlResponse : NSHTTPURLResponse!, error : NSError!) -> Void in
if (error != nil)
{
self.alertWithMessaage(error.localizedDescription)
}
else{
var datastring = NSString(data: responseData, encoding: NSUTF8StringEncoding)
println("== \(datastring)")
var error:NSError? = nil
var UserDict = NSJSONSerialization.JSONObjectWithData(responseData, options:nil, error: &error) as? NSDictionary
}
}
Swift 4.2 Update Code
in your viewDidLoad()
create faceBook Button for Login and Logout.
let loginButton = FBLoginButton(permissions: [ .publicProfile, .email, .userPosts, .userPhotos])
loginButton.center = view.center
view.addSubview(loginButton)
Now Create Function to get FaceBook Posts
func getPosts() {
let accessToken = AccessToken.current?.tokenString
let params = ["access_token" : accessToken ?? ""]
let request = GraphRequest(graphPath: "/me/posts/", parameters: params, httpMethod: .get)
request.start(completionHandler: { (test, result, error) in
if(error == nil)
{
print(result!)
}
})
}
In result you will get Data of your facebook posts!

Resources