Google javascript client api : how to fetch profile name? - javascript

I am trying to implement SignIn with Google with redirect approach. I am following this link
My code looks like below
<script src="https://apis.google.com/js/platform.js?onload=startGoogleApp" async defer></script>
<script>
var startGoogleApp = function () {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: '#googleClientId',
ux_mode: 'redirect',
redirect_uri: '#googleRedirectUri',
fetch_basic_profile: true
});
auth2.signIn();
});
}
</script>
But issue is in Google's id_token is not having the name even though I have passed fetch_basic_profile: true I also tried with scope: 'profile'.
I want to fetch name along with email. don't know what am I doing wrong here.
I want it in part of token as it is mentioned in documentation I am following. I don't want fetch name with additional api call. Is it possible?
id_token looks like this
{
"iss": "accounts.google.com",
"azp": "*********",
"aud": "***********",
"sub": "*********",
"hd": "***.com",
"email": "*****#***.com",
"email_verified": true,
"iat": 1599717107,
"exp": 1599720707,
"jti": "*******"
}

Googles Id token is not guaranteed to return all of the profile claims on ever response.
If you want the users profile information then you should go though the Google People API. people.get
// Make sure the client is loaded and sign-in is complete before calling this method.
function execute() {
return gapi.client.people.people.get({
"resourceName": "people/me",
"requestMask.includeField": "addresses",
"sources": [
"READ_SOURCE_TYPE_PROFILE"
]
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error", err); });
}
gapi.load("client:auth2", function() {
gapi.auth2.init({client_id: "YOUR_CLIENT_ID"});
});
Code ripped from the try me found on people.get

Related

How to display page visits in my web site using data from Google Analytics?

I have a web site and I want, for every article I publish, to display the number of people who visited that page.
My idea is to show the number of page visits by fetching this data from my Analytics account.
By following the tutorial on Google Analytics to handle reports, I have created a small chunk of code to retrieve a specific page's visits number:
let analytics_api_controller = (function () {
const API_KEY = "<secret>";
const CLIENT_ID = "<secret>";
function authenticate() {
return gapi.auth2.getAuthInstance()
.signIn({ scope: "https://www.googleapis.com/auth/analytics https://www.googleapis.com/auth/analytics.readonly" })
.then(function () { console.log("Sign-in successful"); },
function (err) { console.error("Error signing in", err); });
}
function loadClient() {
gapi.client.setApiKey(API_KEY);
return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/analyticsreporting/v4/rest")
.then(function () { console.log("GAPI client loaded for API"); },
function (err) { console.error("Error loading GAPI client for API", err); });
}
function execute() {
return gapi.client.analyticsreporting.reports.batchGet({
"resource": {
"reportRequests": [{
"viewId": "<secret>",
"dateRanges": [{
"startDate": "2018-03-01",
"endDate": "2019-05-01"
}],
"metrics": [{ "expression": "ga:pageviews" }],
"dimensions": [{ "name": "ga:pagePath" }],
"dimensionFilterClauses": [{
"filters": [{
"operator": "EXACT",
"dimensionName": "ga:pagePath",
"expressions": ["/articles/2019/05/10/myarticle.html"]
}]
}]
}]
}
}).then(function (response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
}, function (err) {
console.error("Execute error", err);
});
}
function _viewsPerPage(pageUrl) {
return execute();
}
// Ctor
window.addEventListener("load", function(e) {
gapi.load("client:auth2", function () {
gapi.auth2.init({ client_id: CLIENT_ID });
});
this.window.setTimeout(function() {
authenticate().then(loadClient);
}, 2000);
});
return {
viewsPerPage: _viewsPerPage
};
})();
The setTimeout is something I added to quickly workaround some timing issues (I need to wait for the API to load, something I will properly solve later).
Problem
The code works fine and this is what happens:
The page loads.
The code kicks in and I am asked to sign in to give permission to access my Analytics reports from my Google account.
I give consent.
In F12 tools I manually run: analytics_api_controller.viewsPerPage(), which gives me the report in the console.
The problem is point 2! Every single time I load the page, I am asked to sign in and give permission. This thing is supposed to go in production, so every user will be prompted to access my Analytics info? I assume if they try they'll fail...
Why am I asked to sign in to use this API?
Am I using the correct API to solve this issue?
I think I am not really understanding how I am supposed to use the Google Analytics API. What am I doing wrong? How should this objective be addressed?
You used a Client-side Application that requires the users to login to access your google analytics data. You should use a Service Application that allows your app to login and access your google analytics data (server-side).
PHP quickstart for service accounts

Google People API gapi.client.people.people.connections.list returns Request had insufficient authentication scopes

Google People API gapi.client.people.people.connections.list returns error 403 with error message Request had insufficient authentication scopes even though the initialization includes the required scope
gapi.client.init({
apiKey: '***masked***',
discoveryDocs: ["https://people.googleapis.com/$discovery/rest?version=v1"],
clientId: "***masked***.apps.googleusercontent.com",
'scope': "https://www.googleapis.com/auth/contacts.readonly"
});
the request looks like this
api.client.people.people.connections.list({
'resourceName': 'people/me',
'personFields': 'names,emailAddresses'
}).then(function (response) {
console.log(response.result.emailAddresses[0].value);
if (importGmailCallback) {
importGmailCallback(response);
}
}, function (reason) {
console.log('Error: ' + reason.result.error.message);
});
Waiting for sign in changes happens here
Promise.resolve(window.gapi.auth2.getAuthInstance().signIn()).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(googlePeopleSignedInCallback);
// Handle the initial sign-in state.
googlePeopleSignedInCallback(gapi.auth2.getAuthInstance().isSignedIn.get());
}, function (error) {
console.log(error);
});
I had a success using similar values in API Explorer, tried to remove access and re-authenticated, deleted all cookies, but no luck
Try removing the inverted commas in scope.
Replace:
'scope':"https://www.googleapis.com/auth/contacts.readonly"
with
scope:"https://www.googleapis.com/auth/contacts.readonly"
Try to add this scope as well:
"https://www.google.com/m8/feeds"

