47

Sorry for a big edit. I am starting over as I am not stating my question correctly.

I am trying to write a client side app in HTML5. I do not want it to be hosted on a website. I am not even sure this is possible, I am fairly new to this type of application.

Anyway, I want to access Google services, which requires authenticate such as OAuth. Being that it is javascript, it sounds like OAuth2 is what I need.

I am trying to open up the google authentication in a popup (I have this part), let the user allow access, and then pass flow back to my application which can then query Google services. Problem is either 1. it asks the user to copy/paste a token into the app whenever I use response_type=code, but if I use response_type=token it requires that I redirect back to a valid URL which, since this is not hosted on a webserver, there is none.

So how can I use OAuth, and let the user grant access seamlessly?

esac
  • 24,099
  • 38
  • 122
  • 179

4 Answers4

65

You should have some Redirect URL defined for Google to redirect to after the authentication is done. If you cant host your pages on any web site, you can very well host it in local host.

Regarding getting the access token from the popup to the main parent window, you can setup a timer in parent window which keeps on checking the document location of the popup. Once the document location matches the Redirect URL, u can parse the access token which will will be in the URL itself.

Hope you will find it useful.

Vasp
  • 15
  • 4
saiy2k
  • 1,852
  • 1
  • 23
  • 42
  • I read your tutorial, and I am wondering if it is possible to get the token in the way you suggest, and once the token is store in the parent window, use php to make API calls. The reason I would want it this way, is that I am using the google-api-php-client library. THANK YOU – IberoMedia Jul 13 '12 at 06:05
  • I beleive there will be functions in google-api-php library to authorize and to get access token. Why cant you use them? http://code.google.com/p/google-api-php-client/wiki/OAuth2 – saiy2k Jul 13 '12 at 07:15
  • Because I am trying to implement a series of forms, or a process. If either the access token or refresh token are not available, then user needs to authorize access to calendar and spreadsheets, b/c at every stage of the process, or after submission of a form (multipart form process) there is recording of time lapsed and form data in the calendar and spreadsheet. The problem with using php library is that it then opens into the same page, and I have not way to returning POST from the first launching process form. – IberoMedia Jul 13 '12 at 18:07
  • You can write a php file (can name it settoken.php) which gets the token string as POST paramater, save it as PHP session variable and resume your process which u paused to get the User Authentication. Then in client side, after the user authentication is over and you got the token and validated it, you can POST it to settoken.php. But the token need to be passed to the server somehow, I dont think you can access the token stored in window to make calls in your php library. – saiy2k Jul 14 '12 at 10:24
  • Perhaps Ajax w/ PHP in same first form screen? And then record the token into the database before the form is submitted? – IberoMedia Jul 14 '12 at 14:47
  • 1
    really nice one. Your sample appears to be better than the one provided by google +10 – 2sb Jun 01 '13 at 19:21
  • I am trying to use Angular along with this and have a controller function that instead of a click does its stuff indirectly by the framework after a click. I am not sure if that is key in some way means the login function isnt via a click then security issues arise ? But I get an issue as my site isnt https and the google one MUST be. – landed Jan 23 '14 at 20:48
  • @saiy2k can yu help me here http://stackoverflow.com/questions/33754177/google-analytics-custom-plugin-getting-error-invalid-grant I am using your code to get authenticated however I do not know how I can avoid authentication for every session.I am facing problem on using refreshToken . – Prafulla Kumar Sahu Nov 18 '15 at 15:50
15

To avoid a potential click jacking, Google authentication forces you to go to a full page login. I don't think you can control that.

EDIT after comment, here is a code extracted from the Google OAuth2 page that does it:

<body>
    <a href="javascript:poptastic('https://accounts.google.com/o/oauth2/auth?scope=https://www.google.com/m8/feeds&client_id=21302922996.apps.googleusercontent.com&redirect_uri=https://www.example.com/back&response_type=token');">Try
    out that example URL now</a>
