【问题标题】:Inserting accounts into Mirror API using service account returns "invalid_grant" error使用服务帐户将帐户插入 Mirror API 会返回“invalid_grant”错误
【发布时间】:2014-08-19 14:12:19
【问题描述】:

我正在使用带有 Google 服务帐户的 Mirror API .NET Library 通过 MyGlass 应用程序进行第 3 方身份验证。我正在按照Authentication for GDK Glassware 文档在服务器端对我的用户进行身份验证,然后插入帐户。

当我尝试使用 Mirror API 插入新帐户时,我收到 OAuth 错误:“invalid_grant”:

堆栈跟踪:

Google.Apis.Auth.OAuth2.Responses.TokenResponseException 未处理 通过用户代码 HResult=-2146233088 Message=Error:"invalid_grant", 说明:"",Uri:"" Source=Google.Apis

在 Google.Apis.Requests.ClientServiceRequest`1.Execute() 中 c:\code\google.com\google-api-dotnet-client\default_182\Tools\Google.Apis.Release\bin\Debug\output\default\Src\GoogleApis\Apis\Requests\ClientServiceRequest.cs:line 96\r\n

它被ClientServiceRequest.cs 中的 Execute() 函数解包并抛出。第 96 行。

源代码:

const string password = "notasecret";
X509Certificate2 certificateToExport = new X509Certificate2(HostingEnvironment.MapPath("/Path/To/Certificate.p12"), password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
var rsa = (RSACryptoServiceProvider)certificateToExport.PrivateKey;

// Have to export the provider or you get an "Invalid Algorithm" error when 
// trying to sign the request.
RSACryptoServiceProvider cryptoProvider = new RSACryptoServiceProvider();
cryptoProvider.ImportParameters(rsa.ExportParameters(true));

var serviceAccountCredential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(id: "MYCLIENTID.apps.googleusercontent.com")
{
Key = cryptoProvider,
Scopes = new List<string>() { "https://www.googleapis.com/auth/glass.thirdpartyauth" },
User = "MYCLIENTID@developer.gserviceaccount.com"
});

var mirrorService = new MirrorService(new BaseClientService.Initializer() { HttpClientInitializer = serviceAccountCredential });
Account account = new Account() { AuthTokens = new AuthToken[] { new AuthToken() { AuthTokenValue = sessionKey, Type = "sessionKey" } } };

// Exception thrown here
Account insertedAccount = mirrorService.Accounts.Insert(account, userToken: userToken, accountType: "example.com", accountName: accountName).Execute();

我已经反复检查了一些事情:

  • 我有正确的客户 ID 和电子邮件地址。
  • 我已提供范围:https://www.googleapis.com/auth/glass.thirdpartyauth
  • MyGlass 应用程序 web 视图作为查询参数传递给我的 userToken 被 返回 提供给 MirrorAPI。
  • 我正在使用 Google 提供给我的证书签署请求。
  • MyGlass 正在使用正确的身份验证重定向 URL
  • Google Analytics documentation 表示出现“invalid_grant”错误:
  1. 您的服务器时钟与 NTP 不同步。
  2. 已超出刷新令牌限制。

服务器时钟同步。这发生在多台机器上。将调查是否/如何超过令牌限制。我的印象是 API 库会为我处理刷新。

我觉得我完全误解了某些东西(很可能)。我会很感激有人指出我在这里有什么问题。

【问题讨论】:

  • 如果这个问题需要进一步澄清,请告诉我。
  • 您确实了解服务帐户是它自己的实体,这意味着即使您可以将服务帐户与镜像 api 一起使用,您也只能设法写入服务帐户玻璃时间线。我不认为服务帐户拥有一副玻璃。你到底想做什么?
  • account 命令可让您在 Glass 上的 Account Manager 中插入一个新帐户。您正在使用服务帐户登录。你到底想做什么。需要更多信息。
  • 感谢 DalmTo。我正在尝试将一个帐户插入到镜像 api 中,以便我可以检索在 MyGlass 中安装应用程序时经过身份验证的眼镜组上的帐户。我正在关注 Google 关于此的文档,其中明确指出您应该使用服务帐户来执行此操作。诚然文档可能有误,但他们在整个审批过程中自己都提到过,所以我很确定它是正确的。
  • 不,它专门用于在服务器端应用程序上运行。这就是为什么它是服务帐户而不是客户帐户的原因。

标签: .net authentication google-glass google-gdk google-mirror-api


【解决方案1】:

chat thread 来看,问题是由于ServiceAccountCredential 类中传递的数据错误导致服务帐户身份验证失败。

原问题中使用的代码 sn-p 应修正为:

var serviceAccountCredential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(id: "MYCLIENTID@developer.gserviceaccount.com")
{
    Key = cryptoProvider,
    Scopes = new List<string>() { "https://www.googleapis.com/auth/glass.thirdpartyauth" }
});

【讨论】:

  • 再次感谢阿兰。非常感谢。
【解决方案2】:

确保您已将 Glassware 提交至 https://developers.google.com/glass/distribute/form。请务必提及您还想添加帐户,并为他们提供您的应用程序的帐户类型。我记得在我能够添加帐户之前必须在我的应用程序上执行此操作。你会认为这会在他们的文档中,但我不相信。

【讨论】:

  • 谢谢杰西。作为获取玻璃器皿上市商店的一部分,我已将这些信息提供给谷歌。他们知道我正在尝试进行第 3 方身份验证。
  • 好吧,这就是我所拥有的。我似乎记得在 Python 中有同样的问题,但我认为我的问题是由于 Python 不喜欢密钥格式。我的 Python 看起来和你的 C#/.net 代码几乎一模一样。
  • 我很感激杰西。你知道我可能不得不尝试使用不同的语言,也许是 JS 库。
猜你喜欢
  • 2014-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-18
  • 1970-01-01
  • 2014-09-22
  • 2013-04-18
  • 1970-01-01
相关资源
最近更新 更多