ChatGPT解决这个技术问题 Extra ChatGPT

如何在没有用户干预的情况下授权应用程序(Web 或已安装)?

假设我有一个需要在后台服务中访问云端硬盘文件的网络应用程序(“mydriveapp”)。它要么拥有正在访问的文件,要么在所有者与之共享文档的 Google 帐户中运行。

我知道我的应用程序需要一个刷新令牌,但我不想编写代码来获取它,因为我只会这样做一次。

注意。这不是使用服务帐户。该应用程序将在传统的 Google 帐户下运行。在某些情况下,服务帐户是一种有效的方法。然而,使用 Oauth Playground 模拟应用程序的技术可以节省大量冗余工作,并且适用于不支持共享到服务帐户的任何 API。


p
pinoyyid

注意 2022 年 6 月。似乎 Google 已经更新了他们的验证要求,增加了额外的步骤(或否定方法 - 取决于您的观点)。有关更多详细信息,请参阅最近的评论

这可以通过位于 https://developers.google.com/oauthplayground 的 Oauth2 Playground 来完成

脚步:-

创建 Google 帐户(例如 my.drive.app@gmail.com) - 如果您使用现有帐户,则跳过此步骤。使用 API 控制台注册 mydriveapp(https://console.developers.google.com/apis/credentials/oauthclient?project=mydriveapp 或只是 https://console.developers.google.com/apis/)创建一个新的一组凭据。 Credentials/Create Credentials/OAuth Client Id 然后选择 Web application Include https://developers.google.com/oauthplayground 作为有效的重定向 URI 请注意客户端 ID(Web 应用程序)和客户端密码登录为 my.drive.app@gmail。 com 转到 Oauth2 playground 在设置(齿轮图标)中,设置

OAuth 流程:服务器端

访问类型:离线

使用您自己的 OAuth 凭据:TICK

客户端 ID 和客户端密码:从第 5 步开始

单击步骤 1 并选择 Drive API v3 https://www.googleapis.com/auth/drive(话虽如此,此技术也适用于列出的任何 Google API)单击授权 API。系统将提示您选择您的 Google 帐户并确认访问 单击第 2 步和“交换令牌的授权码” 复制返回的刷新令牌并将其粘贴到您的应用程序、源代码或某种形式的存储中,您的应用程序可以从中检索它。

您的应用程序现在可以在无人看管的情况下运行,并使用如 https://developers.google.com/accounts/docs/OAuth2WebServer#offline 所述的刷新令牌来获取访问令牌。

注意。请注意,刷新令牌可能会被 Google 过期,这意味着您需要重复第 5 步以获取新的刷新令牌。当您尝试使用刷新令牌时,这种情况的症状将是返回的无效授权。

NB2。如果您想要一个访问您自己(并且只有您自己)Drive 帐户的 Web 应用程序,而无需编写只会运行一次的授权代码,这种技术非常有效。只需跳过第 1 步,并在第 6 步中将“my.drive.app”替换为您自己的电子邮件地址。确保您了解刷新令牌被盗时的安全隐患。

请参阅下面 Woody 的评论,他在其中链接到此 Google 视频 https://www.youtube.com/watch?v=hfWe1gPCnzc

. . .

这是一个快速的 JavaScript 例程,展示了如何使用 OAuth Playground 中的 Refresh Token 来列出一些 Drive 文件。您可以简单地将其复制粘贴到 Chrome 开发控制台中,或使用 node.js 运行它。当然提供您自己的凭据(以下都是假的)。

function get_access_token_using_saved_refresh_token() {
    // from the oauth playground
    const refresh_token = "1/0PvMAoF9GaJFqbNsLZQg-f9NXEljQclmRP4Gwfdo_0";
    // from the API console
    const client_id = "559798723558-amtjh114mvtpiqis80lkl3kdo4gfm5k.apps.googleusercontent.com";
    // from the API console
    const client_secret = "WnGC6KJ91H40mg6H9r1eF9L";
    // from https://developers.google.com/identity/protocols/OAuth2WebServer#offline
    const refresh_url = "https://www.googleapis.com/oauth2/v4/token";

    const post_body = `grant_type=refresh_token&client_id=${encodeURIComponent(client_id)}&client_secret=${encodeURIComponent(client_secret)}&refresh_token=${encodeURIComponent(refresh_token)}`;

    let refresh_request = {
        body: post_body,
        method: "POST",
        headers: new Headers({
            'Content-Type': 'application/x-www-form-urlencoded'
        })
    }

    // post to the refresh endpoint, parse the json response and use the access token to call files.list
    fetch(refresh_url, refresh_request).then( response => {
            return(response.json());
        }).then( response_json =>  {
            console.log(response_json);
            files_list(response_json.access_token);
    });
}

// a quick and dirty function to list some Drive files using the newly acquired access token
function files_list (access_token) {
    const drive_url = "https://www.googleapis.com/drive/v3/files";
    let drive_request = {
        method: "GET",
        headers: new Headers({
            Authorization: "Bearer "+access_token
        })
    }
    fetch(drive_url, drive_request).then( response => {
        return(response.json());
    }).then( list =>  {
        console.log("Found a file called "+list.files[0].name);
    });
}

get_access_token_using_saved_refresh_token();

请注意,我的研究表明刷新令牌是“长期存在的”并且不会被 Google 过期,但可以在 API 控制台上撤销。此外,Google 有一段 4 分钟的短视频,介绍如何从 Playground 获取刷新令牌:youtube.com/watch?v=hfWe1gPCnzc
实际上,如果您还编写了一个单独的设置页面,该页面通过向管理员询问权限来生成刷新令牌,那么它会更干净。管理员使用该页面部署应用程序或稍后重新配置。使用 oauth 游乐场只是避免编写此类管理页面的一种快速方法。
实际上,如果您根本不编写任何代码,它会更干净。为什么要浪费数小时而不是数天时间来搞清楚 OAuth,争论谷歌库的泄漏抽象,所有这些都是为了一个你只会运行一次的应用程序?这不干净,简直是疯了。
我在哪里执行第 3 步? V2也没有出现。将尝试使用 Drive V3
@fommil 绝对的废话!它不仅有效,我还用一个 JS 片段更新了这个问题来证明它。随意更仔细地遵循这些步骤。只有 webhook 通知需要域验证,OAuth 不需要。
m
m02ph3u5

警告 2022 年 5 月 - 此答案可能不再有效 - 请参阅 David Stein 的评论

让我为 pinoyyid 的出色答案添加一条替代路线(这对我不起作用 - 弹出重定向错误)。

除了使用 OAuthPlayground,您还可以直接使用 HTTP REST API。因此,与 pinoyyid 的答案不同的是,我们将在本地做事。按照 pinoyyid 答案中的步骤 1-3 进行操作。我将引用它们:

创建 Google 帐户(例如 my.drive.app@gmail.com) - 如果您使用现有帐户,则跳过此步骤。使用 API 控制台注册 mydriveapp(https://console.developers.google.com/apis/credentials/oauthclient?project=mydriveapp 或只是 https://console.developers.google.com/apis/)创建一个新的一组凭据(NB OAuth 客户端 ID 不是服务帐户密钥,然后从选项中选择“Web 应用程序”)

现在,而不是游乐场,将以下内容添加到您的凭据中:

授权的 JavaScript 源:http://localhost(我不知道这是否是必需的,但只是这样做。)授权的重定向 URI:http://localhost:8080

截图(德语):

https://i.stack.imgur.com/uStOy.png

确保通过下面的蓝色按钮实际保存您的更改!

现在您可能想要使用 GUI 来构建您的 HTTP 请求。我使用了 Insomnia,但您可以使用 Postman 或纯 cURL。我推荐 Insomnia,因为它可以让您轻松通过同意屏幕。

使用以下参数构建一个新的 GET 请求:

URL: https://accounts.google.com/o/oauth2/v2/auth
Query Param: redirect_uri=http://localhost:8080
Query Param: prompt=consent
Query Param: response_type=code
Query Param: client_id=<your client id from OAuth credentials>
Query Param: scope=<your chosen scopes, e.g. https://www.googleapis.com/auth/drive.file>
Query Param: access_type=offline

如果您选择的工具不能自动处理 URL 编码,请确保自己正确处理。

在您触发您的请求之前,请设置一个网络服务器以侦听 http://localhost:8080。如果您安装了 node 和 npm,请运行 npm i express,然后创建一个 index.js

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('ok');
  console.log(req)
});

