Google Plus Login - unknown RPC service errors - javascript

I have integrated Google Plus login on my site, and all was working well until yesterday at around 5pm, my G plus login stopped working in Chrome. No changes to the code, but the button no longer works, the mouse hover does not produce a hand (only a text select), and all of a sudden I am getting several unknown RPC errors in the console:
Uncaught TypeError: Cannot read property 'prototype' of undefined VM2122:6
Unknown RPC service: _ready cb=gapi.loaded_0:64
Unknown RPC service: _ready cb=gapi.loaded_0:64
Unknown RPC service: _resizeMe cb=gapi.loaded_0:64
I thought this was related to my Google Plus login button HTML, but I have not been able to track down the problem. I found this topic but it was not helpful, I am not using jQuery to create the button, just pure HTML:
<div id="gConnect">
<button class="g-signin"
data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-clientId="REDACTED"
data-callback="onSignInCallback"
data-theme="dark"
data-cookiepolicy="single_host_origin">
</button>
</div>
and in my JS:
var helper = (function() {
var BASE_API_PATH = 'plus/v1/';
return {
/**
* Hides the sign in button and starts the post-authorization operations.
*
* #param {Object} authResult An Object which contains the access token and
* other authentication information.
*/
onSignInCallback: function(authResult) {
gapi.client.load('plus','v1', function(){
// $('#authResult').html('Auth Result:<br/>');
// for (var field in authResult) {
// $('#authResult').append(' ' + field + ': ' +
// authResult[field] + '<br/>');
// }
if (authResult['access_token']) {
gapi.auth.setToken(authResult); // Store the returned token. Unnecessary?
$('#loggedIn').show('slow');
$('#gConnect').fadeOut('slow');
helper.profile();
} else if (authResult['error']) {
// There was an error, which means the user is not signed in.
// As an example, you can handle by writing to the console:
console.log('The user is not signed in.');
$('#loggedIn').hide('slow');
$('#gConnect').show();
}
// console.log('authResult', authResult);
});
},
/**
* Calls the OAuth2 endpoint to disconnect the app for the user.
*/
disconnect: function() {
// Revoke the access token.
$.ajax({
type: 'GET',
url: 'https://accounts.google.com/o/oauth2/revoke?token=' +
gapi.auth.getToken().access_token,
async: false,
contentType: 'application/json',
dataType: 'jsonp',
success: function(result) {
console.log('revoke response: ' + result);
$('#loggedIn').hide();
$('#profileImg').empty();
$('#greeting').empty();
$('#gConnect').show();
},
error: function(e) {
console.log(e);
}
});
},
/**
* Gets and renders the list of people visible to this app.
*/
people: function() {
var request = gapi.client.plus.people.list({
'userId': 'me',
'collection': 'visible'
});
request.execute(function(people) {
$('#visiblePeople').empty();
$('#visiblePeople').append('Number of people visible to this app: ' +
people.totalItems + '<br/>');
for (var personIndex in people.items) {
person = people.items[personIndex];
$('#visiblePeople').append('<img src="' + person.image.url + '">');
}
});
},
/**
* Gets and renders the currently signed in user's profile data.
*/
profile: function() {
gapi.client.load('oauth2', 'v2', function() {
// get email
var request = gapi.client.oauth2.userinfo.get();
request.execute(function(obj) {
userInfo.setEmail(obj.email);
});
// get profile
var request = gapi.client.plus.people.get( {'userId' : 'me'} );
request.execute(function(profile) {
userInfo.setProfile(profile);
});
});
}
};
})();
function onSignInCallback(authResult) {
helper.onSignInCallback(authResult);
}
I haven't been able to find any documentation of changes in the Google+ API or anyone else having this specific problem. Weird piece of additional info is that I can still login using a mobile browser (Android), but functionality of the app is compromised (beyond the scope of this post).

try enabling third-party cookies on your Browser and it should work :)

Related

How to Access Google Photos API with Javascript using google-api-javascript-client and read JSON data?

