I am trying to get calendar info from google in javascript. I ve read 'how to' manuals. They didn't help. Even this 'helpful' copypasted code (to authorize) didn't. Would somebody be so kind to teach me how to use google api? Maybe someone has some samples to share
And this beautiful js code :
<html>
<button id="authorize-button" onclick='handleAuthClick()'>Authorize</button>
<script type="text/javascript">
var clientId = '***';
var apiKey = '***';
var scopes = 'https://www.googleapis.com/auth/plus.me';
function handleClientLoad() {
gapi.client.setApiKey(apiKey);
window.setTimeout(checkAuth,1);
}
function checkAuth() {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
}
function handleAuthResult(authResult) {
var authorizeButton = document.getElementById('authorize-button');
if (authResult && !authResult.error) {
authorizeButton.style.visibility = 'hidden';
makeApiCall();
} else {
authorizeButton.style.visibility = '';
authorizeButton.onclick = handleAuthClick;
}
}
function handleAuthClick(event) {
// Step 3: get authorization to use private data
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
return false;
}
// Load the API and make an API call. Display the results on the screen.
function makeApiCall() {
// Step 4: Load the Google+ API
gapi.client.load('plus', 'v1', function() {
// Step 5: Assemble the API request
var request = gapi.client.plus.people.get({
'userId': 'me'
});
// Step 6: Execute the API request
request.execute(function(resp) {
var heading = document.createElement('h4');
var image = document.createElement('img');
image.src = resp.image.url;
heading.appendChild(image);
heading.appendChild(document.createTextNode(resp.displayName));
document.getElementById('content').appendChild(heading);
});
});
}
</script>
Error Message (from Console):
'Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('file://') does not match the recipient window's origin ('null').'
so im stuck on 'gapi.auth.authorize'. nothing works after
Based on the error you're receiving, my guess is that you either do not have your Javascript Origin configured properly on the Google API console you got your Client ID from, and/or you are trying to run your script from the file system instead of through a web server, even one running on localhost. The Google API client, near as I've been able to tell, does not accept authorization requests from the file system or any domain that has not been configured to request authorization under the supplied Client ID.
Google API Console reference :
In Client ID for web application:
Javascript Origins : http://localhost:3000/
Key for browser applications:
Referers : http://localhost:3000/
localhost would work 100%
i got the same error and as you preferred, after running html file in my local web server problem solved.
i created credentials for web application and set following values both to my local with "http://localhost:5000" string
"Authorized JavaScript origins"
"Authorized redirect URIs
i checked the json file too. i got the following json file as a result.
{"web":
{
"client_id":"myClientID",
"project_id":"my-project",
"auth_uri":"https://accounts.google.com/o/oauth2/auth",
"token_uri":"https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
"client_secret":"XqXmgQGrst4xkZ2pgJh3Omxg",
"redirect_uris":["http://localhost:5000"],
"javascript_origins":["http://localhost:5000"]
}
}
https://developers.google.com/drive/v2/web/auth/web-client
Some APIs will work fine when queried from local files, but some won't.
In response to an error such as yours, try to serve your files from a web server. If you need a quick web server running, use Python's builtin HTTP server (Mac OSX and Linux systems have Python pre-installed). This HTTP server can turn any directory in your system into your web server directory. cd into your project directory and run the following command:
python -m SimpleHTTPServer 3000 The number at the end is the port number your http server will start in and you can change that port number. In our example, your directory would be served from: http://localhost:3000.
Related
I want to make JSON-RPC calls from localhost (WAMP environment) to the Google FusionTables API (and a couple of other APIs) using the Google Client Library for JavaScript
Steps I have taken:
setup a project on the Google Developer Console
enabled the FusionTables API
created a service account and downloaded the JSON file.
successfully loaded the JS client library with the auth package: gapi.load('client:auth2', initAuth);
constructed the init method parameter the following 3 ways:
the downloaded JSON verbatim
the downloaded JSON modified to include the scope
just the client ID and scope
tried (and failed) to initialize the GoogleAuth instance: gapi.auth2.init(params)
function failed(reason) {
console.log(reason);
}
gapi.load('client:auth2', initAuth);
function initAuth() {
var APIkey = 'MY API KEY';
gapi.client.setApiKey(APIkey); //I understand this to be unnecessary with authorized requests, included just for good measure
var GDTSAKey = 'MY SERVICE ACCOUNT KEY';
var scopes = 'https://www.googleapis.com/auth/fusiontables';
gapi.auth2.init({
client_id: "101397488004556049686",
scope: 'https://www.googleapis.com/auth/fusiontables'
}).then(signin, failed("couldn't initiate"));
//passing the downlaoded JSON object verbatim as parameter to init didn't work either
} //initAuth()
function signin() {
gapi.auth2.getAuthInstance().signIn().then(makeAPIcall), failed("couldn't sign-in");
}
function makeAPIcall(){
gapi.client.load('fusiontables', 'v2', function(){
var tableId = '1PSI_...';
var table = gapi.client.fusiontables.table.get(tableId);
document.querySelector("#result").innerHTML = table;
});
}
based on JS client library >> Samples
the gapi.auth2.init method invokes the second callback (which I understand to be an error handler): failed("couldn't initiate"), but then, curiously, I also get `couldn't sign in' which could only have originated from within the provided success handler. What's going on? How do I get this to work?
Note: I am only willing to try the CORS/xhr, if there is no way to do it with JS client lib.
What's going on?
You are trying to use a service account with the Google JavaScript client library which does not support service accounts.
How do I get this to work?
Switch to Oauth2 authentication or if you must use a service account switch to a server sided language like PHP or python for example. Which support service account authentication.
I've followed the guide on how to use GCS on their site:
but
Once Unauthorized used
I then get
Failed to load resource: the server responded with a status of 400 ()
{"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad
Request"}],"code":400,"message":"Bad Request"}}
Here is my step
create the javascript page from this
authSample.html
change clientId to google console page
OAuth 2.0 user ID:??????????????????????.apps.googleusercontent.com
change apiKey to google console page
OAuth 2.0 user api key
run the authSample.html
What am I doing wrong?
So this bug occurs because of an incorrect way of loading and authorising API's.
The correct way is to first use
gapi to load client (no auth required)
next load, the "storage","v1"
finally Authorise
gapi.load('client', () => {
gapi.client.load('storage', 'v1', authResult =>{
gapi.auth.authorize({
client_id: CLIENT_ID,
scope: SCOPES,
immediate: false
},authResult=>{
if (authResult && !authResult.error) {
var request = gapi.client.storage.buckets.list({
'project': PROJECT_ID
});
request.execute(function(resp) {
console.log(resp)
});
} else {
alert("Un-Authorised")
}
});
});
});
The supported client libraries are limited to a number of languages only. If you wish to build a solution around those, you can refer these here
https://cloud.google.com/storage/docs/json_api/v1/libraries#api-client-libraries
I am trying to consume signalR on a website. SignalR is a self hosted service.
SignalR url: http://localhost8080:/signalr
Website is running # http://localhost:31775/
I am getting error on browser console
GET
http://localhost:31775/signalr/negotiate?connectionData=%5B%5D&clientProtocol=1.3&_=1442784297380
404 (Not Found)
This error tells me that proxy that the code below is trying to generate is using website url i.e. relative path. However I want to use absolute path where my signalR service is hosted.
AngularJS Factory
app.factory("signalRService", ['$', '$rootScope', function ($, $rootScope) {
var proxy;
var connection;
return {
connect: function () {
connection = $.hubConnection();
proxy = connection.createHubProxy('myHub');
connection.start();
proxy.on('addMessage', function (tags) {
$rootScope.$broadcast('addMessage', tags);
});
},
send: function () {
proxy.invoke('send');
},
};
}]);
I also added javascript reference for this.
<script src="js/jquery.signalR-2.0.3.min.js"></script>
To validate if my self hosting is running file. I checked http://localhost:8080/signalr/hub on browser
What you are missing is a bit of configuration of the proxy:
connection = $.hubConnection('http://localhost:8080/signalr');
How to generalize on that piece of code (the url could be an argument of your connect method, or whatever fits your Angular strategy) is up to you.
I'm trying to access (CRUD) Google Drive from a Firefox extension. Extensions are coded in Javascript, but neither of the two existing javascript SDKs seem to fit; the client-side SDK expects "window" to be available, which isn't the case in extensions, and the server-side SDK seems to rely on Node-specific facilities, as a script that works in node no longer does when I load it in chrome after running it through browserify. Am I stuck using raw REST calls? The Node script that works looks like this:
var google = require('googleapis');
var readlineSync = require('readline-sync');
var CLIENT_ID = '....',
CLIENT_SECRET = '....',
REDIRECT_URL = 'urn:ietf:wg:oauth:2.0:oob',
SCOPE = 'https://www.googleapis.com/auth/drive.file';
var oauth2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL);
var url = oauth2Client.generateAuthUrl({
access_type: 'offline', // 'online' (default) or 'offline' (gets refresh_token)
scope: SCOPE // If you only need one scope you can pass it as string
});
var code = readlineSync.question('Auth code? :');
oauth2Client.getToken(code, function(err, tokens) {
console.log('authenticated?');
// Now tokens contains an access_token and an optional refresh_token. Save them.
if(!err) {
console.log('authenticated');
oauth2Client.setCredentials(tokens);
} else {
console.log('not authenticated');
}
});
I wrap the node GDrive SDK using browserify on this script:
var Google = new function(){
this.api = require('googleapis');
this.clientID = '....';
this.clientSecret = '....';
this.redirectURL = 'urn:ietf:wg:oauth:2.0:oob';
this.scope = 'https://www.googleapis.com/auth/drive.file';
this.client = new this.api.auth.OAuth2(this.clientID, this.clientSecret, this.redirectURL);
}
}
which is then called using after clicking a button (if the text field has no code it launches the browser to get one):
function authorize() {
var code = document.getElementById("code").value.trim();
if (code === '') {
var url = Google.client.generateAuthUrl({access_type: 'offline', scope: Google.scope});
var win = Components.classes['#mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('navigator:browser');
win.gBrowser.selectedTab = win.gBrowser.addTab(url);
} else {
Google.client.getToken(code, function(err, tokens) {
if(!err) {
Google.client.setCredentials(tokens);
// store token
alert('Succesfully authorized');
} else {
alert('Not authorized: ' + err); // always ends here
}
});
}
}
But this yields the error Not authorized: Invalid protocol: https:
It is possible though, depending on the use case, it might also of limited interest.
Firefox ships with a tiny http server, just the bare bones. It is included for test purposes but this is not a reason to overlook it.
Lets follow the quickstart guide for running a Drive app in Javascript
The tricky part is to set the Redirect URIs and the Javascript Origins. Obviously the right setting is http://localhost, but how can you be sure that every user has port 80 available?
You can't and, unless you have control over your users, no port is guaranteed to work for everyone. With this in mind lets choose port 49870 and pray.
So now Redirect URIs and the Javascript Origins are set to http://localhost:49870
Assuming you use Add-on SDK, save the quickstart.html (remember to add your Client ID) in the data directory of your extension. Now edit your main.js
const self = require("sdk/self");
const { Cc, Ci } = require("chrome");
const tabs = require("sdk/tabs");
const httpd = require("sdk/test/httpd");
var quickstart = self.data.load("quickstart.html");
var srv = new httpd.nsHttpServer();
srv.registerPathHandler("/gdrive", function handler(request, response){
response.setHeader("Content-Type", "text/html; charset=utf-8", false);
let converter = Cc["#mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
response.write(converter.ConvertFromUnicode(quickstart));
})
srv.start(49870);
tabs.open("http://localhost:49870/gdrive");
exports.onUnload = function (reason) {
srv.stop(function(){});
};
Notice that quickstart.html is not opened as a local file, with a resource: URI. The Drive API wouldn't like that. It is served at the url http://localhost:49870/gdrive. Needless to say that instead of static html we can use a template or anything else. Also the http://localhost:49870/gdrive can be scripted with a regular PageMod.
I don't consider this a real solution. It's just better than nothing.
From here https://developer.mozilla.org/en/docs/Working_with_windows_in_chrome_code you could try window = window || content || {}
Use the JavaScript client API and not the node.js client. Although browserify will make it work. You will have to expose your client secret in the latter. The flow of client side authentication is very diff than server side. Refer to https://developers.google.com/accounts/docs/OAuth2
Having said all this. Its really not that difficult to implement an app with REST based calls. The methods in all client libraries mimic the corresponding REST URLs. You could set up some functions of your own to handle request and response and the rest would feel the same.
I am trying to use the Google plus API (via googie-api-javascript) implementation like so (omitting full code):
var clientId = '7454475891XxxxxxXom4c6n.apps.googleusercontent.com'; //fake client
var apiKey = '-uTH_p6NokbrXXXXXXXXXXXXX'; //Fake Key
var scopes = 'https://www.googleapis.com/auth/plus.me';
function handleClientLoad() {
gapi.client.setApiKey(apiKey);
window.setTimeout(checkAuth,1);
}
function checkAuth() {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
makeApiCall();
} else {
//handle user-approval
}
}
// Load the API and make an API call. Display the results on the screen.
function makeApiCall() {
gapi.client.load('plus', 'v1', function() {
var o = gapi.client.plus;
alert(o);
});
}
The code works well upto the point of gapi.client.load (including the user allowing access) - this callback gets called but alert(o) will return undefined.
Upon inspecting the HTTP request I see the .load issues a request to:
https://content.googleapis.com/discovery/v1/apis/plus/v1/rpc?fields=methods%2F*%2Fid&pp=0&key=-uTH_p6NokbrXXXXXXXX
This returns HTTP 400 with the following message:
{"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad Request"}],"code":400,"message":"Bad Request"}}
My question is - what do I need to change to make this work?
Is there some secret setting I need to enable ? Google+ is enabled in the google-developer-console under the APIs list.
Thanks for the help,
Alon
Problem:
.load issues a request to the google discovery service to load the .JS. The service will error out if the request it receives contains an api-key. (I don't know why the library works like this, it seems like a bug?)
Fix:
gapi.client.setApiKey(""); //NEW
gapi.client.load('plus', 'v1', function()
//re-add the key later if you need it
From Discovery Service docs:
requests you make to the Discovery Service API should not include an API key. If you do provide a key, the requests will fail.
Weird... :P
A little update & more of an explanation. The current Discovery Service page is a little more specific now. They indicate that if the app has an Oauth2 token, then the API Key value is not required. However, I also found that if I have an authenticated user and thus an Oauth2 token (access_token) present, the Discovery Service fails with the error noted in the OP. This seems to contradict the documentation.
You can see the token in the developer tools console with:
console.log(gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse());
Embed that somewhere in a <script>...</script>in your HTML or in a .js file that is called otherwise. Must be after gapi.load(...). It'll stop the script if executed before gapi.load(...) is called.
To get a current user this has to be after the user is authenticated, of course. It does return an object if a user has not been authenticated however. If you are in Chrome, you can expand The Object in the developer tools console window to get a nice outline format of all the stuff in the auth response.
Note that currentUser is undefined prior to a successful authentication. Since this 'fails silently' you should use a conditional statement to verify either the sign in status or that a current user exists in your real code.
For completeness the object instantiation process in my app goes like this, at a high level:
1.) gapi.load(...) - After this gapi.client, gapi.auth2 and other objects are available.
2.) gapi.client.setApiKey("") would be called to 'clear' the api key if it had been set previously for some other purpose.
3.) gapi.auth2.init(...) - After this the auth instance is available via gapi.auth2.getAuthInstance .
4.) Then the login is kicked off using the .signIn() method of the auth instance. The auth instance would be instantiated with something like auth_instance = gapi.auth2.getAuthInstance(); If that's how you do it then the sign in would be auth_instance.signIn().
(...) - means there are several parameters needed.
I also found the Google tictactoe example useful as an example and a simple base for further work.
I hope this is helpful to someone!
you need to call the method
function handleAuthClick(event) {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false} handleAuthResult);
return false;
}
function makeApiCall() {
gapi.client.load('plus', 'v1', function () {
var request = gapi.client.plus.people.get({
'userId': 'me'
});
request.execute(function (resp) {
'method ajax with you application'
});
});
}
you can see what this do here