Google Apps Script から OAuth 2.0 で kintone API を利用する

目次

はじめに

cybozu.com共通管理メニュー内の外部連携でOAuthクライアントの設定ができます。
今回は、Google Apps Script(以下GAS)の チュートリアル (External link) を参考に、OAuth 2.0の承認を経て、kintone APIでデータを取得するサンプルコードを作成します。
機能としては、kintone APIより取得したメッセージをGoogleドキュメントに書き込み、GmailでGoogleドキュメントへのリンクを送信するサンプルを作成します。
なお、コードを簡素化するため、OAuth 2.0認証にGASの ライブラリ (External link) を利用します。

cybozu.comのOAuthクライアントについてのドキュメントは こちらです。

開発手順

  1. kintone アプリの開発
  2. OAuth2 ライブラリの設定
  3. OAuth クライアントの設定
  4. GAS アプリの開発
  5. GAS アプリの OAuth スコープの設定
  6. 動作確認

1. kintone アプリの開発

画面を参考にGoogleドキュメントへ送信するメッセージを入力するフィールドを設定します。

フィールドの種類 フィールド名 フィールドコード
文字列(1行) メッセージ message

「フォームを保存」し、「アプリを更新」します。

kintoneアプリの設定は以上です。

2. OAuth2 ライブラリの設定

  1. Google Apps Script (External link) にて、Google Workspace Developer Hubにお持ちのGoogleアカウントでログインします。

  2. 「新規スクリプト」をクリックして、GASのエディターを表示します。

  3. プロジェクト名を適当に入力し、「リソース」メニューから、「ライブラリ」を選択します。

  4. ライブラリのスクリプトID「1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF」を入力し、「追加」ボタンでライブラリを追加します。
    最新のバージョンを選択して、設定を保存します。(詳細は こちら (External link) を参照してください)

3. OAuth クライアントの設定

kintoneのcybozu.com共通管理ページより、外部連携の設定画面にて、「OAuthクライアントの追加」をクリックします。

リダイレクトエンドポイントは次の形式で設定します。

https://script.google.com/macros/d/SCRIPT_ID/usercallback/

今回作成したSCRIPT_IDは、GASエディターのファイルメニューの「プロジェクトのプロパティ」より、取得します。

クライアント名とリダイレクトエンドポイントを入力し、「保存」すると以下の情報が、自動生成されます。

  • クライアントID
  • クライアントシークレット
  • 認可エンドポイント
  • トークンエンドポイント

「連携利用ユーザーの設定」をクリックし、API利用を許可するユーザーを選択し、設定を保存します。

以上でOAuthクライアントの設定は終了です。

4. GAS アプリの開発

GASのアプリは、こちらの チュートリアル (External link) を参考に開発します。

アプリの機能

  1. OAuth 2.0でkintone APIへのアクセスを認証する。
  2. kintone APIより、メッセージを取得する。
  3. 「Hello, World!」という名前で、Googleドキュメントを作成する。
  4. Googleドキュメントのボディーにkintoneからのメーセージを書き込む。
  5. GmailでGoogleドキュメントへのリンクを送信する。

OAuth 2.0の認証に関しましては、上記で設定した OAuth2 for Apps Script (External link) というGASのライブラリを利用します。

4.1. GAS のコーディング

以下を参考にコーディングします。

 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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
* Google Apps Script から、OAuth 2.0 を使って、kintone API を利用する
* Copyright (c) 2019 Cybozu
*
* Licensed under the MIT License
*/

/*
* kintone への承認リクエスト
*/
function doGet() {
  'use strict';
  const service = getService();
  if (service.hasAccess()) {
    createAndSendDocument(service.getAccessToken());
    return HtmlService.createHtmlOutput('Success');
  }
  // 承認されていない場合、承認リンクを HTML ページに表示
  const authorizationUrl = service.getAuthorizationUrl();
  const template = '<a href="' + authorizationUrl + '" target="_blank">Authorize</a>';
  return HtmlService.createHtmlOutput(template);
}

/**
 * OAuth 2.0 service のセットアップ
 */
function getService() {
  'use strict';
  // OAuth 2.0 承認サービスの生成
  return OAuth2.createService('kintone')
    .setAuthorizationBaseUrl('https://{サブドメイン名}.cybozu.com/oauth2/authorization')// 認可エンドポイント
    .setTokenUrl('https://{サブドメイン名}.cybozu.com/oauth2/token')// トークンエンドポイント

    // kintone のクライアント ID およびクライアントシークレットを設定
    .setClientId('{クライアントID}') // OAuth クライアント ID
    .setClientSecret('{クライアントシークレット}') // OAuth クライアントシークレット

    // OAuth2.0 承認後のコールバック関数名の設定
    .setCallbackFunction('authCallback')

    // 承認トークンを維持するプロパティーストアの設定
    .setPropertyStore(PropertiesService.getUserProperties())

    // Kintone API リクエストのスコープ設定
    .setScope('k:app_record:read'); // Kintone APIのスコープ
}

