GoogleUser.getAuthResponse() doesn't contain access_token - google-api

UPDATE2: I revisited this issue and have solved the problem by carefully following the doco linked below. But first, for those who are struggling with this, you are in good company. There are so many versions of the doco from Google it is confusing! Do you include platform.js or client.js in your html? Do you load gapi.auth or gapi.auth2? Do you use gapi.auth2.render or gapi.auth.authorize, or gapi.auth2.init, and so on.
The way that returns an access_token (as of this article date) is linked below. I managed to get this working by carefully following the guide and reference using platform.js. Other libraries are then dynamically loaded such as client.js using gapi.load('drive', callback).
https://developers.google.com/identity/sign-in/web/listeners
https://developers.google.com/identity/sign-in/web/reference
==== ORIGINAL ISSUE FOR PROSPERITY ====
UPDATE 1:
I've updated the code sample to do a recursive search of the googleUser object. At least this shouldn't break in a subsequent library.
Below is a code snippet to handle an issue where the access_token in the Google gapi.auth2.AuthResponse object is not at the top level... it is hidden :( in the depths of the object!
So it is retrievable, but not at the top level!!?? I've noticed it seems to be a timing issue... once the application is running for a while on subsequent checks, it does contain the access token at the top level!!
var authResponse = _.googleUser.getAuthResponse();
_.id_token = authResponse.id_token; // Always exists
// access_token should also be a param of authResponse
if (authResponse.access_token) {
debug("Worked this time?");
_.access_token = authResponse.access_token;
} else {
// !!! Internal object access !!!
debug("Attempt to get access token from base object.");
_.access_token = _.objRecursiveSearch("access_token", _.googleUser);
if (_.access_token) {
debug("Access token wasn't on authResponse but was on the base object, WTF?");
} else {
debug("Unable to retrieve access token.");
return false;
}
}
_.objRecursiveSearch = function(_for, _in) {
var r;
for (var p in _in) {
if (p === _for) {
return _in[p];
}
if (typeof _in[p] === 'object') {
if ((r = _.objRecursiveSearch(_for, _in[p])) !== null) {
return r;
}
}
}
return null;
}
I'm guessing getAuthResponse somehow provides a callback once it is ready, but I can't see where in the API.
https://developers.google.com/identity/sign-in/web/reference

I know this question is fairly old, but it appears first when googling for ".getAuthResponse() doesn't have access_token," which is how I got here.
So for those of you in 2016 (and maybe later) here's what I have found out
There's a secret argument on .getAuthResponse, not documented anywhere I have found. If you would run the following in your app
console.log(gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse);
You would see that you get the following (copy/pasted from my console)
function (a){if(a)return this.hg;a=.HE;var c=.rf(this.hg);!a.Ph||a.dL||a.Lg||(delete c.access_token,delete c.scope);return c}
This shows that the .getAuthResponse() function looks for an argument, and as far as I can tell doesn't even check its value -- it simply checks if it is there and then returns the whole object. Without that function, the rest of the code runs and we can see very clearly it is deleting two keys: access_token and scope.
Now, if we call this function with and without the argument, we can check the difference in the output. (note: I used JSON.stringify because trying to copy/paste the object from my browser console was causing me some issues).
console.log(JSON.stringify(gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse()));
console.log(JSON.stringify(gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse(true)));
getAuthResponse() object
{
"token_type":"Bearer",
"login_hint":"<Huge mess of letters>",
"expires_in":2112,
"id_token":"<insert your ridiculously long string here>",...}
getAuthResponse(true) object
{
"token_type":"Bearer",
"access_token":"<an actual access token goes here>",
"scope":"<whatever scopes you have authorized>",
"login_hint":"<another mess of letters>",
"expires_in":2112,
"id_token":"<Insert your ridiculously long string here>",
...}

Figured out the fix for this. Turns out that if we don't provide the login scope config in gapi.auth2.init it doesn't return access_token in getAuthResponse. Please call gapi.auth2.init as given below and access_token will be present.
gapi.auth2.init({
client_id: <googleClientID>,
'scope': 'https://www.googleapis.com/auth/plus.login'
})

Related

Get room/rooms of client [duplicate]

I can get room's clients list with this code in socket.io 0.9.
io.sockets.clients(roomName)
How can I do this in socket.io 1.0?
Consider this rather more complete answer linked in a comment above on the question: https://stackoverflow.com/a/24425207/1449799
The clients in a room can be found at
io.nsps[yourNamespace].adapter.rooms[roomName]
This is an associative array with keys that are socket ids. In our case, we wanted to know the number of clients in a room, so we did Object.keys(io.nsps[yourNamespace].adapter.rooms[roomName]).length
In case you haven't seen/used namespaces (like this guy[me]), you can learn about them here http://socket.io/docs/rooms-and-namespaces/ (importantly: the default namespace is '/')
Updated (esp. for #Zettam):
checkout this repo to see this working: https://github.com/thegreatmichael/socket-io-clients
Using #ryan_Hdot link, I made a small temporary function in my code, which avoids maintaining a patch. Here it is :
function getClient(roomId) {
var res = [],
room = io.sockets.adapter.rooms[roomId];
if (room) {
for (var id in room) {
res.push(io.sockets.adapter.nsp.connected[id]);
}
}
return res;
}
If using a namespace :
function getClient (ns, id) {
return io.nsps[ns].adapter.rooms[id]
}
Which I use as a temporary fix for io.sockets.clients(roomId) which becomes findClientsSocketByRoomId(roomId).
EDIT :
Most of the time it is worth considering avoiding using this method if possible.
What I do now is that I usually put a client in it's own room (ie. in a room whose name is it's clientID). I found the code more readable that way, and I don't have to rely on this workaround anymore.
Also, I haven't tested this with a Redis adapter.
If you have to, also see this related question if you are using namespaces.
For those of you using namespaces I made a function too that can handle different namespaces. It's quite the same as the answer of nha.
function get_users_by_room(nsp, room) {
var users = []
for (var id in io.of(nsp).adapter.rooms[room]) {
users.push(io.of(nsp).adapter.nsp.connected[id]);
};
return users;
};
As of at least 1.4.5 nha’s method doesn’t work anymore either, and there is still no public api for getting clients in a room. Here is what works for me.
io.sockets.adapter.rooms[roomId] returns an object that has two properties, sockets, and length. The first is another object that has socketId’s for keys, and boolean’s as the values:
Room {
sockets:
{ '/#vQh0q0gVKgtLGIQGAAAB': true,
'/#p9Z7l6UeYwhBQkdoAAAD': true },
length: 2 }
So my code to get clients looks like this:
var sioRoom = io.sockets.adapter.rooms[roomId];
if( sioRoom ) {
Object.keys(sioRoom.sockets).forEach( function(socketId){
console.log("sioRoom client socket Id: " + socketId );
});
}
You can see this github pull request for discussion on the topic, however, it seems as though that functionality has been stripped from the 1.0 pre release candidate for SocketIO.

Calling Parse.Cloud.beforeSave() From custom web hooks

I started off cloning the cloud code example blog app. And in the controllers I have the basic REST crud operations. I tried adding the code here to my controller, as well as just directly in main.js:
Parse.Cloud.beforeSave(Parse.User, function(req, res)
{
for (var dirtyKey in req.object.dirtyKeys()) {
if (dirtyKey === "username" || dirtyKey === "email") {
res.error("User is not allowed to modify " + dirtyKey);
return;
}
}
res.success();
})
In my terminal, I am running parse develop [app] to update files as I change. And when I add the above code it does register a trigger.
Deploying recent changes...
Your changes are now live.
I2014-07-15T03:30:18.108Z]Deployed v63 with triggers:
_User:
before_save
Yet I am still able to, from the rest api using postman, able to update the username and email fields.
I suppose, that the real question should be, is that if I am building my app like this; do I still use these beforeSave() triggers like described? Or is it better to simply make those checks in the method (in this case, the User.update method i created) and validate everything there? Because I cant seem to get the triggers to actually run.
The issue is a common mistake with how for..in works in JavaScript with an array, in your code above dirtyKey will be populated with the index, what you want instead is:
for (var i in req.object.dirtyKeys()) {
var dirtyKey = req.object.dirtyKeys()[i];
if (dirtyKey === "username" || dirtyKey === "email") {
res.error("User is not allowed to modify " + dirtyKey);
return;
}
}

