LoginSignup
0
0

More than 1 year has passed since last update.

ChatworkのOAuthフローをDockerを使ってPoCする

Last updated at Posted at 2021-12-03

経緯

とあるプロジェクトでChatworkとの連携機能を設計することになり、PoC(概念実証)を行いました。検証の過程でローカル環境を汚したくなかったのと、HTTPSサーバ環境をサクッと構築したかったのでDockerを使うことにしました。

準備

Chatwork OAuthクライアントの作成

Chatworkのサービス連携 > OAuth からOAuthクライントを作成します。
クライアント名はお好みで設定して構いません。
リダイレクト先URLにはこれから作成するlocalhostサーバのURL(https://localhost:3443/oauth )を入力します。
スクリーンショット_2021-07-27_14.51.56.png
クライアントの作成が完了すると、クライアントIDとクライアントシークレットが発行されます。これらは後ほど使いますので控えておきます。
スクリーンショット_2021-07-27_14_53_18.png

docker-compose.ymlの作成

手軽にHTTPSサーバ環境を構築するために https-portal というコンテナを使用します。https-portal は自己署名証明書(オレオレ証明書)の発行までやってくれるのでとても便利です。
アプリケーションサーバには Express.js を使用するのでNode.jsのコンテナを使用します。プロジェクトのサーバ環境がGoogle Cloud PlatformなのでNode.jsのバージョンは12を選びました。

docker-compose.yml

version: '3'
services:
  https-portal:
    image: steveltn/https-portal:1
    ports:
      - '3443:443'
    environment:
      STAGE: local
      DOMAINS: 'localhost -> http://app:3000'
    volumes:
      - ./https-portal-data:/var/lib/https-portal

  app:
    image: node:12
    env_file: ./app.env
    environment:
      - TZ=Asia/Tokyo
      - DEBUG=app:*
    tty: true
    volumes:
      - ./src:/app
    working_dir: /app
    command: npm start

Express.jsの環境構築

express-generatorで雛形を生成

コンテナのコンソールからExpress.js の雛形を生成します。
今回はviewにEJSを使用するので、オプションに--view=ejsを加えます。
また、ChatworkのAPIを実行するためにaxiosを使用するのでパッケージをインストールしておきます。

$ docker-compose run --rm app bash
$ npx express-generator --view=ejs
$ npm i axios --save
$ npm install
$ exit

環境変数の定義

app.env

Express.jsで使用する環境変数を定義します。ルームIDはブラウザのURLから取得できます。
スクリーンショット_2021-07-27_15_06_37.png

# クライアントID
CLIENT_ID=[OAuthクライアント作成で生成したクライアントID]

# クライアントシークレット
CLIENT_SECRET=[OAuthクライアント作成で生成したクライアントシークレット]

# メッセージのテスト送信に使用するRoom ID
TEST_ROOM_ID=999999999

OAuthリダイレクト用のRouterを追加

今回は /oauth というパスを用意することにしました。

src/app.js

...
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var oauthRouter = require('./routes/oauth'); // <- 追加
...
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/oauth', oauthRouter); // <- 追加

/oauth ではアクセストークンの取得とテストメッセージの送信を直列で行うようにします。実際は取得したトークンをDBへ保存したりする処理が必要になりますが、PoCなのでそこまでは実装しません。

src/routes/oauth.js

const express = require('express');
const router = express.Router();

// axios
const axiosBase = require('axios');
const axios = axiosBase.create({
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-Requested-With': 'XMLHttpRequest',
  },
  responseType: 'json',
});

router.get('/', async function (req, res, next) {
  let isSuccess = false;

  try {
    /**
     * Access Tokenを取得する
     */
    var tokenParams = new URLSearchParams();
    tokenParams.append('grant_type', 'authorization_code');
    tokenParams.append('code', req.query.code);

    const authKey = Buffer.from(
      process.env.CLIENT_ID + ':' + process.env.CLIENT_SECRET,
      'utf-8'
    ).toString('base64');

    const tokenResult = await axios.post(
      'https://oauth.chatwork.com/token',
      tokenParams,
      {
        headers: {
          Authorization: `Basic ${authKey}`,
        },
      }
    );
    const token = tokenResult.data.access_token;

    /**
     * テストメッセージを送信する
     */
    var messageParams = new URLSearchParams();
    messageParams.append('body', 'Hello!');

    const messageResult = await axios.post(
      `https://api.chatwork.com/v2/rooms/${process.env.TEST_ROOM_ID}/messages`,
      messageParams,
      {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      }
    );

    console.log(messageResult.data);
    isSuccess = true;
  } catch (error) {
    console.error(error);
    isSuccess = false;
  }

  res.render('oauth', {
    isSuccess,
  });
});

module.exports = router;

結果表示用のviewファイルも追加します。

src/views/oauth.ejs

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="/stylesheets/style.css" />
  </head>
  <body>
    <% if (isSuccess) { %> Success!! <% } else { %> failure... <% } %>
  </body>
</html>

動かしてみる

ターミナルからdocker-compose を実行します。ログが見えるようにフォアグラウンドで実行することにします。

$ docker-compose up

全てのコンテナが問題なく起動したら、下記のURLからOAuth認証フローを開始します。stateはPoCでは使用しないので適当な文字列を設定しておきます。

https://www.chatwork.com/packages/oauth2/login.php?response_type=code&client_id={client_id}&state={state}&scope=offline_access%20rooms.messages:write

「許可」ボタンをクリックします。
スクリーンショット_2021-07-27_14.48.20.png
ブラウザにSuccess!!と表示されていればメッセージの送信まで成功していますのでChatworkのチャンネルを確認してみましょう。
スクリーンショット_2021-07-27_14.37.41.png
チャンネルにメッセージが送信されていることが確認できました。
スクリーンショット_2021-07-27_14_40_06.png

まとめ

Dockerとhttps-portalを使うことで面倒なHTTPSサーバの準備も極めて簡単に構築することができました。OAuth認証のリダイレクトURLにはHTTPSプロトコルを要求されるケースが多いので、他のサービス連携の調査にも活用できると思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0