さしぐめのブログ

Web / Meme / 海外アニメコミュニティ等の雑記。IDがモンテネグロドメインを内包してるって最高。

Twitter APIのOAuth+nodejsでサブアカにツイートさせる認証

Twitter APIで、「とりあえず自分のアカウントにツイートさせる」アプリが作りたかったが、「アプリを申請したのと別のアカウントにツイートさせる」必要が出てきた。

アプリ申請者は管理画面で自分のトークンを入手できるが、サブ垢ならOAuthトークンをリクエストしないといけない。Postmanでささっとやってしまう。

※あくまで自分で使うときだけのやり方なので、第三者に認証させる時は使えません

1. アプリのコンシューマキー・シークレットを確認

f:id:sasigume:20210718115450p:plain

アプリ管理画面の「Keys and tokens」の「Regenerate」でコンシューマキーとシークレットを取得。

2. Firebaseとかに保存する

Firebaseの認証機能でTwitterログインを有効化すれば、コールバックURLを用意してくれる。

f:id:sasigume:20210718115637p:plain

コールバックURLが用意できたら、アプリに登録する。また「3-legged OAuth」を有効化して、書き込み権限もオンにする。

3. PostmanでPOST

f:id:sasigume:20210718115914p:plain

Postmanでコレクションを作り、以下のように設定する。

項目
認証方法 OAuth 1.0
Add auth data to Request Headers
Signature Method HMAC-SHA1
Consumer Key さっきのコンシューマキー
Consumer Secret さっきのシークレット
Callback URL コールバックURL
Timestamp {{$timestamp}}
nonce 適当に打つ (実製品ではちゃんと生成すること!!)
Version 1.0

そして以下のURIにPOSTする。

https://api.twitter.com/oauth/request_token?oauth_callback=URLエンコードしたコールバックURL

これでoauth_tokenoauth_token_secretが手に入る。

4. ログインしてVerifier取得

サブアカで以下のURIにアクセスする。

https://api.twitter.com/oauth/authorize?oauth_token=さっきのoauth_token

f:id:sasigume:20210718115758p:plain

プレビューすると認証画面が出る。ログインしてアクセスを許可する。

リダイレクトされたコールバックURLにoauth_verifier=確認コードが付いているので、コレクションのOAuth設定に値を追加していく。

項目
Access Token request_tokenまたはコールバックURLのoauth_token
Token Secret request_tokenのoauth_token_secret
Verifier コールバックURLのoauth_verifier

5. アクセストークン取得

新しいPOSTリクエストを作る。

https://api.twitter.com/oauth/acess_token

POSTすれば、サブアカのoauth_tokenoauth_token_secretと、ついでにuser_idscreen_nameが手に入る。

これがTwitter API v1.1の「ユーザー用トークン」である。

Firebase Functionsでの実装例

import * as functions from 'firebase-functions';
const config = functions.config() as AdminConfig;
import { TwitterClient } from 'twitter-api-client';

const post = functions.https.onRequest(async (request, response) => {
  const tweet = 'あああ';

  const client = new TwitterClient({
    apiKey: config.twitter.key,
    apiSecret: config.twitter.secret,
    accessToken: config.twitter.user_token,
    accessTokenSecret: config.twitter.user_secret,
  });

  try {
    await client.tweets
      .statusesUpdate({
        status: tweet,
      })
      .then(async (apiResponse) => {
        if (apiResponse.created_at) {
          response.status(200).json(apiResponse);
        } else {
          response.status(500).json(
            apiResponse ?? {
              message: `ERROR: No response`,
            }
          );
        }
      })
      .catch((e) => {
        response.status(500).json({
          message: `ERROR: ${e}`,
        });
      });
    return;
  } catch (e) {
    response.status(500).json({
      message: `ERROR: ${e}`,
    });
  }
  return;
});

export default post;

めちゃくちゃ適当だが、こんな感じでツイート用のREST APIが作れる。ここではWebhookを想定しているが、ちゃんと秘匿しないと第三者にツイートされまくるので注意。

参考

https://gist.github.com/0mg/5276918

Copyright © 2021 Ryo Ando. Built w/ Love & Hatena Blog.