Googleplus API emails list is undefined - api

According to the googleplus documentation the there are many fields for the user, one example is emails. But when I make a https://www.googleapis.com/plus/v1/people/me?key=, i don't get back the emails i have defined in my contact section under emails. I tried making them public as well, still no luck.

A couple things:
There is a known issue where the email list will not be returned
You can request an additional scope, userinfo.email to get a user's verified email address
The following example shows how this can be done in JavaScript:
<html>
<script type="text/javascript">
function onSigninCallback(resp){
console.log(resp);
gapi.client.load("oauth2", "v2", function(){
gapi.client.oauth2.tokeninfo(
{'access_token' : resp.access_token}).
execute(function(innerResp){console.log(innerResp.email);});
});
}
</script>
<body>
<span class="g-signin"
data-scope="https://www.googleapis.com/auth/userinfo.email"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-clientId="YOUR_CLIENT_ID"
data-callback="onSigninCallback"
data-theme="dark"
data-cookiepolicy="single_host_origin">
</span>
</body>
<script>
/**
* Load the Google+ JavaScript client libraries.
*/
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/auth:plusone.js?onload=startApp';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
</html>
An open issue, "ability to obtain an emails list" exists in the Google+ Platform Issue tracker, feel free to star the issue or add a comment.

Related

Google SignIn State

I'm trying to build a Google signin button into my website. I'm trying to avoid using their built-in button. The code below works to sign in a user, but I can't figure out how to make my webpage remember that they're signed in when the user refreshes the page, or leaves the site and comes back.
Using Chrome's developer tools, I can see that there's an entry for https://accounts.google.com under both Local Storage and Session Storage. They seem to more or less contain the same information, including the user's validated token.
What I don't understand is how to get the gapi.auth2.init() function to recognize and use this token. The documentation doesn't seem to cover it.
<html>
<head>
<title>Login Test</title>
<script src="http://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://apis.google.com/js/platform.js?onload=renderButton" async defer></script>
</head>
<script>
var googleUser = {};
function renderButton() {
gapi.load('auth2', function(){
auth2 = gapi.auth2.init({
client_id: 'MY_CREDENTIALS.apps.googleusercontent.com',
});
attachSignin(document.getElementById('customBtn'));
});
};
function attachSignin(element) {
auth2.attachClickHandler(element, {},
function(googleUser) {
document.getElementById('name').innerText = "Signed in: " +
googleUser.getBasicProfile().getName();
}, function(error) {
alert(JSON.stringify(error, undefined, 2));
}
);
}
</script>
<body>
<div id="gSignInWrapper">
<span class="label">Sign in with:</span>
<input type="button" id="customBtn" value="Google"></input>
</div>
<p id="name"></p>
</body>
</html>
You can use listeners. This is the relevant part:
// Listen for sign-in state changes.
auth2.isSignedIn.listen(signinChanged);
// Listen for changes to current user.
auth2.currentUser.listen(userChanged);
You can also get up to date values by
var isSignedIn = auth2.isSignedIn.get();
var currentUser = auth2.currentUser.get();
To strictly detect returning users only you can do:
var auth2 = gapi.auth2.init(CONFIG);
auth2.then(function() {
// at this point initial authentication is done.
var currentUser = auth2.currentUser.get();
});
When it comes to your code I would do:
auth2 = gapi.auth2.init(CONFIG);
auth2.currentUser.listen(onUserChange);
auth2.attachClickHandler(element, {});
This way all changes in sign-in state are passed to onUserChange (this includes returning users, new sign-ins from attachClickHandler, new sign-ins from different tab).

Google-plus sign in: the code runs twice, user was logged out right after he logs in

