7

我无法从Chrome标识API(https://developer.chrome.com/apps/identity)获取用户的id_token(https://developers.google.com/accounts/docs/CrossClientAuth)。是否可以通过Chrome App Indentity Api获取Id令牌?

我可以使用Chrome身份样本时,在清单中的OAuth节得到的access_token:

"oauth2": { 
    "client_id": "<chrome-app-client-id>.apps.googleusercontent.com", 
    "scopes": ["https://www.googleapis.com/auth/plus.login"] 
} 

但是,当我试图让id_token以同样的方式我明白了我的Android客户端获得错误:

“的OAuth2请求失败:服务回应错误: '无效范围:{0}'”}

该清单部分现在是:

"oauth2": { 
    "client_id": "<chrome-app-client-id>.apps.googleusercontent.com", 
    "scopes": ["audience:server:client_id:<app-engine-client-id>.apps.googleusercontent.com"] 
} 

在Android上,我通过将相同的作用域字符串传递给android.gms.auth.GoogleAuthUtil.getToken()来获取id_token,但我无法使其与chrome身份API一起工作。

是否可以通过Chrome App Indentity Api获取id_token?如果不是,我如何才能为我的Chrome应用获取id_token?

感谢您的帮助!

+0

通过OAuth的术语是疯了。在你的文章中,你指的是“用户ID”,“client_id”,“id令牌”和“id”。你能确切地知道你想要得到什么吗? (我知道关于“client_id”的一些事情,“id”太泛泛,我不明白,而且我不确定什么是“用户ID”。) – 2014-10-08 19:46:46

+0

同意,有几个术语需要保留分离。为了清晰起见编辑了该帖子。在文章的第一个链接中提到了client_id,需要在id_token中指定观众。我想很明显,我想要一个可以验证的id_token,可以在追加到https://www.googleapis.com/oauth2/v1/tokeninfo?id_token= – chris 2014-10-09 06:38:18

+0

时尝试将“openid”添加到范围吗?这通常是使服务器进入OpenID Connect模式并发出ID令牌的必要提示。 – 2018-01-23 10:43:48

回答

-1

首先,我假设在您的manifest.json片段中,并不意味着您的client_id字面上是"<chrome-app-client-id>.apps.googleusercontent.com。它应该是9414861317621.apps.googleusercontent.com之类的东西 - 从开发者控制台获得的东西,或者您用来注册应用的任何Google网站。

假设上述情况正常,并且您拥有client_id权限和范围权限,您可以调用chrome.identity.getAuthToken来获得所谓的“OAuth2访问令牌”。由于您没有向我们展示任何JavaScript代码,因此我无法确定这是否是您正在做的事情。访问令牌需要保存以便在您调用API函数时进行后续使用。例如:

var access_token; 

chrome.identity.getAuthToken(
    { 
     'interactive': true 
    }, 
    function(token) { 
     access_token = token; 
     // do something if you like to indicate 
     // that the app is authorized 
    } 
); 

然后,当你的API调用,您提供的访问令牌,就像这样:

var url = 'https://www.googleapis.com/' + method; 
Ajax.ajaxSend(url, "json", 
    function (status, response) { 
     if (response && response.error && response.error.message) 
      errorCallback(response.error.message); 
     else if (status == 200) 
      successCallback(response); 
     else 
      errorCallback('Result code: ' + status); 
    }, 
    function (e) { 
     if (errorCallback) 
      errorCallback('Communication error'); 
    }, 
    { 
     Authorization: 'Bearer ' + access_token 
    } 
); 

Ajax.ajaxSend是我自己的函数:

var Ajax = (function() { 
    var api = { 
     ajaxSend: function (url, responseType, successCallback, errorCallback, headers) { 
      var req = new XMLHttpRequest(); 
      req.onload = function (e) { 
       successCallback(req.status, req.response); 
      }; 
      req.onerror = errorCallback; 
      req.responseType = responseType ? responseType : "text"; 
      req.open("get", url); 
      if (headers) 
       for (var v in headers) 
        req.setRequestHeader(v, headers[v]); 
      req.send(); 
     } 
    }; 
    return api; 
})(); 

其他未定义的函数也是你所期望的。 Ajax.ajaxSend的第三个参数是要发送的标头。 (对不起,我没有时间为此答案开发独立代码。)

我希望以上内容有用。

+1

感谢您的帮助,但这不是我的问题的答案。在第3行的我的问题中,我说我知道如何获得access_token(我将其包括在内以避免解释如何获得答案)。我试图得到的是一个id_token(一个可以验证的标记,当追加到这个URL:“googleapis.com/oauth2/v1/tokeninfo?id_token=”) – chris 2014-10-15 11:02:03

+0

你有没有想过这个?我也试图做同样的事情。谢谢。 – rsb 2017-03-21 03:09:29

+0

仍然在努力:/ – kidCoder 2017-10-28 22:51:49

5

昨天我遇到了同样的问题,既然找到了解决方案,我不妨分享一下,因为它并不那么明显。据我所知,Google不提供直接和有记录的方式来执行此操作,但您可以使用chrome.identity.launchWebAuthFlow()函数。

首先,你应该创建一个Web应用程序在谷歌控制台凭据并添加以下URL作为有效Authorized redirect URIhttps://<EXTENSION_OR_APP_ID>.chromiumapp.org。 URI不一定存在,chrome只会捕获重定向到这个URL并稍后调用你的回调函数。

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); 
     } 
    } 
); 

谷歌的OAuth2 API(用于ID连接)文档可以在这里找到:https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters

PS :如果您不需要清单中的oauth2部分。您可以放心地忽略它,并仅以代码形式提供标识符和范围。

编辑: 对于那些有兴趣,你不需要身份的API。你甚至可以使用tab API使用一些小技巧来访问令牌。代码有点长,但是你有更好的错误信息和控制。请记住,在以下示例中,您需要创建Chrome App凭据。

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}); 
}); 
+0

嗨Piotr。我试过你的解决方案,但我得到*授权页无法加载*错误。我正在做你正在做的事情,清单中的范围相同。 – 2016-06-12 16:50:59

+0

嗨@Aegidius,你知道了吗?我有同样的问题。谢谢。 – rsb 2017-03-21 13:05:09

+0

@Aegidius,同样在这里,不确定这种方法是否仍然有效? – seesoe 2017-10-05 21:18:54

相关问题