Google Contacts API with Google JavaScript Client Lib - javascript

I am trying to work with the Google Contacts API v3.
Because of the OAuth2 authentication and authorization I'm started with the Google APIs Client Library for JavaScript.
I have no problems with that part of the API access.
But after doing the auth part I don't know what to do next. Can I use the google-api-javascript-client for the Google Contacts API v3? In the list of the supported Google APIs by the javascript-client the contacts API does not appear. But I have full access with the OAuth 2.0 Playground tool.
I am really confused which client is working best with the latest Google Contacts API. What is about the gdata-javascript-client?

To use the v3 contacts api with the authentication token provided by gapi (Google JS client lib) this one is helpful, using alt=&json
$.getJSON('https://www.google.com/m8/feeds/contacts/default/full/?access_token=' +
authResult.access_token + "&alt=json&callback=?", function(result){
console.log(JSON.stringify(result));
});

I know it's an old question but this question shows up when looking on how to read the contacts information from a Google account.
If you only need to access the contact to import it or show the email, phone numbers, or other information and you don't need to modify it, you can use the People API (https://developers.google.com/people/). For javascript you can check the samples tab.
I created a gist, which is almost the sample from Google but adding the requestField parameters.
https://gist.github.com/ddbb1977/7a4b408ed17c7249252a

The problem you are encountering is that the Contacts API v3 is an older API that works with the deprecated GData Client Library. Therefore it is incompatible with the newer Google APIs JavaScript Client.
For now you will need to load and use the GData Client library. For further information on the difference between the GData library and the Google APIs client, please refer to this recent SO question: gapi.client.load versus google.load

Unfortunate Google Contacts API does not work with the new Javascript Client Library. It only works with GData Client Library. I tried working GData Client Library, but it is difficult as you get warnings in the documentation at every juncture that the library has been deprecated.
Therefore, I used a hydrid,
using the new Client Library, to get an authentication.
Use a URL to get the contacts
Unfortunately, because of cross domain restrictions you need to use JSONP, otherwise the browser fails.
<script src="https://apis.google.com/js/client.js"></script>
.....
function contactsInit() {
var clientId = 'YOURCLIENTID.apps.googleusercontent.com';
var scopes = 'https://www.google.com/m8/feeds';
gapi.auth.authorize({
client_id: clientId, scope: scopes, immediate: false},
handleAuthResult);
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
var url =
"https://www.google.com/m8/feeds/contacts/default/" +
"full?alt=json-in-script&access_token=" +
authResult.access_token +
"&max-results=7000&v=3.0";
var myJSONP = new Request.JSONP({
url: url,
callbackKey: 'jsoncallback',
data: {
},
onRequest: function(url){
// a script tag is created with a src equal to url
},
onComplete: function(data){
// the request was completed.
}
}).send();
}
}
}
function Skeleton() {}
if (!gdata) {
var gdata = new Skeleton();
gdata.io = new Skeleton();
gdata.io.handleScriptLoaded = function(data) {
processContacts(data);
}
}
Notes:
I use Mootools for JSONP but you could also use jquery or vanilla js with How to make a JSONP request from Javascript without JQuery?
You need to provide your own YOURCLIENTID, and define the processContacts function.
The gdata.io.handleScriptLoaded(data) is necessary since this what the url expects during callback.
I use a limit of 7000, but I don't think it is necessary.
If you don't want to use JSONP you could forward the access_token to your webserver, and process the URL there, e.g. with cURL or with Node.js just replace json-in-script with json.
In json-in-script is important on a browser since otherwise the browser croaks.
Thanks to the other answers on this page, that pointed me in the right direction.
I hope that Google will make the Contacts API capable with the new Javascript Client Library. I hope that others will other be able to use this solution in the meantime.

For fetching list of contacts using Google plus use this :-
<script src="https://apis.google.com/js/client.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script>
function auth() {
var config = {
'client_id': 'OAUTH_CLIENT_ID',
'scope': 'https://www.google.com/m8/feeds'
};
gapi.auth.authorize(config, function() {
fetch(gapi.auth.getToken());
});
}
function fetch(token) {
$.ajax({
url: "https://www.google.com/m8/feeds/contacts/default/full?access_token=" + token.access_token + "&alt=json",
dataType: "jsonp",
success:function(data) {
console.log(JSON.stringify(data));
}
});
}
In the HTML Body :-
<button onclick="auth();">GET CONTACTS FEED</button>
The output will have as a field with the contact containing the phone number.
Make sure to get the client id from google developer console with proper redirect uri.

This is what we found to work to get individual data:
var data = (JSON.stringify(data.feed.entry[0].gd$email, null, 4));
console.log(data);
If you run JSON.stringify(data) you can see all of the headers that you can call on.

