【问题标题】:OAuth2 based SSO基于 OAuth2 的 SSO
【发布时间】:2020-11-14 21:58:24
【问题描述】:

我们的项目包含几个子应用程序,我们正在寻找一种解决方案来实现 SSO 以避免每个子应用程序的身份验证。

假设这是我们项目的结构:

authentication server(call it AS or IdP or something else)
order-system
product-system
data-analysis-system
.......

我们发现有很多类似this的“基于OAuth2实现SSO”的文章。

在那篇文章中,我们更喜欢SAML 策略,因为它简单明了,但是对于原生应用程序有一些限制,然后我们专注于 OAuth2。

这是工作流程:

OAuth2 中的 1 条规则

资源服务器 (SP) – 这是您尝试访问的网络服务器 信息。

客户端——这是用户与资源服务器交互的方式。 这可能是基于浏览器的 Web 应用程序、本地移动应用程序、桌面 应用程序,一个服务器端应用程序。

授权服务器 (Idp) – 这是拥有用户的服务器 身份和凭证。这是用户实际验证的人 并授权。

OctoDroid为例,规则很明确:

Client: OctoDroid
Idp: GitHub
SP: Github
User: one who use OctoDroid application.

工作流程是 OctoDroid(Client) 要求你(User) 通过 Github(Idp) 登录并授予权限,以从 Github(SP) 获取资源(repos,issues)。

但是在我们的应用程序中,每个子系统究竟可以处理什么? SPClient

如果被视为SP,网络浏览器是Client吗?我一直认为Client 应该是一个应用程序。并且子系统对每个请求都通过Idp验证access_token,然后返回相关资源,这样会不会增加Idp的压力?

如果被视为ClientSP 是谁?

2 应用规则

对于同一个用户,他在不同的子系统中可能有不同的规则,例如他可以读/写来自order-system的所有订单,但他不能访问product-system。那么规则配置应该发生在哪里呢?在 Idp 中还是在各个子系统中?

3 会话同步

对于一个典型的单点登录系统,当用户登录(通过Idp)时,所有子系统都应该登录,当用户注销时,所有子系统都应该注销。

但是在上述 OAuth2 工作流程中,不同的SPs 或Clients 似乎是独立的。当您从OctoDroid 注销时,您仍然可以在登录后使用OpenHub。在这种情况下,OAuth2 似乎与 SSO 不同,它们如何协同工作?

4 Idp 连接到另一个 Idp

在我们的应用程序中,除了基本的用户名和密码登录之外,身份验证服务器还应提供来自 google、facebook 和其他 CAS 提供商的登录。这可能吗?


顺便说一句,我不确定我是否说得足够清楚,如果没有,请在 cmets 中问我。

【问题讨论】:

  • 服务,它们是自行部署的(即-docker + k8s)还是将Web应用程序部署到服务器(即-weblogic)
  • 每个服务都部署在一个单独的端口上

标签: oauth-2.0 single-sign-on openid-connect


【解决方案1】:

我想加入讨论,并提供一些关于最有效的模式的真实反馈。很多 OAuth 行话没有帮助并且使人们感到困惑。马克 Kavindu 的答案虽然被接受...

第一季度。子系统

软件生产公司通常希望构建一个包含 UI 和 API 的平台。大多数时候,用您的术语来说,UI 是客户端(它们获得令牌),而 API 是子系统(它们接收令牌)。有一些例外,例如后端客户端,但这些往往是次要的。

SAML 是服务器端 Web 应用程序使用的一项旧技术,现在仍用于联合登录。如今,大多数公司都希望构建移动应用程序和基于 Javascript 的应用程序,正如 Kavindu 所说,OAuth 2.x 和 Open Id Connect 更适合这些应用程序 - 与许多库一起使用。

第二季度。规则

这里的一个选项是管理授权服务器中的规则。例如,您可以将 OAuth 自定义范围用作高级权限,然后将其添加到访问令牌并由 API 读取:

  • 订单范围意味着您可以执行订单相关操作
  • 产品 + 写入范围意味着您可以更新产品系统

这对于简单的应用程序来说可能没问题。对于更复杂的应用程序,它不能很好地扩展,并且存在 Order API 的范围/声明开始对 Products API 产生不利影响的风险。

