AppSheetとPower Automate Premiumを組み合わせる
Microsoft365にはPower AutomateやPower Automate for Desktopの使用ライセンスがあると言えど、プランによってはPremiumコネクタが使えないであったり、Power Automate側からPower Automate for Desktopを呼び出し動かすといった高度な自動化は使えません(E3などの大企業向けはPremiumライセンスがついています)。
そこで、今回Power Automate Premiumの体験版ライセンスを使ってこれらの機能を試してみようと思います。
目次
今回利用するツール等
今回これを試してみようと思った理由は、AppSheetでOneDrive上のExcelを読み書きし、その後処理の自動化をPower Automateでやらせてみたかったという点。しかし、これを行うにはプレミアムコネクタを利用する必要があった為。これが無いとAppSheet側からWebhookでPower Automateを発火させることが出来ません。
尚、Power Automate Premiumは1ユーザ月額2,248円となります。体験版は30日使えますが1度だけ延長も可能です。
体験版を入手する手順
ライセンスを購入する
ライセンスを購入するにはMicrosoft365テナントの管理者である必要があります。以下の手順でMicrosoft365管理センターから購入することが可能です。
- Microsoft365管理センターを開く
- 左サイドバーより、課金情報→サービスを購入するをクリックする
- 右パネルのフィルターにてPower Automateを検索する
- Power Automate Premiumがいるので、詳細をクリックする
- プランを選択ではPower Automate Premium(体験版)を選択する
- 右サイドパネルが開かれるので、登録カードを選択し、数量を入れ、0円請求であることを確認して注文をクリックします
- 完了したらライセンス割当に移ります
これで体験版を手に入れることが出来ました。30日を経過すると自動的に課金が始まってしまいますので、期限前にお使いの製品ページからPower Automate Premiumに入り、サブスクリプションのキャンセルを実行する必要があります。
図:管理センターから購入が必要です
図:注文をして手に入れます
ユーザに割り当てる
購入してもユーザに割り当てなければ意味がありません。以下の手順でこのライセンスをユーザに割り当てましょう。体験版は25ライセンスついてくるので、短い期間ですが検証用には十分使えるハズです。
- Microsoft365管理センターのページを開く
- 左サイドバーから課金情報→ライセンスをクリックする
- Power Automate Premiumをクリックする
- ライセンスの割当をクリックする
- 右サイドバーが出てくるので、対象者のテナント内のメアドを入れて選択する
- 割り当てをクリックする
これで対象者はPower Automateのプレミアムコネクタが利用可能になり、またPower Automate for DesktopをPower Automate for Desktopから呼び出すトリガー機能が利用可能になります。
図:ライセンス割り当て画面
Power Automateで使ってみる
今回はシンプルにAppSheet側からのリクエストをPower Automate側で受け取って、Teamsの特定チャンネルに完了通知のメッセージでも送ってみようかと思います。
過去に同様の処理を以下のエントリーで作成しています。
図:フローの全体図
Power Automate側
まずはPower Automate側にAppSheetからの受け口を作っておきます。2023年に新UIに切り替わってるので新UIで説明をいたします。
- Power Automateにログインする
- 左サイドバーより作成をクリックして、インスタントクラウドフローをクリックする
- フロー名は適当にAppSheet受信とでもいれる
- 下のトリガーする方法は、HTTP要求の受信時を選択し、作成をクリックします。
- フローをトリガーできるユーザーはとりあえず認証無しで実行できる「誰でも」を選択しておきます。
- manualというフローのみが表示されてるのでクリックして要求本文の JSON スキーマに以下の内容を記述します。
12345678{"type": "object","properties": {"message": {"type": "string"}}} - 下部にある詳細パラメータをクリックし、メソッドをクリックする
- 次の行にメソッドが出てくるので「POST」を選択します。
- まだ受信用URLは出ないので、manualのコネクタ下の+をクリックします。
- 検索まどで「変数」を検索し、「変数を初期化する」を追加する
- Nameは適当、TypeはString、Valueをクリックして⚡️アイコンをクリックしmanualのmessageを選択する
- 画面右上の保存ボタンをクリックする
- 再度、manualのコネクタをクリックすると受信用のURLが出てるのでこれを控えておく
- 変数を初期化の下の+ボタンをクリックしてアクションを追加します。
- 検索ワードとして「Teams」と入れてコネクタごとにグループ化するのチェックを外し、「チャットまたはチャンネルでメッセージを投稿する」をクリックします。
- 投稿者はフローボットのままで良いです。投稿先をクリックしてチャネルをクリックします
- チームでは既存のチームを選び、チャネルでも同様に既存のチャネルを選びます。
- message項目をそのまま投稿しようと思うので、メッセージにカーソルを合わせて⚡️のアイコンをクリック
- 10.で取得しておいた変数の値を格納という項目をメッセージ欄に入力する
- 右上の保存ボタンをクリックする
これでPower Automate側のフローは構築完了しました。14.のURLを元に今度はAppSheet側でWebhookリクエストを構築します。
図:HTTP要求の受信時を利用します
図:受信用のURLをコピーする
図:チャット投稿アクション
AppSheet側
AppSheet側でAutomationを作成します。今回は請求というテーブルに対してのアクションを作ります
- 適当なテーブルに対してのAutomationを適当に作る
- プロセスのステップを追加し、Call a webhookを選択する(PAリクエストという名前にしました)
- URLに前述の14.で取得したPower Automate側のURLを入力する
- HTTP Verbは「POST」を選択する
- Bodyには以下のようなJSONを入力します。AppSheetの列の値を入れたい場合は、"<<[field_name]>>"といった値をJSONの値としてセットします
123{"message": "Hello AppSheet"}
IDだけはAppSheet側のID列の値を入れて、メッセージは適当に入力しておきます。 - 右上のSAVEボタンをクリックして保存する
図:Automationを作成する
実行してみる
この状態でAppSheet側でレコードの追加や更新を行うとAutomationが作動し、Power AutomateのPOSTのURLが叩かれます。するとPower Automate側でメッセージを受け取ってTeamsに投稿してくれます。
但し現在は誰でもPower AutomateのURLを叩ける状態であるため、実際の業務で使用する場合は特定のユーザのみが叩けるようにするべきでしょう。その場合、OAuth2.0認証をAzure Portalで用意しておいてAccess Tokenを利用して叩く必要があります。もし、トリガーできるユーザを「テナントのすべてのユーザ」とした状態で何もせずAppSheetで叩くとPOSTリクエストが届きません(AppSheet側では成功と出ますが、実際は401エラーで以下のようなエラーが出ています。
図:無事にTeams側に投稿することが出来ました
1 2 3 4 5 6 |
{ "error": { "code": "DirectApiAuthorizationRequired", "message": "The request must be authenticated only by Shared Access scheme." } } |
OAuth認証をして実行させる
先にGAS側から構築してコールバックURLを取得。これをPA側で使います。その後全部整備できたら、GAS側で初回認証を実行します。ドライブにスタンドアローンスクリプトを作成し作業を開始します。
今回説明の為に便宜的にGoogleのGASを使っていますが、Azure側でOAuth2.0認証する手段が別に用意しHTTPリクエストでAppSheetで取得できるのであれば、Google Drive等利用せずにAzure側で完結できますのでAccess TokenをAppSheet側へ渡せればGoogleレスで運用が可能です。
GAS側の実装
次にGAS側で前述の値を元にOAuth2.0認証を行わせてAccess Tokenを取得する仕組みを装備し、認証を実行します。AppSheet側からはAccess Tokenのリクエストに対する返却する関数のみを実行する形にしておく。
ライブラリの追加
以下の手順でOAuth2 for Apps Scriptライブラリを追加しましょう。
- スクリプトエディタを開きます。
- メニューより「リソース」⇒「ライブラリ」を開きます。
- ライブラリを追加欄に「1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF」を追加します。
- 今回はバージョンは43を選択してみます。
- 保存ボタンを押して完了
これで、OAuth2.0認証にまつわる様々な関数を手軽に利用できるようになります。
図:ライブラリを追加した様子
コールバックURLを取得する
コールバックURLとは、認証を完了しAccess Tokenを取得したら戻るべきURLを指定するものです。これは、スクリプトIDをもとに作られているので、スクリプトIDを取得して組み立てます。
- スクリプトエディタのメニューより「ファイル」⇒「プロジェクトのプロパティ」を開く
- 情報の中にある「スクリプトID」を控えておく。
- https://script.google.com/macros/d/スクリプトID/usercallback として組み立てる。これがコールバックURLとなる。
- この値をAzure PortalのアプリのリダイレクトURLとして指定する
図:スクリプトIDはファイル毎に異なるのです。
スクリプトプロパティに値を格納
ここで一旦次項のAzure側の作業を行っておきます。全て完了したら、この項目に戻ってきてスクリプトプロパティに3つの値を格納しておきます。
- appid : クライアントIDの値
- tenant : テナントIDの値
- secret : クライアントシークレットの値
図:スクリプトプロパティに値を格納する
ソースコード
Power AutomateのOAuth2.0認証を行うための一連のソースコードです。認証後はAppSheet側からgetAccessToken関数を叩いてトークンを返すところが重要なポイントです。
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 |
function doGet(){ //認証済みかチェックする let service = checkOAuth(); if (!service.hasAccess()) { //認証画面を出力 let output = HtmlService.createHtmlOutputFromFile('template').setHeight(450).setWidth(500).setSandboxMode(HtmlService.SandboxMode.IFRAME).setTitle("OAuth2.0認証"); //出力する return output; } else { //認証済みメッセージを表示 return HtmlService.createHtmlOutput("<center><b>認証済みだよ</b></center>"); } } //アクセストークンURLを含んだHTMLを返す関数 function authpage(){ let service = checkOAuth(); let authorizationUrl = service.getAuthorizationUrl(); let html = "<center><b><a href='" + authorizationUrl + "' target='_blank' onclick='closeMe();'>アクセス承認</a></b></center>" return html; } //認証チェック function checkOAuth() { //スクリプトプロパティから値を取得する let prop = PropertiesService.getScriptProperties(); let appid = prop.getProperty("appid"); let appsecret = prop.getProperty("secret"); let tenant = prop.getProperty("tenant"); //認証用の各種変数 let tokenurl = `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`; let authurl = `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/authorize`; //スコープの指定 let scope = "https://service.flow.microsoft.com//.default"; //認証を実行する return OAuth2.createService("Power Automate") .setAuthorizationBaseUrl(authurl) .setTokenUrl(tokenurl) .setClientId(appid) .setClientSecret(appsecret) .setScope(scope) .setCallbackFunction("authCallback") //認証を受けたら受け取る関数を指定する .setPropertyStore(PropertiesService.getScriptProperties()) //スクリプトプロパティに保存する .setParam("response_type", "code"); } //認証コールバック function authCallback(request) { let service = checkOAuth(); let isAuthorized = service.handleCallback(request); if (isAuthorized) { return HtmlService.createHtmlOutput("認証に成功しました。ページを閉じてください。"); } else { return HtmlService.createHtmlOutput("認証に失敗しました。"); } } //ログアウト function reset() { checkOAuth().reset(); } //Access Tokenを取得して返す関数 function getAccessToken(){ //Graph APIサービスを取得する var service = checkOAuth(); if (service.hasAccess()) { let token = service.getAccessToken(); let bearer = "Bearer " + token; return bearer }else{ //エラーを返す(認証が実行されていない場合) return "error"; } } |
認証用template.html
認証用ページとして表示するためのHTMLファイルです
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 |
<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'> <center> <img border="0" src="https://officeforest.org/library/oauth2.png" alt="oauth2"> <h3 id='header'>OAuth認証の許可が必要です。</h3> </center> <hr> <div id="info"> <p> このスクリプトは、Power Automateにアクセスするために、特別なログイン処理を利用しています。<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> |
ウェブアプリケーションとしてデプロイ
次に「ウェブアプリケーションとしてデプロイ」をしなければOAuth認証が出来ません。また、このウェブアプリケーションとしてデプロイはいくつかのハマりポイントがありますので注意が必要です。公開の仕方は以下の手順。
- スクリプトエディタを開く
- 右上のデプロイをクリック
- 新しいデプロイをクリック
- 種類の選択ではウェブアプリを選択し、次のユーザとしてアプリケーションを実行で誰の権限で動かすかを指定する。自分か?アクセスしてるユーザの二択。
- アプリケーションにアクセスできるユーザを指定する。今回は自分だけ十分ですのでアクセスできるユーザは「自分」である必要性があります。
- 最後に導入すると、ウェブアプリケーションのURLが取得できます。このURLでアクセスをします。URLの最後がexecが認証用URLになります。
- 次回以降コードを編集して再デプロイ時はデプロイを管理から同じURLにて、新しいバージョンを指定して発行することが出来ます。
図:ウェブアプリとして出力します
初回認証を実行する
GASの認証およびOAuth2.0認証を実行します。
- 適当な関数をまずスクリプトエディタ上で実行してGASの実行の認証を行います。
- 次に前述でデプロイしたexecで終わるURLにアクセスし、アクセス承認をクリックします。
- 「認証に成功しました。ページを閉じてください。」と出たらOAuth2.0認証完了ですので、認証用ページはすべて閉じてOK.
これでスクリプトプロパティに、oauth2.Power Automateという名称でトークンやRefresh Tokenが格納されました。
図:初回認証を実行する
図:OAuth認証を実行する
Azure側の作業
前述まででとりあえずAppSheet側からPower Automateを叩けました。しかし誰でも叩ける問題のある状態です。そこで、OAuth2.0認証をしてセキュアに実行する必要があるのですがAppSheetではOAuth2.0認証は出来ません。そこでGAS側で認証をさせて、Access Tokenを受取りこれをもって、リクエストを投げてみたいと思います。
Azure Portalでアプリを作る
以下の手順でPower Automateへアクセスするためのアプリを作成します。この段階でClient IDとTenant IDを取得することが可能です。
- Azure Portalを開きアプリの登録をクリックする
- 左上の新規登録をクリックする
- アプリの名前を適当に入力し、プラットフォームはWebを選択し、リダイレクトURLは前述で取得したコールバックURLを指定します。
- 登録をクリックする
- 概要画面が出ますが、ここでクライアントIDとテナントIDを取得可能なので控えておく。
- 左サイドバーからAPIのアクセス許可をクリックする
- Graph APIがすでに1個ありますがこれは削除しておき、アクセス許可の追加をクリックする
- Microsoft APIの中に「Power Automate」がいるのでクリックする
- 委任されたアクセス許可をクリックし、アクセス許可はUser(Access Microsoft Flow as signed in user)をチェックし、アクセス許可の追加をクリック
- xxxxに管理者の同意を与えますをクリックする(管理者権限が必要です)
- 左サイドバーの認証をクリックする
- 暗黙的な許可およびハイブリッド フローの項目で、「アクセストークン」にチェックを入れて保存をクリックする。
これでアプリの基本部分は用意できましたが、まだ認証に必要な要素が足りないので次の項目を実行します。
図:アプリの登録から始まる
図:クライアントIDとテナントID
図:APIアクセス許可
図:管理者の許可を与える
トークン構成
左サイドバーのトークン構成を開き、オプションの要求の追加を追加する必要性があります。
- トークンの種類ではアクセスを選択
- 要求は「aud」をチェックする
- 追加をクリックする
図:オプション要求を追加する
シークレットの作成
次にClient Secretを作成します。以下の手順でシークレットを作成し値をコピーしておきます。
- 左サイドバーの証明書とシークレットをクリックする
- 新しいクライアントシークレットをクリックする
- 右サイドバーが出てくるので有効期限をセットして追加をクリックする
- 値が今回必要なClient Secretなのでコピーする(この時にしか表示されない)
図:シークレットを作成する
Power Automate側の変更
前回の段階で誰でも叩けるタイプのURLとなってしまっています。これを変更するためにPower AutomateのHTTP要求の受信時の内容を変更して、改めてPOST用のURLを取得します。
- フローをトリガーできるユーザを「自分のテナントの全てのユーザ」に変更します(特定ユーザでもOK)
- 一旦閉じて、右上の保存をクリックする
- ページを一旦リロードしましょう。これでHTTP要求受信時のURLが変わります。
- 再度、HTTP要求の受信時であるmanualのコネクタを開く
- HTTP URLが変わってるのでこのURLをコピーしておく(最期がapi-version=2016-06-01みたいなURLです)
図:新URLを取得しておく
AppSheet側の実装
アクセストークンを取得するプロセス
前述までのAppSheetのAutomationはトリガーとPAリクエストのプロセスのみです。この間にAccess TokenをGAS側から取得するプロセスを一個追加します。
- トリガーとPAリクエストの間の+ボタンをクリックしてステップを追加する
- 名前はAccessTokenとして、Call a scriptとして指定し、Apps Script Projectにて前述のスタンドアローンスクリプトを指定する
- Function Nameは「getAccessToken」を選択する
- Return Valueにチェックを入れて、Stringのままでオッケーとする
これでAccessTokenはこのステップで[AccessToken].[Output]とすれば取得ができるので、次のPAリクエストにてAccessTokenを指定してPOSTリクエストをすることが可能です。
リクエストのプロセスの変更
PAリクエスト側は2箇所変更を必要とします。
- URLには改めてPower Automate側でHTTP要求の受信時コネクタで取得したURLに置き換える
- HTTP HeadersにてAddをクリックし、以下の値を入力する
1Authorization: [AccessToken].[Output] - 右上のSAVEボタンを保存する
これでAppSheetでレコード追加や修正を行うとAccess Tokenを使ってPower Automateにリクエストをし、Teamsにメッセージが無事に投稿されました。
図:URL修正とHeader追加する
関連リンク
- AppSheetとPower Automateとの連携について
- Power Automate - 管理者が管理する試用ライセンス
- Power Automate ライセンスの種類
- Power Automateのプレミアムコネクタを使ってRest API連携してみた
- Power Automate でプレミアムコネクタなしでGraph APIを利用する
- Power Automate(クラウドフロー)無料版と有料版の違い
- すべてのプレミアム階層のコネクタの一覧
- Microsoft Power AutomateのHTTPアクションで任意のkintone REST APIを実行する
- Azure API Management を使用して API から Power Automate をトリガーするにはどうすればよいですか?
- Add OAuth authentication for HTTP request triggers
- 自動化ワークフローから Webhook を呼び出す
- How to use expressions in HTTP Headers