如何为GoogleWebAuthorizationBroker.AuthorizeAsync设置return_uri?

时间:2015-07-03 14:34:53

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

我正在尝试在非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生成的示例网址所示:

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应用程序的控制。

3 个答案:

答案 0 :(得分:18)

您可以使用以下代码:(来自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);
        }
    }    
}

答案 1 :(得分:0)

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

单击“帮助我选择”

Step 1

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

Step 2

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

enter image description here

使用“下载JSON”并将其保存到您的应用程序中,以在下面的代码中进行引用。当您查看此文件时,您还会注意到一组不同的参数,并告诉代理这是一个应用程序。在此示例中,我正在访问范围Calendar 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

答案 2 :(得分:0)

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

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