ElixirのTwitter OAuthライブラリ "ExTwitter" の使い方

公開:2021/01/02
更新:2021/01/02
5 min読了の目安(約4500字TECH技術記事

ritou です。

Elixir で Twitter の OAuth をごにょごにょするためのライブラリである "ExTwitter" の使い方メモです。

ExTwitter

extwitter | Hex

裏ではOAuth 1.0用のライブラリを使っているようですね。

oauther | Hex

使い方

何が行われるか

OAuth 1.0(1.0aとか呼ばれてるやつ) の処理を大きく4段階に分けます。

  1. Temporary Credentials : Request Token/Request Token Secretを取得
  2. Resource Owner Authorization : Twitterにリダイレクトしてリソースアクセスに対するリソースオーナーの許可を得る
  3. Token Credentials : Access Token/Access Token Secretを取得
  4. Authenticated Requests : リソースアクセス

基本的に、プロトコルが OAuth 1.0でも2.0でも今後出てくる新しいやつでも、処理の比重が変わるだけでこの4つの段階を踏んでリソースアクセスが行われます。

設定

Consumer Key/Secret をConfigに持つか、手動でセットして使います。

# 0. Configure

iex(1)> twitter_consumer_key = "(masked)"
"(masked)"

iex(2)> twitter_consumer_secret = "(masked)"
"(masked)"

iex(3)> redirect_url = "http://localhost:3000/cb"
"http://localhost:3000/cb"

iex(4)> ExTwitter.configure(
...(4)>   :process, # プロセス単位の指定も可能
...(4)>   consumer_key: twitter_consumer_key,
...(4)>   consumer_secret: twitter_consumer_secret
...(4)> )
:ok

最初の引数で :process とするとプロセス単位の指定もできるので、各種トークンをセットする場合は利用する方が良いかもしれません。

1. Temporary Credentials

まずはRequest Token/Secretを取得します。

# 1. Temporary Credentials

iex(5)> request_token = ExTwitter.request_token(redirect_url)
#ExTwitter.Model.RequestToken<
  oauth_callback_confirmed: "true",
  oauth_token: "6xR8F(masked)",
  oauth_token_secret: "3T3Zl(masked)",
  ...
>

実際のプロダクトでは、取得した Request Token/Request Token Secretをセッションに紐付けて保持しておく必要があります。

2. Resource Owner Authorization

TwitterにリダイレクトするためのURLにはRequest Tokenの値が含まれます。

# 2. Resource Owner Authorization

iex(6)> {ok, authorize_url} = ExTwitter.authorize_url(request_token.oauth_token)
{:ok,
 "https://api.twitter.com/oauth/authorize?oauth_token=6xR8F(masked)"}

3. Token Credentials

リソースアクセスについてのリソースオーナーの許可をもらうと、Twitterからは以下のようなURLに戻されます。

http://localhost:3000/cb?oauth_token=6xR8F(masked)&oauth_verifier=EyNQV(masked)

セッションに紐づいている Request Token の値と oauth_token の値が一致することを確認し、oauth_verifier の値を用いてAccess Token/Access Token Secretを取得します。

# 3. Token Credentials

iex(7)> oauth_verifier = "EyNQV(masked)"
"EyNQV(masked)"

iex(8)> {:ok, access_token} = ExTwitter.access_token(oauth_verifier, request_token.oauth_token)
{:ok,
 #ExTwitter.Model.AccessToken<
   oauth_token: "(masked)-lgZnr(masked)",
   oauth_token_secret: "YbUEZ(masked)",
   screen_name: "ritou",
   user_id: "(masked)",
   ...
 >}

※ここで、ExTwitter.access_tokenと言う関数に Request Token の値のみを渡しています。
Access Token/Access Token Secretを取得する際に Request Token Secret も署名生成に利用すると思っていましたがライブラリでも使っていないようなので、Twitterの実装がそういうことなんでしょうと言う感じです。指定して署名作っても通るのかな。もう忘れてしまいました。

気を取り直して、実際のプロダクトではAccess Token/Access Token Secretをユーザーやらセッションやらに紐づけておきます。

4. Authenticated Requests

リソースアクセスの際は、一度Configに保持した状態から関数を使います。

# 4. Authenticated Requests

iex(9)> ExTwitter.configure(
...(9)>   :process, # プロセス単位の指定にしておくのが無難そう
...(9)>   consumer_key: twitter_consumer_key,
...(9)>   consumer_secret: twitter_consumer_secret,
...(9)>   redirect_url: redirect_url,
...(9)>   access_token: access_token.oauth_token,
...(9)>   access_token_secret: access_token.oauth_token_secret
...(9)> )
:ok

iex(10)> user = ExTwitter.verify_credentials()
#ExTwitter.Model.User<
  ...
  name: "👹秋田の猫🐱",
  ...
>

エラーハンドリング

トークンを指定しないでリソースアクセスにいくと ExTwitter.Error が発生するのでハンドリングする必要がありそうです。

iex(11)> ExTwitter.configure(
...(11)>   consumer_key: twitter_consumer_key,
...(11)>   consumer_secret: twitter_consumer_secret
...(11)> )
:ok

iex(12)> user = ExTwitter.verify_credentials()                                   
** (ExTwitter.Error) Your credentials do not allow access to this resource
    (extwitter) lib/extwitter/api/base.ex:135: ExTwitter.API.Base.parse_error/2
    (extwitter) lib/extwitter/api/users.ex:10: ExTwitter.API.Users.verify_credentials/1

iex(13)> try do                                
...(13)>   ExTwitter.verify_credentials()        
...(13)> rescue                                
...(13)>   e in ExTwitter.Error -> IO.inspect(e)
...(13)> end                                  
%ExTwitter.Error{
  code: 220,
  message: "Your credentials do not allow access to this resource"
}
%ExTwitter.Error{
  code: 220,
  message: "Your credentials do not allow access to this resource"
}

まとめ

  • Configureして関数利用、と言うスタイル、プロセス単の指定も可能なのでシンプルに使えそう
  • エラーハンドリングには気をつける必要がありそう

他のOAuthのライブラリの使い方も調べたらまた書きます。
ではまた。