Google Calendar API 返回 invalid_grant 和错误请求

2023-12-19

在我的开发环境中,我有一个用户刚刚收到以下范围的 OAuth 令牌。

  • https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar
  • https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/calendar.events
  • https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/calendar.readonly

一切看起来都很好,我为用户存储了令牌。然后,我请求列出用户的日历,并收到带有错误请求的 invalid_grant 。我使用另一个用户的令牌(也在我的开发环境中)尝试相同的请求,并且它工作正常。

我最初只有第一个作用域设置,即写级别访问权限。这就是所有现有代币的创建方式。在测试过程中,我添加了其他范围。

我尝试在我的项目中更新 Google API 的 NuGet 包。

这是我的班级正在打电话。

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

    private const string APPNAME = "REDACTED";

    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();
    }

    public async Task<Cal> GetCalendar(Guid siteGuid, string calendarId) {
        SiteAuthToken token = await GetToken(siteGuid);
        CalendarService svc = BuildCalendarService(token);

        CalendarListEntry entry = svc.CalendarList
                                     .Get(calendarId)
                                     .Execute();

        Cal retVal = new Cal() {
            Id   = entry.Id,
            Name = entry.Summary
        };

        return retVal;
    }

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

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

        return retVal;
    }

    #endregion
}

在您描述的情况下,使用 Google Developer 对我帮助很大OAuth 游乐场 http://developers.google.com/oauthplayground。默认情况下,您可以使用 OAuthPlayground 本身作为客户端来获取授权(并观察流量)。但诀窍是进入 [设置] 齿轮并选中 [x] 使用您自己的 OAuth 凭据复选框并尝试授权您的客户端。在我看来,这是一个非常有用的调试工具,我想确保您了解它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Google Calendar API 返回 invalid_grant 和错误请求 的相关文章

  • 无法使用 strptime() 获取秒数

    我收到 YYYY MM DDThh mm ss S Z hh mm 这种格式的日期时间 我正在尝试使用复制该值strptime如下所示 struct tm time 0 char pEnd strptime datetime Y m dT
  • UTF8/UTF16 和 Base64 在编码方面有什么区别

    In c 我们可以使用下面的类来进行编码 System Text Encoding UTF8 System Text Encoding UTF16 System Text Encoding ASCII 为什么没有System Text En
  • 部署 MVC4 项目时出错:找不到文件或程序集

    过去 我只需使用 Visual Studio 2012 发布到 AWS 菜单项即可部署我的 MVC4 网站 到 AWS Elastic Beanstalk 现在 程序可以在本地编译并运行 但无法部署 从消息来看 它似乎正在寻找不在当前部署的
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 使用 LINQ 查找列表中特定类型的第一个元素

    使用 LINQ 和 C 在元素列表中查找特定类型的第一个项目的最短表示法是什么 var first yourCollection OfType
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud

随机推荐