我正在尝试在我的应用程序中使用Google Oauth2来实现增量授权。
首先,当用户登录时,应用程序将请求某些作用域和脱机访问。我正在数据库中生成和存储refreshToken,以便在需要时刷新访问令牌以进行API调用。
现在,我将实现一个新的功能,它将请求一个新的作用域,但是只有当用户尝试使用这个新功能时,我才会请求这个作用域。
我面临的问题是,当应用程序促使用户同意新的作用域时,Google请求所有以前接受的作用域的访问权限。
我尝试过不使用离线访问(使用“授予”法),而且它似乎正在工作(正如描述中所说的“向用户请求附加作用域”)。这样做,Google只要求新的范围,生成的访问令牌似乎运行良好。但是如果我尝试使用离线访问(使用“grantOfflineAccess”方法),谷歌会询问所有的作用域。如果我再次接受所有的作用域,它将返回一个授权代码,并且我可以再次生成refreshToken,但是我只想接受新的作用域。
我想知道在请求离线访问时不可能这样做,因为您需要生成一个包含所有作用域的新refreshToken,但是我找不到有关这方面的任何信息。
我是否做错了什么,还是不可能通过离线访问实现这一点?
UPDATE:也生成(而不是使用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=trueUPDATE2:我找到了一个这里报道的问题,有人评论说在安装的应用程序中不可能这样做。但是有一条评论解释了如何使用web服务器流来实现它,下面是使用OAuth2游乐场(https://developers.google.com/oauthplayground)的步骤:
1)选择作用域。 2)授权进入 3)令牌的交换代码。 4)请求令牌信息端点:token=. 5)验证令牌只包含作用域。 6)取消选择作用域并选择Google作用域。 7)在授权窗口中编辑URL并附加&include_granted_scopes=true。 8)授权驾驶范围。 9)将代码交换为令牌。 10)向令牌信息端点发出请求。 11)验证它是否包含日历和驱动器作用域。
同样,我在第一个验证中获得日历作用域,在第二个验证中获得驱动范围。即使使用刷新令牌,我也无法获得两个作用域的访问令牌。在此之后,非常奇怪的是,我检查了访问我的帐户的应用程序,OAuth2操场有两个作用域:

提前谢谢你!
发布于 2018-08-02 17:38:28
我终于完成了使用JS库实现增量授权。使用grantOfflineAccess函数,您可以发送要请求的新范围。默认情况下,当使用include_granted_scopes时,gapi.auth2.authorize是正确的。
所以您只需要发送新的作用域,例如:
GoogleUser.grantOfflineAccess({scope: 'https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/calendar'}然后,您将收到一个用于交换refreshToken的授权代码。您可以通过使用新的access_token生成一个refreshToken并调用令牌信息端点:token=.
我肯定这是我一开始尝试过的事情,所以我想我做错了什么。
无论如何,由于图书馆的问题,我决定不使用增量授权。基本上问题是,为了获得更好的用户体验和避免问题,您应该能够使用prompt: 'consent',这样用户就不需要选择帐户来接受新的作用域。但这是不可能的,如果用户选择不同的帐户来接受应用程序中的不同作用域,则可能会出现问题。
发布于 2021-06-20 19:18:13
谢谢,我也有同样的问题!你的答案帮我解决了这个问题。下面是我们需要用两个库完成的最终工作流。希望这些代码片段可能会有所帮助。
使用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;
})
}有了这个刷新令牌(您应该持久化它),您可以随时使用谷歌越界库创建Google的客户端。
实现增量授权
前端:
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与您的应用程序集成。对于带有Node.js后端的详细工作流,您可能会发现我的精神很有帮助。
https://stackoverflow.com/questions/51495056
复制相似问题