【问题标题】:How do I set return_uri for GoogleWebAuthorizationBroker.AuthorizeAsync?如何为 GoogleWebAuthorizationBroker.AuthorizeAsync 设置 return_uri?
【发布时间】:2015-09-21 10:35:00
【问题描述】:

我正在尝试在我的非 MVC .NET Web 应用程序中使用Google Calendar API。 (这似乎是一个重要的区别。)

我尝试使用来自 Google 的 this example 和 Daimto 的 this example 的代码,以及一些来自 related posts here 的有用提示。

我写了如下方法:

public void GetUserCredential( String userName )
{
    String clientId = ConfigurationManager.AppSettings[ "Google.ClientId" ];            //From Google Developer console https://console.developers.google.com
    String clientSecret = ConfigurationManager.AppSettings[ "Google.ClientSecret" ];    //From Google Developer console https://console.developers.google.com
    String[] scopes = new string[] {
            Google.Apis.Calendar.v3.CalendarService.Scope.Calendar          
    };

    // here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
    UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync( new ClientSecrets
    {
        ClientId = clientId,
        ClientSecret = clientSecret             
    }, scopes, userName, CancellationToken.None, new FileDataStore( "c:\\temp" ) ).Result;

    // TODO: Replace FileDataStore with DatabaseDataStore
}

问题是,当调用 Google 的 OAuth2 页面时,redirect_uri 一直被设置为 http://localhost:<some-random-port>/authorize。我不知道如何将其设置为其他内容,如AuthorizeAsync 生成的以下示例 URL:

https://accounts.google.com/o/oauth2/auth?access_type=offline
    &response_type=code
    &client_id=********.apps.googleusercontent.com
    &redirect_uri=http:%2F%2Flocalhost:40839%2Fauthorize%2F
    &scope=https:%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar

Google 以 redirect_uri_mismatch 错误页面作为响应,其中包含以下消息:

“请求中的重定向 URI:http://localhost:XXXXX/authorize/ 与注册的重定向 URI 不匹配”

我只能在我的 Google Developer's Console Credentials 页面中注册这么多重定向 URI。我不倾向于注册 65535 端口,并且我想在我的网站上使用 /authorize 以外的页面。具体来说,我想在开发过程中使用http://localhost:888/Pages/GoogleApiRedirect,但除了我在开发者控制台中所做的之外,我不知道在哪里设置它。

如何显式设置redirect_uri 的值?我也愿意以“这种方法完全错误”的形式做出回应。

编辑:

在过去一天玩这个之后,我发现通过使用本地应用程序而不是 Web 应用程序的客户端 ID/客户端密钥,我至少可以访问 Google 的网络授权页面而不会抱怨redirect_uri_mismatch。这仍然是不可接受的,因为它仍然返回到http://localhost:<some-random-port>/authorize,这超出了我的 Web 应用程序的控制范围。

【问题讨论】:

  • 您是否尝试过将 Visual Studio 配置为为您的 Web 应用项目使用预定义端口?检查此文档,以便您可以定义一个端口并在您的开发人员控制台中使用它。 msdn.microsoft.com/en-us/library/ms178109(v=vs.140).aspx
  • 感谢@Gerardo 的建议。是的,它已经为端口 888 进行了预配置。我还尝试过 1024 以上的“非特权”端口。我在一些与我的情况相似的情况下看到了这个建议。如果它确实有效,我想我可以忍受/authorize 作为我的重定向页面。这不是一个理想的解决方案,但我可以接受。
  • 您也可以尝试直接在 IIS 中部署项目,从那里您可以对 Web 应用程序的端口进行更多控制。 msdn.microsoft.com/en-us/library/vstudio/…
  • 另一个好建议,@Gerardo。事情是,redirect_uri 只是一个 parameter 看在上帝的份上!为什么会被任意、不受控制地设置成原来的样子?我对完全缺乏关于这个问题的文档感到既惊讶又沮丧。这让我想知道,正如我在问题结束时提出的那样,我是否完全错误地处理了这个问题,我根本不应该使用 AuthorizeAsync
  • @Peter - 我已经在我的开发机器 (localhost:888) 和我的测试机器 beta.??????.com 上进行了测试,下面的示例在两者上都运行良好。

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


【解决方案1】:

