- 「Geolocation access has been blocked」というエラーが出て、現在地取得ができない
- JavaScript の書き方もユーザーの許可設定も間違っていないのに動かない
- nginx で直せると聞いたが、どこに何を書けばいいかわからない
Web アプリで現在地を取得する機能を作っていると、Chrome のコンソールにこのエラーが表示されることがあります。この記事を読めば、原因の切り分け方と nginx での解決方法がわかります。
[Violation] Permissions policy violation: Geolocation access has been blocked because of a permissions policy applied to the current document.最初は JavaScript の問題かと思いがちですが、実は ブラウザ側のポリシー(Permissions-Policy)によって Geolocation API が禁止されていることが原因です。
位置情報がブロックされる3つのレイヤー
位置情報まわりのトラブルは、だいたい次の 3つのレイヤー のどこかで止められています。
①プロトコルレイヤー
Geolocation API は HTTPS が必須です。HTTP では、そもそも API 自体が使えません。
②ブラウザ・ユーザー権限レイヤー
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> には、次のような値を指定できます。
()
→ だれにも許可しない(完全に禁止)self
→ 自分自身の origin には許可する(デフォルト)self "https://example.com"
→ 自分とhttps://example.comからのコンテンツにのみ許可
今回のケースでコンソールに出ていた以下は、「どこからも geolocation を使わせない」という非常に強い制限です。
Permissions-Policy: geolocation=()また、ヘッダー自体が無い場合でも、環境や iframe 内などで デフォルト禁止になるケースがあります。
原因の切り分け方
Chrome DevTools で以下を確認できます。
- DevTools → Network タブ
- ページをリロード
- どれかのリクエストをクリック
- Headers → Response Headers を確認
もし次のような項目があれば、これが犯人です。
permissions-policy: geolocation=()nginxでの解決方法
結論:nginx のレスポンスヘッダーに geolocation を許可する設定を追加すれば解決します。
add_header Permissions-Policy "geolocation=(self)";これは、「このサイト自身のコンテンツ(self)では Geolocation を許可する」という指定です。serverブロックに追記します。
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
実際にこれらすべてが正常に動作するようになりました。
それでも直らない場合
もし nginx に追加したのに解決しない場合、たとえば Cloudflare の Security → HTTP headers や、Django の middleware で Permissions-Policy を追加しているケースでは、ヘッダーが上書きされている可能性があります。
もう一つ、nginx特有の落とし穴として、add_headerは同じスコープ内に自分で書いたものしか継承されないという仕様があります。locationブロック側で別のadd_headerを書いていると、serverブロックで設定したPermissions-Policyが丸ごと無視されることがあるので、該当するlocationにも同じ行を追記してみてください。
DevTools のレスポンスヘッダーを必ず確認しましょう。
まとめ
| 問題 | Chrome が geolocation をブロックしていた |
|---|---|
| 原因 | Permissions-Policy で geolocation が無効 |
| 解決 | nginx に add_header Permissions-Policy "geolocation=(self)" を追加 |
Geolocation を使うサイト(現在地検索、マップアプリ、位置情報機能など)では、今後ますます Permissions-Policy の設定が重要になります。同じエラーが出た場合は、まずレスポンスヘッダーを確認してみてください。

コメント