当access_type=online时,该应用程序希望:具有离线访问权限。

58

我有一个使用OAuth 2.0认证的Google应用程序。以前一切正常,但最近开始出现以下“请求权限”屏幕:

enter image description here

奇怪的是,当我传递access_type=online时,会出现这个屏幕。同样,这在最近之前都是有效的。

这可能的原因是什么?TIA

编辑:

请求的范围为:

https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/userinfo.profile

我已经尝试过:

  • 使用access_type=online和不使用access_type=online
  • 使用approval_prompt=auto和不使用approval_prompt=auto

编辑#2:

这是我用来生成认证URL的Python代码:

encoded_params = urllib.urlencode({
    "response_type" : "code",
    "client_id" : MY_CLIENT_ID,
    "scope" : " ".join(MY_SCOPES),
    "redirect_uri" : MY_REDIRECT_URI,
    "state" : random_security_token,
    "access_type" : "online",
    "approval_prompt" : "auto",
    })

auth_url = "https://accounts.google.com/o/oauth2/auth?" + encoded_params

更新(10月14日):

即使有了新的权限范围,我仍然会看到同意屏幕。最近,在我使用进行身份验证的新设备上,我又看到了这个屏幕。


你是如何请求oauth2权限的?你有一个可以从Google Drive预先认证启动的应用程序,还是使用API独立运行?如果是后者,你能否将授权代码添加到问题中? - daw
@daw 我正在使用Python手动生成认证URL,请查看我所做的修改。 - Tzach
1
嗯,看起来还不错。我正在请求相同的范围,并在从Google Drive启动时收到此不需要的提示。Google自己正在将“access_type:offline”添加到他们创建的URL中。我想知道是否因为电子邮件地址可以离线使用,所以他们覆盖了访问类型? - daw
1
@Tzach,你解决了你的问题吗?我也遇到了同样的问题,但是找不到解决方案。 - Ioannis Tzikas
2
你的 redirect_url 中包含 "localhost" 吗?我也遇到了这个问题。我将 redirect_url 更改为公共域名地址,到目前为止它已经解决了这个问题。我还没有能够再现这个错误。不确定那是否是真正的解决方法。 - infrared
显示剩余3条评论
9个回答

28

当您的应用程序请求令牌并且用户针对所询问的范围仍有有效的访问或刷新令牌时,我认为G会执行此操作。

解决方案是在完成使用令牌之后(无论是在用户注销登录还是在验证用户之后立即),通过发出此请求来撤销令牌:

https://accounts.google.com/o/oauth2/revoke?token={token}

您无需提供任何应用程序凭据,只需要将令牌作为URL参数提供即可。

(文档在这里:https://developers.google.com/accounts/docs/OAuth2WebServer#tokenrevoke

我遇到了同样的问题,无论使用何种access_typeapproval_prompt值的组合都似乎不能解决它。撤销令牌就是解决的办法。

我不确定如何撤销所有待处理的应用程序令牌,除非您刚好存储了它们。要使用您自己的用户帐户进行测试,您可以在此手动撤销现有的应用程序令牌:

https://security.google.com/settings/security/permissions

4
谢谢!这帮了我省去了很多无用功 :). 你帖子里的最后一个链接解决了问题。 - Shreyas

19

更新:

现在电子邮件的范围是:

email

Legacy Google+ APIs已于2019年3月7日停止使用。您的应用程序以前请求的范围现在可能已被弃用或无效。开发人员应更新其代码,以删除或更新对Google+、Google+ API及任何相关OAuth范围的引用。

来源:https://developers.google.com/+/scopes-shutdown

-- 旧答案 --

Google最近更改了电子邮件的范围。 您应该进行替换。

https://www.googleapis.com/auth/userinfo.email

随着:

https://www.googleapis.com/auth/plus.profile.emails.read 

和:

https://www.googleapis.com/auth/plus.login

然后离线访问应该消失。

另请参阅:

https://developers.google.com/+/api/oauth#email

警告:此范围已弃用。Google将在2014年9月1日之后不再支持此范围。有关详细信息,请参见迁移到Google+登录。

这还改变了接收电子邮件地址的方式:

https://developers.google.com/+/api/auth-migration#email

还要记住,您必须在管理控制台中激活Google+ API才能使其正常工作。


