JavaScript | Web API:パフォーマンス・セキュリティ - 権限管理設計

JavaScript JavaScript
スポンサーリンク

「権限管理設計」は“技術”じゃなくて“信頼”の設計

位置情報、カメラ、マイク、通知、センサー、ストレージ…。
Web API の多くは「権限(permission)」をユーザーに確認してから使います。

ここで大事なのは、
「どうやって権限を取るか」よりも
「ユーザーにどう信頼してもらうか」 という視点です。

権限設計が雑だと、
「なんか怖いサイト」「よく分からないけど全部聞いてくるサイト」になります。
逆に、丁寧に設計できると、それだけで“ちゃんとしてるサービス”に見えます。


原則 1: 「必要なときに、必要なものだけ」聞く

まとめて全部聞くのは最悪の UX

よくある悪いパターンは、
ページを開いた瞬間に、いきなり権限ダイアログが連発する設計です。

位置情報も
通知も
カメラも
マイクも

「とりあえず全部許可してね」みたいなやつです。

ユーザーからすると、

何に使うのか分からない
今それが必要なのか分からない
とりあえず「拒否」したくなる

という心理になります。

権限設計の基本は、
「その機能を使う直前に、その機能に必要な権限だけを聞く」 ことです。

位置情報が必要になるのは「近くの店を探すボタン」を押したとき
カメラが必要になるのは「写真を撮るボタン」を押したとき
通知が必要になるのは「通知をオンにする設定」をユーザーが選んだとき

このタイミングで初めて、
ブラウザの権限ダイアログを出すようにします。

例: 位置情報を「ボタンを押したときだけ」聞く

HTML:

<p>
  現在地を使って、近くのカフェを表示できます。<br>
  位置情報はサーバーに保存せず、このページ内だけで利用します。
</p>
<button id="nearCafeBtn">近くのカフェを探す</button>
<p id="message"></p>

JavaScript:

const btn = document.querySelector("#nearCafeBtn");
const message = document.querySelector("#message");

btn.addEventListener("click", () => {
  if (!("geolocation" in navigator)) {
    message.textContent = "このブラウザは位置情報に対応していません。";
    return;
  }

  message.textContent = "ブラウザのダイアログで「許可」を選ぶと、近くのカフェを表示できます。";

  navigator.geolocation.getCurrentPosition(
    (pos) => {
      message.textContent = "現在地を取得しました。カフェを検索中…";
      // 検索処理を書く
    },
    (err) => {
      if (err.code === err.PERMISSION_DENIED) {
        message.textContent = "位置情報の利用が拒否されました。手動でエリアを選択できます。";
      } else {
        message.textContent = "位置情報を取得できませんでした。";
      }
    }
  );
});
JavaScript

ここでやっているのは、

ユーザーの操作(ボタン)をきっかけにする
その権限が何に使われるかを事前に説明する
拒否されたときのルートも用意する

という「権限設計の基本形」です。


原則 2: 「用途」と「範囲」を自分の言葉で説明する

ブラウザのダイアログ任せにしない

ブラウザは「位置情報を許可しますか?」と聞いてくれますが、
それだけだとユーザーはこう思います。

何に使うの?
どこまで使われるの?
保存されるの?

だから、アプリ側で先に説明します。

何のために使うのか(例: 近くのカフェを表示するため)
どこまで使うのか(例: このページ内だけで使い、サーバーには保存しない)
いつ使うのか(例: ボタンを押したときだけ)

この 3 つを短く書けると、かなり安心感が出ます。

例: 通知権限を「設定画面」で丁寧に聞く

HTML:

<p>
  お気に入りのカフェのセール情報を通知で受け取ることができます。<br>
  通知は 1 日 1 回までで、いつでもオフにできます。
</p>
<button id="enableNotifyBtn">通知をオンにする</button>
<p id="notifyMessage"></p>

JavaScript:

const btn = document.querySelector("#enableNotifyBtn");
const msg = document.querySelector("#notifyMessage");

btn.addEventListener("click", async () => {
  if (!("Notification" in window)) {
    msg.textContent = "このブラウザは通知に対応していません。";
    return;
  }

  msg.textContent = "ブラウザのダイアログで「許可」を選ぶと、セール情報を通知できます。";

  const result = await Notification.requestPermission();

  if (result === "granted") {
    msg.textContent = "通知が有効になりました。いつでも設定からオフにできます。";
    // 通知登録処理を書く
  } else if (result === "denied") {
    msg.textContent = "通知は拒否されました。後からブラウザの設定で変更できます。";
  } else {
    msg.textContent = "通知の設定は保留されました。";
  }
});
JavaScript

ここで大事なのは、
「ユーザーの不安を先回りして潰す説明」 を入れていることです。

頻度(どれくらいの頻度で通知するか)
取り消し可能性(いつでもオフにできるか)

このあたりを書いておくと、
「一度許可したら終わりではない」と伝わって、心理的ハードルが下がります。


原則 3: 「拒否されても成立する」設計にする

権限は“取れたらラッキー”くらいの気持ちで設計する

権限は、拒否されるのが普通です。
「拒否されたら何もできません」は、設計として弱いです。

