Garoon CSRF トークン利用例

目次

はじめに

今回は CSRF トークンの簡単な説明と利用例を 【Garoon JavaScript API】ワークフロー承認後にスケジュールを登録する の記事を例にして説明します。

CSRFトークンが必要になるケース

CSRF トークンは、正規のページからアクセスされていることを証明するための値です。
Garoon REST API では、次のすべてに当てはまる場合、CSRF トークンを使用して API を実行する必要があります。

  • セッション認証で Garoon REST API を実行する。
  • Web ブラウザーの Fetch API または XMLHttpRequest オブジェクトを使う。
  • POST/PATCH/PUT/DELETE メソッドの API を実行する。

サンプル

次の記事で紹介されているソースコードを、CSRF トークンを使って Garoon REST API を実行するように書き換えてみます。
【Garoon JavaScript API】ワークフロー承認後にスケジュールを登録する

なお、この記事で CSRF トークンを使う題材に取り上げていますが、JavaScript カスタマイズで Garoon REST API を実行する際は、CSRF トークンが不要な garoon.api() で実行することをおすすめします。

細かいワークフローの設定は上記の記事を参考に設定してください。
「wf_to_sch.js」のコードだけ、次のサンプルコードに置き換えてください。

サンプルコード

68 行目の sample のみ、ご使用のサブドメイン名に変更してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
 * Garoon JavaScript、REST APIを使ったサンプルプログラム
 *
 * 「wf_to_sch.js」ファイル
 *
 * Copyright (c) 2018 Cybozu
 *
 * Licensed under the MIT License
 */

(function() {
  'use strict';
  const myJQuery = jQuery.noConflict(true);
  (function($) {
    // CSRFトークンを取得する
    const TOKEN = garoon.base.request.getRequestToken();

    // POSTするボディを作成する
    function createBody(stDT, endDT, code, sub, menu, notes, visib) {
      const scheduleObj = {
        __REQUEST_TOKEN__: TOKEN,
        eventType: 'REGULAR',
        start: {
          dateTime: stDT,
          timeZone: 'Asia/Tokyo'
        },
        end: {
          dateTime: endDT,
          timeZone: 'Asia/Tokyo'
        },
        attendees: [{
          type: 'USER',
          code: code
        }],
        subject: sub,
        eventMenu: menu,
        notes: notes,
        visibilityType: visib
      };
      return scheduleObj;
    }

    // ワークフロー承認イベントで発火する
    garoon.events.on('workflow.request.approve.submit.success', (event) => {

      const request = event.request;
      const items = request.items;
      // イベントオブジェクトからリクエストボディを作成するのに必要な情報を取得する
      const applicantCode = request.applicant.code;
      const startDT = items.From.value.date + 'T' + items.From.value.time + ':00+09:00';
      const endDT = items.To.value.date + 'T' + items.To.value.time + ':00+09:00';
      const eventMenu = items.Menu.value;
      const subject = items.Title.value;
      const url = location.protocol + '//' + location.hostname +
                '/g/workflow/view.csp?pid=' + request.id +
                '&fid=' + request.folders[request.folders.length - 1].id;
      const notes = url + '\n' + items.Memo.value;
      let scope;
      if (request.items.Scope.value === '公開') {
        scope = 'PUBLIC';
      } else if (request.items.Scope.value === '非公開') {
        scope = 'PRIVATE';
      }
      // リクエストボディ作成
      const body = createBody(startDT, endDT, applicantCode, subject, eventMenu, notes, scope);
      // スケジュール登録API実行
      $.ajax({
        url: 'https://sample.cybozu.com/g/api/v1/schedule/events',
        method: 'POST',
        dataType: 'json',
        data: JSON.stringify(body),
        contentType: 'application/json'
      }).always(console.log);

    });

  })(myJQuery);
})();

サンプルコード解説

CSRF トークンを取得する Garoon JavaScript API

16
const TOKEN = garoon.base.request.getRequestToken();

CSRF トークンを取得する Garoon JavaScript API です。

リクエストボディを生成する

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// POSTするボディを作成する
function createBody(stDT, endDT, code, sub, menu, notes, visib) {
  const scheduleObj = {
    __REQUEST_TOKEN__: TOKEN,
    eventType: 'REGULAR',
    start: {
      dateTime: stDT,
      timeZone: 'Asia/Tokyo'
    },
    end: {
      dateTime: endDT,
      timeZone: 'Asia/Tokyo'
    },
    attendees: [{
      type: 'USER',
      code: code
    }],
    subject: sub,
    eventMenu: menu,
    notes: notes,
    visibilityType: visib
  };
  return scheduleObj;
}

リクエストボディを生成する関数です。
リクエストボディ内に登録する予定の情報を記述し、スケジュール登録 API を実行します。

オブジェクトの構造については スケジュールオブジェクト を参照してください。

リクエストボディに必要な情報を取得する

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
garoon.events.on('workflow.request.approve.submit.success', (event) => {
  const request = event.request;
  const items = request.items;
  // イベントオブジェクトからリクエストボディを作成するのに必要な情報を取得する
  const applicantCode = request.applicant.code;
  const startDT = items.From.value.date + 'T' + items.From.value.time + ':00+09:00';
  const endDT = items.To.value.date + 'T' + items.To.value.time + ':00+09:00';
  const eventMenu = items.Menu.value;
  const subject = items.Title.value;
  const url = location.protocol + '//' + location.hostname +
            '/g/workflow/view.csp?pid=' + request.id +
            '&fid=' + request.folders[request.folders.length - 1].id;
  const notes = url + '\n' + items.Memo.value;
  let scope;
  if (request.items.Scope.value === '公開') {
    scope = 'PUBLIC';
  } else if (request.items.Scope.value === '非公開') {
    scope = 'PRIVATE';
  }
  // 以下省略
});

ワークフロー申請を承認したときのイベント のイベントオブジェクトから、リクエストボディに必要な情報を取得します。
詳細については ワークフローオブジェクト を参照してください。

REST API を実行する

66
67
68
69
70
71
72
73
// スケジュール登録API実行
$.ajax({
  url: 'https://sample.cybozu.com/g/api/v1/schedule/events',
  method: 'POST',
  dataType: 'json',
  data: JSON.stringify(body),
  contentType: 'application/json'
}).always(console.log);

このサンプルコードでは、jQuery.ajax() を用いて REST API を実行します。

jQuery.ajax() の公式リファレンス: https://api.jquery.com/jquery.ajax/ (External link)

おわりに

CSRF トークンが必要な場合にも、Garoon REST API が実行できるようになりました。

また、Garoon REST API は今後も機能を増やしてく予定です。
追加してほしい機能の API がありましたら、 次期 Garoon REST API 人気投票 からアンケートにご協力お願いします。

information

この Tips は、2018 年 8 月版 Garoon で動作を確認しています。