Google Apps ScriptとMicrosoft Graph APIの連携 - 準備編【GAS】

G Suiteには、Google Driveというクラウドストレージサービスがあるので、通常は他のオフィスサービス(Microsoft365)と連携する必要がありませんが、G Suiteをアプリケーションの環境、通常はMicrosoft365を使って、Excelのファイル類などについては、OneDriveやSharepointを利用している事もあるでしょう。

そんな時にGAS側からMicrosoft365とりわけExcelファイルの読み書きができたら非常に便利になると思います。今回はGoogle Apps Scriptにて、Microsoft365側のExcelファイルへアクセスする手順を残しておきたいと思います。

準備するもの・使用するファイル

事前準備

今回のスクリプトはOAuth2.0認証が必要となるため、その為の簡単設定ライブラリとして、OAuth2 for Apps Scriptライブラリを利用させていただきます。また、Microsoft365側では、Application Registration Portalにてアプリの作成を登録し、アプリケーションIDとアプリケーションシークレット等の情報を入手する必要があります。

GAS側の事前準備

ライブラリの追加

以下の手順でOAuth2 for Apps Scriptライブラリを追加しましょう。

  1. スクリプトエディタを開きます。
  2. メニューより「リソース」⇒「ライブラリ」を開きます。
  3. ライブラリを追加欄に「1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF」を追加します。
  4. 現時点ではバージョンは30が最新ですので、それを選択しておきます。
  5. 保存ボタンを押して完了

これで、OAuth2.0認証にまつわる様々な関数を手軽に利用できるようになります。

図:ライブラリを追加した様子

コールバックURLを取得する

コールバックURLとは、認証を完了しAccess Tokenを取得したら戻るべきURLを指定するものです。これは、スクリプトIDをもとに作られているので、スクリプトIDを取得して組み立てます。

  1. スクリプトエディタのメニューより「ファイル」⇒「プロジェクトのプロパティ」を開く
  2. 情報の中にある「スクリプトID」を控えておく。
  3. https://script.google.com/macros/d/スクリプトID/usercallback として組み立てる。これがコールバックURLとなる。

図:スクリプトIDはファイル毎に異なるのです。

Microsoft365側の事前準備

続いて、Microsoft365側での処理を行います。ここでは、アプリケーションの作成を行い、アプリケーションIDとアプリケーションシークレット等を生成します。

  1. Application Registration Portalにログインする。
  2. アプリの追加ボタンを押す。
  3. Application Nameを入力しCreateボタンを押します。アルファベット以外も使えますよ。
  4. この段階でアプリケーションIDはすでに生成されているので、控えて置きます。
  5. アプリケーションシークレットにて、「新しいパスワードを生成」をクリックし、パスワードを発行します(このパスワードはこの時の1回しか表示されません)。
  6. 「プラットフォームの追加」にて、追加ボタンを押し、Webを選択。
  7. ここで、GAS側で取得したコールバックURLをリダイレクトURLに入力します。
  8. Microsoft Graphのアクセス許可では、スコープを設定します。User.Read、Files.ReadWrite、offline_accessを追加します。offline_accessを入れないと「リフレッシュトークン」が取得できないので、注意。
  9. 保存ボタンを押して完了です。

図:スコープの設定で許可するアクションを選びます。

認証を行う処理を作成する

OAuth2 for Apps Scriptのページの「Create the OAuth2 Service」にあるコードを元に、Google Apps Script側で構築をします。この時、Microsoft365側で取得したアプリケーションIDやシークレットを使います。

GAS側コード

//メニューを構築する
function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('▶OAuth認証')
      .addItem('認証の実行', 'startoauth')
      .addSeparator()
      .addItem('ログアウト', 'reset')
      .addToUi();
}

//認証用の各種変数
var appid = 'ここにアプリケーションIDを入れます';
var appsecret='ここにアプリケーションシークレットを入れます。';
var scope = "User.Read Files.ReadWrite offline_access"
var endpoint = "https://graph.microsoft.com/v1.0"
var targetfile = "ここにターゲットとなるxlsxファイル名を入れます。"
var tokenurl = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
var authurl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"