I am very new to using API and getting JSON data using OAuth. Could anybody help me? I am trying to access clients google photos and read them. These code snippets are from google photos documentation. I modified it but still having error: "Failed to load resource: the server responded with a status of 401 ()" and "Uncaught {error: "idpiframe_initialization_failed", details: "Not a valid origin for the client: http://127.0.0.…itelist this origin for your project's client ID."}"
Thank you!!!
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
<script>
var GoogleAuth;
var SCOPE = 'https://www.googleapis.com/auth/drive.photos.readonly';
function handleClientLoad() {
// Load the API's client and auth2 modules.
// Call the initClient function after the modules load.
gapi.load('client:auth2', initClient);
}
function initClient() {
// Retrieve the discovery document for version 3 of Google Drive API.
// In practice, your app can retrieve one or more discovery documents.
var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/photos/v1/rest';
// Initialize the gapi.client object, which app uses to make API requests.
// Get API key and client ID from API Console.
// 'scope' field specifies space-delimited list of access scopes.
gapi.client.init({
'apiKey': 'XXXXXXXXXXXX',
'discoveryDocs': [discoveryUrl],
'clientId': 'XXXXXXXXXXXXXXXXXX',
'scope': SCOPE
}).then(function () {
GoogleAuth = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
GoogleAuth.isSignedIn.listen(updateSigninStatus);
// Handle initial sign-in state. (Determine if user is already signed in.)
var user = GoogleAuth.currentUser.get();
setSigninStatus();
// Call handleAuthClick function when user clicks on
// "Sign In/Authorize" button.
$('#sign-in-or-out-button').click(function () {
handleAuthClick();
});
$('#revoke-access-button').click(function () {
revokeAccess();
});
});
}
function handleAuthClick() {
if (GoogleAuth.isSignedIn.get()) {
// User is authorized and has clicked 'Sign out' button.
GoogleAuth.signOut();
} else {
// User is not signed in. Start Google auth flow.
GoogleAuth.signIn();
}
}
function revokeAccess() {
GoogleAuth.disconnect();
}
function setSigninStatus(isSignedIn) {
var user = GoogleAuth.currentUser.get();
var isAuthorized = user.hasGrantedScopes(SCOPE);
if (isAuthorized) {
$('#sign-in-or-out-button').html('Sign out');
$('#revoke-access-button').css('display', 'inline-block');
$('#auth-status').html('You are currently signed in and have granted ' +
'access to this app.');
} else {
$('#sign-in-or-out-button').html('Sign In/Authorize');
$('#revoke-access-button').css('display', 'none');
$('#auth-status').html('You have not authorized this app or you are ' +
'signed out.');
}
}
function updateSigninStatus(isSignedIn) {
setSigninStatus();
}
</script>
<button id="sign-in-or-out-button"
style="margin-left: 25px">Sign In/Authorize
</button>
<button id="revoke-access-button"
style="display: none; margin-left: 25px">Revoke access
</button>
<div id="auth-status" style="display: inline; padding-left: 25px"></div>
use this link to get more details
On right side there is button Execute, on click that button you will get all photos ,
you can also find code just clicking a icon right side square icon of text Try this API, a popup will open, click on JAVASCRIPT Tab , you will find code
https://developers.google.com/photos/library/reference/rest/v1/mediaItems/search
Accessing Google Photo API with your standard Google Apps Script token
I believe you can use the token that you already have with Google Apps Script.
I did go into the Console and setup the credentials for this project but I'm not using them.
function listImages() {
var token='';
var html='';
var n=0;
do{
var params = {muteHttpExceptions:true,headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()}};
var url=Utilities.formatString('https://photoslibrary.googleapis.com/v1/mediaItems?pageSize=100%s',(token!=null)?"&pageToken=" + token:"");
var resp=UrlFetchApp.fetch(url,params);
Logger.log(resp);
var js=JSON.parse(resp.getContentText());
for(var i=0;i<js.mediaItems.length;i++) {
html+=Utilities.formatString('<br />%s - File Name: %s<br /><img src="%s" width="265"/>',++n,js.mediaItems[i].filename,js.mediaItems[i].baseUrl);
}
token=js.nextPageToken;
}while(token!=null);
var userInterface=HtmlService.createHtmlOutput(html).setWidth(1200).setHeight(500);
//SpreadsheetApp.getUi().showModelessDialog(userInterface, 'Images')//dialog
SpreadsheetApp.getUi().showSidebar(userInterface);//sidebard
}
Try This Code
call onAuthPhotoApiLoad function on button click
**also include js of google **
var scopeApi = ['https://www.googleapis.com/auth/photoslibrary', 'https://www.googleapis.com/auth/photoslibrary.readonly', 'https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata'];
function onAuthPhotoApiLoad() {
window.gapi.auth.authorize(
{
'client_id': "Put Client ID Here",
'scope': scopeApi,
'immediate': false
},
handlePhotoApiAuthResult);
}
function handlePhotoApiAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
GetAllPhotoGoogleApi();
}
}
function GetAllPhotoGoogleApi() {
gapi.client.request({
'path': 'https://photoslibrary.googleapis.com/v1/mediaItems:search',
'method': 'POST',
'body': {
"filters": {
"mediaTypeFilter": {
"mediaTypes": ["PHOTO"]
}
}
}
}).then(function (response) {
console.log(response);
}, function (reason) {
console.log(reason);
});
}

