使用AppEngine、Webapp2和Cloud Endpoints Proto Datastore实现多个身份验证提供程序

5
我正在制作一个Web应用程序,允许用户使用simpleauth进行身份验证。目前,我将支持Google和Facebook。除了登录和注销(使用webapp2),Web应用程序将由Cloud Endpoint API组成。客户端将是Web、Android和iOS。
我的问题是,使用Endpoints Proto Datastore,如果用户的身份验证提供程序是Facebook(或任何其他受支持的OAuth2提供程序),我可以使用user_required=True并调用endpoints.get_current_user()@Model.method中获取我的用户吗?如果不可能,这是否意味着我不应该有user_required=True,而应该从提供程序获取永久用户ID,并将其保存在数据存储中,为该用户生成自己的身份验证令牌,然后将该令牌传递给每个请求?

编辑: 不要在不同的方法之间传递认证令牌,让已认证的用户请求一个“API令牌”,然后将其传递给API方法是否有意义?这个令牌需要包含在POST或GET主体中吗?还是可以放在头/cookie中(我在SO上看到了一些关于云端点的头和cookie的问题,但那是一段时间以前的事情)。假设非Google认证无法工作。

1个回答

2
这篇回答不会直接回答你的问题,但是应该能给你一个好的想法,如何安全地实现身份验证。我最近实现了类似的东西,并花了相当长的时间来确定在Google AppEngine环境中进行身份验证的最佳方法。
Google支持OpenId Connect协议。Facebook的实现应该与Getting Started with OAuth 2.0书中描述的非常相似。我将更多地关注Google的实现,因为我更熟悉它,但是使用其他OAuth提供程序时,概念应该非常相似。
成功验证用户后,OpenId Connect将为您提供一个id_token。它还将为您提供一个访问令牌。访问令牌是应该保密的内容。永远不要通过网络发送它。另一方面,ID令牌非常方便。它包含有关您的用户的一些信息,并且已加密,因此不会“轻易”地暴露任何有关用户的信息。您必须破解id_token才能发现有关用户的任何信息。如果它被破解,也不会暴露关于用户的任何关键信息。您可以将其存储为cookie,然后在所有后续请求中使用它来验证用户,通过检查是否有与id_token匹配的访问令牌。唯一的缺点是id_token非常长,大约需要650字节。这意味着每个http请求都会携带该负载。如果发送那么多信息对于您的用例来说太多了,您可以只发送前几个字符,例如12个字符,然后仅匹配第一部分。 id_token在分析数据时也很有用。当分析http请求时,它将显示出来,但不会透露关于用户的任何信息,并且您仍然可以区分来自不同用户的请求。
此外,顺便提一下,不要尝试使用AppEngine的用户服务,因为它无法很好地与任何类型的自定义身份验证配合使用。
希望这能给你一个想法并让你走上正确的轨道。

谢谢!我的计划是使用第三方服务的唯一用户ID(例如Facebook帐户ID或Google帐户ID)和提供者前缀(例如google:12345),并将其存储在webapp2的用户模型中。然后,我将生成自己的访问令牌,并且只有在需要重新验证时才会返回第三方服务。我的最大问题是如何在云端终端中使用它,而不必手动在每个请求中发送访问(或API)令牌(无论是在正文中还是作为标头),然后必须手动解决终端用户。 - Eliezer
@Eliezer 如果您将其存储为cookie,则它将随每个HTTP请求自动发送。您仍需要在服务器上检查具有该ID(从cookie中检索)的客户端是否被授权进行请求(但是,即使您选择使用Cloud Endpoints文档中提到的Google用户服务,您也必须执行此步骤- https://developers.google.com/appengine/docs/python/endpoints/auth)。 - markovuksanovic
在Java中,您可以设置Servlet过滤器并在其中进行授权检查。我相信Python也有类似的功能。 - markovuksanovic
我不确定是否可以使用Endpoints Proto Datastore访问cookie头(如果可以,那对我来说会方便很多)。我更愿意调用endpoints.get_current_user(),而不是编写代码手动检查令牌是否对该用户有效。我的备选方案是使用注释来处理服务器端的身份验证检查,但我很想听听appengine团队(或确切知道的人)是否存在更优雅的解决方案。 - Eliezer
1
@eliezer 每个http请求都会发送cookie。我相信有一种方法可以访问它。get_current_user将返回User对象,只要您在AppEngine游乐场中停留(使用AppEngines的身份验证服务),它就可以很好地发挥作用。一旦您尝试做更花哨的事情,例如集成Facebook,AppEngine的用户服务就不再那么有用了。您将遇到比收益更多的问题。虽然我也很想听听Google和appengine团队对此问题的看法。 - markovuksanovic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接