Giuseppe Sala
Giuseppe Sala

Reputation: 373

Swift : Twitter Application-Only Authentication

I'm building an app that contains references to some shop of my city. Now I'd like to insert, in the detail view of each shop, a table with the last 3 or 5 tweet from the shop's account.

I'd like not use third party solution.

Reading the Twitter's documentation I understand that for use the Rest Services i have to authenticate my app, so I have registered the app and requested the Access Token with "read only" option, and here start the problems.

I'm not able to access the Rest service, every time I have "Authentication error" as response.

The documentation on Twitter website is here: https://developer.twitter.com/en/docs/basics/authentication/overview/application-only

where are described the three steps for the application-only auth:

  1. Encode consumer key and secret
  2. Obtain a bearer token
  3. Authenticate API requests with the bearer token

I looked for solution here:

Then on google i found this: http://rshankar.com/retrieve-list-of-twitter-followers-using-swift/

and this is my attempt:

1. first of all I created the func to encode consumer_key and consumer_secret

    let consumerKey = "xxxxxxxxxxxxxxxx"
    let consumerSecret = "xxxxxxxxxxxxxxxx"
    let authUrl = "https://api.twitter.com/oauth2/token"

    func getBase64EncodeString() -> String {
        let consumerKeyRFC1738 = consumerKey.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
        let consumerSecretRFC1738 = consumerSecret.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
        let concatenateKeyAndSecret = consumerKeyRFC1738! + ":" + consumerSecretRFC1738!
        let secretAndKeyData = concatenateKeyAndSecret.data(using: String.Encoding.ascii, allowLossyConversion: true)
        let base64EncodeKeyAndSecret = secretAndKeyData?.base64EncodedString(options: NSData.Base64EncodingOptions())
        return base64EncodeKeyAndSecret!
    }

2. then the func to obtain bearerToken

    func getBearerToken(completion:@escaping (_ bearerToken: String) -> Void) {
    var request = URLRequest(url: URL(string: authURL)!)
    request.httpMethod = "POST"
    request.addValue("Basic " + getBase64EncodeString(), forHTTPHeaderField: "Authorization")
    request.addValue("application/x-www-form-urlencoded;charset=UTF-8", forHTTPHeaderField:"Content-Type")
    let grantType = "grant_type=client_credentials"
    request.httpBody = grantType.data(using: String.Encoding.utf8, allowLossyConversion:  true)
    URLSession.shared.dataTask(with: request, completionHandler: { (data: Data?, response:URLResponse?, error: NSError?) -> Void in
        do {
            if let results: NSDictionary = try JSONSerialization .jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments  ) as? NSDictionary {
                if let token = results["access_token"] as? String {
                    completion(token)
                } else {
                    print(results["errors"]!)
                }
            }
        } catch let error as NSError {
            print(error.localizedDescription)
        }
        } as! (Data?, URLResponse?, Error?) -> Void).resume()
}

3. and finally Authenticate API requests with the bearer token

    func getResponseForRequest(url:String) {
      var results:NSDictionary
      getBearerToken(completion: { (bearerToken) -> Void in
        var request = URLRequest(url: URL(string: url)!)
        request.httpMethod = "GET"
        let token = "Bearer " + bearerToken
        request.addValue(token, forHTTPHeaderField: "Authorization")
        URLSession.shared .dataTask(with: request, completionHandler: { (data: Data?, response:URLResponse?, error: NSError?) -> Void in
            self.processResult(data!, response: response!, error: error)
            } as! (Data?, URLResponse?, Error?) -> Void).resume()
    })
}

At the moment i have a message error at the line:

    } as! (Data?, URLResponse?, Error?) -> Void).resume()

in the getBearerToken func.

The error message is:

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

so until i haven't verified if the authentication works.

Can someone help me?

Upvotes: 0

Views: 1171

Answers (1)

shilei365
shilei365

Reputation: 223

use this:

var request = URLRequest(url: url)
    request.httpMethod = HttpMethod.POST.rawValue
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.addValue("Basic \(base64)", forHTTPHeaderField: "Authorization")
    request.httpBody = "grant_type=client_credentials".data(using: .utf8)

Upvotes: 1

Related Questions