没有 cookie 的 IdentityServer4 外部身份验证

Posted

技术标签:

【中文标题】没有 cookie 的 IdentityServer4 外部身份验证【英文标题】:IdentityServer4 External Authentication without cookies 【发布时间】:2018-12-09 02:35:19 【问题描述】:

我无法理解 ASP.NET Core 身份验证的工作原理。

我想使用刷新令牌实现 JWT 访问令牌身份验证。据我所知,这是验证客户端(移动应用程序、SPA Web 应用程序)的行业标准。出于安全目的,我宁愿不实现自己的授权逻辑,包括 JWT 生成和刷新令牌处理。由于 ASP.Net 本身并不支持这一点,我自然会选择使用 IdentityServer4,这是一个用于处理此类内容的大型开源库。

但是IdentityServer4 很大程度上基于 OAuth,我不确定它如何与 SPA 应用程序和移动应用程序(我信任的客户端)一起使用。它要求客户端重定向到某个任意网页以输入其凭据,然后重定向回应用程序。总的。我从未见过像 Snapchat、Instagram 等主要应用程序具有这种身份验证流程,您在登录流程中会被定向到某些网页/浏览器。幸运的是,IdentityServer4 有一个小功能可以为我信任的客户 (http://docs.identityserver.io/en/latest/quickstarts/2_resource_owner_passwords.html) 处理用户名/密码身份验证

太好了,这似乎符合我的需要。但是...现在我想添加 Facebook 身份验证。 IdentityServer4 允许 External Authentication,但它仍然是基于 cookie 的(据我所知)。这需要 android/ios/SPA 应用程序重定向到网页,然后重定向回应用程序。同样,从用户的角度来看,这并不理想。 Facebook 提供原生移动 SDK 来处理这种类型的身份验证,该身份验证返回访问令牌,因此无需使用 cookie 重定向到网页。

现在假设我的 iOS 应用程序使用 Facebook SDK 为用户获取访问令牌并将其发送到后端。后端根据 Facebook SDK 验证令牌,然后在其自己的数据库中注册本地用户。

现在,当同一个 iOS 用户尝试登录应用程序时,应用程序将从 SDK 为该用户生成一个 facebook 访问令牌并将其发送到后端。但是我不确定如何利用IdentityServer4 为用户生成 JWT,因为我需要该用户的用户名和密码。这就是我卡住的地方。我似乎在与图书馆抗争,这让我相信我严重误解了一些东西。

TLDR; IdentityServer4 似乎很大程度上基于 cookie,当您从身份验证网页来回重定向时,这些 cookie 并不能很好地适应移动应用程序/SPA 网页。我是否使用了错误的工具来完成这项工作?有哪些替代解决方案?

【问题讨论】:

【参考方案1】:

作为大型社交应用的说明:我认为这取决于谁保存了密码。 Facebook、Instagram、Snapchat、Google 充当第三方的身份提供者。他们自己要求用户注册并指定他们保留的密码。因此,他们可以使用任何自定义方法来处理这些密码的验证。但是,如果他们中的任何一个提供了使用另一个登录的可能性,即 Instagram 允许使用亚马逊凭据登录,那么他们将需要遵循 OAuth 之类的标准方式并重定向到第三方进行登录.上次我查看 Instagram、Facebook 和 Snapchat 时只提供注册,而没有选择通过 3rd 登录的选项,这就解释了为什么不需要重定向。

现在,如果我们确定重定向是必要的邪恶,那么跨数据传输的方法就不会那么多了。 IE。我们要么需要通过查询字符串传递数据,要么使用 cookie。我还想念其他人吗?

两者都有局限性,但由于 cookie 是持久化的,并且浏览器会在每个请求中自动携带它们,因此它们似乎是该工作的更好选择,尤其是在外部 IdP 需要多次重定向以跟踪身份验证请求的状态时。这里提到了同样的原因:

http://docs.identityserver.io/en/latest/topics/signin_external_providers.html

【讨论】:

【参考方案2】:

如果您想要 OpenID Connect 和 OAuth2 为您提供的功能,它绝对是适合这项工作的工具。听起来您可能需要令人信服,而且您的用例可能不需要提供的全部功能。

如果您有多个客户端应用程序和 API,那么我认为此时使用 OpenID Connect 和 IdentityServer4 是正确的选择。

关于原生应用程序,您曾经使用“严重”一词来描述使用用户的默认浏览器执行登录过程,这可以理解为什么您一开始可能会这么想,但它并不像您想象的那样糟糕并且有很多优点:

    客户端应用程序与身份验证的实际完成方式完全分离,即联合身份验证、社交登录(在您的情况下为 Facebook)、多因素、视网膜扫描等。您的身份服务器处理所有这些复杂性,并且是单点管理(和失败 - 所以让它高度可用!) 单点登录是可能的 - 如果他们已经登录到您的 IDP,那么他们可以直接进入(尽管您可以完全控制流程 - 希望他们每次都同意或确认登录请求 - 您可以这样做那个) 如果用户在浏览器中设置了密码管理器,那么它也可以工作

iOS 和 Android 都提供 API 来完成这些工作,并且运行良好。如果您的原生 UI 和 Web UI 看起来很相似,那么来自用户 PoV 的流程就不会很不和谐。

您仍然可以使用刷新令牌(最终由平台保护),因此您实际上不必经常进行交互流程。

下面的一些附加阅读。业界对此进行了很多思考,因此绝对值得消化当前的最佳实践。

https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html

IETF 当前最佳实践:https://www.rfc-editor.org/rfc/rfc8252

不要让 Scott 恨你;):https://www.scottbrady91.com/OAuth/Why-the-Resource-Owner-Password-Credentials-Grant-Type-is-not-Authentication-nor-Suitable-for-Modern-Applications

对于客户端 SPA 浏览器应用,OIDC 提供隐式授权类型并使用静默刷新和 IDP 会话监控机制来维护会话。查看实现此方法的 oidc-client-js 库。

【讨论】:

您提到“但它并不像您想象的那样糟糕,并且有很多优势”。就个人而言,我不介意浏览器流程,但是当我查看大型应用程序(如 instagram、snapchat、facebook 等)时,这些应用程序都不会首先重定向到浏览器。你说它的“最佳实践”,但没有一个主要的应用程序重定向到浏览器,所以这就是我无法理解的。这些人是怎么做到的? 我不能真正代表大型社交应用程序,因为我来自业务应用程序 PoV 以及随之而来的所有要求。至于如何他们这样做 - 可能他们使用平台功能回家滚动东西 - 可能使用类似于引擎盖下的刷新令牌的东西。

以上是关于没有 cookie 的 IdentityServer4 外部身份验证的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的“Set-Cookie”响应标头没有被翻译成实际的 cookie?

没有设置安全标志和 HttpOnly 标志的 Cookie

没有 cookie 的安全会话管理

切换状态 Cookie 设置成功,但是没有 cookie 存在时的行为呢?

没有 cookie 的 Laravel 会话

为啥我的 cookie 设置没有被应用?