Go言語でのTwitterAPI anacondaの認証で悩んだところ


GoのTwitterAPI Anacondaの認証で悩んだところのメモ

前提

この記事では、WSLのUbuntu 18.04.2 LTS上にインストールしたgo1.10.4
Twitter API AnacondaはVer1.1を利用しています。
また、コード内に出てくるConsumerKey,ConsumerSecretは別の場所で定義しています。
必要に合わせて書き換えてみてください。

きっかけ

コンソール上で一定時間間隔で自動更新する自分用のTwitterクライアントを作ろうと思ったのと、
Go言語を勉強しようと思っていたので、ちょうどいいからGoでTwitterクライアントを作ることにしました。

少し調べてみると、anacondaというGo言語用のTwitterAPIを見つけたのでこれを利用してみることに。

Twitterクライアント自体は過去にもjavaで作った(大したものじゃないけど)ので、なんとなくの流れは
知っていました。

雑な私の認識(間違ってたらごめんなさい)


  1. TwitterDeveloperでアプリケーションの登録(ConsumerKey,ConsumerSecretを得る)
  2. アプリケーション内でConsumerKeyとConsumerSecretを使ってAccessTokenとAccessTokenSecretを取得
    (よく見るアプリケーション連携の画面)
  3. AccessTokenとAccessTokenSecretを利用してOAuth認証し、TwitterAPIを作成
  4. 作成したTwitterAPIからツイートの投稿やツイートの検索・取得などをする

とりあえずanacondaのページのサンプルからTwitterAPIを作ろうと思った

1を済ませて、2をやろうと思ってサンプルコードを見たところ、

api := anaconda.NewTwitterApiWithCredentials("your-access-token", "your-access-token-secret", "your-consumer-key", "your-consumer-secret")

このように書けば認証できるらしい。

TwitterDeveloperのAppのページからAccessTokenの画面でCreateとすれば自分用のアクセストークンを取得することはできますが(下記画像の下のボタン)、この方法だと自分用しか作れないし、間違えてコードをpublicにしてしまったらアカウントを乗っ取られたりしそうで怖いと思ったので、よく見るPIN認証の方法がないかなと思ってAPIを眺めていました。

見てみた感じ、
func (*TwitterApi) AuthorizationURLがなんだかそれっぽい

func (c *TwitterApi) AuthorizationURL(callback string) (string, *oauth.Credentials, error)
AuthorizationURL generates the authorization URL for the first part of the OAuth handshake. Redirect the user to this URL. This assumes that the consumer key has already been set (using SetConsumerKey or NewTwitterApiWithCredentials).

この関数を呼び出すと認証のURLを作成してくれるらしい。認証後にcallbackのURLにリダイレクトしてくれるみたい。
え、このコールバックって何入れればいいの?ってまずなりました。
とりあえず、適当に自分のサイトのURLを入れて関数を呼び出してみました。
表示されたURL(fmt.Printlnで表示してクリックしました)で連携を認証すると、PINが表示されることもなく自分のサイトに(当たり前)

どうやら調べてみると、URLにoob(out-of-bandの略らしいです)と指定すると認証画面の後にPINが表示されました。
uri,cred,err := api.AuthorizationURL("oob")
こんな感じ。

そのあと
func (*TwitterApi) GetCredentialsにAuthorizationURLで得た認証情報(*oauth.Credentials)と表示されたPIN情報(string)を渡し、得ることが出来る(*oauth.Credentials)の中にあるAccessTokenとAccessTokenSecretを利用することで目的の認証に成功しました。

Code

getAuth()
func getAuth() (*anaconda.TwitterApi,error){
    //ConsumerKey,ConsumerSecretの設定
    anaconda.SetConsumerKey(ConsumerKey)
    anaconda.SetConsumerSecret(ConsumerSecret)
    //AuthorizationURL,GetCredentialsは*anaconda.TwitterAPIのメソッドなので
    //空のTwitterApiを作成して呼び出ししています。
    api := anaconda.NewTwitterApi("","")

    //oobを指定してPIN認証画面へ
    uri,cred,err := api.AuthorizationURL("oob")

    if err != nil{
        return nil,err
    }   
    fmt.Println("次のURLで表示されるPINを入力してね")
    fmt.Println(uri)

    stdin := bufio.NewScanner(os.Stdin)
    fmt.Printf("PIN -> ")
    stdin.Scan()
    oauth_verifier := stdin.Text()

    cred,_,err = api.GetCredentials(cred,oauth_verifier)
    if err != nil{
        return nil,err
    }
    //credの中にTokenとSecretが入っている
    api = anaconda.NewTwitterApi(cred.Token,cred.Secret)    
    fmt.Println("authorize successful")
    return api,err
}

参考にさせていただいたサイト等

anaconda
Twitter 開発者 ドキュメント日本語訳:PINベース認証