我正在使用OAuth2身份验证,我有一个拥有多个用户的CMS,每个用户都有自己的配置文件。我们公司的Google帐户可以访问多个Google Analytics帐户。对于使用CMS的每个用户,我使用不同的用户名连接到Google AnalyticsAPI,每个用户的令牌都保存在数据库数据存储中。问题是,如果一个用户断开连接并撤消其令牌,则使用相同Google帐户的其他任何用户都无法访问Analytics API,这没有任何意义。
编辑:经过进一步调查,我发现当第一个用户进行身份验证时,保存在数据存储中的令牌包含'refresh_roken'和'access_token'。但是,当其他用户进行身份验证时(他们使用相同的Google帐户,但使用不同的Google Analytics帐户),他们的令牌只会包含“access_token”。如果其中一个人撤销了他的令牌,他们就会失去联系。
如何阻止这种情况发生并让每个用户都收到自己的refresh_token?
编辑2:
我在数据存储中存储单独的行,每个用户一个。让我澄清一下 - 如果你看一下this diagram,想象一个CMS,其中一个CMS用户需要查看“Liz的个人帐户”中的统计信息,另一个CMS用户需要查看“Liz团队帐户”的统计信息。
两个CMS用户都来自同一家公司,他们都使用相同的Google帐户 - “liz@gmail.com”。 CMS用户A使用“liz@gmail.com”连接到Analytics API,收到refresh_token并想查看“Liz的网站”的统计信息。然后CMS用户B也使用“liz@gmail.com”连接到Analytics API,但现在他不再收到refresh_token,只有access_token - 这是一个问题,因为在access_token之后将再次要求用户连接到期。
当一个用户断开连接时我通常做的是从数据存储中删除令牌并撤销令牌,但是我可能不应该撤销它,是吗?在任何情况下,如果在我的场景中用户A断开连接,这将删除他的数据存储令牌,这意味着我们将不再存储refresh_token,因为用户B首先没有它。
用户帐户图:
答案 0 :(得分:5)
我认为您需要检查databaseDatastore。如果操作正确,您的数据库数据存储区应该为代码中userName
标识的每个用户存储refreshTokens。
当新用户进行身份验证时,您应该在数据库中为它们插入新行。
// New User we insert it into the database
string insertString = "INSERT INTO [dbo].[GoogleUser] ([username],[RefreshToken],[Userid]) " +
" VALUES (@key,@value,'1' )";
然后,当您想再次访问它时,您应该再次通过用户名
选择它using (SqlCommand command = new SqlCommand("select RefreshToken from GoogleUser where UserName = @username;", myConnection))
如果由于某种原因它不起作用,那么你应该只删除这一个用户。几乎听起来如果一个身份验证失败,你将全部删除它们。
// Deletes the users data.
string deleteString = "delete [dbo].[GoogleUser] from " +
" where username = @key";
如果没有看到你如何实现databasedatastore,我无法提供更多帮助,但这是我的databasedatastore.cs
版本<强>更新强>
如果您只访问单个Google Analytics帐户,则应使用服务帐户。
更新以响应您的更新
您需要查看我的数据库数据存储区。但严重的是,您不应该有多个用户使用相同的Gmail帐户。
第一步:
用户liz@gmail.com登录到您的应用程序验证应用程序,应使用refreshtoken将一行插入您的数据库用户名liz@gmail.com。您的数据库广告应该处理保存它。
当访问令牌到期时假设您已正确创建数据库缓存,它将使用refreshtoken自动获取用户名liz@gmail.com的新访问令牌。
第2步:
其他人使用liz@gmail.com登录,数据库数据存储检查数据库中的用户名liz@gmail.com并获取与liz@gmail.com关联的刷新令牌并请求新的访问令牌。
您不应该从数据库中删除刷新令牌或用户,除非由于某种原因它不起作用。如果用户访问Google帐户并撤消您的访问权限,则可能无效。应该只有一个用户名liz@gmail.com和与之关联的刷新令牌。
服务帐户是一种不需要用户对其进行身份验证的身份验证。它的工作原理是在开发者控制台中创建服务帐户身份验证,然后将电子邮件地址添加到Google分析管理员,就像您将其他任何用户一样。现在,服务帐户可以直接访问Google Analytics(分析)帐户,就像用户一样。
然后,您的应用程序从API请求数据,而不提示用户访问。您可以显示Liz,Jim并起诉所有数据,而不要求他们进行身份验证。
答案 1 :(得分:0)
您描述了预期的行为。如果您只是意味着用户断开连接(不撤消应用权限),请尝试将access_type设置为&#34;离线&#34;。
&#34; Google Analytics帐户&#34;和#34; Google帐户&#34;。您可以将分析API身份验证为Google帐户。
附加说明:
他们使用相同的Google帐户,但使用不同的Google Analytics帐户
Google Analytics使用Google帐户登录。也许你的意思是不同的配置文件?
如果一个用户断开连接并撤消其令牌,那么使用相同Google帐户的其他任何用户都无法访问Analytics API,这没有任何意义
如果您的应用已撤消Google帐户的权限,则您的应用将无法再访问。不存在&#34; Google Analytics帐户&#34; - 您使用Google帐户登录Google Analytics。通过身份验证后,您的应用就可以访问Google帐户所执行的所有Google Analytics配置文件/属性。
首次通过oauth身份验证时,您会收到该Google帐户的访问权限和刷新令牌(如您所见)。除非他们在安全中心应用程序权限中删除您的应用程序,然后再次完成oauth,否则您将无法为同一个Google帐户收到另一个用户。
答案 2 :(得分:0)
我认为你需要让refreshToken再次存储在不同的表而不是用户依赖表中。您可以使用以下方法再次获取刷新令牌:
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
现在使用刷新令牌对用户进行身份验证,每次获取新的访问类型以获得用户相关令牌并将其存储在会话或数据库中。并且每次在使用之前进行交叉检查是否已过期以及是否已过期,然后再次使用刷新令牌获取访问令牌。
$client->refreshToken('stored refresh token');
希望它会有所帮助。请注意,这是PHP脚本语法,因此要使用https://developers.google.com/api-client-library/
编程语言答案 3 :(得分:0)
您可以要求Google向该范围添加有关该帐户的其他信息以解决此问题。我建议添加profile
,因为它不需要为用户提供任何其他提示,并且会为Google帐户(而不是Google Analytics帐户)提供唯一的ID。使用OAuth2 Ruby gem,您的最终请求可能如下所示:
client = OAuth2::Client.new(
ENV["GOOGLE_CLIENT_ID"],
ENV["GOOGLE_CLIENT_SECRET"],
authorize_url: "https://accounts.google.com/o/oauth2/auth",
token_url: "https://accounts.google.com/o/oauth2/token"
)
# Configure authorization url
client.authorize_url(
scope: "https://www.googleapis.com/auth/analytics.readonly profile",
redirect_uri: callback_url,
access_type: "offline",
prompt: "select_account"
)
请注意,示波器有两个以空格分隔的条目,一个用于对Google Analytics的只读访问,另一个只有profile
,这是一个OpenID Connect标准。
这会导致Google在id_token
响应中提供名为get_token
的附加属性。值得注意的是,如果您更改范围,您将再次为已经使用原始范围进行身份验证的用户获取刷新令牌。如果您已经有很多用户并且不想让他们全部取消Google中的应用,那么这非常有用。 ;)
要从Google文档中的id_token,check out this page中获取信息。最终,您希望使用自那个唯一的每个帐户提供的sub
参数。
哦,还有一个最后的注意事项:您不需要 prompt=select_account
,但它对您的用户可能需要进行身份验证的这些类型的情况非常有用多个Google帐户(即您未使用此帐户进行登录/身份验证)。