有没有一种方法可以在Google的Gmail / Google日历OAuth批准流程中预先检查或避免范围复选框?

25

我们目前使用 google-api-python-client 来处理用户的 OAuth 流程。我们收到了几封用户的邮件,询问为什么他们的帐户无法成功导入,当我们查看时,发现他们的令牌没有适当的权限范围。例如,我们期望找到以下所有权限范围:

https://www.googleapis.com/auth/gmail.metadata openid https://www.googleapis.com/auth/userinfo.email

但我们只收到了最后两个权限。当我们查看 OAuth 流程时,我们注意到我们的 OAuth 流程如下(应用程序名称和帐户名称已隐去)。请注意,请求的权限范围有一个复选框,默认情况下未被选中。 (从2020年中期到大约一周前,此流程还有另外2个确认步骤,但最后一个复选框默认已被勾选。)

enter image description here

将其与受欢迎的应用程序 Fantastical 的 OAuth 流程进行比较(包括 Spark 在内的许多其他应用程序看起来都很相似):

enter image description here

在发现链接到Google博客上的这篇文章StackOverflow答案后,似乎有一些应用程序被纳入了第二个流程,但第一个流程是新默认值。有两个问题:

  1. 复选框默认情况下未选中似乎是最近的更改,我找不到任何有关它的文档。 它是否是新的默认行为,还是OAuth流程中有参数/其他内容可以更改以使其默认选中? 当它未选中时,用户会认为他们不需要选中它,所以他们点击继续,然后我们的应用程序必须抛出错误并向用户解释他们需要检查该范围复选框。这似乎有点疯狂,因为现在复选框未选中,而这是我明确要求的作用域…这是整个流程的重点。

有没有办法使我们的OAuth流程与早期的那些更简单的流程(如Fantastical、Spark和任何其他在2018年之前创建的OAuth应用程序)保持一致?或者是否有一个时间表,让这些“祖传”的应用程序过渡到新的流程?上面提到的Google博客文章表示,新的流程将在“2019年初向现有客户端扩展”,所以我们已经超时了大约2.5年。目前的情况是,它让“新”的OAuth应用程序(我们的应用程序是在2019年创建的,所以并不算新...)处于极不利的位置,因为它需要更多步骤,需要明确的同意,更容易出现用户错误,并且因为该流程与用户已经习惯使用的许多其他应用程序不同,所以似乎我们的应用程序并没有受到足够的审查或“安全”保障。
这已经是一个问题几个月了,所以我也发布这篇文章来帮助处于同样境地的其他人。以下是其他一些可能对某些人有用的要点:
- 如果我从那个Fantastical流程中获取client_id和redirect_url,并在我们应用程序的链接中使用它们,那么流程看起来就和他们的一样。所以它似乎是由客户端ID驱动的,而不是URL或我们流程中发生的某些事情。 - 我们的应用程序已经通过了Google的第三方安全评估,并且通过了,所以很可能与我们请求的范围或我们应用程序在批准过程中的状态无关。
  • 我们的流程和Fantastical都在webview中进行,因此它们不太可能与一个是本地应用程序,另一个是webview有关。

  • 这种情况发生在我们请求的几个不同范围内,因此它不太可能与我们请求的范围有关(例如Fantastical的范围比我们的流程中的gmail.metadata范围更为广泛/严格)。


  • 1
    你已经找到解决方案了吗? - Victor Buldakov
    1
    据我所知,这是在过去1-2年中创建的OAuth应用程序的更改行为,而在此之前创建的应用程序/密钥将被纳入其中,并最终过渡到这种新流程。@VictorBuldakov 不行。 - zzz
    我也遇到了同样的问题。你找到解决这个问题的方法了吗? - Sandhiya
    据我所知,@Sandhiya,目前还没有解决方案,不幸的是。 - zzz
    3个回答

    5

    在我的情况下(安卓应用程序),当请求授权范围时,禁用的复选框会与登录选项同时出现。

    我通过将登录和授权请求分为两个步骤来避免这种情况,如下所示:

    首先,仅使用 requestEmail 选项进行登录。对于用户而言,这是一个对话框,他们可以在其中选择帐户,但它已经授予基本内容(个人资料、电子邮件和 openid):

    GoogleSignInOptions options =
            new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                    .requestEmail()
                    .build();
    
    GoogleSignInClient signInClient =
            GoogleSignIn.getClient(context, options);
    
    signInClient
            .addOnCompleteListener(task -> {
                signInLauncher.launch(signInClient.getSignInIntent());
            });
    

    稍后,在处理登录结果时,请求额外的权限范围(在我的情况下是Google Drive),并再次包含电子邮件权限
    GoogleSignIn.requestPermissions(
            this,
            requestCode,
            account,
            emailScope, driveScope);
    

    重复请求电子邮件权限很重要,因为否则在权限请求返回时它将为空。但是,由于在登录时已经授予了该权限,它不会显示在复选框上。
    Google的文章末尾所指出的,“profile”,“email”和“openid”在登录时是允许的。
    感谢Max在对这个回答的评论中指出了这种方法。

    这样做不意味着您会得到3个不同的对话框吗?意思是:1.从列表中选择帐户2.授予基本权限(电子邮件,服务器授权码)。 3.范围?在Android上,这就是我得到的。确实有助于解决复选框未被选中的问题(实际上它们对于#2被禁用并且对于#3不存在),但这也意味着用户需要3个步骤... - android developer
    @androiddeveloper 在我的情况下,我只得到了两个对话框:1. 选择帐户,已经授予基本权限。2. 范围(我只请求Google Drive访问作为附加范围)。 - jmart
    但是您是否要求获取电子邮件和服务器授权码(或称为其他名称)? - android developer
    1
    @androiddeveloper 我修改了我的答案并包含了代码,这样你就可以看到我正在使用的方法。 - jmart
    起初我以为你是正确的,但在重置Google帐户设置中授予的内容之后,现在它显示了3个对话框,就像我说的那样。但我也使用requestServerAuthCode,而不仅仅是requestEmail。至少没有复选框...此外,在另一个应用程序上,可能是因为它使用了旧的证书,在范围的最后一步上不会显示任何内容(显示立即关闭的内容)。 - android developer
    我认为,对于旧证书来说,结果有点随机。有时会出现两个对话框,有时会出现三个。如果我在没有使用“requestPermissions”的情况下请求所有作用域,是否能看到复选框也是如此。 - android developer

    0
    我最终解决这个问题的方法是通过检查前端的Google oAuth服务器响应。
    在响应中,它包含了一个以空格分隔的字符串,其中列出了用户授权(复选框选中)的范围。
    "scope": "email profile openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/calendar.events"
    

    现在我们可以使用这些信息来查看我们需要的作用域复选框是否存在。
    例如,如果我知道我的应用程序需要https://www.googleapis.com/auth/calendar.events范围,则可以检查响应范围中是否包含该字符串。
    基于此,我可以停止进程并让用户知道他们必须标记复选框并再次呈现同意对话框。
    不确定这是否适用于所有情况,但这是我目前正在使用的解决方案。

    0

    对我有效的方法是设置

    enable_serial_consent: false
    

    但是,正如此处所提到的:

    自2019年之前创建的OAuth客户端ID将禁用更细粒度的Google帐户权限。对于较新的OAuth客户端ID没有影响,因为更细粒度的权限始终对它们启用。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接