function startoauth(){
  //UIを取得する
  var ui = SpreadsheetApp.getUi();
  
  //認証済みかチェックする
  var service = checkOAuth();
  if (!service.hasAccess()) {
    //認証画面を出力
    var output = HtmlService.createHtmlOutputFromFile('template').setHeight(310).setWidth(500).setSandboxMode(HtmlService.SandboxMode.IFRAME);
    ui.showModalDialog(output, 'OAuth2.0認証');
  } else {
    //認証済みなので終了する
    ui.alert("すでに認証済みです。");
  }
}

//アクセストークンURLを含んだHTMLを返す関数
function authpage(){
  var service = checkOAuth();
  var authorizationUrl = service.getAuthorizationUrl();
  var html = "<center><b><a href='" + authorizationUrl + "' target='_blank' onclick='closeMe();'>アクセス承認</a></b></center>"
  return html;
}

//認証チェック
function checkOAuth() {
  return OAuth2.createService("Microsoft Graph")
    .setAuthorizationBaseUrl(authurl)
    .setTokenUrl(tokenurl)
    .setClientId(appid)
    .setClientSecret(appsecret)
    .setScope(scope)
    .setCallbackFunction("authCallback") //認証を受けたら受け取る関数を指定する
    .setPropertyStore(PropertiesService.getScriptProperties())  //スクリプトプロパティに保存する
    .setParam("response_type", "code");
}

//認証コールバック
function authCallback(request) {
  var service = checkOAuth();
  Logger.log(request);
  var isAuthorized = service.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput("認証に成功しました。ページを閉じてください。");
  } else {
    return HtmlService.createHtmlOutput("認証に失敗しました。");
  }
}

//ログアウト
function reset() {
  checkOAuth().reset();
  SpreadsheetApp.getUi().alert("ログアウトしました。")
}

HTML側コード

template.htmlというダイアログ用のファイルを用意します。ここでアクセス承認を実行し、ログインをすると、アクセストークンその他が取得可能になります。

<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<script type="text/javascript" src="https://apis.google.com/js/api.js"></script>
<script>
  google.script.run.withSuccessHandler(onSuccess).authpage();
  
  function onSuccess(data){
    document.getElementById("kinoko").innerHTML = data;
  }

</script>

<style type="text/css">
/* --- ボックス --- */
div.section {
width: 480px; /* ボックスの幅 */
background-color: #ffffff; /* ボックスの背景色 */
border: 1px #c0c0c0 solid; /* ボックスの境界線 */
font-size: 100%; /* ボックスの文字サイズ */
}

/* --- 見出し --- */
div.section h3 {
margin: 0; /* 見出しのマージン */
padding: 6px 10px; /* 見出しのパディング(上下、左右) */
background-color: #f5f5f5; /* 見出しの背景色 */
border-bottom: 1px #c0c0c0 solid; /* 見出しの下境界線 */
font-size: 120%; /* 見出しの文字サイズ */
}

/* --- ボックス内の段落 --- */
div.section p {
margin: 1em 10px; /* 段落のマージン(上下、左右) */
}
</style>

<div class='section'>
<img border="0" src="http://blog.movereem.nl/images/oauth.png" alt="oauth2">
<h3 id='header'>OAuth認証の許可が必要です。</h3>
<hr>
<div id="info">
<p>
このスクリプトは、Microsoft Graph APIにアクセスするために、特別なログイン処理を利用しています。<br>
既に特別なログインに関する設定はなされており、承認がされるとプログラムを実行することが出来ます。この承認がなされない場合、プログラムの実行に制限が掛かり、
処理が続行できません。<br><br>

<div id="kinoko"></div>
</div>
<p>
<script>
function closeMe(){
  if(google && google.script && google.script.host){
      google.script.host.close();
  } else if(window && window.close){
      window.close();
  } 
}
</script>
</div>
  • 実際にこれらのコードで、startoauthを実行すると、スプレッドシート上で認証用のダイアログが出ます。
  • 認証でMicrosoft365アカウントにログインします。
  • 取得したAccess Tokenほかはスクリプトプロパティのoauth2.Microsoft Graphという項目にガッツリ値が格納されます。ここにはAccess Token, Refresh Token, expire_inのタイムなどが入っています。
  • reset関数はログアウトされて、再度認証ができるようになります。

図:Microsoft側でのOAuth認証画面

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)