1

I'm using Swifter to authenticate users using SSO. Swifter generates the following URL (keys removed):

let url = URL(string:"twitterauth://authorize?consumer_key=[KEY]&consumer_secret=[SECRET]&oauth_callback=swifter-[KEY]")!

UIApplication.shared.open(url, options: [:], completionHandler: { (success) in

However when Twitter opens, only the usual app is displayed with out any opportunity to authenticate. Is there something missing here?

user11145365
  • 184
  • 9

1 Answers1

2

I will show how to (in 2021) not need to sign in every time. Please follow these steps (replace YOURAPPNAME with whatever your app name is):

  1. add YOURAPPNAME:// as a callback URL on the twitter developer portal, under authentication settings. To do this, you need to enable 3-legged OAuth, and add this in the callback URLS. You also need to enter a website URL, but it can be anything (i have https://www.google.com).

  2. in your podfile, make sure you have the line:

pod 'Swifter' , :git => 'https://github.com/mattdonnelly/Swifter.git'

DO NOT just use pod 'Swifter' because there is another project called Swifter that is not by mattdonnelly and will not work.

  1. Click on your project in the Project Explorer, select the info tab. At the bottom you will see URL Types. Expand it and click the plus sign. In the URL Schemes enter YOURAPPNAME (if your app name is "demoApp" enter demoApp not demoApp://
  2. If your app delegate isnt already using the open url function (standard is no but mine was because i have google sign in, in my case i dont need to do anything) in your app delegate import Swifter and add this function:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        
    Swifter.handleOpenURL(url, callbackURL: URL(string: "YOURAPPNAME://")!)
        
    return true
}
  1. in your view controller, you need to first authorize twitter, and then you can do whatever (tweet, lookup feeds, etc.). You can do this with swifter.authorize, which opens a brower. For those looking to not need this after the first time, that is where the swifter.verifyAccountCredentials comes in. To find CONSUMER_KEY and CONSUMER_SECRET go to the keys and tokens area of the twitter developer portal.
import Swifter
import AuthenticationServices

class ViewController: UIViewController, ASWebAuthenticationPresentationContextProviding {
    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        return self.view.window!
    }
    
    var swifter: Swifter!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        if UserDefaults.standard.string(forKey: "twitterOAuthToken") == nil {
            swifter = Swifter(consumerKey: CONSUMER_KEY, consumerSecret: CONSUMER_SECRET)
            if let url = URL(string: "YOURAPPNAME://") {
                swifter.authorize(withProvider: self, callbackURL: url) { (token, response) in
                    UserDefaults.standard.set(token?.key, forKey: "twitterOAuthToken")
                    UserDefaults.standard.set(token?.secret, forKey: "twitterOAuthSecret")
                    print("signed in!!")
                }
            }
            
        } else {
            swifter = Swifter(consumerKey: CONSUMER_KEY, consumerSecret: CONSUMER_SECRET, oauthToken: UserDefaults.standard.string(forKey: "twitterOAuthToken") ?? "", oauthTokenSecret: UserDefaults.standard.string(forKey: "twitterOAuthSecret") ?? "")
            swifter.verifyAccountCredentials(includeEntities: nil, skipStatus: nil, includeEmail: nil) { (json) in
                print("signed in!")
            } failure: { (error) in
                self.swifter = Swifter(consumerKey: CONSUMER_KEY, consumerSecret: CONSUMER_SECRET)
                if let url = URL(string: "YOURAPPNAME://") {
                    self.swifter.authorize(withProvider: self, callbackURL: url) { (token, response) in
                        UserDefaults.standard.set(token?.key, forKey: "twitterOAuthToken")
                        UserDefaults.standard.set(token?.secret, forKey: "twitterOAuthSecret")
                        print("signed in!!")
                    }
                }
            }
        }
        
        
        
       let button = UIButton()
        button.layer.backgroundColor = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1)
        button.frame = CGRect(x: 200, y:0, width: 200, height: 200)
        button.center = view.center
        button.addTarget(self, action: #selector(tweet), for: .touchUpInside)
        view.addSubview(button)

    }
    
    @objc func tweet() {
        swifter.postTweet(status: "wild") { (json) in
            print("tweeted!")
        } failure: { (error) in
            print("tweet failed")
        }
    }
}