4
好的,谢谢!实际上新的范围应该是emailprofile,因为它们相当于问题中请求的范围。 - Tzach
5
嗯,我将使用“电子邮件配置文件”作为我的范围字符串,但仍然会收到“具有离线访问权限”的权限请求。真正奇怪的是,这只在集成测试中发生,而不是手动操作时。在两种情况下,我都在运行相同的服务器环境并使用相同的谷歌凭据。 - Frank Schwieterman
1
嗯,这很奇怪。对我来说,将"approval_prompt"设置为"auto"有帮助,但我猜你可能已经尝试过了。 - dominik
1
看起来他们仍然会支持userinfo.email,尽管已被弃用(我不再看到那个警告,只有在迁移指南中看到这样的描述:“已弃用但将继续维护并保持向后兼容性。Google将继续使用这些范围生成新的令牌。”) - UpTheCreek
@dominik的建议是正确的。我已经将"approval_prompt"更改为"auto",并且"Have offline access"提示已被禁用。 - mujaffars
显示剩余4条评论

18

在OAuth请求的redirect_url参数中使用http://localhost将导致用户在每次登录后第一次认证时被要求授予离线访问权限。


1
谢谢。这个有文档记录吗?这种行为有原因吗? - Tzach
1
我没有看到。这只是我的试错经验。此外,“localhost”行为在许多问题中都有提到:https://dev59.com/IHrZa4cB1Zd3GeqPzjMS http://stackoverflow.com/questions/28957654/google-keeps-asking-for-consent-for-offline-access-even-after-the-user-has-autho https://dev59.com/UYfca4cB1Zd3GeqPeBWQ?lq=1 - Ian Mackinnon

5

Tzach。为了在第一次登录后不提示同意屏幕,您可能需要将该值传递给以下函数:

$client->setApprovalPrompt("auto");


已经尝试过了,请阅读问题和其他答案。 - Tzach

1
我认为这个问题已经得到了回答,但我现在找不到链接。
简而言之,Google最近对作用域进行了一些更改,以实现增量作用域。其中的一部分变化是,如果您的应用程序导致身份验证提示,但用户已经进行了身份验证,则Google必须请求某些内容,因此会要求离线访问权限。请尝试设置。
approval_prompt=auto

为了避免提示。

1
谢谢,但当我明确要求在线访问时,为什么要请求离线访问的原因?这可能会使用户感到困惑,甚至可能防止他批准访问。 - Tzach
我同意,这个问题已经多次向谷歌提出。在你的情况下,重点是让你的应用程序根本不提示。 - pinoyyid
1
顺便提一下,我已经在请求中加入了 approval_prompt=auto,但仍然会出现提示屏幕。 - Tzach

1
我遇到了同样的问题。尽管我没有进行设置。
access_type=online

然而,据我所知,缺省情况下


access_type 

online 

来自:https://developers.google.com/identity/protocols/OAuth2WebServer

"默认访问方式称为在线访问。"

解决这个问题的方法是移除:

prompt=consent

当然,在第一次操作时仍然需要同意表单,只是现在不再需要请求离线访问的同意表单,这可能会吓走一些潜在用户。

我认为 prompt 参数旨在替换 approval_prompt 参数。但如果我将其设置为“同意”,那应该意味着我希望每次显示正常的同意屏幕,而不是“离线访问”同意屏幕。这里的文档:https://developers.google.com/identity/protocols/OpenIDConnect#prompt似乎没有反驳这种想法,所以我不确定为什么它会以这种方式运作。但至少我现在已经成功按照自己的方式使用了它。


0

嗯,我不知道这是否构成了一个答案,但我发现一些用户看到:

'具有离线访问权限'

与其他人相比(他们得到了我认为你想要看到的):

'查看有关您帐户的基本信息'


问题是,尽管我在过去的某个时候已经批准了该应用程序,但我仍然会看到这个屏幕。就像是额外的批准。 - Tzach
1
也许这与将 approval_prompt 替换为 prompt 有关? - jmazin

-1
你正在使用Google APIs客户端库吗?

https://developers.google.com/api-client-library/

在自己刷新令牌时,它将access_type设置为“离线”

在Python版本中,我更改了oauth2client/client.py的第1204行

    'access_type': 'offline',

    'access_type': 'online',

现在它已经正确地工作。


我没有使用这个库,请参考问题中生成URL的确切代码。 - Tzach

-2

我尝试了这个问题中的所有方法。在我的情况下,只有清除cookies起作用。


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