this is a page built on example
<html>
<head>
<title>Demo: Getting an email address using the Google+ Sign-in button</title>
<style type="text/css">
html, body { margin: 0; padding: 0; }
.hide { display: none;}
.show { display: block;}
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
<!--<script src="https://apis.google.com/js/plusone.js" type="text/javascript"></script>-->
<script src="https://apis.google.com/js/client:plusone.js" type="text/javascript"></script>
<script type="text/javascript">
/*
* Triggered when the user accepts the sign in, cancels, or closes the
* authorization dialog.
*/
function loginFinishedCallback(authResult) {
if (authResult) {
console.log('authResult : ',authResult);
if (authResult['error'] == undefined){
gapi.auth.setToken(authResult); // Store the returned token.
toggleElement('signin-button'); // Hide the sign-in button after successfully signing in the user.
getEmail(); // Trigger request to get the email address.
} else {
console.log('An error occurred');
}
} else {
console.log('Empty authResult'); // Something went wrong
}
}
/*
* Initiates the request to the userinfo endpoint to get the user's email
* address. This function relies on the gapi.auth.setToken containing a valid
* OAuth access token.
*
* When the request completes, the getEmailCallback is triggered and passed
* the result of the request.
*/
function getEmail(){
// Load the oauth2 libraries to enable the userinfo methods.
gapi.client.load('oauth2', 'v2', function() {
var request = gapi.client.oauth2.userinfo.get();
request.execute(getEmailCallback);
});
}
function getEmailCallback(obj){
var el = document.getElementById('email');
var email = '';
console.log("OBJ = ",obj)
if (obj['email']) {
email = 'Email: ' + obj['email'];
}
//console.log(obj); // Uncomment to inspect the full object.
el.innerHTML = email;
toggleElement('email');
}
function toggleElement(id) {
var el = document.getElementById(id);
if (el.getAttribute('class') == 'hide') {
el.setAttribute('class', 'show');
} else {
el.setAttribute('class', 'hide');
}
}
</script>
</head>
<body>
<div id="signin-button" class="show">
<div class="g-signin" data-callback="loginFinishedCallback"
data-approvalprompt="auto"
data-clientId="751931329576.apps.googleusercontent.com"
data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email"
data-height="short"
data-cookiepolicy="http://semicon-equip.com"
>
</div>
<!-- In most cases, you don't want to use approvalprompt=force. Specified
here to facilitate the demo.-->
</div>
<div id="email" class="hide"></div>
</body>
</html>
Question 1: It always fails with "Uncaught TypeError: Cannot read property 'load' of undefined",
until I use
<script src="https://apis.google.com/js/client:plusone.js" type="text/javascript"></script>
instead of the example code:
<script src="https://apis.google.com/js/plusone.js" type="text/javascript"></script>
What's the difference between plusone.js and client:plusone.js ?
Question 2: Why the code run twice per page loads ?
Qestion 3: the user was logged out after he just signed in, how to fix ?
error demo page for the above (all the errors are in the background console).
This is not really an answer to the question, but a step by step procedure to reproduce it.
Below the simple html page I'm using to test (similar to the example from Ray C Lin).
I've made it as simple as possible to avoid interactions with other part of the code :
<html>
<head>
<script type="text/javascript"
src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<input type="button" id="signOut" value="Sign out"></button>
<span id="signinButton">
<span class="g-signin"
data-accesstype="offline"
data-callback="signinCallback"
data-clientid="YOUR_CLIENT_ID_HERE"
data-cookiepolicy="single_host_origin"
data-scope="email"
</span>
</span>
<script type="text/javascript">
$('#signOut').on('click', function() {
gapi.auth.signOut();
});
function signinCallback(authResult) {
console.log("signinCallback: ", authResult);
}
(function() {
var po = document.createElement('script');
po.type = 'text/javascript';
po.async = true;
po.src = 'https://apis.google.com/js/client:plusone.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
</body>
</html>
You will have to update data-clientid with your own google client id, and display this page from an authorized javascript origin.
Please note that this might not work from localhost, as Ian suggested in a comment to this post https://plus.google.com/102746521318753162868/posts/Z5Gkro9YXVs
First, sign in using your Google account : you will see a successful callback in the console.
If you click on Sign out, you will see a callback with 'user_signed_out' in the console.
So far so good.
Sign-in again, and wait 1 hour, until the token expires (this is awful to test, as I don't know how to reduced the token lifetime).
After one hour, click on the sign out button : no callback is called.
Click on the sign-in button again :
you get a successfull callback with an authorization code and access token
immediately after, you get a 'user_signed_out' callback.
Once a session has expired, there is no way to return to a "normal" situation, you always get this second callback with 'user_signed_out'.
Actually, there is one way to return to a "normal" situation: revoke the access to the app from the google dashboard.
This is not really an issue for me as I'm using Google+ only to sign-in the user to my app using the one time authorization code, and I'm not using the access token from the client.
But this prevent automatic login from working, as the user is immediately considered as "signed out" from a google perspective.
Q1: client:plusone.js is just telling the loader to automatically load the "client" module. It's basically automatically doing gapi.load("client"), except it is already packaged up for you in one download. You could do it the other way around as well, plusone:client.js!
Q2: Not sure, it may be some JS quirk. In general, try and make your code able to handle multiple callbacks, you may get another if the state changes (e.g. the user logs out of their google account).
Q3: I don't see that on the test page - I am signed OK, and still signed in on refresh! Check you're not blocking third party cookies in your browser or similar?

How to ask for permissions with Google+ Badge API?

I am using Google+ Badge API to get Followers and +1's. Also, i have the Signin button using the Google+ Signin API. When i login using the Signin button, it asks for the email permission. But, when i want to Follow or +1 the Google+ Page it asks me to login and never asks for the permissions.
<html>
<head>
<title>Demo: Getting an email address using the Google+ Sign-in button</title>
<style type="text/css">
.hide { display: none;}
.show { display: block;}
</style>
<script src="https://apis.google.com/js/plusone.js" type="text/javascript"></script>
<script type="text/javascript">
/*
* Triggered when the user accepts the the sign in, cancels, or closes the
* authorization dialog.
*/
function loginFinishedCallback(authResult) {
if (authResult) {
if (authResult['error'] == undefined){
gapi.auth.setToken(authResult); // Store the returned token.
toggleElement('signin-button'); // Hide the sign-in button after successfully signing in the user.
getEmail(); // Trigger request to get the email address.
} else {
console.log('An error occurred');
}
} else {
console.log('Empty authResult'); // Something went wrong
}
}
/*
* Initiates the request to the userinfo endpoint to get the user's email
* address. This function relies on the gapi.auth.setToken containing a valid
* OAuth access token.
*
* When the request completes, the getEmailCallback is triggered and passed
* the result of the request.
*/
function getEmail(){
// Load the oauth2 libraries to enable the userinfo methods.
gapi.client.load('oauth2', 'v2', function() {
var request = gapi.client.oauth2.userinfo.get();
request.execute(getEmailCallback);
});
// This sample assumes a client object has been created.
// To learn more about creating a client, check out the starter:
// https://developers.google.com/+/quickstart/javascript
gapi.client.load('plus','v1', function(){
var request = gapi.client.plus.people.list({
'userId': 'me',
'collection': 'visible'
});
request.execute(function(resp) {
console.log('Num people visible:' + resp.totalItems);
});
});
// This sample assumes a client object has been created.
// To learn more about creating a client, check out the starter:
// https://developers.google.com/+/quickstart/javascript
gapi.client.load('plus','v1', function(){
var request = gapi.client.plus.people.get({
'userId': 'me'
});
request.execute(function(resp) {
console.log('Retrieved profile for:' + resp.displayName);
console.log(resp);
});
});
}
function getEmailCallback(obj){
var el = document.getElementById('email');
var email = '';
if (obj['email']) {
email = 'Email: ' + obj['email'];
}
//console.log(obj); // Uncomment to inspect the full object.
el.innerHTML = email;
toggleElement('email');
}
function toggleElement(id) {
var el = document.getElementById(id);
if (el.getAttribute('class') == 'hide') {
el.setAttribute('class', 'show');
} else {
el.setAttribute('class', 'hide');
}
}
</script>
</head>
<body>
<div id="signin-button" class="show">
<div class="g-signin" data-callback="loginFinishedCallback"
data-clientid="MY_CLIENT_ID"
data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"
data-height="short"
data-cookiepolicy="single_host_origin"
>
</div>
</div>
<!-- Place this tag where you want the badge to render. -->
<div class="g-plus" data-width="210" data-href="//plus.google.com/MY_PAGE_ID" data-rel="publisher" data-theme="dark"></div>
<div id="email" class="hide"></div>
</body>
</html>
Is there a way around where i can ask users for permissions when they login using the Follow AND +1 button?
Also, if a user has set his/her profile fields (like birthday) privacy to 'ONLY ME', then can i request for those fields? If yes, how?
1- there isn't a Badges API.
2- You should distinguish between
- using Google functionality, like the badges or the +1 button, which requires the user to login to Google+
- using your service's functionality, like the sign-in button, which requires the user to connect their Google+ account to your service
In short the user has to sign-in to Google+ (which doesn't require any permissions because Google+ is the identity provider) and connect to your service/site/app which requires them to give you permission.

Google Plus Signin 'Unknown RPC service: widget-interactive-I0_1370237493291'

Sorry for such a noob question.
I just followed following google plus signin's Step1 to Step4.
https://developers.google.com/+/web/signin/
The signin seemed to succeed, while an error 'Unknown RPC service: widget-interactive-I0_1370237493291' emerged. Here are the console logs on Chrome.
XHR finished loading: "https://plusone.google.com/_/scs/apps-static/_/js/k=oz.connect.en_US.B31L_d…sv=1/d=1/ed=1/am=GA/rs=AItRSTOhxGvE7YZFbwjOy6nLkxCnNjz3og/cb=gapi.loaded_1". signin:15
XHR finished loading: "https://plusone.google.com/_/scs/apps-static/_/js/k=oz.gapi.en.hgKKOofQjvI.…sv=1/d=1/ed=1/am=EQ/rs=AItRSTOeNwU4i5ApX9gPGjnZ0AzovKWmWw/cb=gapi.loaded_0". signin:15
Unknown RPC service: widget-interactive-I0_1370237493291 cb=gapi.loaded_0:71
signed in
I think the error is about something incomplete. I cannot figure out what the exactly the error is and how to get it clear. What am I missing?
Here is the code. The origin is http://localhost:3000
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Gplus</title>
</head>
<body>
<h1>Gplus</h1>
<span id="signinButton">
<span
class="g-signin"
data-callback="signinCallback"
data-clientid="362449793624.apps.googleusercontent.com"
data-cookiepolicy="single_host_origin"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-scope="https://www.googleapis.com/auth/plus.login">
</span>
</span>
<script type="text/javascript">
function signinCallback(authResult) {
if (authResult['access_token']) {
// Successfully authorized
// Hide the sign-in button now that the user is authorized, for example:
document.getElementById('signinButton').setAttribute('style', 'display: none');
console.log('signed in');
} else if (authResult['error']) {
// There was an error.
// Possible error codes:
// "access_denied" - User denied access to your app
// "immediate_failed" - Could not automatically log in the user
// console.log('There was an error: ' + authResult['error']);
}
}
</script>
<!-- Place this asynchronous JavaScript just before your </body> tag -->
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/client:plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
</body>
</html>
I had the same problem when I was trying that code sample. When trying to figure it out, I found this post:
https://groups.google.com/forum/?fromgroups#!topic/google-plus-developers/Ax3cMLhMR4Q
in the Google+ Developers Forum that seems to indicate that it's not really an 'error' but some kind of warning. If I find out more, I'll post an update here.
Hope this helps.

Oauth2 - Unsafe JavaScript attempt to access frame with URL

I am using the following code to rendered the facebook login button
<div id="facebook-login">
<script>
FB.init({
appId:"appid", cookie:true,
status:true, xfbml:true
});
FB.Event.subscribe("auth.login", function(response) {
window.location = "http://xxx"; // redirect if user has logged in
});
</script>
<fb:login-button perms="publish_stream"><?php print 'Login with Facebook'; ?></fb:login-button>
</div>
But it no longer works today, and I think it is related to the oauth2.
So I tried to update the code as suggested in Facebook's developer docs.
The new code:
<div id="facebook-login">
<script>
window.fbAsyncInit = function() {
FB.init({
appId:"appid", cookie:true,
status:true, xfbml:true, oauth:true, xfbml: true, channelUrl: '//mydomain/channel.php'
});
FB.Event.subscribe("auth.login", function(response) {
window.location = "http://xxx"; // redirect if user has logged in
});
};
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
}(document));
</script>
<fb:login-button scope="publish_stream"><?php print 'Login with Facebook'; ?></fb:login-button>
</div>
Now whenever I click the facebook login button, the chrome console keeps throwing the following error
Unsafe JavaScript attempt to access frame with URL https://www.facebook.com/login.php?...
I think it is a js cross domain issue, but I have setup the channel url. Any idea on how to solve this problem?
Thanks.
Regards,
Kit
Be sure to replace the code to the new oAuth 2.0
param => scope
response.session => response.authResponse
response.session.access_token => response.authResponse.accessToken
FB.getSession().uid => FB.getAuthResponse().userID
link:
https://developers.facebook.com/blog/post/525/
Finally i found the answer. the get_facebook_cookie() no longer works for OAuth 2.0. we need the facebook php-sdk as mentioned in Facebook Developers – Facebook for Websites
You can also tried the example in Facebook Javascript SDK – A Simple Login Page with OAuth 2.0