当前位置: 首页 > 知识库问答 >
问题:

Google OAuth 2.0-离线访问的增量授权

乐正远航
2023-03-14

我试图在我的应用程序中使用Google Oauth2实现增量授权。

起初,当用户登录时,应用程序正在请求一些范围和脱机访问。我正在数据库中生成和存储刷新令牌,以便在需要时刷新访问令牌以进行API调用。

现在我要实现一个新功能,它将请求一个新的作用域,但我只想在用户尝试使用这个新功能时请求这个作用域。

我面临的问题是,当应用程序提示用户同意新范围时,谷歌正在请求访问所有以前接受的范围。

我尝试过不使用脱机访问(使用“grant”方法),它似乎起到了作用(正如描述中所说的“向用户请求额外的作用域”)。这样一来,谷歌只需要申请新的作用域,生成的访问令牌似乎工作正常。但如果我尝试离线访问(使用“GrantofLeaceAccess”方法),谷歌会要求提供所有范围。如果我再次接受所有作用域,它会返回一个授权码,我可以再次生成refreshToken,但我只想接受新的作用域。

我想知道,当请求脱机访问时,可能无法执行此操作,因为您需要生成一个包含所有作用域的新refreshToken,但我找不到有关此操作的任何信息。

我是做错了什么,还是无法通过离线访问实现这一点?

更新:同样生成URL(而不是使用JS库),如本文所述,谷歌要求提供所有范围。这是生成的URL的一个示例:

https://accounts.google.com/o/oauth2/v2/auth?
  scope=my_new_scope&
  redirect_uri=https://myapp.example.com/callback&
  response_type=code&
  client_id=my_client_id&
  prompt=consent&
  include_granted_scopes=true

更新2:我在这里发现了一个报告中的问题,有人评论说,不可能对已安装的应用程序执行此操作。但是有一条注释解释了如何使用html" target="_blank">web服务器流,这些是使用OAuth2的步骤(https://developers.google.com/oauthplayground):

1) 选择谷歌日历范围。

2) 授权访问

3) 把代码换成令牌。

4)向令牌信息终结点发出请求:https://www.googleapis.com/oauth2/v2/tokeninfo?access_token=...

5) 验证令牌是否仅包含Google日历范围。

6)取消选择谷歌日历范围,选择谷歌驱动器范围。

7) 在授权窗口中编辑URL并附加

8)授权驱动器范围。

9)用代码交换令牌。

10) 向令牌信息endpoint发出请求。

11)验证它是否包含日历和驱动器范围。

做同样的事情,我在第一个验证中得到日历范围,在第二个验证中得到驱动范围。即使使用刷新令牌,我也无法获得两个范围的访问令牌。在那之后,这很奇怪,我检查了可以访问我的帐户的应用程序,OAuth2 playground有两个作用域:

提前谢谢!

共有2个答案

慕震博
2023-03-14

谢谢,我也有同样的问题!你的回答帮助我弄明白了。下面是我们需要用两个库完成的最后一个工作流程。希望代码片段可能会有所帮助。

  1. 使用Google登录(google-auth库)进行身份验证以获得刷新令牌。
  2. 实现增量授权:授权您的应用程序使用其信息将其与新的Google API集成。例如,谷歌日历(google-auth库和googleapis)

通过Google登录进行身份验证以获取刷新令牌

前端:

$('#signinButton').click(function() {
   auth2.grantOfflineAccess().then(signInCallback);
 });

后端:

const { OAuth2Client } = require('google-auth-library');

/**
* Create a new OAuth2Client, and go through the OAuth2 content
* workflow. Return the refresh token.
*/
function getRefreshToken(code, scope) {
  return new Promise((resolve, reject) => {
    // Create an oAuth client to authorize the API call. Secrets should be 
    // downloaded from the Google Developers Console.
    const oAuth2Client = new OAuth2Client(
      YOUR_CLIENT_ID,
      YOUR_CLIENT_SECRET,
      YOUR_REDIRECT_URL
    );

    // Generate the url that will be used for the consent dialog.
    await oAuth2Client.generateAuthUrl({
      access_type: 'offline',
      scope,
    });
    
    // Verify the integrity of the idToken through the authentication 
    // code and use the user information contained in the token
    const { tokens } = await client.getToken(code);
    const ticket = await client.verifyIdToken({
      idToken: tokens.id_token!,
      audience: keys.web.client_secret,
    });
    idInfo = ticket.getPayload();
    return tokens.refresh_token;
  })
}

