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


73

假设我有一个Web应用程序,需要在后台服务中访问云端硬盘文件。它要么拥有要访问的文件,要么在所有者共享文件的Google帐户中运行。

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

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

Answers:


147

可以通过https://developers.google.com/oauthplayground上的Oauth2游乐场来完成。

脚步:-

  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然后选择Web application
  4. 包括https://developers.google.com/oauthplayground作为有效的重定向URI
  5. 注意客户端ID(Web应用程序)和客户端密钥
  6. 以my.drive.app@gmail.com身份登录
  7. 前往Oauth2游乐场
  8. 在设置(齿轮图标)中,设置
    • OAuth流程:服务器端
    • 访问类型:离线
    • 使用您自己的OAuth凭据:
    • 客户编号和客户机密:从步骤5开始
  9. 点击第1步,然后选择Drive API v3 https://www.googleapis.com/auth/drive(尽管如此,该技术也适用于所列的任何Google API)
  10. 单击授权API。系统将提示您选择您的Google帐户并确认访问权限
  11. 单击步骤2和“交换令牌的授权代码”
  12. 复制返回的Refresh令牌,并将其粘贴到您的应用程序,源代码中或粘贴到某种形式的存储中,您的应用程序可以从中获取它。

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

注意 请注意,刷新令牌可能已由Google过期,这意味着您需要重复执行第5步才能获得新的刷新令牌。症状是当您尝试使用刷新令牌时返回了无效授权。

NB2。如果您想让一个Web应用程序访问您自己的(并且只有您自己的)Drive帐户,而又不用费心编写只会运行一次的授权代码,则该技术很好用。只需跳过第1步,然后在第6步中用您自己的电子邮件地址替换“ my.drive.app”,请确保您知道刷新令牌被盗后的安全隐患。

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

。。。

这是一个快速的JavaScript例程,显示了如何使用OAuth Playground中的刷新令牌列出一些云端硬盘文件。您可以简单地将其复制粘贴到Chrome开发者控制台中,或通过node运行它。当然,请提供您自己的凭证(以下所有凭证均为伪造的)。

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

6
请注意,我的研究表明,刷新令牌是“长期存在的”令牌,不会被Google过期,但是可以在API控制台上撤销。此外,Google播放了一段短短4分钟的视频,介绍如何从Playground获取刷新令牌:youtube.com/watch?v=hfWe1gPCnzc
woody

2
实际上,如果您还编写了一个单独的设置页面,该页面通过询问管理员权限来生成刷新令牌,则它会更清洁。管理员使用该页面来部署应用程序或稍后重新配置。使用oauth Playground是避免编写此类管理页面的快速方法。
Zig Mandel

13
实际上,如果您根本不编写任何代码,它会干净得多。为什么要花数小时而不是数天来弄清楚OAuth,对Google库的泄漏抽象进行处理,而对于只运行一次的应用程序全都浪费呢?这不是干净的,是临界的疯狂。
pinoyyid 2015年

1
在哪里执行第3步?V2也没有出现。将在Drive V3上尝试
丹尼尔(Dan)

6
这是有史以来最好的答案。如果可以的话,我给它十票。您只是使oauth精神错乱是可以忍受的。谢谢!
mga

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。我推荐失眠,因为它可以让您轻松通过同意屏幕。

使用以下参数构建一个新的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编码,请确保正确使用它。

在您发出请求之前,请设置一个Web服务器以进行监听http://localhost:8080。如果您安装了node和npm run 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内置Web服务器php -S localhost:8080

现在触发您的请求(在Insomnia中),并提示您输入登录名:

登录提示

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

返回您的终端并检查输出。如果您记录了整个内容,请向下滚动(例如pgdown),直到看到带有的行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

同样,请确保编码正确。

触发您的请求并检查服务器的输出。在响应中,您应该看到一个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时犯了一个错误
。– pinoyyid

可能可以,但是我无法发现错误。如果游乐场也处于关闭/不可达状态,则非游乐场路径可能很有用。
m02ph3u5
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.