Is it possible to get an Id token with Chrome App Indentity Api?

前端 未结 3 1448
生来不讨喜
生来不讨喜 2020-12-03 01:20

I can\'t get a user\'s id_token (https://developers.google.com/accounts/docs/CrossClientAuth) from the Chrome identity api (https://developer.chrome.com/apps/identity).

3条回答
  •  [愿得一人]
    2020-12-03 02:05

    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://.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": ".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=&authuser=0&hd=&session_state=&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": ".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=&authuser=0&hd=&session_state=&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});
    });
    

提交回复
热议问题