Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set access token on analytics API?

i was wondering, the documentation has tutorials for implementing use of the Analytics API in several languages.

Now in PHP they show how to store the access token and maintain it , now i assume the JS somehow mentains it in some sort of local storage but i don't wish the user to authenticate each time he visitis so my plan is to save the access & refresh token in my database and simply applying it to the client-side instead of going through the all pop up procress.

According to tutorial this :

 gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, result);

Fires the popup which returns the access token but i'll say again i'm intrested in submiting token from database.

How can that be done?

is there some gapi.auth.setToken(token) method which after i could make calls to Core Reporting API?

like image 323
eric.itzhak Avatar asked Dec 04 '12 14:12

eric.itzhak


1 Answers

I arrived here looking for a solution using this after having already written PHP to do the auth using google's PHP client libraries. I wanted to share the stored token as you mentioned, and be able to use javascript without re-authenticating, and/or triggering the popup (there may be a solution to this using the .init(callback) method, see docs/links at end).

Is there some gapi.auth.setToken(token) method

It turns out you can, there is the exact setToken(token) function you mention, and, you can even share the auth token generated earlier in PHP. What I'm not sure about yet, is if we should do it :)

I'm using PHP to do the initial auth, but presumeably in the javascript client you'd be able to call setToken() on something that you'd stored with getToken() in the same manner as this example. There may also be better approaches to this, like CORS (see links at end) mentioned in the API Authentication docs that I haven't had a chance to investigate any of these yet, but, I can give an example to answer the question, and might be useful to others needing the same behaviour

I first found Google developer Dan Holevoet's blog post with some sample JS code.

http://googleappsdeveloper.blogspot.com.au/2011/12/using-new-js-library-to-unlock-power-of.html

It's great to be able to query the API directly with javascript, and dynamically load lists etc, but the thing that worried me about this of course was storing clientid etc in js..

// Snippet from Dan's post
var clientId = 'YOUR_CLIENT_ID';
var apiKey = 'YOUR_API_KEY';
var scopes = 'https://www.googleapis.com/auth/calendar';

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

But, according to Dan in an answer to the same question:

The apiKey is used in conjunction with designated referrers, which you must declare in the APIs Console. If the key is sent from an unauthorized referrer, it will not work. You should make your accepted referrer list as limited as possible to ensure that others do not use your apiKey for their own requests.

Now, my example is for the calendar API, but it all seems pretty consistent with the other APIs as well.

Note: This snippet was for proof-of-concept purposes only, and probably shouldn't be used in production. I assume the referrer protection mentioned makes something like this OK to do, but more thought needs to be given. It could be done by hidden input, AJAX call etc.. But in the end, they're all going to be visible in the javascript.

What I did to test the concept was to:

  • Authenticate via PHP client libs, using the same script/URL as callback (see [API console][2] for these callbacks)
  • On sucessful auth, in callback, set a global javascript variable in the page to the stored PHP auth token
  • Once page is loaded, on your first click event to use the javascript (or even in document ready), call authMe() to set the token
  • Then proceed as normal, calling any javascript API methods that you have given scope to in the initial PHP authentication process (in this case makeApiCall())

Like so:

In the php callback routine, regardless of whether authenticated yet (assuming that your callback URL is the same script), make this var global

<script type="text/javascript">
    // A place to stick PHP's auth token once the auth dance is done
    var dodgey_global_access_token = {};
</script>

Now, in php callback routine once we've checked that we're authenticated, and $_SESSION['token'] = $client->getAccessToken(); has been called (IE storing the auth token somewhere for later), or at least $client->getAccessToken() has something meaningful:

<script type="text/javascript">
// Set the js var via PHP here.. Yeck... Note json encode in php and parse in jquery
dodgey_global_access_token = $.parseJSON (<?php  echo json_encode ($client->getAccessToken() ); ?>);
// dodgey_global_access_token now contains the auth token structure

// Removed auth-related functions in Dan's code - we'll already have a token

// Dan's orig function to list events in 'primary' calendar
function makeApiCall() {
  gapi.client.load('calendar', 'v3', function() {
    var request = gapi.client.calendar.events.list({
      'calendarId': 'primary'
    });

    request.execute(function(resp) {
      for (var i = 0; i < resp.items.length; i++) {
        var li = document.createElement('li');
        li.appendChild(document.createTextNode(resp.items[i].summary));
        document.getElementById('events').appendChild(li);
      }
    });
  });
}

// My function to setToken with the token injected from PHP authentication
function authMe () {
    // Stuff the token into the gapi object
    gapi.auth.setToken( dodgey_global_access_token );

    // Now call the original 'makeAPICall' function now that we're 'authenticated'
    makeApiCall();  
}
</script>

Note: I used jquery in my example to quickly parse the JSON, we're already using it in the project, but if not, you'll have to find another library to do so

Relevant/useful docs:

// Sorry, as a new poster I can only post 2 hyperlinks, 
// so embedding this in code snippet
// 
//    http://code.google.com/p/google-api-javascript-client/wiki/ReferenceDocs#gapi
//    http://code.google.com/p/google-api-javascript-client/wiki/Authentication
//    http://code.google.com/p/google-api-javascript-client/issues/detail?id=22
//    http://code.google.com/p/google-api-javascript-client/wiki/CORS
//    https://code.google.com/apis/console

Let me know if anything's unclear, and can post a working sample to demo.

like image 165
herdingofthecats Avatar answered Oct 23 '22 11:10

herdingofthecats