「実行するユーザー: 自分」の Web アプリで、誰が開いているかを見分ける
Web アプリを「自分」として実行する設定で配ると、Session.getActiveUser().getEmail() が空文字を返すことがあります。 不具合ではなく、そういう仕様です。どこまで見分けられるかを、デプロイの設定ごとに整理します。
Web アプリをデプロイするときは、「実行するユーザー」(英語の画面では Execute as)を選びます。選べるのは「自分(Me)」と「アクセスしているユーザー(User accessing the web app)」です。この選択で、スクリプトが誰の権限で動くかが決まり、誰が開いているかを知る方法も変わります。
| 自分 | アクセスしているユーザー | |
|---|---|---|
| スクリプトが動く権限 | デプロイした人 | 開いた人 |
| 開いた人のアドレス | 基本は空(本人と、同じ Workspace の人は取れる) | 取れる |
| 開いた人の承認画面 | 出ない | 初回に出る |
| データの共有 | デプロイした人だけでよい | 開く人全員に要る |
「自分」で実行すると、開いた人のアドレスは基本的に取れない
「自分」を選ぶと、誰が開いても、スクリプトは常にデプロイした人として動きます。スプレッドシートや Drive は、デプロイした人の権限で読み書きされます。
このとき、Session.getActiveUser().getEmail() は基本的に空文字を返します。利用者の承認なしにスクリプトが動く場面ではアドレスを取れない、というのが公式のリファレンスの説明です。その例に挙がっているのが、「execute as me」でデプロイした Web アプリです。
例外は、デプロイした本人が開いたときと、デプロイした人と開いた人が同じ Google Workspace のドメインにいるときです。
Session.getEffectiveUser() は、スクリプトを動かしている権限の持ち主を返します。「自分」で実行する Web アプリでは、誰が開いても開発者のアカウントになります。開いた人を見分ける用途には使えません。
同じ Workspace の中で配るなら、アドレスが取れる
公式のリファレンスには、デプロイした人が開いた人と同じ Google Workspace のドメインに属していれば、この制限はおおむねかからない、と書かれています。会社の Workspace のアカウントでデプロイして、同じ会社の人に使ってもらうなら、getActiveUser() で開いた人のアドレスが取れます。
「自分」で実行したままなので、データはデプロイした人の1か所に置いたままです。共有もいりません。そのうえで、誰が開いたかはアドレスで見分けられます。
取れるのは、条件がそろっているときだけです。
| 開いた人 | アドレス |
|---|---|
| デプロイした人と同じドメインの Workspace アカウント | 取れる |
| 別の会社の Workspace アカウント | 空 |
| 個人の Gmail アカウント | 空 |
デプロイした人が個人の Gmail アカウントの場合は、同じドメインという条件が成り立ちません。本人以外は空になります。
デプロイの「アクセスできるユーザー」を、同じドメインの人だけ(マニフェストの値では DOMAIN)に絞っておくと、開ける人がそのまま「アドレスが取れる人」になります。
公式の言い方は「generally(おおむね)」で、どんな場合に外れるかは書かれていません。空文字が返ってきたときの扱いは、決めておいてください。
function currentEmail() {
const email = Session.getActiveUser().getEmail();
if (!email) throw new Error('Google Workspace のアカウントでログインしてから開いてください');
return email.toLowerCase();
}
サーバーの関数の先頭でこれを呼び、返ったアドレスを書き込みの名義や権限の判定に使います。空のときは、画面に案内を出して止めています。止めずに使わせたいなら、throw のところで、後で扱う「端末に置いた目印」に切り替えます。
ここで取れるアドレスは、本人が名乗ったものではなく、Google にログインしているアカウントのものです。表示名や端末の目印と違って、他人を名乗ることはできません。
「アクセスしているユーザー」なら取れるが、代わりに失うものがある
「アクセスしているユーザー」を選ぶと、スクリプトは開いた人の権限で動きます。開いた人のアドレスも取れるようになります。
そのかわり、開いた人それぞれが、初回に権限の承認画面を通ることになります。スクリプトが読み書きするスプレッドシートやフォルダも、開いた人の権限で触ります。全員に共有しておく必要があり、共有された人はアプリを通さずにシートを直接開いて書き換えられます。
この設定では、新しい利用者が承認できる頻度に上限があります。公式のガイドに具体的な値は書かれていません。
データの置き場所を1か所にまとめたいなら「自分」、誰が開いたかを確実に知りたいなら「アクセスしているユーザー」です。両方は取れません。
誰が入れるかは、デプロイの設定で決まる
「アクセスできるユーザー」の設定は、開けるかどうかを決めます。マニフェストでの値と、開ける人の対応はこうです。
| 値 | 開ける人 |
|---|---|
MYSELF |
デプロイした本人だけ |
DOMAIN |
デプロイした人と同じドメインのユーザー |
ANYONE |
Google アカウントでログインしている人 |
ANYONE_ANONYMOUS |
ログインしていない人も含めて誰でも |
「自分」で実行していても、DOMAIN にしておけば社外の人は開けません。アプリの中で誰かを見分ける前に、まずここで入口を絞っておくのが筋です。
「自分」で実行したまま、人を見分ける
アドレスが取れない場面では、アプリの中で使える目印は本人確認になりません。書き込みの名義やお気に入りの持ち主を分けるための目印として扱います。
デプロイした人だけは、アドレスで見分けられる
デプロイした本人が開いたときは、getActiveUser() でアドレスが取れます。最初に動いたときに getEffectiveUser() のアドレスを控えておきます。開いた人のアドレスとそれを比べれば、管理者かどうかを判定できます。
function isOwner() {
const props = PropertiesService.getScriptProperties();
let owner = props.getProperty('ownerEmail');
if (!owner) {
owner = Session.getEffectiveUser().getEmail(); // 「自分」で実行しているので、デプロイした人
props.setProperty('ownerEmail', owner);
}
const me = Session.getActiveUser().getEmail(); // 本人以外は空文字
return me !== '' && me.toLowerCase() === owner.toLowerCase(); // 空文字どうしの一致を除く
}
そのまま貼って使えます。同じ Workspace の人もアドレスが取れることがあります。ただ、比べる相手はデプロイした人のアドレスなので、ほかの人とは一致しません。
ほかの人は、端末に置いた目印で見分ける
ほかの人には、初回に表示名を決めてもらいます。画面の側で crypto.randomUUID() などで作った値をブラウザに保存しておき、サーバーを呼ぶたびに引数で渡します。サーバーはその値と表示名の組を表に控えておきます。
ブラウザに保存するところは localStorage を使うのが手軽です。ただ、HTML Service のページで localStorage が使えるかどうかは、公式のドキュメントに書かれていません。ページはサンドボックスの iframe の中で動いています。
使う前に、自分のデプロイで確かめておいてください。保存できなかったときは、名前を聞き直す画面へ戻します。
この目印は、別のブラウザや別の端末では引き継がれません。端末を変えた人には、同じ名前で入り直してもらうことになります。
getTemporaryActiveUserKey() は、確かめてから使う
Session.getTemporaryActiveUserKey() は、開いている人ごとに違う値になり、その人が誰かは明かさないキーです。値は30日ごとに変わり、スクリプトごとにも別の値になります。
30日で値が変わるので、表に控えて長く使う目印には向きません。また、「自分」で実行する Web アプリで、このキーが開いた人ごとに分かれるかどうかは公式に書かれていません。使うなら、先にそこを確かめる必要があります。
目印は鍵ではない
表示名と端末の目印は、本人が名乗ったものです。他人の名前を名乗ることも、ブラウザの保存領域を書き換えることもできます。
「この人にだけ見せる」「この人だけ編集できる」を目印で作ると、それは目隠しであって鍵ではありません。同じ Workspace の中でアドレスが取れているなら、判定はアドレスで行ってください。本当に見せたくないものは、デプロイの「アクセスできるユーザー」で入口を絞るか、別のアプリに分けてください。使う人にも、そう説明しておくと誤解が起きません。
書かなくても動く状態のコードを、下のツールで配っています。
社内wiki手順書や議事録を1か所にまとめます。契約も月額もなく、データは自分の Google ドライブの中だけに置かれます。