Google日历返回无效授权

时间:2019-12-10 17:49:24

标签: c# .net google-calendar-api

我有一个客户正试图从我们的Web应用程序访问他们的日历。一切对我们所有其他客户都有效,因此我不确定这里有什么不同,除了该客户在澳大利亚并且使用非gmail.com电子邮件地址。

客户能够授权我们的应用程序,并且我们确实为用户获得了oauth令牌。我们要求日历访问权限,并且客户已授予它访问权限。当我们请求所有日历的列表时,我们会收到无效的授权消息。

以下是我们用于访问其日历的代码。被调用的方法是GetAllWritableCalendars。

public class GoogleCalendarAdapter : ICalendarAdapter {
    #region attributes
    private readonly ISiteAuthTokenQueryRepository _tokenRepo;
    private readonly GoogleCalendarSettings        _settings;

    private const string APPNAME = "SomeAppName";

    private const string ACL_OWNER = "owner";
    private const string ACL_WRITER = "writer";
    #endregion

    #region ctor
    public GoogleCalendarAdapter(ISiteAuthTokenQueryRepository tokenRepo,
                                 GoogleCalendarSettings        settings) {
        _tokenRepo = tokenRepo;
        _settings  = settings;
    }
    #endregion

    #region methods
    private GoogleAuthorizationCodeFlow BuildAuthorizationCodeFlow() {
        return new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer() {
            ClientSecrets = BuildClientSecrets(),
            Scopes        = BuildScopeList()
        });
    }

    private CalendarService BuildCalendarService(SiteAuthToken token) {

        return new CalendarService(new BaseClientService.Initializer() {
                ApplicationName       = APPNAME,
                HttpClientInitializer = BuildUserCredential(token)
        });
    }

    private ClientSecrets BuildClientSecrets() {
        return new ClientSecrets() {
            ClientId = _settings.ClientId,
            ClientSecret = _settings.ClientSecret
        };
    }

    private string[] BuildScopeList() {
        return new [] { CalendarService.Scope.Calendar };
    }

    private UserCredential BuildUserCredential(SiteAuthToken token) {
        TokenResponse responseToken = new TokenResponse() {
            AccessToken  = token.AccessToken,
            RefreshToken = token.RefreshToken
        };

        return new UserCredential(BuildAuthorizationCodeFlow(), APPNAME, responseToken);
    }

    public async Task<List<Cal>> GetAllWritableCalendars(Guid siteGuid) {
        SiteAuthToken token = await GetToken(siteGuid);
        CalendarService svc = BuildCalendarService(token);

        IList<CalendarListEntry> calendars = svc.CalendarList
                                                .List()
                                                .Execute()
                                                .Items;

        return calendars.Where(c => c.AccessRole.Equals(ACL_OWNER,  StringComparison.CurrentCultureIgnoreCase) ||
                                    c.AccessRole.Equals(ACL_WRITER, StringComparison.CurrentCultureIgnoreCase))
                        .Select(c => new Cal() {
                            Id   = c.Id,
                            Name = c.Summary
                        })
                        .OrderBy(o => o.Name)
                        .ToList();
    }

    private async Task<SiteAuthToken> GetToken(Guid siteGuid) {
        SiteAuthToken retVal = await _tokenRepo.GetSiteAuthToken(siteGuid);

        if (retVal == null) {
            throw new ApplicationException($"Could not find a SiteAuthToken for specified site (SiteGuid: {siteGuid})");
        }

        return retVal;
    }

    #endregion

2 个答案:

答案 0 :(得分:3)

凭据 Google 您的应用 使用的授权设置的作用域,如果每次将新的作用域添加到应用程序时都对其进行更新,则可以将其存储在数据库中。

访问令牌 用户 您的应用程序< / em> 来获取Google数据(在这种情况下为日历)。生命周期有限,因此无法保存到数据库中。

刷新令牌 是允许您的应用程序为客户端获取更多令牌的令牌。它的寿命也很有限。

有关更多信息,请参见:Using OAuth 2.0 to Access Google APIs

每次更改范围或添加更多范围时,都必须重新生成凭据。每个客户端每个用户帐户有50个刷新令牌,请参见Token expiration。因此,将令牌存储在数据库中毫无意义,因为它们将在某个时候被弃用,如果您有51个客户端,则第一个令牌将被弃用。

检查:

  1. 如何在数据库中进行设置
  2. 如果您正确续签令牌
  3. 如果您为用户使用正确的令牌

您可以删除所有令牌(不提供凭据),而您当前的用户只需进入同意屏幕并再次允许它,他们就不会失去连接。

答案 1 :(得分:0)

我后来以不同的方式问了这个问题。也许这更有意义。也许还有更多可用信息。无论如何,我发现了如何正确测试事情。

Look at this question