.NET Google Calendar API v3:多帐户身份验证

时间:2013-12-12 17:02:34

标签: calendar google-api-dotnet-client

我正在尝试编写一个程序,用于在多个Google帐户的CRM和Google日历之间同步事件。

这是一个Windows控制台应用程序。

对于每个Google帐户,我在API控制台中启用了Calendar API,创建了一个名为“UpdateSync”的应用程序(类型:native),然后下载了JSON文件。

我使用帐户邮件地址(即email1@gmail.com.json)重命名了这些文件

接下来,我写了下面的代码:

    /// <summary>
    /// Loads updated event from Google Calender after last synchonization date
    /// </summary>
    /// <param name="user">The user we want to get appointments</param>
    public List<Appointment> LoadAppointments(User user)
    {
        Console.WriteLine("LoadAppointments({0})", user.Email);
        List<Appointment> Appointments = new List<Appointment>();

        UserCredential credential;
        using (var stream = new FileStream(string.Format("credentials\\{0}.json", user.Email), FileMode.Open, FileAccess.Read))
        {
            try
            {
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets, new[] { CalendarService.Scope.Calendar }, "user", CancellationToken.None, new FileDataStore("UpdayeSync.Credentials")).Result;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }

        BaseClientService.Initializer initializer = new BaseClientService.Initializer();
        initializer.HttpClientInitializer = credential;
        initializer.ApplicationName = "UpdateSync";
        service = new CalendarService(initializer);

        EventsResource.ListRequest req = service.Events.List("primary");
        req.TimeMin = DateTime.Now.AddMonths(-2).ToString("o");
        req.ShowDeleted = true;
        req.UpdatedMin = XmlConvert.ToString(LastSync, XmlDateTimeSerializationMode.Utc);
        req.SingleEvents = true;

        Events events;
        try
        {
            events = req.Execute();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            return null;
        }

        // [...]
    }

为每个JSON文件调用此代码。

第一次通话时,要同步的帐户是“email1@gmail.com”。 Google Chrome自动启用,并使用我自己的帐户(email2@gmail.com)自动登录,并要求我允许我的程序访问Calendar API。

我接受了。

此弹出窗口再也没有显示过。

任何帐户的更改都是在我自己的日历上完成的,而不是JSON文件所引用的。

怎么了?如何使用独特的程序访问多个Google帐户?

这个程序将作为计划任务在服务器上运行,我不能打开任何窗口,因为没有人会看到服务器的屏幕。我不能要求用户认证自己,因为没有用户。

但我可以对任何用户的Google帐户执行任何操作(启用API,创建密钥,授予应用程序等)。

1 个答案:

答案 0 :(得分:2)

您应该为每个用户创建一个新的CalendarService(轻量级组件)。 CalendarService和所有其他Google服务都实现为不可变(为简单起见并支持线程安全操作)。

为每个用户创建一项新服务,并使用不同的userId(“user1”,“user2”等)作为GoogleWebAuthorizationBroker.AuthorizeAsync的参数。

更新:

您还应该创建自己的流程类:

class ForceUIGoogleAuthorizationCodeFlow : AuthorizationCodeFlow
{
    public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
    {
        return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl))
        {
            ClientId = ClientSecrets.ClientId,
            Scope = string.Join(" ", Scopes),
            RedirectUri = redirectUri,
            ApprovalPrompt = "force",
        };
    }
}

然后,

使用以下代码替换您对GoogleWebAuthorizationBroker的调用:

var initializer = new GoogleAuthorizationCodeFlow.Initializer
{
       ClientSecrets = clientSecrets,
       Scopes = [SCOPED_HERE];
       initializer.DataStore = new FileDataStore("Credentials");
};
var flow = new ForceUIGoogleAuthorizationCodeFlow(initializer);
// Create authorization code installed app instance and authorize the user.
crdentials = await new AuthorizationCodeInstalledApp(flow, 
      new LocalServerCodeReceiver()).AuthorizeAsync
      ("USER_ID_HERE", taskCancellationToken).ConfigureAwait(false);