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で動作を確認しています。