/**
 * 最初の OAuth2 承認の際のコールバック処理
 */
function authCallback(request) {
  'use strict';
  const service = getService();
  const authorized = service.handleCallback(request);
  if (authorized) {
    createAndSendDocument(service.getAccessToken());
    return HtmlService.createHtmlOutput('Success!');
  }
  return HtmlService.createHtmlOutput('Denied.');
}

/**
 * Google ドキュメントを作成し、そのリンクをメールで送信
 */
function createAndSendDocument(accessToken) {
  'use strict';
  // Kintone API の URL および、アプリ ID、レコード番号
  const appUrl = 'https://{サブドメイン名}.cybozu.com/k/v1/record.json?app={アプリ ID}&id={レコード番号}';
  // kintone API の呼び出し
  const response = UrlFetchApp.fetch(appUrl,
  // ヘッダーにアクセストークンを設定
    {
      headers: {
        Authorization: 'Bearer ' + accessToken
      }
    }
  );
  const result = JSON.parse(response.getContentText());// レスポンスを JSON 形式に変換

  // ログインユーザーの E メールアドレスを取得
  const email = Session.getActiveUser().getEmail();

  // 新規 Google ドキュメントを 'Hello, world!' という名前で作成
  const doc = DocumentApp.create('Hello, world!');

  // E メールの題目としてドキュメント名を取得
  const subject = doc.getName();

  // ドキュメントのボディーに kintone API から取得したメッセージを追加
  doc.getBody().appendParagraph(result.record.message.value);
  // ドキュメントの URL を取得
  const docUrl = doc.getUrl();
  // ドキュメントの URL を E メールのボディーに追加
  const body = 'Link to your doc: ' + docUrl;

  // ドキュメントへのリンクをログインユーザーへ E メール送信
  GmailApp.sendEmail(email, subject, body);
}
4.2. コードの解説
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
/*
* kintone への承認リクエスト
*/
function doGet() {
  'use strict';
  const service = getService();
  if (service.hasAccess()) {
    createAndSendDocument(service.getAccessToken());
    return HtmlService.createHtmlOutput('Success');
  }
  // 承認されていない場合、承認リンクを HTML ページに表示
  const authorizationUrl = service.getAuthorizationUrl();
  const template = '<a href="' + authorizationUrl + '" target="_blank">Authorize</a>';
  return HtmlService.createHtmlOutput(template);
}

doGet関数は、GASコードをのちほどWebアプリケーションとして実行した際、最初に自動で呼び出される関数です。
OAuth2.0認証サービスを生成し、すでに承認されていれば、アクセストークンを引き渡し、kintone APIよりデータを取得する関数を呼び出します。
まだ、認証されていない場合には、承認リンクをブラウザーに表示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * OAuth 2.0 service のセットアップ
 */
function getService() {
  'use strict';
  // OAuth 2.0 承認サービスの生成
  return OAuth2.createService('kintone')
    .setAuthorizationBaseUrl('https://{サブドメイン名}.cybozu.com/oauth2/authorization')// 認可エンドポイント
    .setTokenUrl('https://{サブドメイン名}.cybozu.com/oauth2/token')// トークンエンドポイント

    // kintone のクライアント ID およびクライアントシークレットを設定
    .setClientId('{クライアントID}') // OAuth クライアント ID
    .setClientSecret('{クライアントシークレット}') // OAuth クライアントシークレット

    // OAuth2.0 承認後のコールバック関数名の設定
    .setCallbackFunction('authCallback')

    // 承認トークンを維持するプロパティーストアの設定
    .setPropertyStore(PropertiesService.getUserProperties())

    // Kintone API リクエストのスコープ設定
    .setScope('k:app_record:read'); // Kintone APIのスコープ
}

OAuth2.0ライブラリを使って、OAuth2.0承認サービスを生成します。上記で設定したOAuthクライアントの各種情報を設定しています。

PropertiesService.getScriptProperties()にて、承認トークンの設定を保存するサービスの指定をしています。
スコープの値は、 kintone の OAuth スコープで確認してください。

コールバック関数は、authCallbackを指定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/**
 * 最初の OAuth2 承認の際のコールバック処理
 */
function authCallback(request) {
  'use strict';
  const service = getService();
  const authorized = service.handleCallback(request);
  if (authorized) {
    createAndSendDocument(service.getAccessToken());
    return HtmlService.createHtmlOutput('Success!');
  }
  return HtmlService.createHtmlOutput('Denied.');
}

