0

In a web app, I have developed a client-server authentication that is working correctly, flow:

  • the client generates the access code with grantOfflineAccess
  • the client passes the code to server
  • the server (same client_id), checks the integrity of the code, and then requires an access_token with a refresh_token to Google.
  • tokens are saved for later reuse in offline mode.

Now I want to generate the access code in the Chrome app, so that the access code is passed to the (same) server, to request the tokens for late reuse offline.

Using the same client_id used for the web app, I am requesting the code with chrome.identity.launchWebAuthFlow, with this url params (cleaned for readability):

https://accounts.google.com/o/oauth2/v2/auth?
scope=profile email https://www.googleapis.com/auth/drive
include_granted_scopes=true
state=state_parameter_passthrough_value // I actually left this as it is
redirect_uri=https://<app-id>.chromiumapp.org/chromelogin
response_type=code
access_type=offline
client_id=[same_as_webapp]

This actually works, and I do get the access code, as part of the url passed to the callback passed to chrome.identity.launchWebAuthFlow.

The problem is that when I then send the access code to my web server, when it tries to generate the tokens I get an Invalid Credentials 401 error.

Am I missing something?

I have also tried to use a different client_id, one specifically tied to the Chrome app via the app ID. In doing so I did check that the key in manifest.json is equal to the key provided by the installed app (as described here). However, after successfully generating the access code, the server got the same error message.

EDIT

Server side, I use the access code like to to generate the tokens:

$aCode = $_POST['authcodefromclient'];
$token = $googleClient->authenticate( $aCode );
don
  • 4,113
  • 13
  • 45
  • 70

2 Answers2

0

Here is a brief summary of the OAuth flow.

The first time you request authorization, you will a short lived Access Code. Use this Access Code to request an offline Refresh Token. Save the Refresh Token. Whenever your app needs to access the protected resource, it uses the Refresh Token to request an Access Token. This Access Token is supplied as an http Authorization header when you call the Google API. From your description it reads that you are using an Access Code when you should be using an Access Token.

pinoyyid
  • 21,499
  • 14
  • 64
  • 115
  • That is the way I'm doing it as I've outlined in the steps I take to generate the access and refresh tokens. As a matter of fact, my flow does work for my web app and server side app. The authorisation fails only when I try to do the exact same thing with the code generated in the Chrome app using `chrome.identity.launchWebAuthFlow `. – don Mar 02 '17 at 19:17
  • Once you've authorized your app, you have no need to reuathorize it. If you look through the page you linked to, it does nothing with the Access Code. – pinoyyid Mar 02 '17 at 19:32
  • That is understood, I am trying to authorize the app for the first time: 1. new user grants access from the client app; 2. code is passed to server; 3. server does the offline auth logic. As I mentioned, I have already implemented the oauth2 logic, and it is working between my web app and the server, so my problem lies with the implementation of the same logic within a Chrome app. – don Mar 02 '17 at 19:50
  • I guess I'm not understanding why you start the flow in Chromium using launchWebAuthFlow which the docs say "is for users logged into a non-Google account" and then complete it on the server. There may be a constraint that the Access Code must be submitted from the same IP. – pinoyyid Mar 02 '17 at 21:50
  • I've run some tests and it does not seem to be related to the IP of the user, as the system works even when the web app is at a different IP address than the server. As I mentioned in the question, I'm doing it like so because I want to gain offline access, which does not seem to be possible with `chrome.identity.getAuthToken` – don Mar 13 '17 at 16:53
0

It is possible via chrome.identity.launchWebAuthFlow(), however this will require the Chrome user to type in their login credentials. Checkout this answer: Get id_token with Chrome Identity API

If you do not need to access the user's Google account for a long period of time, you can gain temporary access with the access_token from chrome.identity.getAuthToken. I like this because the Chrome user does not have to type in their credentials (if they are logged into the Chrome browser or ChromeBook). I pass the access_token to my server and then verify it by calling: https://www.googleapis.com/oauth2/v3/tokeninfo?access_token={0}

jfbloom22
  • 804
  • 7
  • 21