有了这个刷新令牌(您应该将其持久化),您可以随时使用googleapis库创建Google API的客户端。

实现增量授权

前端

const googleOauth = gapi.auth2.getAuthInstance();
const newScope = "https://www.googleapis.com/auth/calendar"

googleOauth = auth2.currentUser.get();
googleOauth.grantOfflineAccess({ scope: newScope }).then(
    function(success){
      console.log(JSON.stringify({ message: "success", value: success }));
    },
    function(fail){
      alert(JSON.stringify({message: "fail", value: fail}));
    });

后端:

const { google } = require('googleapis'); 

// Create an oAuth client to authorize the API call. Secrets should be 
// downloaded from the Google Developers Console.
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

client.setCredentials({ refresh_token: refreshToken });

就这样!您可以使用该客户端将任何Google API与应用程序集成。查看带有节点的详细工作流。js后端,你可能会发现我的要点很有帮助。

束俊材
2023-03-14

我终于使用JS库实现了增量授权。使用grantoflineaccess函数,您可以发送想要请求的新作用域。默认情况下,当您使用gapi时,include_grated_scopes为true。auth2。批准

所以你只需要发送新的作用域,例如:

GoogleUser.grantOfflineAccess({scope: 'https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/calendar'}

然后,您将收到一个用于交换刷新令牌的授权码。通过使用新的refreshToken生成一个access_令牌并调用令牌信息endpoint,可以检查一切是否正常:https://www.googleapis.com/oauth2/v2/tokeninfo?access_token=...

我肯定这是我一开始试过的,所以我猜我做错了什么。

无论如何,由于库的问题,我决定不使用增量授权。基本上,问题是,为了更好的用户体验和避免问题,您应该能够使用提示:“同意”,这样用户就不需要选择一个帐户来接受新的范围。但是这是不可能的,如果用户选择不同的帐户来接受应用程序的不同范围,您可能会遇到问题。

 类似资料:
  • 我试图使用VBScript和Oauth脱机访问谷歌日历API。我设法获得了一个刷新令牌和一个访问令牌,现在我想进入实际使用API的步骤,使用以下代码: 我得到的回应是: 即使访问令牌是有效的--如果我将sURL更改为https://www.googleapis.com/oauth2/v1/tokeninfo并运行该脚本,我将得到以下响应,显示一个有效的令牌: 如果我粘贴URL https://ww

  • 我正在尝试使用Google OAuth2 api获取用户的配置文件。用户身份验证后,在同意页面上,我总是被要求“离线访问” 浏览器中的网址如下所示:- https://accounts.google.com/o/oauth2/auth?scope=email 如上面的URL中可见,我已将范围参数传递为“电子邮件” Google Auth API页面说:- “此范围要求您的应用程序能够访问: 用户的

  • 我正在使用<code>Microsoft.Owin.Security。Google(版本)middlware为我的应用程序提供Google OAuth。 它的配置如下: 非常简单的东西。我使用身份服务器作为MW来发出声明。 这是完全有意义的,因为我在URL中请求作用域: https://accounts.google.com/o/oauth2/auth?scope=openid简介邮件 然后我接受

  • 这是我之前问题的后续:如何从远程服务器访问Google Drive应用程序数据? 我有一个需要访问Google Drive AppFolder的应用程序,包括客户端(在线、JavaScript)和服务器端(离线、Python)。我的应用程序是独一无二的,因为客户端和服务器可能无法通过原始身份验证进行通信。 因此,我使用下面的代码来获取服务器的auth令牌(启动客户端): 服务器存储包括刷新令牌在内

  • 我正在尝试使用Google API获得<code>离线访问</code>。我必须从谷歌日历中提取数据,而无需用户每次登录。 我已将以下内容添加到我的 Gem 文件中: https://accounts.google.com/o/oauth2/auth?access_type=offline 我错过什么了吗?

  • 问题内容: 我正在为基于Web的幻灯片显示构建应用程序,其中一个“主”用户可以在幻灯片之间移动,每个人的浏览器都可以跟随。为此,我使用websockets和Redis作为全局通道来发送消息。每个连接的客户端都将信息存储在数组中。然后,我有一个单独的线程用于订阅Redis通道,其中定义了一个“ on.message”块,该块应将消息发送给数组中的每个人,但是该数组在此块内为空(在该块中的其他任何地方