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

pin*_*yid 62 google-api google-drive-api google-oauth gmail-api

假设我有一个需要在后台服务中访问Drive文件的Web应用程序.它将拥有自己正在访问的文件,或者在所有者共享文档的Google帐户中运行.

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

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

pin*_*yid 123

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

脚步:-

  1. 创建Google帐户(例如my.drive.app@gmail.com) - 如果您使用的是现有帐户,请跳过此步骤.
  2. 使用API​​控制台注册mydriveapp(https://console.developers.google.com/apis/credentials/oauthclient?project=mydriveapp或仅https://console.developers.google.com/apis/)
  3. 创建一组新凭据(Credentials/Create Credentials/OAuth Client Id 请勿 NB Web application,然后从选择中选择"Web应用程序")
  4. https://developers.google.com/oauthplayground包含为有效的重定向URI
  5. 请注意客户端ID(Web应用程序)和Client Secret
  6. 以my.drive.app @gmail.com身份登录
  7. 去Oauth2游乐场
  8. 在"设置"(齿轮图标)中,进行设置
    • Oauth流程:服务器
    • 访问类型:离线
    • 使用您自己的OAuth凭据:TICK
    • 客户端ID和客户端密钥:从步骤5开始
  9. 点击第1步,然后选择云端硬盘API https://www.googleapis.com/auth/drive(尽管如此,此技术也可用于列出的任何Google API)
  10. 单击"授权API".系统会提示您选择自己的Google帐户并确认访问权限
  11. 单击步骤2和"交换令牌的授权代码"
  12. 复制返回的刷新令牌并将其粘贴到您的应用程序,源代码或应用程序可以从中检索它的某种形式的存储中.

您的应用现在可以无人值守运行,并使用https://developers.google.com/accounts/docs/OAuth2WebServer#offline所述的刷新令牌来获取访问令牌.

NB.请注意,Google可以过期刷新令牌,这意味着您需要重复步骤5以获得新的刷新令牌.当您尝试使用刷新令牌时,此症状将是返回的无效授权.

NB2.如果您想要一个可以访问您自己的(并且只有您自己的)云端硬盘帐户的网络应用程序,而无需编写只能运行一次的授权代码,这种方法效果很好.只需跳过步骤1,并在步骤6中将"my.drive.app"替换为您自己的电子邮件地址.确保您知道刷新令牌被盗后的安全隐患.

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

...

这是一个快速JavaScript例程,演示如何使用OAuth Playground中的Refresh Token列出一些Drive文件.您只需将其复制粘贴到Chrome开发者控制台,或者使用节点运行它.当然提供你自己的凭据(下面的都是假的).

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();
Run Code Online (Sandbox Code Playgroud)

  • 实际上,如果你根本不编码任何东西,那就更清洁了.为什么浪费时间,如果没有几天找出OAuth,争论谷歌图书馆的漏洞抽象,所有的一个应用程序,你只会运行一次?这不是很干净,它的边缘疯狂. (10认同)
  • 请注意,我的研究表明刷新令牌是"长期存在的"并且未被Google过期,但可以在API控制台上撤消.此外,谷歌还有一个关于如何从Playground获取刷新令牌的短片4分钟视频:https://www.youtube.com/watch?v = hfWe1gPCnzc (6认同)
  • 这是有史以来最好的答案.如果可以,我会给它十票.你只是让oauth精神错乱可以忍受.谢谢! (4认同)
  • 实际上,如果您还通过向管理员请求权限来编写生成刷新令牌的单独设置页面,那么它会更加清晰.管理员使用该页面来部署应用程序或稍后重新配置.使用oauth游乐场只是避免编写此类管理页面的快捷方法. (2认同)
  • @joe你可能是对的。我快速阅读了一下,似乎 Google 忘记了处理 OAuth 用于个人应用程序的用例。我已经更新了答案。 (2认同)

m02*_*3u5 6

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

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

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

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

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

截图(德语):

OAuth 源/重定向设置

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

现在您可能想要使用 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
Run Code Online (Sandbox Code Playgroud)

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

在您发出请求之前,请设置一个网络服务器来侦听http://localhost:8080. 如果您安装了 node 和 npm run npm i express,则创建一个index.js

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
Run Code Online (Sandbox Code Playgroud)

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

现在触发您的请求(在 Insomnia 中),您应该会收到登录提示:

登录提示

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

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

复制该代码;这是您想要交换访问和刷新令牌的授权代码。不要复制太多 - 如果有 & 号,&请不要复制它或之后的任何内容。&分隔查询参数。我们只想要code.

现在成立了一个HTTP POST请求指向https://www.googleapis.com/oauth2/v4/token形式的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
Run Code Online (Sandbox Code Playgroud)

再次确保编码正确。

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

{
  "access_token": "xxxx",
  "expires_in": 3600,
  "refresh_token": "1/xxxx",
  "scope": "https://www.googleapis.com/auth/drive.file",
  "token_type": "Bearer"
}
Run Code Online (Sandbox Code Playgroud)

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

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

OAuthing快乐!

  • 问题是 Google OAuth 2.0 要求您将项目指定为“测试”或“已发布”。为“测试”项目颁发的 OAuth 2.0 令牌的有效期仅为一周,之后用户必须再次完成 OAuth 同意流程。为“已发布”项目颁发的 OAuth 2.0 令牌是永久性的,但发布需要将您的项目提交给 Google 进行审核和批准,并附上视频和安全政策的书面解释……等等。总之,Google 搞砸了它的项目。为普通用户提供的整个服务和 API 在功能上对我们不可用。 (9认同)