你可以使用这个代码:(来自http://coderissues.com/questions/27512300/how-to-append-login-hint-usergmail-com-to-googlewebauthorizationbroker的原创想法)

dsAuthorizationBroker.RedirectUri = "my localhost redirect uri";
UserCredential credential = await dsAuthorizationBroker.AuthorizeAsync(...

dsAuthorizationBroker.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Util.Store;

namespace OAuth2
{    
    public class dsAuthorizationBroker : GoogleWebAuthorizationBroker
    {
        public static string RedirectUri;

        public new static async Task<UserCredential> AuthorizeAsync(
            ClientSecrets clientSecrets,
            IEnumerable<string> scopes,
            string user,
            CancellationToken taskCancellationToken,
            IDataStore dataStore = null)
        {
            var initializer = new GoogleAuthorizationCodeFlow.Initializer
            {
                ClientSecrets = clientSecrets,
            };
            return await AuthorizeAsyncCore(initializer, scopes, user,
                taskCancellationToken, dataStore).ConfigureAwait(false);
        }

        private static async Task<UserCredential> AuthorizeAsyncCore(
            GoogleAuthorizationCodeFlow.Initializer initializer,
            IEnumerable<string> scopes,
            string user,
            CancellationToken taskCancellationToken,
            IDataStore dataStore)
        {
            initializer.Scopes = scopes;
            initializer.DataStore = dataStore ?? new FileDataStore(Folder);
            var flow = new dsAuthorizationCodeFlow(initializer);
            return await new AuthorizationCodeInstalledApp(flow, 
                new LocalServerCodeReceiver())
                .AuthorizeAsync(user, taskCancellationToken).ConfigureAwait(false);
        }
    }


    public class dsAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
    {
        public dsAuthorizationCodeFlow(Initializer initializer)
            : base(initializer) { }

        public override AuthorizationCodeRequestUrl
                       CreateAuthorizationCodeRequest(string redirectUri)
        {
            return base.CreateAuthorizationCodeRequest(dsAuthorizationBroker.RedirectUri);
        }
    }    
}

【讨论】:

  • 这个答案根本没有帮助。没有任何解释......只是挥动一根魔杖并使其以某种神秘莫测的方式工作并不能真正回答最初的问题,即“为什么原始代码不起作用?”
  • 我认为这个答案没有帮助。 RedirectUri 没有实际设置。
  • 感谢您的帮助。但是一个问题,不关闭身份验证窗口。如何关闭此验证窗口,然后重定向到当前工作项目页面?
  • 这不会返回一个TOKEN!我发布了一条回复,希望能帮助人们解决这个问题。
【解决方案2】:

如果您尝试在 .NET 应用程序非网络服务器应用程序(即 C# Console App 命令行程序)中使用 GoogleWebAuthorizationBroker.AuthorizeAsync,则在凭据中创建 Google OAuth 配置文件 (https://console.developers.google.com/apis) 时选择以下选项至关重要.它是隐藏的,如果你不这样做,如果你选择单选按钮“其他”,它必须经过一个批准过程。 另外请注意,仅复制在以下步骤中创建的 JSON 参数的内容并将您的 client_id/secret 替换为 Web 应用程序版本仍然会失败。为您的 Google API 控制台创建一个新的 OAuth 客户端配置文件。

点击“帮我选择”

选择您想要的 API 库,即(Google 日历 API) 选择“用户数据”

“是的 - 不需要授权文件”即 Javascript 和重定向 现在您有一个未经授权的个人资料

使用“下载 JSON”并将其保存到您的应用程序以在下面的代码中引用。当您查看此文件时,您会注意到一组不同的参数,并告诉代理这是一个应用程序。在此示例中,我正在访问范围日历 API。只需将范围更改为您尝试访问的任何 API。

   string[] Scopes = { CalendarService.Scope.Calendar }; //requires full scope to get ACL list..
                string ApplicationName = "Name Of Your Application In Authorization Screen";

                //just reference the namespaces in your using block

                using (var stream = new FileStream("other_client_id.json", FileMode.Open, FileAccess.Read))
                {
                    // The file token.json stores the user's access and refresh tokens, and is created
                    // automatically when the authorization flow completes for the first time.
                    string credPath = "other_token.json";
                    credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                        GoogleClientSecrets.Load(stream).Secrets,
                        Scopes,
                        "user",
                        CancellationToken.None,
                        new FileDataStore(credPath, true)).Result;               
                }

                // Create Google Calendar API service.
                var service = new CalendarService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = ApplicationName,
                });

                //Then your ready to grab data from here using the methods mentioned in Google Calendar API docs

【讨论】:

  • 只是想说非常感谢您对这个隐藏的回复。昨天帮了我。
  • 我没有选项“您将从哪里调用 API?”.... 解决方案不起作用或过时...
  • 我试过这个并在我的 Windows 桌面应用程序中收到以下错误:System.AggregateException: One or more errors occurred. ---&gt; Google.Apis.Auth.OAuth2.Responses.TokenResponseException: Error:"invalid_client", Description:"Unauthorized", Uri:"" at Google.Apis.Auth.OAuth2.Responses.TokenResponse你能帮忙吗?
【解决方案3】:

在创建 oAuth 客户端 ID 时选择“其他”帮助我解决了重定向问题。 (使用“Web 应用程序”选项会尝试使用随机端口重定向到某个 url,这很烦人)

现在我的 Gmail API 就像一个魅力 :)

【讨论】:

    猜你喜欢
    • 2021-09-04
    • 2015-02-18
    • 2015-11-17
    • 2018-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-27
    相关资源
    最近更新 更多