【问题标题】:Google OAuth works locally, but times out on serverGoogle OAuth 在本地工作,但在服务器上超时
【发布时间】:2017-06-20 14:50:38
【问题描述】:

在本地测试时,我能够进行身份验证并使用Oauth2Service 检索用于创建帐户的基本信息。一旦上线,用户就可以访问谷歌同意页面,但是一旦他们选择了一个帐户(或输入他们的谷歌凭据),它就会停留在加载屏幕上,直到它达到我预定义的 60 秒超时。

我目前收到以下错误:

操作已超时。

说明:在执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详细信息:System.TimeoutException:操作已超时。

来源错误:

在执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪来识别有关异常起源和位置的信息。

堆栈跟踪:

[TimeoutException: 操作超时。] System.Web.Mvc.Async.c__DisplayClass8.b__4() +189 System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +427 System.Web.Mvc.Async.c__DisplayClass37.b__36(IAsyncResult asyncResult) +23 System.Web.Mvc.Async.AsyncInvocationWithFilters.b__3d() +112 System.Web.Mvc.Async.c__DisplayClass46.b__3f() +452 System.Web.Mvc.Async.c__DisplayClass46.b__3f() +452 System.Web.Mvc.Async.c__DisplayClass46.b__3f() +452 System.Web.Mvc.Async.c__DisplayClass33.b__32(IAsyncResult asyncResult) +15 System.Web.Mvc.Async.c__DisplayClass2b.b__1c() +37 System.Web.Mvc.Async.c__DisplayClass21.b__1e(IAsyncResult asyncResult) +241 System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29 System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +111 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53 System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +19 System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +51 System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +111 System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +282

我能够缩小它挂在这条线上的位置:

var token = await Flow.ExchangeCodeForTokenAsync(UserId, authorizationCode.Code, returnUrl,
            taskCancellationToken).ConfigureAwait(false);

对于上下文,这里是包含类:

[AuthorizationCodeActionFilter]
public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
{
    protected new IAuthorizationCodeFlow Flow { get { return FlowData.Flow; } }

    protected new string UserId
    { get { return FlowData.GetUserId(this); } }

    [AsyncTimeout(60000)]
    public async override Task<ActionResult> IndexAsync(AuthorizationCodeResponseUrl authorizationCode,
        CancellationToken taskCancellationToken)
    {

        if (string.IsNullOrWhiteSpace(authorizationCode.Code))
        {
            var errorResponse = new TokenErrorResponse(authorizationCode);
            return OnTokenError(errorResponse);
        }

        var returnUrl = Request.Url.ToString();
        returnUrl = returnUrl.Substring(0, returnUrl.IndexOf("?"));

        var token = await Flow.ExchangeCodeForTokenAsync(UserId, authorizationCode.Code, returnUrl,
            taskCancellationToken).ConfigureAwait(false);

        var oauthState = await AuthWebUtility.ExtracRedirectFromState(Flow.DataStore, UserId,
            authorizationCode.State).ConfigureAwait(false);

        return new RedirectResult(oauthState);

    }

    protected override FlowMetadata FlowData
    {
        get { return new GoogleFlowMetaData(); }
    }

    protected override ActionResult OnTokenError(TokenErrorResponse errorResponse)
    {
        throw new TokenResponseException(errorResponse);
    }
}

对于其他上下文,这是我对 FlowMetaData 的实现:

public class GoogleFlowMetaData : FlowMetadata
{
    public static readonly IAuthorizationCodeFlow flow =
        new ForceOfflineGoogleAuthorizationCodeFLow(new GoogleAuthorizationCodeFlow.Initializer
        {
            ClientSecrets = new ClientSecrets
            {
                ClientId = ConfigurationManager.AppSettings["Google.ClientID"],
                ClientSecret = ConfigurationManager.AppSettings["Google.ClientSecret"]
            },
            Scopes = new[] {
                Scope.UserinfoProfile,
                Scope.UserinfoEmail
            },
            DataStore = new GoogleDataStore(new DBContext())
        });

    public override string GetUserId(Controller controller)
    {
        var user = controller.User.Identity;
        if (controller.User.Identity.IsAuthenticated)
        {
            return controller.User.Identity.GetUserId();
        }
        var userId = (string)controller.Session["google_userId"];
        if (string.IsNullOrWhiteSpace(userId))
        {
            userId = Guid.NewGuid().ToString();
            controller.Session["google_userId"] = userId;
        }
        return userId;
    }

    public override IAuthorizationCodeFlow Flow
    {
        get { return flow; }
    }

    internal class ForceOfflineGoogleAuthorizationCodeFLow : GoogleAuthorizationCodeFlow
    {
        public ForceOfflineGoogleAuthorizationCodeFLow(GoogleAuthorizationCodeFlow.Initializer initializer)
            : base(initializer)
        {

        }

        public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
        {
            var ss = new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl));
            ss.AccessType = "offline";
            ss.ApprovalPrompt = "force";
            ss.ClientId = ClientSecrets.ClientId;
            ss.Scope = string.Join(" ", Scopes);
            ss.RedirectUri = redirectUri;
            return ss;
        }
    }
}

使用的 Nuget 包:

  • Google.Apis
  • Google.Apis.Auth
  • Google.Apis.Auth.Mvc
  • Google.Apis.Core
  • Google.Apis.Oauth2.v2

其他注意事项:

  • 托管在 Windows Web Server 2008 (IIS 7) 上
  • 作为子域托管
  • 我是子域/域的经过验证的所有者
  • 子域有 SSL
  • 子域和域已添加到项目的 Google API 管理器的“允许域”列表中
  • 在 Google API Manager 中为 OAuth 客户端 ID 设置了重定向 URL
  • 验证 API Manager 和应用程序之间的 ClientID 和 ClientSecret 匹配
  • Token storage in database is setup and working
  • 隐私政策在 OAuth 客户端中设置
  • Server's system clock is valid.

关于如何解决此问题的任何建议或想法? 如果有任何其他信息可以提供帮助,请告诉我!

【问题讨论】:

    标签: asp.net-mvc asynchronous oauth-2.0 google-oauth google-api-dotnet-client


    【解决方案1】:

    将解决方案迁移到 Azure,而不是在我自己的服务器上托管,它解决了问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-17
      • 2021-04-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多