How to check if user is logged in or not with "Google Sign In" (OAuth 2.0)

I am implementing Google log in for the first time as described here and here.
I am using HTML with Javascript.
The problem that needs solving is as follows: How can I, after the initial login, on a different page (say a landing page, or portal that the user sees after logging in), check if the user is logged in? Is there a service I can call to check the user's login in status with my app key or something similar?
I assume I would have to include the google API on each page.
Login Page Code:
Script In Head (Code from Google's tutorial listed above):
<head>
....
<script src="https://apis.google.com/js/platform.js" async defer></script>
<script>
function onSignIn(googleUser)
{
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId());
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail());
alert(profile.getName());
}
function logout()
{
alert('logging out');
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
}
...
</head>
Code In Body (1st line from Google's tutorial listed above, 2nd line to trigger logout test)
<body>
...
<div class="g-signin2" data-onsuccess="onSignIn"></div>
<div onmousedown="logout()">Logout</div>
...
</body>
Is there some way I can include the google API on another page, and then call some check login status function? Or another way to concretely tell if the user is logged in or out?
You do not need to store anything on local storage. The library allows you to check if the user is logged in or not using the isSignedIn.get() on the auth2 of the gapi object.
Load the JavaScript library, make sure you are not deferring the load :
<script src="https://apis.google.com/js/platform.js"></script>
Then initialize the library and check if the user is logged in or not
var auth2;
var googleUser; // The current user
gapi.load('auth2', function(){
auth2 = gapi.auth2.init({
client_id: 'your-app-id.apps.googleusercontent.com'
});
auth2.attachClickHandler('signin-button', {}, onSuccess, onFailure);
auth2.isSignedIn.listen(signinChanged);
auth2.currentUser.listen(userChanged); // This is what you use to listen for user changes
});
var signinChanged = function (val) {
console.log('Signin state changed to ', val);
};
var onSuccess = function(user) {
console.log('Signed in as ' + user.getBasicProfile().getName());
// Redirect somewhere
};
var onFailure = function(error) {
console.log(error);
};
function signOut() {
auth2.signOut().then(function () {
console.log('User signed out.');
});
}
var userChanged = function (user) {
if(user.getId()){
// Do something here
}
};
Don't forget to change the app id
You can stringify a custom userEntity object and store it in sessionStorage where you can check it anytime you load a new page. I have not tested the following but it should work (doing something similar with WebAPI tokens in the same way)
function onSignIn(googleUser)
{
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId());
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail());
var myUserEntity = {};
myUserEntity.Id = profile.getId();
myUserEntity.Name = profile.getName();
//Store the entity object in sessionStorage where it will be accessible from all pages of your site.
sessionStorage.setItem('myUserEntity',JSON.stringify(myUserEntity));
alert(profile.getName());
}
function checkIfLoggedIn()
{
if(sessionStorage.getItem('myUserEntity') == null){
//Redirect to login page, no user entity available in sessionStorage
window.location.href='Login.html';
} else {
//User already logged in
var userEntity = {};
userEntity = JSON.parse(sessionStorage.getItem('myUserEntity'));
...
DoWhatever();
}
}
function logout()
{
//Don't forget to clear sessionStorage when user logs out
sessionStorage.clear();
}
Of course, you can have some internal checks if the sessionStorage object is tampered with. This approach should work with modern browsers like Chrome and Firefox.
To check is user Signed-in use:
gapi.auth2.getAuthInstance().isSignedIn.get()
Adding on to Joseph's answer above, you can then get information about the user by calling auth2.currentUser.get().getBasicProfile().
if (auth2.isSignedIn.get()) {
googleUserProfile = auth2.currentUser.get().getBasicProfile()
console.log('ID: ' + googleUserProfile.getId());
console.log('Full Name: ' + googleUserProfile.getName());
console.log('Given Name: ' + googleUserProfile.getGivenName());
console.log('Family Name: ' + googleUserProfile.getFamilyName());
console.log('Image URL: ' + googleUserProfile.getImageUrl());
console.log('Email: ' + googleUserProfile.getEmail());
}
From the docs: https://developers.google.com/identity/sign-in/web/people
according to the link from Phyrik post (https://developers.google.com/identity/sign-in/web/people) -
google stopped supporting the Sign-In Javascript web auth API:
We are discontinuing the Google Sign-In JavaScript Platform Library for web. The library will be unavailable for download after the March 31, 2023 deprecation date. Instead, use the new Google Identity Services for Web.
By default, newly created Client IDs are now blocked from using the older Platform Library, existing Client IDs are unaffected. New Client IDs created before July 29th, 2022 can set plugin_name to enable use of the Google Platform Library.

Google_Auth_Exception' with message 'Error fetching OAuth2 access token, message: 'invalid_grant'

I'm attempting a slight variation of the Google+ web sign-in server side flow as described on the Google Developer's website.
I have a staff login page (staff_login.php) which uses javascript via Google+ (plusone.js).
If the user is already signed in to Google then the authorization code from Google is stored to a session variable.
If the user is not signed in then a 'Staff Login' button is displayed. If the user clicks the button then Google authorization takes place and, if successful, then the authorization code from Google is stored to a session variable.
In both cases, after the session variable has been stored, the user is redirected to another web page (google_login.php).
Most of the time the login process works as expected, but sometimes google_login.php generates an error message: Google_Auth_Exception' with message 'Error fetching OAuth2 access token, message: 'invalid_grant'.
I'm fairly sure the problem lies in the signInCallback function. How do I make it bulletproof?
Here's the (cut-down) code:
staff_login.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="google-signin-clientid"
content="CLIENT-ID.apps.googleusercontent.com">
<meta name="google-signin-scope" content="email">
<meta name="google-signin-cookiepolicy" content="single_host_origin">
<meta name="google-signin-callback" content="signInCallback">
<title>Login</title>
</head>
<body>
<button id="xyzStaffSignIn">Staff Sign In</button>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"
type="text/javascript"></script>
<script type = "text/javascript" >
jQuery(document).ready(function ($) {
console.log('Google (plusone.js) will invoke signInCallback');
window.___gcfg = {
lang: 'en-GB',
parsetags: 'onload'
};
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);
});
function signInCallback(authResult) {
if (authResult) {
if (authResult['error'] == undefined) {
if (authResult['code']) {
setSessionValue('GoogleAuthorisationCode',
authResult['code'], callGoogleLogin);
}
} 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']);
if (!authResult['status']['signed_in']) {
console.log('gapi.signin.render will invoke signInCallback');
gapi.signin.render('xyzStaffSignIn');
}
} else {
console.log('Empty authResult'); // Something went wrong
}
}
}
function setSessionValue(key, value, callback) {
$.post(
'session.php',
{
xyzAction: 'set',
xyzKey: key,
xyzValue: value
},
function (result) {
// Handle or verify the server response if necessary.
if (result['status'] == undefined) {
alert('xyz status problem. Please email our IT department!');
} else {
switch (result['status']) {
case 'Success':
callback();
break;
default:
alert('xyz unexpected status problem.
Please email our IT department!');
console.log(result['status']);
}
}
}
)
}
function callGoogleLogin() {
gapi.client.load('plus', 'v1', loadProfile);
}
/**
* Uses the JavaScript API to request the user's profile, which includes
* their basic information. When the plus.profile.emails.read scope is
* requested, the response will also include the user's primary email address
* and any other email addresses that the user made public.
*/
function loadProfile() {
var request = gapi.client.plus.people.get({'userId': 'me'});
request.execute(loadProfileCallback);
}
/**
* Callback for the asynchronous request to the people.get method. The profile
* and email are set to global variables. Triggers the user's basic profile
* to display when called.
*/
function loadProfileCallback(profile) {
var emailAddress;
// Filter the emails object to find the user's primary account, which might
// not always be the first in the array. The filter() method supports IE9+.
emailAddress = profile['emails'].filter(function (v) {
return v.type === 'account'; // Filter out the primary email
})[0].value; // get the email from the filtered results, should always be defined.
var domain = emailAddress.replace(/.*#/, "");
if ("xyz.com" == domain) {
window.location.href = "google_login.php?xyzEmailAddress=" + emailAddress;
} else {
alert(emailAddress + ' is not a recognized xyz staff member email address.');
}
}
</script>
</body>
</html>
google_login.php
<?php
// This code is called from the javascript on the login screen only
// AFTER Google authorization has succeeded
// Google_Client is as defined at
// https://github.com/google/google-api-php-client/blob/master/src/Google/Client.php
$googleClient = new Google_Client ();
$googleClient->setRedirectUri('postmessage');
$googleClient->authenticate($_SESSION['GoogleAuthorizationCode']);
Need to add/enable APIs from the left hand side panel here https://console.developers.google.com.
APIs which I have added are "google+ API" and "gmail API". I tried and it worked for me.

Facebook post custom action to timeline

I have created a custom action that I want to allow users to post to their timeline with e.g. {User} read {Article}. I can get this to work fine when I do a post using the sample URL like this :
FB.api('/me/fbsite:actionname' +
'?object=http://samples.ogp.me/356694057772404&access_token=abc','post'
But when I replace the sample URL with my own URL I get the error 'The session was invalidated explicitly using an API call'. Can anybody please advise?
EDIT : Changed my Javascript to this, but I now get 'Invalid OAuth Access Token' :
<script type="text/javascript">
function redeem() {
FB.api('/me/fbsite:actionname' +
'?object=http://samples.ogp.me/356694057772404&access_token=\' + <%=UserManager.Current.FB.accessToken %> + \'', 'post',
function (response) {
var msg = 'Error occured';
if (!response || response.error) {
if (response.error) {
msg += "\n\nType: " + response.error.type + "\n\nMessage: " + response.error.message;
}
alert(msg);
}
else {
alert('Post was successful! Action ID: ' + response.id);
}
});
}
That might be because you are using the same access token in same session. So try logging out and log back in, get a new FB access token, and try the query using the new access token you got, that should work as expected.

How do I set a cookie in iOS Phonegap?

I'm using the reddit API and can successfully login and receive a cookie value in return. The code I use is as follows
loginPost = $.ajax({
type: 'POST',
url: 'http://www.reddit.com/api/login/' + username + '?user=' + username + '&passwd=' + password + '&api_type=json',
xhrFields: {
withCredentials: true
},
dataType: "json",
success: function() {
console.log("Define response variables");
var header = loginPost.getAllResponseHeaders();
var responseText = loginPost.responseText;
var match = header.match(/(Set-Cookie|set-cookie): reddit_session=(.+?);/);
if (match) {
reddit_session = match[2];
window.localStorage.setItem("reddit_session", reddit_session);
window.localStorage.setItem("reddit_username", username);
window.localStorage.setItem("reddit_password", password);
console.log("Logged in!");
//alert(responseText);
$('.loginWrapper').slideUp('fast', function() {
$('#feedWrapper').css("top", "44px");
$('#feedWrapper').css("bottom", "0");
// Animation complete.
});
}
else {
reddit_session = null;
window.localStorage.setItem("reddit_session", null);
navigator.notification.alert('Your username or password is incorrect. Please try again.');
console.log("Login Failed");
}
},
});
I am storing the cookie using
var header = loginPost.getAllResponseHeaders();
var match = header.match(/(Set-Cookie|set-cookie): reddit_session=(.+?);/);
if(match){
reddit_session = match[2];
window.localStorage.setItem("reddit_session", reddit_session);
But the cookie isn't sent with a simple request to http://www.reddit.com/api/me.json. All that is returned is an empty JSON response like this {}. If I browse to that link in my browser (and am, of course, logged into reddit) it returns a JSON string with all the user data.
Any idea how I can store the cookie so that it is usable in a UIWebView?
Any idea how I can store the cookie so that it is usable in a UIWebView?
It appears that iOS cookies have been problematic since phonegap 2.5; please see [Handling cookies in PhoneGap/Cordova
I can't see any more current (phonegap 3.3) info [http://docs.phonegap.com/en/3.3.0/_index.html]

Categories

Resources