更复杂的规则属于您的 API,它们随着时间的推移更易于管理。这通常涉及从子系统自身数据中的访问令牌中查找用户。

我个人的偏好是使用基于声明的架构来最好地执行规则。如果对这种方法感兴趣,请参阅下面的我的博客文章:

第三季度。会话同步

有时这是一个基于 OAuth 的系统无法按照利益相关者期望的方式运行的领域,人们只需要了解该技术的局限性即可。最终用户不会关心单次注销是否有效,并且您不会通过安全审查。

例如,在移动设备上,退出浏览器 UI 不会让您退出移动 UI。移动 UI 将继续使用短暂的访问令牌,但当访问令牌到期时(可能是 30 分钟后),系统会提示用户再次登录。

第四季度。联邦

大多数授权服务器可以联合到多个身份提供者以支持多种登录类型。在企业界,这通常使用 SAML 2.0 作为协议。您允许哪些提供程序通常取决于您的子系统处理的资产类型:

  • 对于公司资产,您不允许用户使用其 Facebook 帐户登录
  • 对于个人资产,这可能没问题

在授权服务器中处理多个身份提供者通常是一个很好的技术目标。然后,您的 UI 和 API 只需与授权服务器及其令牌进行交互,从而降低了复杂性。

【讨论】:

    【解决方案2】:

    如果您要构建新内容,请继续使用 OAuth 2.0。与 SAML 相比,它是用户友好的(即基于 JSON 的)并且也是现代的。此外,还有许多资源可以帮助您(即库和 IDP 改编)。还有一件事,既然你想要认证,你应该使用 OpenID Connect (spec)。不妨将其视为基于 OAuth 2.0 构建的简单扩展。

    1 但是在我们的应用程序中,每个子系统究竟可以处理什么? SP 还是客户?

    OAuth 2.0 定义了几种不同的应用程序类型 (read)。根据您的解释,您的系统中很少有它们 - Web 应用程序和本机应用程序(可能是移动应用程序)。如果是这样的话,

    • IDP - 您的身份服务器
    • 客户端 - 您开发的所有应用程序
    • 用户代理 - 用于激活 OAuth 流程的浏览器
    • 最终用户 - 系统用户。

    资源服务器 (SP) 可以是每个应用程序的后端。或者它可能是一个常见的后端服务。但无论如何,它必须受到每个客户端获得的 OAuth 令牌的保护。

    令牌自省 (spec - rfc7662) 定义了如何验证来自资源服务器的令牌。关于 IDP 上的负载,这完全取决于您的部署规模。

    应用中的2条规则

    所以现在我们来到 OpenID Connect。它定义了 ID 令牌,它与您的客户端就最终用户的身份验证状态进行通信。它以 JWT 的形式出现。 JWT 的好处是(除了 JSON 之外),它可以有自定义声明。该规范支持这一点 (Additional Claims)。因此,在您的 IDP 中,您必须配置角色/用户组/权限,并在 ID 令牌中将其传达给客户端。

    3 会话同步

    IDP 使用浏览器会话为您的客户提供 SSO 行为。当您登录到一个客户端时,您的 IDP 会创建一个会话。因此,当最终用户使用另一个客户端时,IDP 可以检查已经登录的状态,请求丢失的权限并完成登录流程,发出所需的令牌。

    OpenID Connect 附带会话管理规范 (source),它为您的客户端提供了一种机制来验证此会话中的更改。请与您选择的 IDP 确认对此的支持。

    4 Idp 连接到另一个 Idp

    这超出了 OAuth2.0 生态系统的范围。 SAML 具有执行此操作的 SAML 联合(注意 - 我不是 SAML 专家)。不同的身份提供者有自己的解决方案(例如:-WSO2 bring your own identity)。此类用户配置取决于您的要求以及 IDP 功能。但正如我所说,这超出了 OAuth 的范围。

    注意 - 关于第 4 个问题,如果您的 IDP 支持并且您可以接受,您可以接受第三方(即 Google、Facebook)颁发的令牌来对应用程序的用户进行身份验证。这可以在 OpenID Connect 之上完成。此外,还有 SCIM (resources) 允许跨不同身份提供者查询用户数据。

    【讨论】:

    • 1 你的意思是每个子系统的前端是Client,系统的后端是Resource Server?我有点困惑。如果每个子系统都是前端和后端混合在一起的传统的基于 JSP 的应用程序呢? 2 IMO,一个RS应该依赖于另一个,客户端也是如此。以OctoDroid OpenHub为例,虽然都是我自己开发的,我不能说一旦用户登录OctoDroid,他就会登录OpenHub。
    • @hguser 没有。客户端可以由前端和后端(即JSP + Servlet)组成。资源服务器只是定义客户端和受保护端点/资源之间的边界。将客户端视为用于获取令牌的组件。资源服务器作为受保护的端点(例如,过滤器后面的几个 servlet,它们对 OAuth 令牌执行授权标头检查)。当然,他们可以生活在一场战争中。但是由于访问级别,每个之间都有一个界限。
    • 其实让我感到困惑的是,在典型的SSO环境中,所有的子系统和IDP都有相同的用户池(例如,他们都是公司的员工)。在 OAuth2 环境中,客户端和 IDP 将拥有不同的用户池。
    • @hguser 我不确定这个疑问的背景。在 OAuth2 中,IDP 是存储用户详细信息的中心位置。它是唯一的真理来源。 IDP 在 ID Token 中分享给客户的是其中存储的用户身份
    【解决方案3】:

    你有很多问题。

    问题第 1 部分

    • 但在我们的应用程序中,每个子系统究竟可以处理什么? SP 还是客户?
    • 如果将其视为 SP,Web 浏览器是客户端吗?
    • 如果被视为客户,谁是 SP?

    我认为这些问题与:OAuth 2.0 四个角色有关

    Oauth2 角色

    让我们从这个经典的流程图开始:

    您可以使用这些规则来确定您的应用程序具有什么角色:

    • 客户

      • 现代网络(react、angular、vue、linkstart 等)和移动应用程序(android/ios)。一般来说,任何需要来自另一个软件的数据的软件都可以是一个客户端。通常,客户端是一个网络,请求的数据是一个 http api rest,但这个概念可能适用于遗留(服务器渲染应用程序)或未来应用程序(商场中的机器人)
    • 资源服务器

      • Http 休息 API。 保持简单!!我们谈论的是用 Postman、Soapui、curl、javascript 等使用的某种后端语言(java、python、nodejs 等)开发的 api
    • 授权服务器

      • 负责生成令牌的应用程序以及与应用程序的安全性相关的更多功能

    问题第 2 部分

    • 那么规则配置应该在哪里进行呢?在 Idp 中还是在每个子系统中?
    • 除了基本的用户名和密码登录, 身份验证服务器应提供来自 google、facebook 和其他的登录 CAS 提供商也是如此。这可能吗?

    身份验证和授权平台

    至此,您了解了 jwt 令牌、用户/密码、用户表等

    但您需要确保具有“来宾”角色的用户无法对 API 休息端点 /user/100 执行 DELETE 调用。所以你需要RULES

    实现此规则的经典解决方案是在您的数据库中拥有一些表,例如:user、roles、user_roles、role_permission、permission_option。选项表必须已注册您的所有 api 端点及其方法。这也可以用来创建用户 <:> web 路由之间的关系。检查this

    您可以根据之前的规则开发自己的安全平台,或者使用一些称为 oauth2 平台/提供者、身份/访问平台等的平台:

    • auth0
    • 钥匙锁等

    更多细节在这里:https://stackoverflow.com/a/62049409/3957754


    问题第 3 部分

    • 好像 OAuth2 与 SSO 不同,它们如何协同工作?

    总而言之,SSO 只是确保您的所有用户都可以使用相同的用户/密码访问应用和网站。

    Oauth2authorization有严格的关系,但是authentication是无法授权的,而且身份验证是和用户/密码有关的,所以这个是oauth2和sso的关系

    一些链接

    【讨论】:

    • “总而言之,SSO 只是确保您的所有用户都可以使用相同的用户/密码访问应用程序和网站。”实际上并非如此,在行业中,SSO 通常意味着在浏览器中具有 SSO cookie 等,这样您就可以自动登录到所有订阅的站点,而无需再次登录。我认为 PO 是专门询问这个问题的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 2015-10-19
    • 1970-01-01
    • 2017-09-05
    • 2016-02-01
    相关资源
    最近更新 更多