GoogleWebAuthorizationBroker无法使用https //accounts.google.com/o/oauth2/v2/auth启动浏览器;重定向uri不匹配

时间:2018-01-02 17:54:07

标签: c# asp.net oauth google-api google-analytics-api

我遇到与此问题完全相同的问题: How do I set return_uri for GoogleWebAuthorizationBroker.AuthorizeAsync?

然而,这个问题在3年前得到解答,所提供的答案对我不起作用;我认为无法实际设置重定向uri。所以这就是问题所在:

Simulate Background Fetch

这会返回以下错误:

performFetchWithCompletionHandler

它正在尝试使用redirect_uri =“http://localhost:/ authorize”启动oauth2页面;当我尝试直接查看它尝试启动的网址时,该页面显示“请求中的重定向URI:http://localhost:XXXXX/authorize/与注册的重定向URI不匹配”

我尝试将localhost:XXXXX添加到Google API控制台中的授权网址,但下次运行时端口不同,例如localhost:XXXYY。我的client_secret.json文件列出了所有已授权的重定向URL,但未被使用。如何设置重定向uri并解决此问题?

2 个答案:

答案 0 :(得分:0)

我今天遇到了同样的问题。 事实证明,没有设置用于处理http / https协议的“默认”程序

enter image description here

答案 1 :(得分:0)

我不确定您是否要构建本地安装的应用程序或asp.net Web应用程序,但是基于您所指出的问题,我假设它是一个Web应用程序,这是我如何解决它。

>

首先,GoogleWebAuthorizationBroker的默认实现是针对本地安装的应用程序。您可以在此link中找到其实现 因此,您的代码在本地计算机上可能工作正常,但是在网络服务器中托管时,它可能会永久加载。

因此,您需要按照Google文档中所述为Web应用程序实现自己的AuthorizationCodeFlow。

这就是我在 ASP.NET Core MVC Web应用程序中实现它的方式

public async Task<IActionResult> ConfigureGA(CancellationToken cancellationToken)
        {
            GoogleAnalyticsModel model = new GoogleAnalyticsModel();
            var state = UriHelper.GetDisplayUrl(Request);
            var result = await GetCredential(state, cancellationToken);
            if (result.Credential != null)
            {
                using (var svc = new AnalyticsService(
                    new BaseClientService.Initializer
                    {
                        HttpClientInitializer = result.Credential,
                        ApplicationName = "Your App Name"
                    }))
                {

                    ManagementResource.AccountSummariesResource.ListRequest list = svc.Management.AccountSummaries.List();
                    list.MaxResults = 1000;
                    AccountSummaries feed = await list.ExecuteAsync();
                    model.UserAccounts = feed.Items.ToList();
                }

                return View(model);
            }
            else
            {
                return new RedirectResult(result.RedirectUri);
            }

        }    
private async Task<AuthorizationCodeWebApp.AuthResult> GetCredential(string state, CancellationToken cancellationToken)
        {
            var userId = userManager.GetUserAsync(User).Result.Id;
            var redirectUri = Request.Scheme + "://" + Request.Host.ToUriComponent() + "/authcallback/";
            using (var stream = new FileStream("client_secret.json",
                 FileMode.Open, FileAccess.Read))
            {
                IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
                    Scopes = new[] { AnalyticsService.Scope.AnalyticsReadonly, AnalyticsReportingService.Scope.AnalyticsReadonly },
                    DataStore = datastore
                });

                return await new AuthorizationCodeWebApp(flow, redirectUri, state)
                        .AuthorizeAsync(userId, cancellationToken);
            }
        }

我在请求oauth凭据(即GetCredential()方法)时传递了应用程序的状态。

在此方法中,创建您自己的IAuthorizationCodeFlow并将您的流,redirect_uri(您还必须在Google Developer Console中设置)和应用程序的状态传递给 AuthorizationCodeWebApp

接下来,您必须实现 authcallback 控制器来处理oauth代码。这段代码类似于google-dotnet-client库found here,但是我采用了相同的代码,因为我正在使用Microsoft.AspNetCore.Mvc

public class AuthCallbackController : Controller
    {
        private readonly UserManager<ApplicationUser> userManager;
        private readonly IGoogleAnalyticsDataStore datastore;

        public AuthCallbackController(UserManager<ApplicationUser> userManager, IGoogleAnalyticsDataStore datastore)
        {
            this.userManager = userManager;
            this.datastore = datastore;
        }

        protected virtual ActionResult OnTokenError(TokenErrorResponse errorResponse)
        {
            throw new TokenResponseException(errorResponse);
        }
        public async virtual Task<ActionResult> Index(AuthorizationCodeResponseUrl authorizationCode,
            CancellationToken taskCancellationToken)
        {
            using (var stream = new FileStream("client_secret.json",
                 FileMode.Open, FileAccess.Read))
            {
                IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
        new GoogleAuthorizationCodeFlow.Initializer
        {
            ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
            DataStore = datastore,
            Scopes = new[] { AnalyticsService.Scope.AnalyticsReadonly, AnalyticsReportingService.Scope.AnalyticsReadonly }
        });

                if (string.IsNullOrEmpty(authorizationCode.Code))
                {
                    var errorResponse = new TokenErrorResponse(authorizationCode);

                    return OnTokenError(errorResponse);
                }
                string userId = userManager.GetUserAsync(User).Result.Id;
                var returnUrl = UriHelper.GetDisplayUrl(Request);

                var token = await flow.ExchangeCodeForTokenAsync(userId, authorizationCode.Code, returnUrl.Substring(0, returnUrl.IndexOf("?")),
                    taskCancellationToken).ConfigureAwait(false);

                // Extract the right state.
                var oauthState = await AuthWebUtility.ExtracRedirectFromState(datastore, userId,
                    authorizationCode.State).ConfigureAwait(false);

                return new RedirectResult(oauthState);
            }
        }
    }

希望这可以回答您的问题,并且超出了问题范围。