app.listen(8080, function () {
  console.log('Listening on port 8080!');
});

并通过 node index.js 运行服务器。我建议不要记录整个 req 对象,或者运行 node index.js | less 以获得巨大的完整输出。
对于其他语言也有非常简单的解决方案。例如在 8080 php -S localhost:8080 上使用 PHP 的内置网络服务器。

现在触发您的请求(在 Insomnia 中),系统会提示您登录:

https://i.stack.imgur.com/EKgyf.png

使用您的电子邮件和密码登录并确认同意屏幕(应包含您选择的范围)。

返回您的终端并检查输出。如果您记录了整个内容,请向下滚动(例如 pgdown in less),直到看到带有 code=4/... 的行。

复制该代码;这是您想要交换访问和刷新令牌的授权代码。不要复制太多 - 如果有一个 & 符号 & 不要复制它或后面的任何东西。 & 分隔查询参数。我们只需要 code

现在将指向 https://www.googleapis.com/oauth2/v4/token 的 HTTP POST 请求设置为 表单 URL 编码。在 Insomnia 中,您只需单击它即可 - 在其他工具中,您可能必须自己将标题设置为 Content-Type: application/x-www-form-urlencoded

添加以下参数:

code=<the authorization code from the last step>
client_id=<your client ID again>
client_secret=<your client secret from the OAuth credentials>
redirect_uri=http://localhost:8080
grant_type=authorization_code

再次确保编码正确。

触发您的请求并检查服务器的输出。在响应中,您应该看到一个 JSON 对象:

{
  "access_token": "xxxx",
  "expires_in": 3600,
  "refresh_token": "1/xxxx",
  "scope": "https://www.googleapis.com/auth/drive.file",
  "token_type": "Bearer"
}

您可以立即使用 access_token,但它的有效期仅为一小时。请注意刷新令牌。这是您始终可以* 交换新访问令牌的一种。

* 如果用户更改密码、撤销访问权限、6 个月不活动等,您将不得不重复该过程。

快乐 OAuthing!


我刚刚仔细检查了我的说明,它们工作正常。如果您遇到问题,则意味着您在 3,4 或 8 处犯了错误。
可能,但我无法发现错误。如果游乐场也关闭/无法到达,非游乐场路径也很有用。
如果范围很多怎么办?我想知道当写了很多范围时,文本看起来如何......
如何在上面的 GET 调用中添加正确编写的多个范围?
问题在于 Google OAuth 2.0 要求您将项目指定为“正在测试”或“已发布”。为“测试”项目颁发的 OAuth 2.0 令牌仅在一周内有效,之后用户必须再次完成 OAuth 同意流程。并且为“已发布”项目颁发的 OAuth 2.0 令牌是永久性的,但发布需要将您的项目提交给 Google 以供审核和批准,并附上视频和对您的安全政策的书面说明……等等。总之,Google 搞砸了为普通用户提供的整个服务和 API 在功能上对我们不可用。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