【解決法付き】Chrome の「Permissions policy violation: Geolocation access has been blocked」エラーとは?原因と nginx での対処方法

  • 「Geolocation access has been blocked」というエラーが出て、現在地取得ができない
  • JavaScript の書き方もユーザーの許可設定も間違っていないのに動かない
  • nginx で直せると聞いたが、どこに何を書けばいいかわからない

Web アプリで現在地を取得する機能を作っていると、Chrome のコンソールにこのエラーが表示されることがあります。この記事を読めば、原因の切り分け方と nginx での解決方法がわかります。

Text
[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-Policygeolocation=() のように禁止されていると、ブラウザはそもそも Geolocation API を使わせてくれません。

コンソールにエラーが出たら、まずはどのレイヤーで止められているかを切り分けることが大切です。

Permissions-Policyでできること

Permissions-Policy は、「このページは、ブラウザのどの機能を使ってよいか」をサーバーが宣言するヘッダー です。

たとえば以下について「どの origin に対して許可するか?」を細かく制御できます。

  • geolocation(位置情報)
  • camera(カメラ)
  • microphone(マイク)
  • fullscreen(フルスクリーン)
  • payment(決済) …など

基本の構文

Text
Permissions-Policy: geolocation=<allowlist>;

<allowlist> には、次のような値を指定できます。

  • ()
    → だれにも許可しない(完全に禁止)
  • self
    → 自分自身の origin には許可する(デフォルト)
  • self "https://example.com"
    → 自分と https://example.com からのコンテンツにのみ許可

今回のケースでコンソールに出ていた以下は、「どこからも geolocation を使わせない」という非常に強い制限です。

Text
Permissions-Policy: geolocation=()

また、ヘッダー自体が無い場合でも、環境や iframe 内などで デフォルト禁止になるケースがあります

原因の切り分け方

Chrome DevTools で以下を確認できます。

  1. DevTools → Network タブ
  2. ページをリロード
  3. どれかのリクエストをクリック
  4. Headers → Response Headers を確認

もし次のような項目があれば、これが犯人です。

Text
permissions-policy: geolocation=()

nginxでの解決方法

結論:nginx のレスポンスヘッダーに geolocation を許可する設定を追加すれば解決します。

Text
add_header Permissions-Policy "geolocation=(self)";

これは、「このサイト自身のコンテンツ(self)では Geolocation を許可する」という指定です。serverブロックに追記します。

NGINX
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 します。

Bash
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 の設定が重要になります。同じエラーが出た場合は、まずレスポンスヘッダーを確認してみてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

普段は主にPython開発をしています。
最近はAI駆動開発にも関わっています。

コメント

コメントする