google sheets gives the option of using apikey for javascript but does not work

i am trying to send four points of data to a spread sheet from a website i am developing. name, email, subject, message.
function loadClient() {
gapi.client.setApiKey(myapikey);
return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/sheets/v4/rest")
.then(function() {
console.log("GAPI client loaded for API");
}, function(error) {
console.error("Error loading GAPI client for API");
});
}
// Make sure the client is loaded before calling this method.
function execute() {
return gapi.client.sheets.spreadsheets.values.append({
"spreadsheetId": mysheetid,
"range": "a1",
"includeValuesInResponse": "false",
"insertDataOption": "INSERT_ROWS",
"responseDateTimeRenderOption": "SERIAL_NUMBER",
"responseValueRenderOption": "FORMATTED_VALUE",
"valueInputOption": "RAW",
"resource": {
"values": [
[
"test#text.com",
"jimmy clarke",
"subject",
"this is a test email"
]
]
}
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
}, function(error) {
console.error("Execute error", error);
});
}
gapi.load("client");
</script>
i expected it to send the data to the google sheet without error.
it tells me that this can only be sent using oauth.
i would prefer not to use oauth. my main pain point is that when i look at the (google made) templates it allows for the use of the api key, though when i run the code i recieve and i receive this error
Object {
result: {…},
body: "{\n \"error\":
{\n \"code\": 401,\n \"message\": \"Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.\",\n \"status\": "UNAUTHENTICATED\"\n }\n}\n", headers: {…}, status: 401, statusText: "Unauthorized" }
Could i have made a mistake in setting it up?
May have found the answer i believe it is due to the fact that i left the
spread sheet as private, which would require the use of the oauth.

Right way to use gapi.client.drive in chrome extension

I'm trying to use drive to save data from chrome extension.
First, I set needed options to manifest.json
"oauth2": {
"client_id": "999999.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/drive.appdata"
]
},
Then try to get list of files:
$.getScript("https://apis.google.com/js/client.js", function () {
gapi.load('client', function () {
console.log("gapi.client is loaded")
gapi.client.load('drive', 'v3', function () {
console.log("gapi.client.drive is loaded");
chrome.identity.getAuthToken({'interactive': true}, function (token) {
gapi.client.setToken({access_token: token});
console.log("token :", token);
gapi.client.drive.files.list().then(function (list) {
console.log(list)
})
});
});
});
});
Console said:
gapi.client is loaded
gapi.client.drive is loaded
token : [TOKEN]
And the error is like that:
"code": 403,
"message": "The granted scopes do not give access to all of the requested spaces."
The error indicates that you are trying to access unauthorized spaces. Your scope only allows you to use the "appDataFolder" space. Therefore, you have to change
gapi.client.drive.files.list()
for
gapi.client.drive.files.list({spaces:"appDataFolder"}).