ブラウザーから承認リンクをクリックした場合にkintoneへ認可リクエストを送信した際に処理されるコールバック関数です。ライブラリ内で認可コードを取得して、アクセストークンを要求・取得する処理が実行されます。

承認されるとkintone APIを実行する関数を呼び出し、ブラウザーに「Success」と表示されます。
また、承認が拒否された場合には「Denied」が表示されます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Kintone API の URL および、アプリ ID、レコード番号
const appUrl = 'https://{サブドメイン名}.cybozu.com/k/v1/record.json?app={アプリID}&id={レコード番号}';
// kintone API の呼び出し
const response = UrlFetchApp.fetch(appUrl,
  // ヘッダーにアクセストークンを設定
  {
    headers: {
      Authorization: 'Bearer ' + accessToken
    }
  }
);
const result = JSON.parse(response.getContentText());// レスポンスを JSON 形式に変換

取得したアクセストークンをヘッダーに設定して、kintone APIでアプリのデータを取得します。URLには、アクセスしたいアプリのIDとレコード番号を含めて指定します。

取得したデータをJSON形式に変換します。

1
2
3
4
5
6
// 新規 Google ドキュメントを 'Hello, world!' という名前で作成
const doc = DocumentApp.create('Hello, world!');
// ドキュメントのボディーに kintone API から取得したメッセージを追加
doc.getBody().appendParagraph(result.record.message.value);
// ドキュメントの URL を取得
const docUrl = doc.getUrl();

Googleドキュメントを新規作成し、ボディーにkintoneから取得したデータを書き込みます。
その後、新規作成したGoogleドキュメントのURLを取得します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// ログインユーザーの E メールアドレスを取得
const email = Session.getActiveUser().getEmail();

// E メールの題目としてドキュメント名を取得
const subject = doc.getName();

// ドキュメントの URL を E メールのボディーに追加
const body = 'Link to your doc: ' + docUrl;

// ドキュメントへのリンクをログインユーザーへ E メール送信
GmailApp.sendEmail(email, subject, body);

ログインしているユーザーのEメールアドレスを取得し、Eメールの題目として、ドキュメント名を指定します。
取得したドキュメントのURLをリンクとして、Eメールのボディーに追加します。

Gmailにて、ログインユーザーへドキュメントへのリンクをメール送信します。

5. GAS アプリの OAuth スコープの設定

GASからGmailやGoogleドキュメントを利用するため、マニフェストファイルにOAuth Scopeを設定します。
参考: OAuth 2.0 Scopes for Google APIs (External link)

  1. GASエディターの「表示」メニューから、「マニフェスト ファイルの表示」を選択します。

  2. 表示された「appsscript.json」に次の値を追加します。

    1
    2
    3
    4
    5
    6
    
    "oauthScopes": [
      "https://www.googleapis.com/auth/script.external_request",
      "https://www.googleapis.com/auth/userinfo.email",
      "https://www.googleapis.com/auth/documents",
      "https://www.googleapis.com/auth/gmail.send"
    ],
  3. 「ファイル」メニューから、「保存」を選択して保存します。

6. 動作確認

GASのスクリプトエディターの「公開」メニューより、「ウェブアプリケーションとして導入」を選択します。

プロジェクトバージョンに「New」を選択し、「導入」ボタンをクリックします。

Googleアカウントのデータへのアクセス承認の許可を確認します。

次のような警告が表示される場合、「(安全でないページ)に移動」をクリックし、続けます。

GASを作成したGoogleアカウントを選択します。

GASのGoogleアカウントへのアクセスを許可します。

「現在のウェブアプリケーションのURL」が表示されますので、コピーして、ブラウザーのアドレス欄に貼り付け、ウェブアプリケーションを実行します。

ブラウザーに表示された承認リンクをクリックする。

kintoneのログイン画面が表示されるので、ユーザー名とパスワードを入力してログインします。

OAuthクライアントのアクセスを許可します。

「Success!」が表示されます。 OAuthクライアントの承認を経て、スクリプトが実行されたことになります。

しばらくするとGmailが送信され、Googleドキュメントへのリンクをクリックしてkintoneアプリで設定したメッセージが表示されていれば、成功です。

まとめ

新たに導入された外部連携の機能で、外部アプリケーションからOAuth 2.0を使って、kintone APIへのアクセスができるようになりました。
これにより、OAuth2.0で安全にユーザーを認証し、外部アプリケーションからkintone APIを通じて、アプリのデータを取得できるようになりました。

OAuth クライアント

information

このTipsは、2019年02月版kintoneで動作を確認しています。