AWSJavaScriptServerless FWTwitter

AWSとTwitter API v2を利用して、自動ツイートシステムを作る方法

Twitter APIのV2への移行により、APIの認証フローやトークンの管理をAWS上で行う方法が紹介されています。SSMリソースをIaCで定義することで、OAuthクライアントシークレットを取得する方法、ツイートのリクエスト内容についての解説、Secrets Storeの使用方法が紹介されています。個人利用で廉価に利用したい場合、Systems Manager Parameter Storeを利用し、GetParameterCommandとPutParameterCommandを利用した処理をすることが推奨されています。また、2つのクラスを利用するOAuthで認証してAPIを利用する方法も紹介されています。

広告ここから
広告ここまで

Twitter APiがV2に変わりましたが、少量のツイートであれば引き続き無料で使うことができます。

APIの認証フローやトークンの管理をAWS上で行う方法を簡単にまとめました。

紹介しないこと

この辺りの内容は今回紹介しません。

  • generateAuthURLrequestAccessTokenを利用した、OAuthクライアントシークレットの取得方法
  • SSMリソースをIaCで定義する方法
  • ツイートのリクエスト内容の解説

Systems ManagerのParameter Storeで手軽に管理する

Secrets Storeを使う方が良いとは思いますが、個人利用で廉価に使いたいため、Systems Manager Parameter Storeを利用します。

使うコマンドは、GetParameterCommandPutParameterCommandの二つで良さそうです。

serverless.tsの場合は、こんな感じでIAMロールを設定しましょう。

    iam: {
      role: {
        statements: [{
          Effect: 'Allow',
          Action: [
            'ssm:GetParameter',
            'ssm:PutParameter'
          ],
          Resource: [
            "arn:aws:ssm:us-west-2:123456:parameter/TWITTER_OAUTH*",
            "arn:aws:ssm:us-west-2:123456:parameter/TWITTER_TOKEN*"
          ]
        }]
      }
    }
  }

取得と更新処理は、次のようなクラスを作りました。

実際にはTypeScriptの型が付いていますが、抽象化させている部分が説明には冗長なので削りました。

import { GetParameterCommand, PutParameterCommand, SSMClient } from "@aws-sdk/client-ssm";

export class SSMSecretManager{
    private readonly client
    constructor(config) {
        this.client = new SSMClient(config)
    }
    public async getSecretsByName(keyName) {
        const getParameterCommand = new GetParameterCommand({
            Name: keyName,
            WithDecryption: true
        })
        const response = await this.client.send(getParameterCommand)
        if (!response.Parameter || !response.Parameter.Value) {
            return null;
        }
        const value = JSON.parse(response.Parameter.Value)
        return value
    }
    public async updateSecrets(keyName, value) {
        const updateSecretCommand = new PutParameterCommand({
            Name: keyName,
            Overwrite: true,
            Type: "SecureString",
            DataType: 'text',
            Value: JSON.stringify(value),
        })
        await this.client.send(updateSecretCommand)
    }
}

2つの秘密情報を取得する

SSMには2つのデータを保存しています。

1つはOAuth用のクライアントシークレットなどの情報、もう1つはアクセストークン・リフレッシュトークンなどです。

const client = new SSMSecretManager({ region: 'us-west-2' })
const clientSecrets = await client.getSecretsByName('TWITTER_OAUTH_CLIENT_SECRETS')
const token = await client.getSecretsByName('TWITTER_TOKEN')

また、取得したトークンが期限切れしている場合は、更新処理が必要です。

const diffFromTheExpiresAt = new Date(token.expires_at).getTime() - new Date().getTime()
if (diffFromTheExpiresAt < 0) {
    // Refresh access token
}

Twitter API v2では、2つのクラスを利用する

OAuthで認証してAPIを利用するため、auth.OAuth2UserClientの2クラスを利用しました。

const authClient = new auth.OAuth2User({
    ...clientSecrets,
    token,
})
const client = new Client(authClient)

クライアントシークレットとアクセストークンの両方を利用しますので、SSMの戻り値を合成して利用しましょう。

アクセストークンを更新する場合、更新後のレスポンスをtokenに再設定します。

const newToken = await authClient.refreshAccessToken()
const client = new Client(new auth.OAuth2User({
    ...clientSecrets,
    token: newToken.token,
}))

SSMでリフレッシュしたアクセストークンを保存する

リフレッシュすると、以前のアクセストークンは利用できません。SSMの値も更新しましょう。

SSMのパラメーターストアには「更新操作」はなく、「上書き」になることに注意が必要です。

上のサンプルコードを再掲しますが、暗号化などの設定も明示的に行うことをお勧めします。


    public async updateSecrets(keyName, value) {
        const updateSecretCommand = new PutParameterCommand({
            Name: keyName,
            Overwrite: true,
            Type: "SecureString",
            DataType: 'text',
            Value: JSON.stringify(value),
        })
        await this.client.send(updateSecretCommand)
    }

関連

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts