Web アプリで現在地を取得する機能を作っていると、Chrome のコンソールに次のような警告が表示されることがあります。
[Violation] Permissions policy violation: Geolocation access has been blocked because of a permissions policy applied to the current document.最初は JavaScript の問題かと思いがちですが、実は ブラウザ側のポリシー(Permissions-Policy)によって Geolocation API が禁止されていることが原因です。
この記事では、このエラーの原因と、その解決方法(nginx 設定)を分かりやすく解説します。
Chrome の「Permissions policy violation: Geolocation access has been blocked」エラー
エラーの意味は「このページでは geolocation が使えません」
Chrome のエラーにはこう書かれていました。
Geolocation access has been blocked because of a permissions policy...これはつまり、「サーバーが返している Permissions-Policy ヘッダーによって、このページでは Geolocation API の利用が禁止されている」という意味です。
JavaScript の navigator.geolocation.getCurrentPosition() を呼んでも、絶対に成功しません。
原因:Permissions-Policy の geolocation が無効になっている
Chrome は 2024〜2025 年頃から Permissions-Policy の扱いを厳格化しており、レスポンスヘッダーに以下のような設定があると Geolocation が完全にブロックされます。
Permissions-Policy: geolocation=()また、ヘッダー自体が無い場合でも、環境や iframe 内などで デフォルト禁止になるケースがあります。
ブラウザ権限まわりの「3レイヤー構造」
位置情報まわりのトラブルは、だいたい次の 3つのレイヤー のどこかで止められています。
- プロトコルレイヤー
- Geolocation API は HTTPS が必須(HTTP だとそもそも使えない)
- ブラウザ・ユーザー権限レイヤー
- Chrome などが出す「このサイトに位置情報の利用を許可しますか?」のダイアログ
- ユーザーが「拒否」していると、
PERMISSION_DENIEDになる
- サーバー側ポリシーレイヤー(Permissions-Policy)
- レスポンスヘッダー
Permissions-Policyで
「このページは geolocation を使っていい・ダメ」を定義できる
- レスポンスヘッダー
今回のエラーは、この 3番目のレイヤー でブロックされているパターンです。
- JavaScript の書き方が正しくても
- ユーザーが「許可」していても
サーバー側の Permissions-Policy で geolocation=() のように禁止されていると、
ブラウザはそもそも Geolocation API を使わせてくれません。
なので、「コンソールのエラーを見たら、まずはどのレイヤーで止められているかを切り分ける」という発想が大事
Permissions-Policy とは何か?
Permissions-Policy は、「このページは、ブラウザのどの機能を使ってよいか」をサーバーが宣言するヘッダー です。
たとえば以下について「どの origin に対して許可するか?」を細かく制御できます。
- geolocation(位置情報)
- camera(カメラ)
- microphone(マイク)
- fullscreen(フルスクリーン)
- payment(決済) …など
基本の構文
Permissions-Policy: geolocation=<allowlist>;<allowlist> には、次のような値を指定できます。MDNウェブドキュメント+1
()
→ だれにも許可しない(完全に禁止)self
→ 自分自身の origin には許可する(デフォルト)self "https://example.com"
→ 自分とhttps://example.comからのコンテンツにのみ許可
今回のケースでコンソールに出ていた以下は、「どこからも geolocation を使わせない」という非常に強い制限です。
Permissions-Policy: geolocation=()原因を確認する方法
Chrome DevTools で以下を確認できます。
- DevTools → Network タブ
- ページをリロード
- どれかのリクエストをクリック
- Headers → Response Headers を確認
もし次のような項目があれば、これが犯人です。
permissions-policy: geolocation=()nginx で geolocation を許可する方法
結論:nginx のレスポンスヘッダーに geolocation を許可する設定を追加すれば解決します。
add_header Permissions-Policy "geolocation=(self)";これは、「このサイト自身のコンテンツ(self)では Geolocation を許可する」という指定です。
nginx の設定例(HTTPS サーバブロック)
server {
listen 443 ssl;
server_name example.com;
# Geolocation を許可
add_header Permissions-Policy "geolocation=(self)";
# ここから下は普段の設定
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/example;
index index.html index.htm;
}設定後は nginx を reload します。
sudo systemctl reload nginx実際に追加したらどうなったか?
この設定を追加したところ、Chrome のコンソールに出ていたエラーは消え、
navigator.geolocation.getCurrentPosition()- Leaflet の現在地機能
- Google Maps API の geolocation
など、すべて正常に動くようになりました。
注意:Cloudflare や Django がヘッダーを上書きする場合も
もし nginx に追加したのに解決しない場合:
- Cloudflare の Security → HTTP headers
- Django の middleware で
Permissions-Policyを追加している
などのケースで、ヘッダーが上書きされている可能性があります。
DevTools のレスポンスヘッダーを必ず確認しましょう。
まとめ
| 問題 | Chrome が geolocation をブロックしていた |
|---|---|
| 原因 | Permissions-Policy で geolocation が無効 |
| 解決 | nginx に add_header Permissions-Policy "geolocation=(self)" を追加 |
Geolocation を使うサイト(現在地検索、マップアプリ、位置情報機能など)では、
今後ますます Permissions-Policy の設定が重要になります。
同じエラーが出た方は、まずレスポンスヘッダーを確認してみてください。
コメント