<script>
    function poptastic(url) {
      var newWindow = window.open(url, 'name', 'height=600,width=450');
      if (window.focus) {
        newWindow.focus();
      }
    }

</script>
</body>
Mic
  • 24,812
  • 9
  • 57
  • 70
  • 3
    I'm not sure this is true. On their own example webpage at http://code.google.com/apis/accounts/docs/OAuth2.html#ClientLibraries there is a link that says 'Try out an example URL now' that if clicked on opens it in a new popup window. – esac Oct 30 '11 at 21:13
  • I've updated the answer. I tried to embed it into an iframe wich could be the reason of redirecting the page. Thanks for the information. – Mic Oct 31 '11 at 00:00
  • Sorry, I was already able to get that part. The window opens, but it wants you to copy/paste some auth token into the client application which I don't want .. I want the user to click 'allow' and then just proceed. This is the part I can't figure out. – esac Oct 31 '11 at 00:56
  • Did you try to specify the `redirect_uri` to a page of your site. Then read the token `#access_token`, pass it to the parent page, close the popup, and use it in your subsequent calls? – Mic Oct 31 '11 at 10:06
  • There is no page on my site. I want it running purely client side. – esac Nov 01 '11 at 00:15
  • 1
    You are not running it purely client side, since you call google. – Mic Nov 01 '11 at 10:41
  • @Mic you're unable to pass the access token to the parent page as the popup window redirects to a different domain (accounts.google.com) - once a redirect takes place within the popup, the link to the parent window is lost – jenovachild Mar 26 '13 at 05:40
  • thanks a lot. after spending more than a day with google docuementation i was almost going to try it in server side code. but the above answer worked nicely. Only one thing it redirects to the given uri in the same popup window itself instead of closing the window. Is it possible? thanks – sjd Nov 11 '13 at 04:23
3

I believe you can use google api (gapi) for Oauth in Javascript. Here is the documentation: Authentication using the Google APIs Client Library for JavaScript

You will not require the user to copy/paste any codes and you will not require to provide a redirect uri

All you need to do is: Go to your project in Google Developers Console and generate the following: 1. Generate new Client Id and choose options 'Installed Application' and 'Other'. 2. Generate a Public API Key

Sample Code from the above documentation:

// Set the required information
var clientId = 'YOUR CLIENT ID';
var apiKey = 'YOUR API KEY';
var scopes = 'https://www.googleapis.com/auth/plus.me';

// call the checkAuth method to begin authorization
function handleClientLoad() {
  gapi.client.setApiKey(apiKey); // api key goes here
  window.setTimeout(checkAuth,1);
}

// checkAuth calls the gapi authorize method with required parameters
function checkAuth() {
  gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult); // scope and client id go here
}

// check that there is no error and makeApi call
function handleAuthResult(authResult) {
  var authorizeButton = document.getElementById('authorize-button');
  if (authResult && !authResult.error) {
    makeApiCall();
  }
}

// API call can be made like this:
function makeApiCall() {
  gapi.client.load('plus', 'v1', function() {
    var request = gapi.client.plus.people.get({
      'userId': 'me'
    });
    request.execute(function(resp) {
      var heading = document.createElement('h4');
      var image = document.createElement('img');
      image.src = resp.image.url;
      heading.appendChild(image);
      heading.appendChild(document.createTextNode(resp.displayName));

      document.getElementById('content').appendChild(heading);
    });
  });
}
mlfan
  • 361
  • 3
  • 7
2

I've written a mini JS library for the task, take it and see if it works for you.

https://github.com/timdream/wordcloud/blob/6d483cd91378e35b54e54efbc6f46ad2dd634113/go2.js

I am recently developing another project that rely on the same script, so I am isolating this one into an independent library project ... check the progress follows (if there are).

Benargee
  • 162
  • 1
  • 2
  • 8
timdream
  • 5,914
  • 5
  • 21
  • 24
  • By the way, http://timc.idv.tw/wordcloud/ *is* the exactly client-side web app that authenticate with Google with the way you exactly you wanted. – timdream Oct 11 '12 at 06:19