My WebAPI2 service returns a JSON string, but $resource does not parse it

Here is my resource:
var app, deps;
deps = ['ngGrid', 'getUsers'];
angular.module('getUsers', ['ngResource'])
.factory('users', function ($resource)
{
return $resource('/Admin/GetUsers', {}, {
query: { method: 'GET', IsArray: true }
});
});
and then I've added code to try to add a step to force parsing:
$scope.myData = users.query(function(response)
{
if (typeof (response) == string)
{
response = JSON.parse(response);
}
});
But it never gets this far, and here's the error in Chrome:
Error: [$resource:badcfg] object
http://errors.angularjs.org/1.2.14/$resource/badcfg?p0=array
at http://localhost:23002/Scripts/angular.js:78:12
at a.module.factory.f.(anonymous function).p.then.m.$resolved (http://localhost:23002/Scripts/angular-resource.min.js:8:517)
at deferred.promise.then.wrappedCallback (http://localhost:23002/Scripts/angular.js:11046:81)
at deferred.promise.then.wrappedCallback (http://localhost:23002/Scripts/angular.js:11046:81)
at http://localhost:23002/Scripts/angular.js:11132:26
at Scope.$get.Scope.$eval (http://localhost:23002/Scripts/angular.js:12075:28)
at Scope.$get.Scope.$digest (http://localhost:23002/Scripts/angular.js:11903:31)
at Scope.$get.Scope.$apply (http://localhost:23002/Scripts/angular.js:12179:24)
at done (http://localhost:23002/Scripts/angular.js:7939:45)
at completeRequest (http://localhost:23002/Scripts/angular.js:8142:7)
Of course I searched for that error, but I found advice to set IsArray to true or false, this makes no difference. If I set a breakpoint and call JSON.parse on the response string, it gets turned into an array of objects, exactly like what I want. So the string is perfectly valid JSON, but angular appears unwilling to parse it as such, it accepts it as a string and then dies.
My controller is very simple:
public List<ApplicationUser> GetUsers()
{
return AdminUsersViewModel.AllUsers;
}
and then, that method uses a LINQ query to get users from the DB, and then iterates over that collection to create a new one, because before I did that, it just blew up. I've made the call in the browser, and see the same string that is appearing in the angular code.
What I need to know is, why isn't angular spotting that this is a collection of objects, and how can I either force it to parse the string, or change the format so angular can tell what it is ?
Thanks for looking.
OK, I got it. I thought the help I read said to use IsArray ( in hindsight, I think it said DON'T use IsArray ). I knew that was non standard, but that's what I did. I ran the non minified version, and found my error. Change to isArray, and it works.
Thanks for looking :-)

Passport and Passport Local req.isAuthenticated always returns false

I haven't been able to track this down, but for my set up, isAuthenticated always returns false even after a successful login. Here's the passport code:
req.isAuthenticated = function() {
var property = 'user';
if (this._passport && this._passport.instance._userProperty) {
property = this._passport.instance._userProperty;
}
return (this[property]) ? true : false;
};
But in a quick look around I don't see the _userProperty proeprty anywhere in the local strategy (sorry if I didn't look hard enough), so I suppose that might be why it's always returning false?
I'd leave a code sample of my application code, but I feel it's probably easier to have a quick look at the repo for my work in progress:
passport api token sessionless
Ultimately, my goal is to have logout work properly for that boilerplate project (which it currently it doesn't).
I guess you forgot to put: req.login(...) inside passport.authenticate('local', function(...){}).
See here (at the end of the page)
Apologies if my original question is not that useful in the first place, but...
I found that my combination of passport, passport-local, and passport-local-mongoose, a solution was to simply create an invalidation method on my mongoose Schema (that has the passportLocalMongoose "plugged in", and when my /logout route gets hit I essentially remove that user's token. Here's that method:
Account.statics.invalidateUserToken = function(email, cb) {
var self = this;
this.findOne({email: email}, function(err, usr) {
if(err || !usr) {
console.log('err');
}
usr.token = null;
usr.save(function(err, usr) {
if (err) {
cb(err, null);
} else {
cb(false, 'removed');
}
});
});
};
I presume it's more interesting to see this in context so again please feel free to refer to the repo listed in question...hope this helps someone.
Also, if a core from one of the aformentioned libs wants to suggest a better way I'd of course love to refactor my code to make it idiomatic; if not, this approach seemed to work.

Significance of Reflection in AJAX-Based Applications

Ajax and Reflection
I am developing an ajax-based application and wondering, what role reflection plays or might play here?
Probably most importantly I am asking myself, if it would be a good approach to
handle all ajax responses through a single handler,
reflect or interpret the data or error
delegate further processing (e.g. where to inject the html) based upon the analysis.
Is this a budding procedure? What pros and cons come to mind?
Additional clearification
My current implementation, which I am not happy with, looks like this.
Register eventhandlers for user action, which lead to ajax requests.
For each request:
Determine which container is the target for the new content
Validate the ajax response
Pass the result to the appropiate rendering function if everything is as expected
Here is an example
function setGamedayScoringChangeHandlers() {
$("#community").delegate("div.community div.nav", "click", function() {
var orderId = $(this).html();
var communityId = $(this).closest('.communityView ').dashId();
requestGamedayScoringByOrderId(communityId, orderId);
});
}
function requestGamedayScoringByOrderId(communityId, orderId) {
var $targetContainer = $('#community-' + communityId + '-gameday');
$.ajax({
url: '?api=league&func=getGamedayScoringByCommunityIdAndOrderId',
data: {
communityId : communityId,
orderId : orderId
},
success: function(result) {
// custom indicator, that sth. didn't work as supposed
if (result.success === false) {
// a php error couldn't be handled as expected
if (result.error === 'phpRuntimeError') {
// ..
}
// ..
}
else {
renderGamedayScoring(result, $targetContainer);
}
}
});
}
Question
How can this and especially the redundant error checking be simplified? Could Reflection, in a sense of: "Is the response valid? And what does the error message say or data look like?" be a reasonable structure do deal with this? Additionally: Is the "coupling" of the actual ajax request and determing the $targetContainer a "normal" procedure?
Many thanks,
Robson
Yes I think register ajax handler trought one pipe is a good way, because it is more easy to control, you will have less redundant code and less boarding effects. If I look at your code comments it seems the response is not as you expect. I use to do like this for controling a group of ajax request talking with server script. I build one request object like :
// myscript.js
var rqPHP = {
url:'php/dispatcher.php', type:'POST', dataType:'json',
success:function(json, status, jXHR){
//console.log('rqPHP.succes : ', json);
if(!json) return console.warn('[rqPHP.success] json is null');
if(!json.cmd) return console.warn('[rqPHP.success] json.cmd is null');
if(!json.res) return console.warn('[rqPHP.success] json.res is null');
if(json.err && json.err.length){ console.warn('[rqPHP.success errors cmd:'+json.cmd+'] '+json.err);}
// so if no errors, dispatch actions based on original command asked
switch(json.cmd){
case 'loadfile' :
// do whatever with response
break;
case 'savefile' :
// do whatever with response
break;
}
},
error:function(jXHR, status, err){
console.warn('[rqPHP.error] ', status,',',err,',',jXHR.responseText);
}
};
then when use this object trought all my group of different actions and I precise wich action and arguments I pass. I use to ask for a json data so I am able to receive an easy parsing response, so I am able to return the original command asked, and some details on errors that may occured for example, and when I need to fire the request :
// myscript.js
rqPHP.data = {'cmd':'loadfile', 'filename':'file.dat', 'arg2':'other argument'};
$.ajax(rqPHP);
Then an example of one server script that will respond :
// dispatcher.php
$pv = $_POST;
$res = '';
$err = array();
// you check the command asked for :
switch(strtolower($pv['cmd'])){
case 'savefile' :
// do whatever
break;
case 'loadfile' :
// do whatever
if(any error){
$err[] = $loadError;// push error with whatever details you'll retrieve in javascript
}else{
$res = ',"res":"'.$dataLoaded.'"';// format json response so you'll check the var exist
}
break;
}
$jsonRes = '{"cmd":"'.$pv['cmd'].'"'.$res.',"err":"'.implode('|', $err).'"}';// json result
print $jsonRes;
They may be some errors, it is just for the principe, I hope that will help, just some last advices :
you should better use the requestObject.data to pass any arguments instead of setting the url like you did, this is much more easy because jQuery does the properly encoding work
you may use POST so the url stay clean, post vars are 'hidden'
in your case, because you may want to centralize server actions with ONE server script, you should use 'json' as dataType because it is much easier to retrieve details from the response, such errors. You have to distinct the ajax error that is trigger when the url doesn't exist, or access denied, well when the server replies it just can't respond to this request, and distinct the properly response of your server script, I mean the script responds well but it may occur an command error, for example for a 'loadfile' command, the argument fileUrl may be wrong or unreadable, so the action is done but the response will be not valid for you...
If you plan to fire many loads for differents parts (I mean you may don't wait response for an ajax before loading a new one), it should be better to set main success and errors functions for keeping centralization and then build one new request object each time you make a load
function rqSuccess(json, status, jXHR){
// put same checking code as before, then you can also retrieve some particular variables
// here, 'this' should correspond to the request object used for the $.ajax so :
console.log('myTarget is : ', this.myTarget, ' , myVariable is : ', this.myVariable);
}
function rqError(jXHR, status, err){
// put same checking code
}
// then each time you want make one or many independant calls, build a new request object
var myRq = {url:'dispatcher.php',type:'POST',dataType:'json',
success:rqSuccess,
error:rqError,
myTarget:$('#myblock'),// any variable you want to retrieve in response functions
myVariable:'Hello !',// after all it is an object, you can store anything you may need, just be carefull of reserved variables of the ajax object (see jQuery $.ajax doc)
// the data object is sanitized and sended to your server script, so put only variables it will need
data : {'cmd':'loadfile',...}
}
$.ajax(myRq);
// you may load an other independant one without waiting for the response of the first
var myRq2 = {...myTarget:$('#anotherblock'), data:{'cmd':'anotheraction'}...}
$.ajax(myRq2);
As a first step, you should change the error handling on the serverside to produce a non-OK/200 response for error cases, e.g. throw a 500. Then have that handled as an actual error on the clientside, along with other errors, instead of putting it through the success-callback.
That way you can use jQuery's abstractions for global error handling: http://api.jquery.com/ajaxError

Resources