位置情報が拒否されたら、エリアを手動選択させる
カメラが拒否されたら、画像アップロードで代替する
通知が拒否されたら、メールやページ内のバッジで知らせる

こういう「代替ルート」を用意しておくと、
権限を取れなくてもサービスとして成立します。

例: 位置情報がなくても検索できる UI

HTML:

<p>
  現在地を使って近くのカフェを探すか、エリアを選択してください。
</p>
<button id="useLocationBtn">現在地で探す</button>

<select id="areaSelect">
  <option value="">エリアを選択</option>
  <option value="shinjuku">新宿</option>
  <option value="shibuya">渋谷</option>
</select>
<button id="searchByAreaBtn">エリアで探す</button>

<p id="result"></p>

JavaScript(位置情報部分だけ抜粋):

useLocationBtn.addEventListener("click", () => {
  if (!("geolocation" in navigator)) {
    result.textContent = "位置情報に対応していません。エリアを選択してください。";
    return;
  }

  navigator.geolocation.getCurrentPosition(
    (pos) => {
      // 現在地で検索
    },
    (err) => {
      if (err.code === err.PERMISSION_DENIED) {
        result.textContent = "位置情報は拒否されました。エリアを選択して検索できます。";
      } else {
        result.textContent = "位置情報を取得できませんでした。エリアを選択してください。";
      }
    }
  );
});
JavaScript

ここでのポイントは、
「拒否されたときのメッセージが“行き止まり”になっていない」 ことです。

「ダメでした」で終わらせず、
「だからこうしてください」と次の行動を提示します。


原則 4: 「権限の状態」をちゃんと把握して、無駄に聞かない

Permissions API で状態を確認する

ブラウザには navigator.permissions という API があり、
一部の権限について「状態」を確認できます。

状態は大きく分けて 3 つです。

granted(許可済み)
denied(拒否済み)
prompt(まだ聞いていない/毎回聞く)

例えば、通知の状態を確認するコードはこうです。

if ("permissions" in navigator) {
  navigator.permissions
    .query({ name: "notifications" })
    .then((status) => {
      console.log("通知の状態:", status.state);
    });
}
JavaScript

これを使うと、

すでに denied なのに、何度もダイアログを出そうとする
すでに granted なのに、毎回「許可してください」と説明する

といった「しつこい・無駄な挙動」を避けられます。

状態に応じて UI を変える

例えば、通知の設定画面でこういう分岐ができます。

granted のとき
「通知はオンです。ブラウザの設定からいつでもオフにできます。」

denied のとき
「通知はブラウザ側で拒否されています。変更するにはブラウザの設定を開いてください。」

prompt のとき
「通知をオンにできます。ボタンを押すとブラウザのダイアログが表示されます。」

これをコードにすると、イメージはこんな感じです。

async function setupNotificationUI() {
  const msg = document.querySelector("#notifyState");

  if (!("Notification" in window)) {
    msg.textContent = "このブラウザは通知に対応していません。";
    return;
  }

  if (!("permissions" in navigator)) {
    msg.textContent = "通知の状態を確認できませんが、ボタンから設定できます。";
    return;
  }

  const status = await navigator.permissions.query({ name: "notifications" });

  if (status.state === "granted") {
    msg.textContent = "通知はオンになっています。ブラウザの設定から変更できます。";
  } else if (status.state === "denied") {
    msg.textContent = "通知はブラウザで拒否されています。設定から変更できます。";
  } else {
    msg.textContent = "通知をオンにできます。ボタンを押すと確認ダイアログが表示されます。";
  }
}
JavaScript

こうやって、
「今どういう状態なのか」をユーザーと共有する のも、権限設計の一部です。


原則 5: 「権限を前提にしない」アーキテクチャにする

権限がなくても“壊れない”コードを書く

権限設計で一番やってはいけないのは、
「権限がないとコードが例外で落ちる」状態です。

例えば、位置情報 API がない環境で
いきなり navigator.geolocation.getCurrentPosition を呼ぶと、
エラーになるブラウザもあります。

なので、必ず存在チェックを挟みます。

if (!("geolocation" in navigator)) {
  // 非対応のときの処理
} else {
  // 対応しているときだけ呼ぶ
}
JavaScript

同じように、
Notificationnavigator.permissions
存在チェックをしてから使うのが基本です。

権限がない
API 自体がない
ユーザーが拒否した

こういう状況を全部「普通のケース」として扱い、
「そのときどう振る舞うか」を先に決めておく のが、権限管理設計です。


初心者として「権限管理設計」で掴んでほしい感覚

権限管理は、API の使い方を覚えることよりも、
ユーザーとの関係性をどう設計するか、という話に近いです。

必要なときに、必要な権限だけを聞く
用途・範囲・頻度を短く説明してからダイアログを出す
拒否されても成立する UI・フローを用意する
Permissions API などで状態を把握し、無駄に聞かない
権限や API を前提にせず、「ない世界」も普通に動くようにする

あなたがコードを書くときに、
「この権限、本当に今必要?」「拒否されたらどうする?」
と一度でも自問できるようになったら、
それはもう“ただ API を叩く人”から
“権限を設計できるエンジニア”に一歩踏み出しています。

タイトルとURLをコピーしました