Yesterday I ran into the same problem, and since I found a solution, I could also share it, since it was not so obvious. As far as I know, Google does not provide a direct and documented way to do this, but you can use the chrome.identity.launchWebAuthFlow() function.
You must first create the Web application credentials in the Google console and add the following URL as a valid Authorized redirect URI : https://<EXTENSION_OR_APP_ID>.chromiumapp.org . The URI should not exist, chrome will simply intercept the redirect to this URL and call your callback function later.
manifest.json
{ "manifest_version": 2, "name": "name", "description": "description", "version": "0.0.0.1", "background": { "scripts": ["background.js"] }, "permissions": [ "identity" ], "oauth2": { "client_id": "<CLIENT_ID>.apps.googleusercontent.com", "scopes": [ "openid", "email", "profile" ] } }
background.js
// Using chrome.identity var manifest = chrome.runtime.getManifest(); var clientId = encodeURIComponent(manifest.oauth2.client_id); var scopes = encodeURIComponent(manifest.oauth2.scopes.join(' ')); var redirectUri = encodeURIComponent('https://' + chrome.runtime.id + '.chromiumapp.org'); var url = 'https://accounts.google.com/o/oauth2/auth' + '?client_id=' + clientId + '&response_type=id_token' + '&access_type=offline' + '&redirect_uri=' + redirectUri + '&scope=' + scopes; chrome.identity.launchWebAuthFlow( { 'url': url, 'interactive':true }, function(redirectedTo) { if (chrome.runtime.lastError) { // Example: Authorization page could not be loaded. console.log(chrome.runtime.lastError.message); } else { var response = redirectedTo.split('#', 2)[1]; // Example: id_token=<YOUR_BELOVED_ID_TOKEN>&authuser=0&hd=<SOME.DOMAIN.PL>&session_state=<SESSION_SATE>&prompt=<PROMPT> console.log(response); } } );
The Google OAuth2 API documentation (for OpenID Connect) can be found here: https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters
PS: If you do not need the oauth2 section in the manifest. You can safely omit it and provide identifiers and areas only in code.
EDIT: For those who wish you do not need an authentication API. You can even access the token using a little trick with the tabs API. The code is a little longer, but you have better error messages and management. Keep in mind that in the following example, you need to create Chrome App credentials.
manifest.json
{ "manifest_version": 2, "name": "name", "description": "description", "version": "0.0.0.1", "background": { "scripts": ["background.js"] }, "permissions": [ "tabs" ], "oauth2": { "client_id": "<CLIENT_ID>.apps.googleusercontent.com", "scopes": [ "openid", "email", "profile" ] } }
background.js
// Using chrome.tabs var manifest = chrome.runtime.getManifest(); var clientId = encodeURIComponent(manifest.oauth2.client_id); var scopes = encodeURIComponent(manifest.oauth2.scopes.join(' ')); var redirectUri = encodeURIComponent('urn:ietf:wg:oauth:2.0:oob:auto'); var url = 'https://accounts.google.com/o/oauth2/auth' + '?client_id=' + clientId + '&response_type=id_token' + '&access_type=offline' + '&redirect_uri=' + redirectUri + '&scope=' + scopes; var RESULT_PREFIX = ['Success', 'Denied', 'Error']; chrome.tabs.create({'url': 'about:blank'}, function(authenticationTab) { chrome.tabs.onUpdated.addListener(function googleAuthorizationHook(tabId, changeInfo, tab) { if (tabId === authenticationTab.id) { var titleParts = tab.title.split(' ', 2); var result = titleParts[0]; if (titleParts.length == 2 && RESULT_PREFIX.indexOf(result) >= 0) { chrome.tabs.onUpdated.removeListener(googleAuthorizationHook); chrome.tabs.remove(tabId); var response = titleParts[1]; switch (result) { case 'Success': // Example: id_token=<YOUR_BELOVED_ID_TOKEN>&authuser=0&hd=<SOME.DOMAIN.PL>&session_state=<SESSION_SATE>&prompt=<PROMPT> console.log(response); break; case 'Denied': // Example: error_subtype=access_denied&error=immediate_failed console.log(response); break; case 'Error': // Example: 400 (OAuth2 Error)!!1 console.log(response); break; } } } }); chrome.tabs.update(authenticationTab.id, {'url': url}); });