google contact v3 is your best friend for this job
here you can find all posible request endpoint
https://developers.google.com/google-apps/contacts/v3/
like for all contact list this is the end point
https://developers.google.com/google-apps/contacts/v3/#retrieving_all_contacts
After get authentication you can do get request to this url to get all contact list
this is an example in python http://code.google.com/p/gdata-python-client/source/browse/samples/contacts/contacts_example.py

Related

Avoid Basic Authentication popup

I been playing with an ip cam (TP LINK NC200), trying to display a snapshot inside an html form.
Of course the IP-CAM asks for authentication with a big popup
so i been trying to solve it this way
document.addEventListener('DOMContentLoaded', function(){
getimg = document.getElementById('getimg');
getimg.addEventListener('click', getsnap);
});
function getsnap(){
user = 'admin'
psw = 'YWRtaW4=' // base64 password
url = "http://"+ user + ':' + psw + "#192.168.100.103:8080/snapshot.jpg";
document.getElementById('cam_img').src = url;
}
<input id="getimg" value="getimg" type="submit">
<iframe id="cam_img"></iframe>
so apparently embedded credentials are blocked (https://www.chromestatus.com/feature/5669008342777856)
I googled for different solutions, there's many ways to do it and most of them are deprecated by browsers updates, what would be the best way to solve this problem? Im open to any ideas, the simpler the better, but this could also be a nice learning curve.
Also, when i solve the Authorization POPUP manually, this are the headers
I tried using ajax with this code
var uName='admin';
var passwrd='admin';
$.ajax({
type: 'GET',
url: 'http://192.168.100.103:8080/snapshot.jpg',
beforeSend: function (xhr){
xhr.setRequestHeader('Authorization', "Basic " + btoa(uName+":"+passwrd));
},
success : function(data) {
//Success block
},
error: function (xhr,ajaxOptions,throwError){
//Error block
},
});
But i keep getting this error
Any help or guidance would be appreciated! Thanks!
It sounds like the camera doesn't allow cross origin requests. Assuming that you can't alter the cameras web server to allow this, your best bet would be to run some kind of proxy in front of it.
This would allow you to set whatever cors headers you need, and give you a lot more flexibility around authentication. Personally I'd probably use a small node service to accomplish this
See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS for details of cors.
I'd suggest doing the basic auth part server side and then create a random key to use as authentication to the node service

How do I to get Firebase Auth token out of IndexDB for Ajax calls

I'm working on a mobile site, hosted with Node.js / Express and which is "lightly" secured via Firebase Phone Authentication. When first loaded, the site is basically empty. After initial Firebase Phone authentication, the JWT token is sent to the node server via AJAX call. Server checks token, verifies the user is authorized, then sends back html content for the site.
So far, so good. This is a great way to protect display content on a simple single page web app.
But here is my current dilemma. I now want to submit data from a form on the site. The blank form was created with the first AJAX call.
After form submit, I'd like to resubmit the same JWT token to accompany an additional AJAX request for data submission to the server. It's not clear to me on how to obtain the token. I'm no longer inside the chained promise that got me the token in the first place... (i.e. I don't have access to the User Object anymore.) I can see the token stored in IndexedDB --> FirebaseLocalStorageDB --> FirebaseLocalStorage Object --> Key: Value (fbase_key.value.stsTokenManager.accessToken )
Here's a screen print of my dev tools in Chrome Browser.
I'm really not sure how to access that token from JavaScript in the browser client. Any ideas on how to get there from here?
Note: All of my initial client script code was contained within
$(document).ready(function () {
...
}
Because of timing and function .on() binding, the subsequent script content for my data form was served after the initial Ajax call post authentication.
Sample code for the initial AJAX submit... Obviously the form data submit to the server will contain a JSON object payload.
var authUserAjaxRequest = function (jwt) {
console.log("authUserAjaxRequest started...");
$.ajax({
type: "POST",
url: '/fb', //the url to call
data: {
data: 'testData'
}, //Data sent to server
dataType: "json",
beforeSend: function (xhr) { //Include the bearer token in header
xhr.setRequestHeader("Authorization", 'Bearer ' + jwt)
}
}).then(function (response) {
$('#admin_note_loc').html(response.admin_note);
$('#page2_data').html(response.page2_data);
$('#page3_summary').html(response.page3_summary);
$('#page4_team').html(response.page4_team);
}).fail(function (err) { //Error during request
console.log("AuthUserReq Error: ", err);
});
Here's a reference. And another. This reference seems pretty outdated, or I'm just doing it wrong. Specific hints are appreciated.
Here's a solution, but it may not be the best one.
I've got a slight scope issue. For all of my original javascript code I'm using
$(document).ready(function () {
...
}
That code works great, allows me to authenticate, obtain tokens, resubmit, etc.
In there I had some code
var handleSignedInUser = function (user) {
// do stuff to display / block key elements on the site.
user.getIdToken().then(function (token) {
console.log("getIdToken(): ", token); // <-- I added this line
authUserAjaxRequest(token);
})
};
Unfortunately because of the nature of my Ajax additions, I was unable to include their controlling JavaScript within the $(document).ready() wrap. Had some issues binding $().on('click'..) functions to the newly created form elements.
Hmmm. Remember the good 'ol days when we used Microsoft Foundation Classes (MFC) and we added handles to link key features? That gave me an idea.
I added a Global variable, var firebaseGlobalObject = {}; to my original script ahead of $(document).ready(function () {...
And after I initialized my Firebase Authentication tools, I made a copy to the Global variable...
// Initialize Firebase
var config = {
apiKey: "...",
authDomain: "....firebaseapp.com",
databaseURL: "https://....firebaseio.com",
projectId: "...",
storageBucket: "...",
messagingSenderId: "..."
};
firebase.initializeApp(config);
firebaseGlobalObject = firebase; // <--- total hack
And then it was time to play in the Chrome Dev Tools Console...
I came up with this beauty...
console.log(firebaseGlobalObject.auth().currentUser.qa)
Total hack, but it definitely displays EXACTLY the same token as the getIdToken() (in my initial code) and as displayed at IndexedDB --> FirebaseLocalStorageDB --> FirebaseLocalStorage Object --> Key: Value (fbase_key.value.stsTokenManager.accessToken )
Obviously when I'm using the console, I'm in global context. So I think I can make this work. I will say, I have no clue why someone chose .qa for that index. There is a bunch of descriptive properties visible at firebaseGlobalObject.auth().currentUser; just not that token.
Does anyone have an alternative answer to this dilemma, besides a hack (that will probably fail with the next firebase update X months from now?)
firebase.auth().currentUser.getIdToken(true)
.then((tokenId)=>{
//Your code
})
https://firebase.google.com/docs/auth/admin/verify-id-tokens#web

Google translation Oauth2.0 from browser

I am creating a simple web page, that make use of the Google Translation Service.
The page has a field, to receive the input from the user and a button to trigger the call to the Translation API. It returns the result translation to the user.
I've successfully done the flow above using Ajax requests, but the access token
is hard-coded into my method and I want to change that to a call that gets sent whenever the token expires (currently I have to request a new token using the Google CLI and replace it in my code).
I have a very basic knowledge of Oauth2.0 and I've read the Google Documentation but couldn't find a part of it that would tell me the endpoint to call to get an access token from the client-side.
Could someone point me in the right direction, please?
Here is my code:
HTML:
<form id="translate_form">
<input id="input" />
<button id="translate_button">Translate</button>
</form>
Javascript
$("#translate_form").submit(function () {
var text = $("#input").val()
sendTranslationRequest(text);
return false;
})
function sendTranslationRequest(inputText) {
var requestBody = {
q: inputText,
source: "en",
target: "fr",
format: 'text'
}
translationAjaxRequest(requestBody);
}
function translationAjaxRequest(requestBody) {
var access_token = [access_token]
$.ajax({
url: "https://translation.googleapis.com/language/translate/v2",
method: "POST",
contentType: "application/json",
beforeSend: function (request) {
request.setRequestHeader("Authorization", "Bearer " + access_token)
},
data: JSON.stringify(requestBody),
success: function (response) {
var translatedText = response.data.translations[0].translatedText
alert(translatedText)
},
error: function () {
console.log("An error occurred on the request:", response)
}
});
}
The relevant endpoints to get an access token and refresh it are:
https://accounts.google.com/o/oauth2/v2/auth
https://www.googleapis.com/oauth2/v4/token
However, you’ll need to perform several steps in order to get an access token and a refresh token. You may want to review this guide on Using OAuth2.0 for Web Server Applications. It will walk you through the prerequisites, obtaining an access token and refreshing your token.
Alternatively, you may use an API Key. Just be mindful of the recommendations on how to secure it, since a stolen API Key may be used to generate calls that would be charged directly to your billing account.

GMail API access from chrome extension? 403 Forbidden

I have an application that accesses Google APIs out of a Chrome extension via the workflow outlined here.
Chrome Extensions OAuth Tutorial
The basics of the workflow are to initialize the OAuth flow
var oauth = ChromeExOAuth.initBackgroundPage({
'request_url': 'https://www.google.com/accounts/OAuthGetRequestToken',
'authorize_url': 'https://www.google.com/accounts/OAuthAuthorizeToken',
'access_url': 'https://www.google.com/accounts/OAuthGetAccessToken',
'consumer_key': '{MY_CLIENT_ID}',
'consumer_secret': '{MY_CLIENT_SECRET}',
'scope': 'https://www.google.com/m8/feeds/ https://apps-apis.google.com/a/feeds/emailsettings/2.0/ https://mail.google.com/',
'app_name': 'Gmail Plugin',
'callback_page': 'src/google-oauth/chrome_ex_oauth.html'
});
Upon installing the extension, the user is taken to dialog page to authenticate and agree to the scopes I ask for. From here I infer that my consumer key and secret are OK. I have allowed access to the GMail, Contacts, and Admin SDK in the Google Developers console.
Prior to this I had requests working with the Contacts API and Admin SDK API. I'm now trying to add some features that utilize the Gmail REST API.
The next step in setting up a request is to make a request from the background page.
function getSentEmails() {
var emailCollection;
var url = "https://www.googleapis.com/gmail/v1/users/me/messages";
var request = {
'method': 'GET',
'parameters': {
'labelIds': 'SENT'
}
};
var callback = function(response, xhr) {
emailCollection = JSON.parse(response);
console.dir(emailCollection);
}
oauth.sendSignedRequest(url, callback, request);
};
The way the signed requests work is to call a method to complete the next step of the OAuth dance,
oauth.authorize(function() {
getSentEmails();
});
This results in a 403 Forbidden every time. I seem to have no issue accessing the other APIs I mentioned though this OAuth flow. I've allowed the scope in my manifest.json
manifest.json
"permissions": [
"tabs",
"storage",
"https://mail.google.com/*",
"https://www.google.com/m8/feeds/*",
"https://apps-apis.google.com/a/feeds/emailsettings/2.0/*",
"https://www.googleapis.com/gmail/v1/users/*",
"https://www.googleapis.com/auth/gmail.modify/*",
"https://www.googleapis.com/auth/gmail.compose/*",
"https://www.googleapis.com/auth/gmail.readonly/*",
"https://www.google.com/accounts/OAuthGetRequestToken",
"https://www.google.com/accounts/OAuthAuthorizeToken",
"https://www.google.com/accounts/OAuthGetAccessToken"
]
I tried an alternate method of building the HTTP request as outlined in the link above.
function stringify(parameters) {
var params = [];
for(var p in parameters) {
params.push(encodeURIComponent(p) + '=' +
encodeURIComponent(parameters[p]));
}
return params.join('&');
};
function xhrGetSentEmails() {
var method = 'GET';
var url = 'https://www.googleapis.com/gmail/v1/users/me/messages';
var params = {'labelIds': 'SENT'};
var callback = function(resp, xhr) {
console.log(resp);
}
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(data) {
callback(xhr, data);
};
xhr.open(method, url + '?' + stringify(params), true);
xhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method, params));
xhr.send();
}
I get the same 403 doing this.
I believe I'm authenticating properly though, because if I change
xhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method, params));
to
xhr.setRequestHeader('Authorization','foo' + oauth.getAuthorizationHeader(url, method, params));
I get a 401 Unauthorized instead.
Again, no trouble accessing the other APIs I mentioned.
Any input would be much appreciated.
This question is probably fairly obscure, so I'll share how I ended up resolving it.
I moved my chrome extensions OAuth 2.0 workflow to the newer (since Chrome 29) chrome.identity setup for apps and extensions.
Detailed instructions for setting up OAuth 2.0 for an extension are here.
Chrome Identity API User Authentication
Now I can use
chrome.identity.getAuthToken(function(token) {
// Do HTTP API call with token
});
And none of my HTTP requests come up forbidden (403) anymore.
Hope this is helpful to extension builders out there!

I dont understand how to implement the Deleting Requests in request dialog

I have read the document here
but I don't understand how should I implement it right.
In my facebook app I use apprequests from JS api like this:
function newInvite() {
var msg = document.getElementById('msg_look_id').value;
var receiverUserIds = FB.ui({
method: 'apprequests',
message: msg,
title: "Select friends to send your gift",
},
function (response) {
alert("IDS : " + response.request_ids);
});
//http://developers.facebook.com/docs/reference/dialogs/requests/
}
then the user see the request in its app request icon (with the red numbers )
the user click it , but then how do I implement the delete request ?
When the user arrives at your app’s canvas page following a request, there is a parameter called request_ids passed to your app.
Since Facebook calls apps in the iframe using the HTTP method POST, I guess this is also a POST parameter (although it is not explicitly mentioned in the docs). That means you have no access to it using pure client-side JavaScript; you have to use a server-side script to get the content of this parameter.

Categories

Resources