401 error when my javascript app tries to access my google cloud endpoints

The project is on Google Appengine cloud endpoints framework.
Python in the backend.
I'm also using endpoints_proto_datastore (not sure if that makes a difference)
Here is my html file -
<html>
<body>
<script>
clientId = 'myclientid-something-something-something.apps.googleusercontent.com'
loginScope = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/admin.directory.user.readonly https://www.googleapis.com/auth/admin.directory.customer.readonly https://www.googleapis.com/auth/gmail.settings.basic';
apiKey = 'my-api-key-from-cloud-console';
doSignIn = function() {
console.log("calling doSignIn");
gapi.client.init({apiKey: apiKey, clientId: clientId,scope: loginScope}).then(renderSignIn);
}
renderSignIn = function(){
gapi.signin2.render('my-signin', {
'scope': loginScope,
'width': 'inherit',
'height': 50,
'longtitle': true,
'theme': 'light',
'onsuccess': getOfflineAccess,
'onfailure': function(){console.log("error")}
});
};
getOfflineAccess =function(){
console.log("calling getOfflineAccess");
gapi.auth2.getAuthInstance().grantOfflineAccess({'redirect_uri': 'postmessage'}).then(getApiAuthorization);
}
getApiAuthorization = function(){
console.log("calling getApiAuthorization");
gapi.auth.authorize({client_id: clientId,scope: loginScope, immediate: false},singedInCallback);
};
singedInCallback = function(authResponse) {
console.log("calling signInCallback");
gapi.client.endpointsapp.userOfflineAccessCode.insert({'auth_code':authResponse.code})
.then( function(){console.log("success");},
function(){console.log("error");}
);
};
init = function() {
console.log("calling init");
var apisToLoad;
var callback = function() {
if (--apisToLoad == 0) {
doSignIn();
}
}
apisToLoad = 2;
gapi.client.load('endpointsapp','v1',callback,"https://endpointsapp.appspot.com/_ah/api"); //dummy name for app
gapi.load('client:auth2', callback);
};
</script>
<div id="my-signin"></div>
<script src="https://apis.google.com/js/api.js?onload=init"></script>
<script src="https://apis.google.com/js/client.js?onload=init"></script>
<script src="https://apis.google.com/js/platform.js"></script>
</body>
</html>
Everything goes smooth at first.
I get a google signing button.
I click on it and then all required permissions are granted.
When the actual API hit is made. That gives me a 401.
The response that I get from the API (gapi.client.endpointsapp.userOfflineAccessCode.insert) is :
{
"error": {
"code": 401,
"errors": [
{
"domain": "global",
"message": "Invalid token.",
"reason": "required"
}
],
"message": "Invalid token."
}
}
When I try the same api endpoint using the google api explorer, if I'm authenticated, everything works, without any issue.
I've been trying to debug this for an entire day but just can't figure out what I'm doing wrong.
Any help is highly appreciated.
ok found the issue. Very basic mistake.
According to https://cloud.google.com/endpoints/docs/frameworks/python/create_api allowed_client_ids is a required field if the API uses authentication. I was not providing this parameter and expecting the API to be available to all client_ids by default.

Categories