11

I am developping a Google Chrome extension, to allow users to authenticate with their Google Accounts, i decided to use Chrome Identity API.

To authenticate the user in my Application i need to get the ID_Token (signed token)

is there a way to get OpenID Connect Token with Google Chrome Identity API ?

Thanks for your help !

user2602584
  • 737
  • 2
  • 7
  • 25
  • Have you read the documentation: https://developer.chrome.com/apps/identity? Also, look at an example or two, such as here: https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/identity – Brian Jul 01 '15 at 10:54
  • 2
    @Brian yes i already read it, and i did the same thing, for now it works fine ! but the result is an **access token** that serve just to access Google API resources like (Drive, Calendar, ...), in my case i need to use the Google identity of the user to authenticate him in my application. The only way is OpenID Connect Token : it is a special kind of token that contains all user information and it's a **Signed Token**. look at this : https://developers.google.com/identity/protocols/OpenIDConnect Thanks for your replay ! – user2602584 Jul 01 '15 at 11:08
  • 1
    Is the token from `getProfileUserInfo` not enough for you? – Xan Jul 01 '15 at 11:56
  • Take a look at this: https://developers.google.com/identity/protocols/OpenIDConnect – Xan Jul 01 '15 at 12:20
  • 1
    @Xan Yes I worked with OpenID Connect in my other web applications (Server Side) it is very helpfull , but for Chrome Extensions it does't work ! i am triying to get the Google User ID with `getProfileUserInfo`, it requires a specific **Scope** ? – user2602584 Jul 01 '15 at 12:30
  • What do you mean by _"doesn't work"_? And no, you don't need any scopes for `getProfileUserInfo`. – Xan Jul 01 '15 at 12:32
  • Yes look at this :http://stackoverflow.com/questions/27990787/chrome-extension-javascript-origins-for-google-api – user2602584 Jul 01 '15 at 12:46
  • im also interested on this. note you can get the user email with oauth but its not the same as the openid. – Zig Mandel Jul 01 '15 at 13:59
  • 1
    @ZigMandel yes we need more than email and exp time, especially the signature ! – user2602584 Jul 01 '15 at 15:14

1 Answers1

16

This is a paste of my answer from the other thread https://stackoverflow.com/a/32548057/3065313

I've came to the same problem yesterday and since I've found a solution, I might as well share it, as it wasn't that 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.

First you should create an Web application credentials in google console and add the following url as a valid Authorized redirect URI: https://<EXTENSION_OR_APP_ID>.chromiumapp.org. The URI does not have to exist, chrome will just catch 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);
        }
    }
);

Google OAuth2 API (for OpenID Connect) documentation can be found here: https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters

PS: If you don't need the oauth2 section in your manifest. You can safely omit it, and provide the identifiers and scopes in code only.

EDIT: For those interested, you don't need the identity API. You can even access the token using a little trick with tabs API. The code is a little longer, but you have better error messages and control. 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});
});
Community
  • 1
  • 1
Piotr Sobiech
  • 452
  • 4
  • 11
  • hi @piotr im facing same problem what is is problem with identity api . iteractive options set to true , but i am not able to get access token . – Amerrnath Sep 30 '15 at 14:10
  • @Amerrnath, did you try to do every point exactly as written here? Maybe you're trying to access the identity API from the content script, it's only available in the background scripts. Also check your Authorized redirect URIs as this is a very important step. Remember that changes when installing extension locally. Sadly, I need more information in order to help you. – Piotr Sobiech Oct 01 '15 at 09:51
  • http://stackoverflow.com/questions/32852920/chrome-extension-authentication-identity-api . I have posted my steps here can you check it. and what will be redirect URI for a chrome extension . thanks. – Amerrnath Oct 05 '15 at 06:41
  • Why should i specify as a web application rather than a Chrome app – Amerrnath Oct 07 '15 at 06:23
  • No access_token is returned with launchWebAuthFlow as configured. Is there a way to get both the access_token and id_token? – dave Feb 21 '16 at 06:23
  • it doesn't work, the domain xxx.chromeapp.org cannot be added into authorized domain list as it is not a top domain. As a result, https://xxx.chromeapp.org/ cannot become a valid redirect URL. – Chen Mar 21 '19 at 04:40