I've exposed a few APIs using go-endpoints. The APIs work fine, but what I'd like to do is restrict usage of the APIs to only a few referers. Since I'm not passing any authentication information, I do not need OAuth (actually, I really do not want to use OAuth as I expect anonymous users to utilize a front-end that uses this API... I just want that front-end and perhaps another one to use my API).
Apparently the way to do this is to make a Public API Key using the Google Developers Console (Project --> APIs and auth --> Credentials --> Create new Key).
I've changed my JavaScript to use this key, by passing it as a param: https://my-app-id.appspot.com/_ah/api/myService/v1/doSomething?key=key_from_developer_console
However, when I make the call, I get a 403 back with this error:
"Access Not Configured. The API () is not enabled for your project. Please use the Google Developers Console to update your configuration."
Well, initially I set the referer to my-app-id.appspot.com/*, which is only place I want my API to be used from. So I figured I'd remove it just to see, but I get the same issue.
There are some old posts here about having to enable Contacts API and Google + API. I tried that, and it didn't work either.
So what gives? There is virtually no documentation from Google on this Public API Key feature. This is really driving me up a wall...
I had this exact same problem yesterday. I decided to generate my own key and added in my own logic to check for the 'key' param from the request. I just added the self-generated key to my env_variables and it works. However, if you try to redeploy after taking this approach, you may still see the access configuration issues..at least I have still.
When user clicks "Share on Twitter" button on my site, I'd like to prepopulate that tweet with an image (let's assume that image is served from my server).
It would be great if I could do it with Twitter's web intent, but that's apparently not possible: https://twittercommunity.com/t/tweet-intent-with-image/18740
It seems like I could use Twitter's POST media/upload API, but in that case I would have to implement 3-legged oAuth authorization? It also seems that is not possible to do it directly from the client (due to CORS issues and I'd have to expose my app's secret key in JavaScript code).
So I guess for this to work I'd need to have some server as middleman between the client running my API and Twitter's oAuth provider?
Is there any service that you could recommend that takes care of it - I found about oAuth.io, I guess they act as a described middleman?
The third possible approach I found would be via Twitter Cards. Is it possible to make it work since I dynamically generate the content via AJAX calls?
This lit a beam of hope in me, but I'm not totally sure what it means yet: https://twittercommunity.com/t/crawler-ajax-escaped-fragment-support/16129
My actual situation: I'm developing an Angular app that displays Highcharts charts and I'd like my users to be able to share their screenshots.
My current high-level idea is: Highcharts' export feature sends request to their server to generate the image, it creates an image and serves it there for 30 seconds - and I'm given it's link in a callback on client.
Now I can store that image somewhere else (my or Twitter's server?) and then we come to the problem described above.
I'd be grateful on any advice how to do this in a most elegant way that would also be as frictionless as possible for the users. (e.g. oAuth requires that they authorize the app to post on their behalf)
In my case we work with other companies which would consume our APIs along with our internal javascript client. I think we need to create a web client id for javascript client. But when exposing APIs externally, is it correct to generate new web client id per company? If so do we have to update clientid each time and redeploy application?
I'm following this documentation and in their example client ids are hardcoded, if I need to give access to new 3rd party users, then I need to generate new client id for them but I'd expect to not redeploy application.
Update: I've created a feature request as per #Alex's suggestion below.
Unfortunately the docs at https://cloud.google.com/appengine/docs/python/endpoints/auth very specifically say, and I quote,
Because the allowed_client_ids must be specified at build time, you
must rebuild and redeploy your API backend after adding or changing
any client IDs in the authorized list of allowed_client_ids or
audiences
so it appears that your perfectly-reasonable use case is very explicitly not covered at this time.
I recommend you visit said page and enter a feature request via the "Write Feedback" link (around the upper right corner of the page) as well as entering a feature request on the Endpoints component of the App Engine feature tracker, https://code.google.com/p/googleappengine/issues/list?can=2&q=component=Endpoints&colspec=ID%20Type%20Component%20Status%20Stars%20Summary%20Language%20Priority%20Owner%20Log -- we monitor both, but with different processes, so trying both is best.
Sorry to be a bearer of bad news. For now, it seems the only workaround is to distribute to the other companies one of a bunch of client ids generated in advance (you can only change the valid bunch when you re-deploy, sigh) and perhaps add some extra, app-layer authorization check of your own -- exactly the kind of work endpoints should be doing on your behalf:-(.
You can use an asterisk as the client ID, that will allow any client to call it without redeploying your API backend. Not sure if this is a documented feature or not, but it works (at least) with both Python and Java.
#Api(name = "myapi",
version = "v1",
scopes = {"https://www.googleapis.com/auth/userinfo.email"},
description = "My flashy API",
clientIds = {"*"})
public class MyAPI { ... }
i tried to use the custom search api ( http://code.google.com/intl/de-DE/apis/websearch/docs ) with java. it works perfectly on eclipse on my local machine.
when i try to do the same from google app engine the reply is: {"responseData": null, "responseDetails": "Quota Exceeded. Please see http://code.google.com/apis/websearch", "responseStatus": 403}
i do not understand. isn't it possible to call search api from GAE apps?
If you look at the very top of that page you linked to, they note that the API has been deprecated and the number of search queries you can make is limited.
However, if you absolutely NEED to use that API instead of the Custom Search API as Google suggests, there are a few troubleshooting steps you can take:
1) Check that your API key is unique to the project, and the limited number of queries you're allowed isn't being consumed by some other application.
2) Google does (did?) hostname filtering so that one computer doesn't use up all the API requests. You may be able to move the queries to Javascript instead of Java -- essentially move the request from the server to the client.
3) Try using a named backend (Java Backends)
Apparently I do not need a 'Maps API key' to use the 'Google Geocoding API' according to:
http://code.google.com/apis/maps/documentation/geocoding/index.html
However, I obtain this:
{
"status": "REQUEST_DENIED",
"results": [ ]
}
Does this mean that my IP is blocked? What can I do to overcome this?
Until the end of 2014, a common source of this error was omitting the mandatory sensor parameter from the request, as below. However since then this is no longer required:
The sensor Parameter
The Google Maps API previously required that you include the sensor parameter to indicate whether your application used a sensor to determine the user's location. This parameter is no longer required.
Did you specify the sensor parameter on the request?
"REQUEST_DENIED" indicates that your request was denied, generally because of lack of a sensor parameter.
sensor (required) — Indicates whether or not the geocoding request comes from a device with a location sensor. This value must be either true or false
Remove the API key parameter and its value.
eg. https://maps.googleapis.com/maps/api/geocode/json?address=[YOUR ADDRESS]&sensor=true
I found that in my case, calling to the service without secure protocol (meaning: http), after adding the key=API_KEY, cause this issue.
Changing to https solved it.
I've noticed that you also get REQUEST_DENIED for some addresses if you don't properly URL encode your address. For example, in
123 Main St #B, Mytown, CA 94110
the '#' character needs to be encoded as %23
For those who are looking this page in 2017 or beyond, like me
Sensor is not required anymore, I tried and got the error:
SensorNotRequired
I just needed to activate my Google Maps Geocoding API, that seems to be necessary nowadays.
Hope it helps someone like me.
If you just copy&paste the example URL that Google gives in their website
http://maps.google.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true_or_false
it will fail because of the wrong parameter of the sensor. You should change it to true or false and not the one that they wrote.
Maybe is the error that you have had, like it happened to me...
I had this problem and I realized that I was assuming that Geocoding came with the JS maps API. However, it is a separate API which I hadn't enabled in the cloud console. Enabling it fixed it right away.
I got this problem as well using the drupal 7 Location module. Autofilling all empty locations resulted in this error. Executing one of the requests to the location api manually resulted in this error in the returned JSON:
"Browser API keys cannot have referer restrictions when used with this API."
Resolving the problem then was easy: create a new key without any restrictions and use it only for Geocoding.
Note for those new to google api keys: by restrictions they mean limiting requests using an api key to specific domains / subdomains. (eg. only request from http://yourdomain.com are allowed).
It's suck Google don't let you that your service is not enabled by this account. Try to enable it first.
Go here https://console.developers.google.com/project
and create a new project with place service activated this may solve your problem.
If you not have configured a billing account with your credit card, the API do not work. The Google is now very hungry for money and not open more your products "free". Obviously that him offer a free limited access number of consults and over this acces, the billing is very high.
https://cloud.google.com/maps-platform/pricing
As you say, this can mean that your IP address has been blocked. I'd make sure that you specify the key parameter on the query string for the Geocoding API request.
https://maps.googleapis.com/maps/api/geocode/xml?sensor=false&address=Placename&key=XXxxxXXxXxxxxXXxx
Also make sure that if you've set up IP Address Restrictions within the Developer Console, you've allowed the correct IP address, just click the project within the list and you'll see the allowed IPs.
If you're still running into issues, you might want to look into printing out the values of the status and error_message elements from the response from Google, you'll see something like this:
REQUEST_DENIED - This IP, site or mobile application is not authorized to use this API key. Request received from IP address 123.4.5.678, with empty referer
If it doesn't mention an IP address restriction, it may well give you enough information about the problem to Google a fix.
For anyone struggling with this issue, I just found out that the Geocoding API can't be used with API keys that have referrer restrictions. Just remove all your referrer restrictions and you should be good.
If you're using any other APIs that do allow keys with referrer restrictions (like the Maps JS API), it's probably best to create a 2nd key with no restrictions to use exclusively for geocoding, because other APIs might display your key publicly and someone else could start using it on their own site.
Google is returning a very useful error message, which helps to correct the issue!
Dim Request As New XMLHTTP30
Dim Results As New DOMDocument30
Dim StatusNode As IXMLDOMNode
Request.Open "GET", "https://maps.googleapis.com/maps/api/geocode/xml?" _
& "&address=xxx", False
Request.Send
Results.LoadXML Request.responseText
Set StatusNode = Results.SelectSingleNode("//status")
Select Case UCase(StatusNode.Text)
Case "REQUEST_DENIED"
Debug.Print StatusNode.NextSibling.nodeTypedValue
...
Error Message Examples
Message 1:
Requests to this API must be over SSL. Load the API with "https://"
instead of "http://".
Message 2:
Server denied the request: You must use an API key to authenticate each request to Google Maps Platform APIs. For additional information, please ...
If none of given solutions fixed the error, the issue probably about Google Cloud Billing settings. You must enable Billing on the Google Cloud Project at billing/enable.
Learn more
{
"error_message" : "You must enable Billing on the Google Cloud Project at https://console.cloud.google.com/project/_/billing/enable Learn more at https://developers.google.com/maps/gmp-get-started",
"results" : [],
"status" : "REQUEST_DENIED"
}
I created another Credential(New API) only for Geocoding, with "Key restrictions" 'None' and "API restrictions" 'Restrict key'
Selected APIs:
Directions API
Geocoding API
Geolocation API
Maps JavaScript API
Places API
and then it's worked.
I just ENABLED my geocoding API, geolocation API and places API on my google cloud platform (where I had generated my API key I was using) and it worked.