peter flanagan
peter flanagan

Reputation: 9790

using twitter api to get token

I am trying to use the twitter api, but need to get authentication. There are 2 types , and I only need Application-only authentication aka app only. This is the type of authentication where an application makes API requests on its own behalf.

The docs explain to use this method, you need to use a bearer token. You can generate a bearer token by passing your consumer key and secret through the POST oauth2 / token endpoint.

Here is the link to docs explaining this endpoint. There is even an example request but still it isn't very clear to me what needs to be done.

I have an API key and API secret key, but am getting the following error:

body: ‘{“errors”:[{“code”:170,“message”:“Missing required parameter: grant_type”,“label”:“forbidden_missing_parameter”}]}’ }

My server side code looks like this

var request = require('request');
var btoa = require('btoa');

const KEY = encodeURIComponent('1234');
const SECRET = encodeURIComponent('5678');

request({
    headers: {
      'Authorization': 'Basic ' + btoa(`${KEY}:${SECRET}`),
      'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
    },
    uri: 'https://api.twitter.com/oauth2/token',
    method: 'POST',
    body:  JSON.stringify({
      'grant_type': 'client_credentials' // I am passing the grant_type here
    })
  }, function (err, res, body) {
    console.log('res', res)
  });

The CURL request in the docs looks like the following:

POST /oauth2/token HTTP/1.1
Host: api.twitter.com
User-Agent: My Twitter App v1.0.23
Authorization: Basic eHZ6MWV2R ... o4OERSZHlPZw==
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 29
Accept-Encoding: gzip

grant_type=client_credentials

Upvotes: 2

Views: 1763

Answers (2)

Khushneet
Khushneet

Reputation: 896

For Swift 5

        let configuration = URLSessionConfiguration.default
        let session = URLSession(configuration: configuration)

        let info = Bundle.main.infoDictionary
        let twitterConsumerKey : String = (info?["TwitterConsumerKey"] as? String)!
        let twitterConsumerSecret : String = (info?["TwitterConsumerSecret"] as? String)!

        let loginString = String(format: "%@:%@", twitterConsumerKey, twitterConsumerSecret)
        let loginData = loginString.data(using: String.Encoding.utf8)!
        let base64LoginString = loginData.base64EncodedString()

        let urlString = NSString(format: "https://api.twitter.com/oauth2/token");
        print("url string is \(urlString)")
        let request : NSMutableURLRequest = NSMutableURLRequest()
        request.url = NSURL(string: NSString(format: "%@", urlString)as String) as URL?
        request.httpMethod = "POST"
        request.timeoutInterval = 30
        request.httpBody = "grant_type=client_credentials".data(using: String.Encoding.utf8)!

        request.addValue("application/x-www-form-urlencoded;charset=UTF-8", forHTTPHeaderField: "Content-Type")
        request.addValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")

        let dataTask = session.dataTask(with: request as URLRequest) {data, response, error -> Void in
            guard let httpResponse = response as? HTTPURLResponse,
                let receivedData = data else {
                    print("error: not a valid http response")
                    return
            }

            switch (httpResponse.statusCode)
            {
            case 200:

                let response = NSString (data: receivedData, encoding: String.Encoding.utf8.rawValue)


                if response == "SUCCESS"
                {

                }

            default:
                print("save profile POST request got response \(httpResponse.statusCode)")
                let str = String(decoding:data!, as: UTF8.self)

                print(str)

            }
        }
        dataTask.resume()

The problem is with the format of http body of request. I was wrongly using dictionary of grant_type : client_credentials instead of string grant_type= client_credentials.

request.httpBody = try! JSONSerialization.data(withJSONObject: ["grant_type" : "client_credentials"], options: [])

Upvotes: 1

peter flanagan
peter flanagan

Reputation: 9790

To to this there were a couple of things. First the request needed to be made server side. You need to install btoa from npm to provide the encoding of the key and secret key. The KEY and SECRET need to be separated by a colon. The body of the request needs to be a string of

'grant_type=client_credentials'

See full code example below.

const btoa = require('btoa');

request({
    headers: {
      'Authorization': 'Basic ' + btoa(`${KEY}:${SECRET}`),
      'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
    },
    uri: 'https://api.twitter.com/oauth2/token',
    method: 'POST',
    body: 'grant_type=client_credentials'
  }, (error, response, body) => {
    const token = JSON.parse(body).access_token;
  });

Upvotes: 2

Related Questions