TokenResponseException - 错误:" invalid_grant",描述:"",Uri:""

时间:2015-01-02 04:04:24

标签: asp.net-mvc google-api google-oauth

我有适用的代码 - 使用Google Calendar API的MVC应用程序和使用Google的OAuth2身份验证的Gmail API。代码有效。加载页面时,将显示来自两个服务的数据。我有一个Javascript计时器以一定的间隔刷新数据(20分钟)。所以一切都按预期工作,直到某个时间点(我想在一段时间间隔之后)开始抛出异常:错误:" invalid_grant",描述:"", URI:"" 即可。该异常没有InnerException,并且在StackTrace中只有该错误消息和此信息(在屏幕截图中):

enter image description here

如果有人知道这个错误可能是什么原因,我真的很感激。那是什么" c:\ code \ google.com ...."在堆栈跟踪消息中,我没有" c:\ code"我的磁盘上的文件夹。我发现了一些与同一错误相关的帖子,但不幸的是他们没有帮助理解问题。也许有更多细节,比如这个截图,有人有关于这个主题的更多信息。非常感谢。

我发现 - AppPool回收临时解决了这个问题。但是,经过一段时间后,又回来了。它与AppPool回收有什么关系?

2 个答案:

答案 0 :(得分:1)

好吧,经过多次阅读后,我找到了这个例外的原因。

https://developers.google.com/accounts/docs/OAuth2#expiration

https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtAuthorization?#helpme

无效授权:已超出刷新令牌限制(默认值为25)。 这就是全部。

根据这些文档:每个Google用户帐户目前有25个令牌限制。如果用户帐户有25个有效令牌,则下一个身份验证请求会成功,但会在没有任何用户可见警告的情况下悄悄地使最旧的未完成令牌无效。

如果应用程序尝试使用无效的刷新令牌,则会返回invalid_grant错误响应。每个唯一的OAuth 2.0客户端和Google Analytics帐户对的限制为25个刷新令牌(请注意,此限制可能会发生变化)。

理解,他们将刷新令牌的数量限制为25,但是当你需要超过这个限制时,他们不会说要做什么。 Arghhh ......我一直在试验并找到了解决方法如何绕过这个限制。确实回收应用程序池确实解决了问题(当然,直到达到下一个25限制)。我们可以从IIS手动回收AppPool,也可以运行命令:

c:\Windows\System32\inetsrv\appcmd.exe recycle apppool /apppool.name:AppPoolName

您可以安排该命令每晚或每小时执行,无论......

但我发现有一个程序化解决方案:

覆盖控制器的OnException方法(它适用于MVC应用程序)

protected override void OnException(ExceptionContext filterContext)
{
    if (filterContext.ExceptionHandled) return;

    // Log exception details
    Global.LogException(filterContext.Exception, EventLogEntryType.Error);

    if (filterContext.Exception.Message.Contains("invalid_grant"))
    {
        // Invalid Grant: The refresh token limit has been exceeded (default is 25).
        // https://developers.google.com/accounts/docs/OAuth2#expiration
        // https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtAuthorization?#helpme

        Global.RecycleAppPool();
        Global.LogException(new Exception("AppPool has been recycled"), EventLogEntryType.Information);
        Response.Redirect("Index");
    }

    var actionName = filterContext.RouteData.Values["action"].ToString();

    // Return friendly error message
    var errorMessage = string.Format("Action {0} failed with error: {1}. Please try again.", actionName, filterContext.Exception.Message);
    filterContext.Result = Content(errorMessage);

    filterContext.ExceptionHandled = true;
    base.OnException(filterContext);
}

RecycleAppPool的定义如下(此操作很快,而不是重新启动IIS :):

public static void RecycleAppPool()
{
    ServerManager serverManager = new ServerManager();
    ApplicationPool appPool = serverManager.ApplicationPools["Homepage"];
    if (appPool != null)
    {
        if (appPool.State == ObjectState.Stopped) appPool.Start();
        else appPool.Recycle();
    }
}

因此,在invalid_grant异常的情况下,异常"吞下":记录,回收apppool并重置刷新令牌的限制。希望这会有所帮助。

如果您发现一些问题,请告诉我。

答案 1 :(得分:1)

服务器时钟也可能不同步。出于某种原因,我无法与互联网时钟同步并且快速运行6分钟。将其重置为正确的工作时间。