[PYTHON] How to hide your Google Maps API key from HTML

I'm worried about API keys when using the Maps JavaScript API

Google says [[Official Samples]](https://developers.google.com/maps/documentation/javascript/adding], despite the fact that ʻAPI keys should not be embedded directly in the code` on the official website. -a-google-map) is coded as follows, and ** YOUR_API_KEY ** appears in the HTML. If you create a web page with this, you will publish the API key all over the world. It's like walking on a public road with Frichin. Is the official sample a naked king?

<script defer
  src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>

For the time being, the Google document [Apply API key restrictions] It says that restrictions by "referrals (websites)" are essential, but this alone is very unfortunate. As you all know, web page names can be easily spoofed by building a web server locally and playing with hosts ... (I don't do that, just in case) Of course, to avoid being charged without your knowledge, [[API usage limit]](https://cloud.google.com/apis/docs/capping-api-usage?authuser=1&authuser=1&hl=ja&visit_id=637360063115512101 -2429778502 & rd = 1) is implemented, but what if someone somewhere uses the API key without permission and accesses it 1 million times? I can't sleep at night ...

Hide your API key out of sight

After all, I don't want to publish the API key in HTML! !! So I decided to use CGI to hide the API key inside the server.

1. 1. Set to environment variable

Pass the API key to CGI with the environment variable set. My environment runs CGI with nginx + fcgiwrap, so set it at the bottom of /etc/nginx/fcgiwrap.conf as follows.

fcgiwrap.conf


location /cgi-bin/ {
・ ・ ・ ・ ・ ・
    fastcgi_param GOOGLE_MAPS_API_KEY  YOUR_API_KEY; <=YOUR_API_Replace KEY with your own key
}

The setting method here differs depending on your environment (apache, etc.), so please set it according to your own environment.

2. Prepare CGI

As a policy, replace the src =" https://maps.googleapis.com/maps/api/js part of the official sample with CGI. I'm using python in my environment, so it looks like this.

getapijs.py


#!/usr/bin/python
# -*- coding: utf-8 -*-
import requests
import os
url = 'https://maps.googleapis.com/maps/api/js' #Official sample HTML is src=I read in url
key = os.environ['GOOGLE_MAPS_API_KEY'] #Extract the API key contained in the environment variable
mysrc = url + "?key=" + key #Concatenate API key to url
response = requests.get(mysrc) #Go to the google map site and bring src
print("'Content-Type': 'text/javascript; charset=UTF-8'") #Header to return to HTML
print("")
print(response.text)

This part also differs depending on your environment, so please write in your own language. The point is that ** bring the API key from the environment variable of the server **, specify the url and get javascript from the google site. The header part should be 'Content-Type':'text / javascript; charset = UTF-8'.

3. 3. Call CGI in javascript window.onload

main.js


function initMap() {
    //Same as the content of the official sample
    // Initialize and add the map
    // The location of Uluru
    var uluru = {lat: -25.344, lng: 131.036};
    // The map, centered at Uluru
    var map = new google.maps.Map(document.getElementById('map'), {zoom: 4, center: uluru});
    // The marker, positioned at Uluru
    var marker = new google.maps.Marker({position: uluru, map: map});
}
window.onload = function() {
    //After displaying the page, write the process you want to execute. This is the point from here!
    fetch("/cgi-bin/getapijs.py").then(res=>{
        //Run CGI and only pass the resulting TEXT next
        return res.text();
    }).then(mytext => {
        //Execute the received javascript with EVAL.
        eval(mytext);
    }).then(() => {
        //Post-execution processing. The official sample HTML&callback=The part that was called in
        initMap();
    }).catch(() =>{
        //Please handle your favorite error
    });
}

In HTML, <script src =" main.js "> </ script> is described in the header part. The style around here varies from person to person, so you can use whatever style you like. The point is, after ** loading the HTML element ** (the defer part of the sample HTML, window.onload in my example), ** execute CGI ** and receive javascript as TEXT ** with EVAL The procedure is to execute **.

Can you sleep with peace of mind?

Since the API key is only in the environment variable, it's okay to publish the source on GITHUB, and even if the website user looks at the HTML or JS with Chrome's developer tools, the API key cannot be found. Compared to the official sample walking on a public road in Frichin, the result is profane. The only thing that makes me feel uncomfortable is using "evil EVAL". You might think it's an evil web page ... Those who have EVAL sealed as a forbidden person cannot use this method, but I think it is more dangerous to expose the API key to the public than using EVAL. Let's stop. If your company prohibits EVAL, please give up and make a heavy app with JAVA. I lightly go with HTML + javascript + python.

Reference

index.html


<!DOCTYPE html>
<html>
  <head>
    <style>
      /* Set the size of the div element that contains the map */
      #map {
        height: 400px;  /* The height is 400 pixels */
        width: 100%;  /* The width is the width of the web page */
      }
    </style>
    <title>Hello World</title>
    <script src="main.js"></script>
  </head>
  <body>
    <h3>My Google Maps Demo</h3>
    <!--The div element for the map -->
    <div id="map"></div>
  </body>
</html>

In addition, I will refer to this article. [How to read external JS from JS that I often use]

Recommended Posts

How to hide your Google Maps API key from HTML
How to update Google Sheets from Python
[Rails] google maps api How to post and display including map information
How to display Map using Google Map API (Android)
How to call Cloud API from GCP Cloud Functions
How to use the Google Cloud Translation API
How to analyze with Google Colaboratory using Kaggle API
How to post a ticket from the Shogun API
How to generate a public key from an SSH private key
Procedure from HTML to JSON Ajax communication of API server
How to use Google Colaboratory
How to get followers and followers from python using the Mastodon API
How to connect to Cloud Firestore from Google Cloud Functions with python code
How to get a job as an engineer from your 30s
[Rails] How to display Google Map
How to use SWIG from waf
Flask reuse How to write html
How to create your own Transform
[Memo] How to use Google MµG
How to use OpenPose's Python API
How to launch Explorer from WSL
How to access wikipedia from python
How to use bing search api
How to convert from .mgz to .nii.gz
[Python] How to use Typetalk API
Use Google Analytics API from Python
From the introduction of GoogleCloudPlatform Natural Language API to how to use it
How to deal with OAuth2 error when using Google APIs from Python
How to get a sample report from a hash value using VirusTotal's API
How to easily operate IOT home appliances from Siri by API hacking
How to access data with object ['key'] for your own Python class
How to create a clone from Github
[Rails] How to introduce Google Analytics [Easy]
How to easily convert format from Markdown
[Memo] How to use BeautifulSoup4 (1) Display html
Explains JavaScript of Google Maps Geocoding API
How to use Google Test in C
[TF] How to use Tensorboard from Keras
How to utilize multi-core from multiple languages
How to use Google Assistant on Windows 10
Use Google Cloud Vision API from Python
How to search Google Drive with Google Colaboratory
How to access RDS from Lambda (python)
How to operate Linux from the console
How to install your own (root) CA
How to create a repository from media
How to access the Datastore from the outside
How to use GCP's Cloud Vision API
Convert from Markdown to HTML in Python
API explanation to touch mastodon from python
Connect to coincheck's Websocket API from Python
Get users belonging to your organization from Garoon REST API with Python + Requests
How to automatically generate API document with Django REST framework & POST from document screen
How to use Service Account OAuth and API with Google API Client for python