I am trying to use the javascript sdk to do an oauth login and access the google plus api. Basically the same code here: https://developers.google.com/api-client-library/javascript/features/authentication
In my firebug console, this is the url that is sending the api request to:
https://content.googleapis.com/discovery/v1/apis/plus/v1/rest?fields=servicePath%2Cresources%2Cparameters%2Cmethods&pp=0&key={key}
This is the error that comes back:
{"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad Request"}],"code":400,"message":"Bad Request"}}
I have:
1. Added Google Plus Api to my project
2. Created oauth credentials
3. Setup my consent screen
However, I am still getting the error.
The reason is that you have the key defined in the request. As specified in the discovery API docs (https://developers.google.com/discovery/v1/getting_started#before_starting):
"The APIs Discovery Service provides only public methods that do not
require authentication. In addition, unlike the requests you make to
many other Google APIs, the requests you make to the Discovery Service
API should not include an API key. If you do provide a key, the
requests will fail. This behavior helps ensure that you don't
accidentally disclose your API key when distributing tools that are
based on the Google APIs Discovery Service."
So you can solve the problem by removing the key from your request entirely.
If you are using Google's javascript client to do this and the error occurs when loading further APIs, you have to unset the key first:
gapi.client.setApiKey( null );
gapi.client.load( "plus", "v1", function( apiresponse ) { ... } );
If another function requires the key later, you have to set it again.
To avoid setting and unsetting the key constantly, I load all the needed APIs before authentication, then set the API key and thus will no longer have the issue.
Related
I've developed a js to help users input there info in a form by fetching public data.
Now I'm thinking to deploy it as kind of an API service.
Is it possible and safe enough for HTTP trigger of PaaS's like GCF and Amazon Lambda to be triggered only from specif domains I allow? Like js's fetching and reading its header's origin and check its domain.
I've considered generating passcodes per my customer and placing it in key.js in user's directory or env value, have my js file open on URL, let user website read the js with return of key.js in query param and check its validity.
But forms can be everywhere in cutomers tree, placing it in env for each custmomer can be bothersome at scaling.
you can use ReCaptcha v3, add the allowed domains that can access your function endpoint, and verify the token is valid on the function implementation.
This isn't a native GCF feature, but you could try
Adding a filter in your GCF code (e.g. express.js) to check the requested domain
Making your GCF private and letting it ensure callers are authorized (GCP callers)
Run in Cloud Run, App Engine or another service with Identity Aware Proxy and screen out callers that way
Scenarios where i require to keep the keys as a secret
Azure / Google Maps API KEYs
STUN & TURN Server credentials for WEBRTC
First I was adding the keys directly , then I found out that those are very high vulnerabilities that others could take those credentials and use it for their needs
Later i tried using environment variables in .env file
But i could not find a way to use it properly
(express + nodeJS)
res.render("pages/crimestats", { apikey: process.env.AZURE_KEY })
here i was passing to the rendering page as a variable , but the key was still visible when i tried to see the source code on the browser.
So what is the proper way to use it ?
What i have in my mind
using an api call to get the key in the frontend
//but then any one can call that api request in the browser console right?
I want my users to login using the Sign In With LinkedIn feature. The LinkedIn API docs provides the following example snippet for getting started:
<script type="text/javascript" src="//platform.linkedin.com/in.js">
api_key: YOUR_API_KEY_HERE
authorize: true
onLoad: onLinkedInLoad
</script>
<script type="text/javascript">
// Setup an event listener to make an API call once auth is complete
function onLinkedInLoad() {
IN.Event.on(IN, "auth", getProfileData);
}
// Handle the successful return from the API call
function onSuccess(data) {
console.log(data);
}
// Handle an error response from the API call
function onError(error) {
console.log(error);
}
// Use the API call wrapper to request the member's basic profile data
function getProfileData() {
IN.API.Raw("/people/~").result(onSuccess).error(onError);
}
</script>
How to I implement this without exposing YOUR_API_KEY_HERE to the public? There's a few npm packages out there that handle this kind of thing, but they are all old (I get nervous whenever a package hasn't been updated in at least a year).
My application uses node and express. Should I go with an old npm package or is there a better way to hide the api_key?
It is ok and necessary to have YOUR_API_KEY_HERE in the javascript or website and it is necessary at times. They important piece is not to share your SECRET_KEY because you need both to do anything with the API. Be sure to always use HTTPS for all communications.
From the linkedin best practices for security application website:
https://developer.linkedin.com/docs/best-practices
API Key & Secret Key
When making calls to the LinkedIn APIs you use two pieces of identifiable information: the API Key (sometimes called the Consumer Key) and the Secret Key (or Consumer Secret).
The API Key is a public identifier of your application and the Secret Key is confidential and should only be used to authenticate your application on the LinkedIn APIs.
Since both the API Key and Secret Key are needed together to confirm your application’s identity, it is critical that you never expose your Secret Key. Here are some suggestions for proper Secret Key storage:
When creating a native mobile application, do not store it locally on a mobile device.
Do not expose in any client side code files like JavaScript or HTML files.
Do not store it in files on a web server that can be viewed externally e.g.: configuration files, include files, etc.
Do not store it in log files or error messages.
Do not email it or post it on a message board or other public forum.
Remember that when exchanging an OAuth 2.0 authorization code for an access token, the Secret Key is passed as part of the request. Do not expose this request publicly!
I have several fragments of code in which I have written my Google's api key or clientId such as:
<ffu:ffuAttachDocumentFromDriveBS
apikey="MY_API_KEY"
clientId="MY_CLIENT_ID"
fileId="#{documentManagerBean.fileId}"
downloadMethod="#{documentManagerBean.downloadFileAndUploadToBeeblos()}"
render="attachment_message, #{id_mpAttachment}_doc"/>
or
_doAuth: function(immediate, callback) {
gapi.auth.authorize({
client_id: MY_CLIENT_ID,
scope: 'https://www.googleapis.com/auth/drive',
immediate: immediate
}, callback);
}
so if anyone were to inspect the code in the browser, they would see them.
Is there any way to hide them?
No, the Google API Key must be placed in your HTML or JS files. So, yes, everyone can look.
But remeber that Google generate the API key for a specific domain.
So, a stolen key, can not be used.
The problem is that some developers, does not attach the API key to their domains properly, Google recommends attach to specific domain to prevent bad usages.
Google provides a Browser key and Server key. The browser key is okay to use on the browser. Your server key is the one you don't want exposed. You can use Cloud Functions or AWS Lambda to do your server side API calls.
I generated Browser API Key in Google Console and set referrers:
Then I go to http://afriflirt.com, open JS console in browser and run this code ("Google Maps Geocoding API" enabled for this api key in settings):
var apiKey = 'AIzaSyAGpR-mG46fDbmWjJwkZZHft_xvZ_dM3cA';
$.getJSON(
'https://maps.googleapis.com/maps/api/geocode/json?address=12345&key=' + apiKey,
function(resp) {alert(JSON.stringify(resp));}
);
in response I see this message:
This IP, site or mobile application is not authorized to use this API
key. Request received from IP address 113.180.75.109, with referer:
http://afriflirt.com/
If I remove referrers - API key start working, but this is not safe.
So it's a problem only when I set referrers. Tried different formats of referrers patterns, but nothing worked. Also tried to wait some time (as I saw "it may take up to 5 minutes for settings to take effect"), but it doesn't help too.
Please let me know if you have any ideas how to fix this.
According to the documentation, you need a server key for the geocoding web service.
Create a server key, enable it for IP address: 113.180.75.109, that should work in your example (but it isn't recommended to use a server key from javascript like that, use a browser key and the Google Maps Javascript API v3 Geocoding Service).