Javascript and REST, gapi.auth.getToken() always returns null

1,877 views
Skip to first unread message

Karine Sanche

unread,
Nov 22, 2014, 5:44:38 PM11/22/14
to google-ca...@googlegroups.com
Hello,

I've been trying since 2 days to understand how to query the Calendar API. I would like to create a widget to replace the Google Agenda Gadget v2.0 who does not work anymore. I badly need such a widget on my desktop.

It's the third project I've been creating on my Google Developers Console, but none works.

I read the doc, but it is really uncomplete, and often refers to the Console's older version, which does not help. Most of the time, there are php, ruby, ajax example, but no javascript equivalent.
For instance, it never explains which type ot client id I should create. I created web application client id, since the others did not seem to work at all. 
In Origin javascript, I put http://localhost since it runs from EasyPHP and the URL of my script is http://localhost/agenda/ (otherwise I get origin_mismatch_error)

I did not activate billing, since there was nowhere mentioned that I had to pay someting to use this API.

My Calendar is free, not enterprise. And it is private, not public.
I shared the calendar with the email address which appears in the client id block

I also tried executing the script from a web server. Same result...

When I launch the script, the Login button hides which should indicate that authorization worked
But the result is always the same : gapi.auth.getToken() returns null

The query works perfectly when I am in the playground. 
So I copied the token from the playground ans I pasted it at the place of oauthToken.access_token, and it worked... till the token expired.

Now I am facing the same problem again. This is desperating. I really need a way to display my calendar 

Any clue ?

Oh and by the way, if you know another Google Calendar widget which still works nowadays, I am still interested.


<a href='#' id='authorize-button' onclick='handleAuthClick();'>Login</a>
<a href='#' onclick='makeApiCall();'>Calendrier</a>
<div id="divretour">
</div>

<script type="text/javascript">

 
var oauthToken;
 
var scopes = 'https://www.googleapis.com/auth/calendar';
 
var clientId = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com';
 
var apiKey = 'XXXXXXXXXXXXXXXXXXX__J5GycyeRqw5uowJdwMfO8';
 
var calendarId = 'mymail...@gmail.com';
 
var start_date = new Date();
 
var end_date = new Date();
 end_date
.setDate(start_date.getDate() + 1);
 
var url = 'https://www.googleapis.com/calendar/v3/calendars/'+calendarId+'/events?timeMin='+start_date.toISOString()+'&timeMax='+end_date.toISOString();
 


function getXhr(){
 
var xhr = null;
 
if(window.XMLHttpRequest) // Firefox et autres
 xhr
= new XMLHttpRequest();
 
else if(window.ActiveXObject){ // Internet Explorer
   
try {
                xhr
= new ActiveXObject("Msxml2.XMLHTTP");
           
} catch (e) {
                xhr
= new ActiveXObject("Microsoft.XMLHTTP");
           
}
 
}
 
else { // XMLHttpRequest non supporté par le navigateur
   alert
("Votre navigateur ne supporte pas les objets XMLHTTPRequest...");
   xhr
= false;
 
}
   
return xhr;
}

 
function makeApiCall(){

 
var xhr = getXhr();
 xhr
.onreadystatechange = function(){
 
 
if(xhr.readyState == 4 && xhr.status == 200){
 leselect
= xhr.responseText;
 
 donnees
= JSON.parse(leselect);
 
var contenu="";
 
for (var i = 0; i < donnees.items.length; i++) {
 contenu
+=donnees.items[i].summary+"<br />";
 
}
 document
.getElementById("divretour").innerHTML = contenu;
 
}
 
}
 
 oauthToken
= gapi.auth.getToken();
 
 xhr
.open("GET",url,true);
 xhr
.setRequestHeader('Authorization', 'Bearer ' + oauthToken.access_token);
 
//xhr.setRequestHeader('Authorization', 'Bearer ' + token);
 xhr
.send();
}


function handleClientLoad() {
  gapi
.client.setApiKey(apiKey);
  window
.setTimeout(checkAuth,1);
  checkAuth
();
}


function checkAuth() {
  gapi
.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
}


function handleAuthResult(authResult) {
 
var authorizeButton = document.getElementById('authorize-button');
 
if (authResult) {
 authorizeButton
.style.visibility = 'hidden';
 
 makeApiCall
();
 
} else {
 authorizeButton
.style.visibility = '';
 authorizeButton
.onclick = handleAuthClick;
   
}
}


