bpeldi2oerkd8の開発日誌

とあるひよっこエンジニアの成長の記録。

認証付きAPIを作る前準備 - 自作サービスづくり8

今回もWeb開発に関する記事です。
前回はbotを使った出欠確認・更新機能の実装を行いました。
developer-bpeldi2oerkd8.hatenablog.com

しかし、作成したAPIには認証がありません。
このため、URLさえわかってしまえば、APIを無関係の方が叩けてしまいます。
これは問題であるため、APIに認証機能を付け、
ユーザーが許可したシステムからしAPIを叩けないように変更します。

APIの認証方法

APIの認証について全く知らなかったため、調べてみました。
調べると、いくつか種類があります。
Basic認証やDigest認証、OAuthなど有名なものも多いですが、
今回はこちらのページにもあるように、
より一般的な手法であるJWT認証を取り入れることにしました。

JWTとは

JWTはJSON Web Tokenの略で、JSON形式で書かれたデータをBase64urlでエンコードした認証用のトークンです。
署名があるため、改ざん防止ができます。
詳しい説明はこちらのサイトが非常に参考になりました。
scgajge12.hatenablog.com

構成の考案

現在のAPI周りの構成は以下のようになっています。
f:id:bpeldi2oerkd8:20210610162127j:plain

ここに認証を付けます。
今回は jsonwebtoken というパッケージを使います。
このドキュメントを見ると、JWTを発行する jwt.sign() と、JWTを検証する jwt.verify() が必要なことがわかりました。

このため、まずJWTを発行する /api/v1/login にアクセスし、JWTを発行した後そのJWTを返し、
そのJWTをヘッダーに追加してAPIを利用するときに検証するという流れを考えました。
これを図にしたのが以下の図です。
f:id:bpeldi2oerkd8:20210710205316j:plain

ここで、JWTを発行する際に通常はユーザー名とパスワードを使うそうですが、
今回はSlack上のチャンネルが対応しているので、
チャンネルIDとそのチャンネルのトークンを利用することにしました。

チャンネルのトークンはSlackの連携設定時に発行するものとし、
セキュリティ上の問題が発生した際に再発行できるようにします。

Slackとの連携機能の実装の際のDBと機能の整理

Slackとの連携機能を実装するうえで、DBと機能の整理をします。

データベースは以下のような構成にします。
(sequelizeというORMを利用)

scheduleテーブル

const Schedule = loader.database.define(
  'schedules',
  {
    scheduleId: {
      type: Sequelize.UUID,
      primaryKey: true,
      allowNull: false
    },
    scheduleName: {
      type: Sequelize.STRING,
      allowNull: false
    },
    description: {
      type: Sequelize.TEXT,
      allowNull: false
    },
    createdBy: {
      type: Sequelize.INTEGER,
      allowNull: false
    },
    updatedAt: {
      type: Sequelize.DATE,
      allowNull: false
    },
    roomId: {
      type: Sequelize.STRING
    }
  },
  {
    freezeTableName: true,
    timestamps: false,
    indexes: [
      {
        fields: ['createdBy', 'roomId']
      }
    ]
  }
);

roomテーブル

const Room = loader.database.define(
  'rooms',
  {
    roomId: {
      type: Sequelize.STRING,
      primaryKey: true,
      allowNull: true
    },
    roomToken: {
      type: Sequelize.STRING,
      allowNull: true
    }
  },
  {
    freezeTableName: true,
    timestamps: false
  }
);

次に、追加する機能を整理します。
追加したい機能は以下の通りです。

  • Slackとの連携がされていない場合、slackとの連携ボタンを表示
  • Slackとの連携がされている場合、slackとの連携設定変更ボタンの表示
  • チャンネルIDの登録とトークン発行機能
  • slackとの連係解除機能
  • チャンネルIDの変更機能
  • トークンの再発行機能


これらの機能をまず実装していきます。
ページの関係で次回に続きます。