function handleAuthClick(event) {
  gapi
.auth.authorize(
     
{client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
 
return false;
}


</script>
<script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>

Lucia Fedorova

unread,
Nov 24, 2014, 8:23:14 PM11/24/14
to google-ca...@googlegroups.com
Hi Karine,

Karine Sanche

unread,
Nov 25, 2014, 7:48:45 AM11/25/14
to google-ca...@googlegroups.com
Thank you very much for your time and you answer. This is a much simpler example, without distracting elements.

Here it is :
<html>
 
<head>
   
<script src="https://apis.google.com/js/client.js"></script>
   
<script>
     
function auth() {
       
var config = {
         
'client_id': 'xxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
         
'scope': 'https://www.googleapis.com/auth/calendar'
       
};
        gapi
.auth.authorize(config, function() {
          console
.log('login complete');
          console
.log(gapi.auth.getToken());
       
});
     
}
   
</script>
 
</head>

 
<body>
   
<button onclick="auth();">Authorize</button>
 
</body>
</html>
And yes, it works ! I get a token in the console. It looks like this :

access_token
"xx29.xXXXX1xxXxx9XXXxxXX...oXfyMjv85iLiZKceGgolJwg"
client_id
"xxxxxxxxxxx-xxxxxxxxxxxxxxx...s.googleusercontent.com"
cookie_policy
undefined
expires_at
"1416922787"
expires_in
"3600"
g-oauth-window
Window
g_user_cookie_policy
undefined
issued_at
"1416919187"
response_type
"token"
scope
"https://www.googleapis.c.../auth/calendar.readonly"
state
""
status
Object { google_logged_in=false, signed_in=true, method="PROMPT"}
token_type
"Bearer"


So now I am going to add the code to request the events, if I succeed I will post it here. I keep you informed.
Once again thank you very much, this was exactly the example I needed.

Karine Sanche

unread,
Nov 25, 2014, 2:55:05 PM11/25/14
to google-ca...@googlegroups.com
I added the code part which gets events from the calendar. First I got a 403 error (accessNotConfigured) but it was because the Calendar API had disappeared from the activated API list. I reactivated it and error disappeared.


If I use the mail address associated to the calendar as calendarId I get a 404 error (even if I encode the @)
If I use 'primary' as calendarId I get a JSON ! At last ! But without any calendar items. 
And what is quite funny, the summary tag displays a @yahoo.com mail address (it's an account which I own, but definitely not the one I asked for) instead of the expected @gmail.com

Same query on OAuth 2.0 Playground returns correct mail address and all the calendar items.

{
 "kind": "calendar#events",
 "etag": "\"0000001950412000\"",
 "summary": "xxxxx...@yahoo.fr",
 "updated": "2014-11-25T18:59:10.412Z",
 "timeZone": "UTC",
 "accessRole": "owner",
 "defaultReminders": [
  {
   "method": "popup",
   "minutes": 30
  }
 ],
 "nextSyncToken": "XXXX_XyXxxXXXXX_XxXXxXXXX=",
 "items": []
}

This is probably a misconfiguration of the project, but I really wonder where... 

Here is the code :

<html>
 
<head>
   
<script src="https://apis.google.com/js/client.js"></script>
   
<script>

 
     
function auth() {
 
       
var config = {

         
'client_id': clientId,
         
'scope': scopes
       
};

        gapi
.auth.authorize(config, function() {
         
  console
.log('login complete');

  oauthToken
= gapi.auth.getToken();
  console
.log(oauthToken);
 
  gapi
.client.load('calendar', 'v3', function() {
 
var request = gapi.client.calendar.events.list({'calendarId': calendarId });
 
  request
.execute(function(resp) {
   document
.getElementById('events').innerHTML=resp.length;
 
});

   
});
 
});
 
}
   
</script>
 
</head>


 
<body>
   
<button onclick="auth();">Authorize</button>

 
<div id="events"></div>

 
</body>
</html>



Le mardi 25 novembre 2014 13:48:45 UTC+1, Karine Sanche a écrit :
Thank you very much for your time and your answer. This is a much simpler example, without distracting elements.
...

Lucia Fedorova

unread,
Nov 26, 2014, 6:54:35 AM11/26/14
to google-ca...@googlegroups.com
Hi Karine,
Is it possible that you are logged in with both the accounts in the same browser? It seems to me like you are getting the token for an incorrect account which happens to have no events. Would you please try this from an incognito window making sure you are only logging in with the gmail address?
...

Karine Sanche

unread,
Nov 26, 2014, 7:36:53 AM11/26/14
to google-ca...@googlegroups.com
Hello Lucia,

Effectively ! On Firefox I was logged on my Analytics account, which uses this @yahoo.fr address as ID. I had to use Firefox because it allows better debugging than Chrome.
While I tested the OAuth 2.0 Playground on Chrome, which I also use to check my agenda, so I was already logged ith my @gmail.com account on this one.

I tried with privacy mode, on Chrome, and this time I saw a login pop-up (first time I saw this one). Which allowed me to get the list of my calendar events...

Seems so obvious now... But I would have never guessed it by reading their doc, since it only focuses on Auth pop-up. 

Now I have to refine the code to filter the event list and something lisible. 

And, most important, transpose this to a Windows Sidebar Widget. I just did a quick try, but apparently a simple iframe displaying the script is not enough. The login popup does show. The script does enter the gapi.auth.authorize() success callback. But no events are listed, and I can't even display the token.

Maybe Google API blocks when it detects an iframe. And browser used by Windows Sidebar is Internet Explorer 7.0, maybe a little bit old. I keep on my researches...

Once again, thank you very much for your help !
Reply all
Reply to author
Forward
0 new messages