Lorawan-stack: 引入新的帐户应用程序(替换 oauth 应用程序)

创建于 2019-10-04  ·  32评论  ·  资料来源: TheThingsNetwork/lorawan-stack

概括

我们目前有很多问题围绕着我们的 OAuth 流程、帐户切换、令牌管理、各自的品牌等。这是试图在一个新的account应用程序下使所有这些更具可操作性,该应用程序将处理所有这些担忧。

我们为什么需要这个?

  • 缺少账户切换功能⟶ #488
  • 缺少用户的品牌和上下文 ⟶ #730
  • 缺少会话管理 ⟶ #1217
  • 用户对 OAuth 身份验证流程的困惑 ⟶ #265

什么已经存在? 你现在看到了什么?

  • 具有有限 UI 的 OAuth 应用

缺什么? 你要看什么?

一个充当 OAuth 提供者的应用程序,以及围绕所有帐户和身份验证问题的全功能和品牌配置 UI

环境

网络

你建议如何实施?

我认为当前实现的一个大问题是用户缺乏清晰度和上下文。 很难将 OAuth 应用程序识别为独立的身份验证实体。 原因是:

  • 缺乏品牌和背景
  • 非常精简和无信息的用户界面
  • 控制台就像它自己处理身份验证一样(“登录”消息而不是“使用您的 {OAuth 提供者服务名称}帐户登录”,跳过授权)
    为了提高清晰度,我们需要使应用程序更加可见、可区分和有目的:
  • 添加可配置的品牌
  • 充实功能

    • 账户切换

    • 会话管理

    • 权限管理

    • 个人资料设置(更改/忘记密码、电子邮件、个人资料图片)

我创建了三个线框图,让我了解我如何设想帐户应用程序:

查看线框图

account_login
account_overview
account_profile_settings
(请注意右上角的用户下拉菜单中集成的帐户切换器)

你可以自己做这个并提交一个拉请求吗?

是的。 @johanstokking @htdvisser ,请让我知道您是否认为继续这样做很好。

identity server uweb umbrella

所有32条评论

关于控制台和 oauth 提供者之间的整个登录/注销混淆问题,这是我的计划:

  • 我们为帐户应用程序使用单独的Account徽标(而不是 TTS 徽标)并使用我们也用于控制台的相同标题组件(cc @pierreph)
  • 我们应该将体验更紧密地联系在一起,而不是为控制台和帐户应用程序设置两个单独的登录屏幕,这意味着

    • 我们将删除控制台登录屏幕/console/login

    • 当控制台没有(有效)访问令牌时,控制台将自动重定向到帐户应用程序登录页面/account/login

    • 就像我们已经对控制台登录按钮所做的那样,我们将使用重定向查询参数在成功登录后将用户发送回控制台

    • 从控制台 UI 注销将导致删除存储的访问令牌,以及从帐户应用程序注销。 这样,用户将始终必须重新输入其凭据才能重新登录控制台。



      • 为了能够做到这一点,我们需要一种方法来触发跨域请求的注销(因为不能保证控制台和帐户应用程序在同一个来源)


      • 在 v2 中,我们使用了一个简单的/users/logout路由,该路由将触发可以从任何地方引用的注销


      • 研究在保持 CSRF 安全的同时实现相同目标的方法会很好



    • 新流程与 v2 控制台的流程非常相似; 我们基本上会牺牲控制台客户端和授权服务器的分离来改善用户体验,这没关系,因为控制台是一种特殊情况的客户端

    • 如果我们将来允许不同的登录程序,我们可能需要修改这个流程

如果我没有听到有关此计划的任何投诉,我将开始实施此计划。

听起来是个很棒的计划。 我同意我们不需要明确注销控制台并通过 UX 中的 OAuth 保持登录状态,尽管它会在下面以这种方式工作。

跨域注销需要什么? 这不是一个简单的两步方法吗? 注销“页面”以删除控制台存储的访问令牌,然后重定向到帐户应用程序注销的通用注销页面? 或者你想要这个没有重定向但发布到注销端点?

对于注销,我们可以从 OpenID Connect 注销中获得一些灵感。 很好的总结可以在这里找到: https ://medium.com/@robert.broeckelmann/openid -connect-logout-eccc73df758f

听起来是个很棒的计划。 我同意我们不需要明确注销控制台并通过 UX 中的 OAuth 保持登录状态,尽管它会在下面以这种方式工作。

跨域注销需要什么? 这不是一个简单的两步方法吗? 注销“页面”以删除控制台存储的访问令牌,然后重定向到帐户应用程序注销的通用注销页面? 或者你想要这个没有重定向但发布到注销端点?

两步法是可以的。 我担心的是帐户应用程序的注销需要禁用 CSRF,这意味着任何拥有注销链接的人都可以引诱某人从他们的帐户中注销。 v2 堆栈目前也可以做到这一点(单击此处将注销您)。
我认为目前这是可以接受的,但不是最佳实践。

我现在为新帐户应用程序做了很多工作:

  • 重构的组件和容器可供控制台和帐户应用程序使用
  • 实施新设计(包括响应能力)
  • 实施的个人资料设置,包括个人资料图片
  • 实施授权管理(查看和撤销)
  • 实施会话管理(查看和撤销)
  • 解决了使用共享 css 模块依赖项时导致空白渲染的问题

我通过硬编码访问令牌来做到这一点,以便能够使用堆栈 API。 我目前无法通过正确的实施来推进,因为我不知道获取帐户应用程序的访问令牌的最佳方式是什么。
现在,“oauth 应用程序”只是一个 SPA,它连接到 oauth 服务器的 auth 端点(登录、注销和其他不需要访问令牌的帐户相关端点)。
@htdvisser向我提到,我们最初的想法是将帐户应用程序作为单独的 oauth 客户端,使用密码授予类型。 我认为我们应该就此展开讨论,因为:

  • 根据来源,不鼓励使用密码授予类型,即使对于“官方”和受信任的客户也是如此
  • 这将需要另一个登录屏幕(在 oauth 提供程序的登录屏幕旁边)
  • 我想知道是否有一种方法可以直接从 oauth 提供程序获取访问令牌,而无需使用另一个单独的客户端,因为我们已经在 oauth 应用程序中进行了身份验证
  • 如果我们为帐户应用程序使用密码授权,我们也应该将它用于控制台

我已经对@htdvisser说过,整个委托的身份验证/授权方面对我来说有点不知所措,而且我觉得自己的知识不足以对这种安全敏感的事情负责。

我们的目标应该是让我们的官方客户端的身份验证流程感觉像本地身份验证(另请参阅我的其他评论),这意味着登录和注销是全局的,并且客户端的身份验证状态和经过身份验证的状态之间应该没有区别授权提供者。

所以,我需要一些帮助和意见才能继续使用帐户应用程序。 我们该如何协调呢?

根据来源,不鼓励使用密码授予类型,即使对于“官方”和受信任的客户也是如此

是的,不得使用密码授予,请参阅此处的规范和推理: https: //tools.ietf.org/html/draft-ietf-oauth-security-topics-13#section -3.4

当前被 #2148 阻止

因此,在参与了一段时间之后,我想我需要一些意见。

帐户应用程序的最初想法是替换当前的 oauth 应用程序并将功能扩展到配置文件和会话管理(请参阅 OP)。 这样做的问题是,为了实现这样的功能,应用程序需要一个访问令牌,本质上意味着帐户应用程序既是 OAuth 提供者又是客户端。

我的想法是引入一个新的 OAuth 客户端 ( account ) 和前端,将功能与当前的 OAuth 应用程序融合在一起。 对于用户来说,看起来好像 OAuth 提供者(登录、注册、验证帐户等)和帐户应用程序客户端(配置文件设置、会话管理、授权管理)是同一个应用程序,而在后台,有是 OAuth 提供者和客户端之间的技术分离。 在后端,帐户客户端将成为oauth包的一部分。 前端方面,我们也可以将这两个东西视为同一个应用程序,使用相同的入口点( account.js )。
同样,路由将反映这种混合,例如:

  • /account/login用于 oauth 登录 [OAuth 提供者层]
  • /account/register用于用户注册 [OAuth 提供者层]
  • /account/forgot-password用于用户注册 [OAuth 提供者层]
  • /account/client/login/ttn-stack用于客户端登录(授权)【OAuth 客户端层】
  • /account/client/oauth/callback交换授权码 [OAuth 客户端层]
  • /account oauth 客户端概览页面【OAuth 客户端层】

另外,我们可以保留这两个问题分开,留下的OAuth提供商( /oauth通过pkg/oauth ),因为它是和治疗的帐户应用程序( /account通过pkg/account ) 作为一个完全独立的东西,就像我们对控制台所做的那样。 OAuth 提供者将只负责身份验证事务,包括授权和用户帐户注册,但不会像当前那样拥有自己的经过身份验证的视图。 相反,在登录后,它会默认重定向到帐户应用程序,然后自动检索令牌。

我觉得第一个解决方案可能会避免我们目前围绕身份验证和帐户管理的一些混乱,但我无法预见它是否会引入其他复杂性。 第二种解决方案似乎更干净,但问题是如何传达/品牌分离。 例如,两者都应该作为“帐户应用程序”进行通信吗? 还是应该是The Things Stack Single Sign OnThe Things Stack Account Application

请让我知道你的意见。

嗯,退一步,让账户应用成为 OAuth 客户端的目的是什么? 我们想要在那里通过 OAuth 实现什么功能?

  • 个人资料设置(姓名、电子邮件、个人资料图片)
  • 会话管理(审查、撤销)
  • 授权管理(审核、撤销)
  • (未来可能会出现其他与 TTES 相关的元设置)

所有这些都需要访问令牌,因为这是授权各个 RPC 的唯一方法。

我们需要分离 OAuth 提供者——它可以是外部的,例如“The Things Network Community”——和用户管理——这是关于管理存储在 The Things Stack 中的用户实体的字段,包括点@kschiffer在上面的评论中写道。

我们的/api/v3/*端点不接受 cookie 身份验证,因为它们启用了 CORS。 它们仅适用于 API 密钥和访问令牌。

  • 个人资料设置(姓名、电子邮件、个人资料图片)
  • 会话管理(审查、撤销)
  • 授权管理(审核、撤销)
  • (未来可能会出现其他与 TTES 相关的元设置)

所有这些都需要访问令牌,因为这是授权各个 RPC 的唯一方法。

我们也可以将这些部分作为控制台的一部分,但这意味着控制台会在某种程度上混合关注点。 我可以看到在没有所有其他控制台功能开销的情况下执行帐户管理会更好的情况,但也许那是我过度设计了这个🤷‍♂️。

通常,问题是我们是否只想将控制台视为管理网络相关事务的工具。 我们可以将其开放为所有 TTS 相关事务的通用管理平台,或者我们可以更加原子并坚持分离并针对不同的关注点使用不同的应用程序/客户端。 这是一个战略问题。 我看到了这两种情况。

我不认为控制台(所有控制台,因为每个集群中都有一个控制台)应该对用户拥有完全权限。 不应使用控制台来管理授权的 OAuth 客户端、会话、主要电子邮件地址、联系信息。 拥有一个专门的用户管理应用程序(帐户应用程序)要好得多。

确实,好点子。 然后回到最初的问题

我的看法是:

混合方法:

  • 来自用户 POV 较少混淆(所有帐户相关事务的一个位置)
  • 更轻松的品牌推广/沟通
  • 符合账户应用的原计划
  • 前端方面,我们不需要新的入口点,因此不需要单独的样板
  • 实现变得更加复杂/令人困惑(帐户应用程序是 oauth 提供者和客户端)

分离方法:

  • 更清洁和更传统的实现
  • 配置更灵活更清晰
  • 在 oauth 应用程序旁边引入一个新应用程序,该应用程序需要明智的品牌推广和沟通
  • 更长的构建(可能是边际的,尚未测试)和更多的资产

我倾向于混合方法。

  • 个人资料设置(姓名、电子邮件、个人资料图片)
  • 会话管理(审查、撤销)
  • 授权管理(审核、撤销)
  • (未来可能会出现其他与 TTES 相关的元设置)

这是帐户应用程序,对吗? 不是 OAuth?

  • 在 oauth 应用程序旁边引入一个新应用程序,该应用程序需要明智的品牌推广和沟通

那么 OAuth 应用程序还有什么用?

您能否列出 OAuth 客户端添加到帐户应用程序的用户的功能,我们无法在帐户应用程序中构建,可能通过新端点?

这是帐户应用程序,对吗? 不是 OAuth?

是的,这是帐户应用程序。 但计划是我们目前拥有的 OAuth 应用程序成为帐户应用程序的一部分。

那么 OAuth 应用程序还有什么用?

用于身份验证(作为 OAuth 流程的一部分)、用户注册、客户端授权、密码重置。 基本上所有与用户身份验证和客户端授权有关的事情。

您能否列出 OAuth 客户端添加到帐户应用程序的用户的功能,我们无法在帐户应用程序中构建,可能通过新端点?

问题更多的是相反,我们不能简单地使用我们想要的帐户应用程序功能扩展我们当前的 OAuth 应用程序,因为我们需要获取访问令牌。 这是一个先有鸡还是先有蛋的问题。 如果帐户应用程序功能(会话、授权等)有不同的授权方式,例如通过 OAuth 应用程序拥有的会话 cookie,那么它会有所不同。 但据我所知,这是不可行的。

OAuth 应用程序是独立的吗? 它是否为 OAuth 客户端实现重定向流? 还是它本身是一个 OAuth 客户端?


强调我的:

我的想法是引入一个新的OAuth 客户端( account ) 和前端,将功能与当前的 OAuth 应用程序融合在一起。 对于用户来说,看起来好像OAuth 提供者(登录、注册、验证帐户等)和帐户应用程序客户端(配置文件设置、会话管理、授权管理)是同一个应用程序,而在后台,有是OAuth 提供者客户端之间技术分离。 在后端帐户客户端将成为oauth包的一部分

我看到这里;

  • OAuth 客户端
  • 当前的 OAuth 应用程序
  • OAuth 提供者
  • 帐户应用程序客户端
  • OAuth 提供者
  • 客户端
  • 后端
  • 账户客户
  • oauth

我试图理解该提案,但我不完全理解什么是静止的。

那么我们想要的功能是什么?

  1. 创建账户
  2. 忘记密码
  3. 登录
  4. 更改密码
  5. 查看和编辑个人资料
  6. 管理会话
  7. OAuth 的东西

    1. 同意屏幕(OAuth 授权代码流程)

    2. 管理 OAuth 授权

如果我们使用会话身份验证,我猜想 1-6 可以在完全不接触 OAuth 的情况下实现。 这是可能的,对吧?

是的对不起。 我们这里有许多不固定的术语,很难解释。 至少它可以很好地洞察问题的复杂性😅。

所以让我们看看现状:

OAuth 提供者
根据 OAuth 2.0 规范提供授权(在我们的例子中也是身份验证)的实体。 在我们的例子中是pkg/oauth包,它反过来使用 OAuth 应用程序(见下文)来实现必要的用户界面来获取用户信息(呈现登录、注册、授权视图等)。

OAuth 应用程序
这是前端的反应 Web 应用程序。 我们的前端代码由不同的应用程序(具有不同的入口点oauth.js / console.js )组成,它们共享共同的部分,例如反应组件和实用程序

OAuth 客户端
使用 OAuth 进行身份验证和授权的注册客户端,例如控制台或 CLI。

oauth 包
负责实现 OAuth 提供程序的 Go 包。 那是pkg/oauth

所以你看,这里有三四个不同的层在起作用。 问题是,如果我们保持目前的授权方式,我们需要同时扮演上述所有角色的东西。

如果我们使用会话身份验证,我猜想 1-6 可以在完全不接触 OAuth 的情况下实现。 这是可能的,对吧?

是的。 没有 oauth / 访问令牌,1-4 已经是可能的。 5 和 6 目前需要访问令牌。 7. ii 尚未实施。 如果没有访问令牌可以实现 5 和 6,那么我们确实不需要另一个 oauth 客户端来执行此操作。 我们仍然需要考虑,将来我们可能想要添加到帐户应用程序的每个功能都不能使用访问令牌作为唯一的授权手段。

如果没有访问令牌可以实现 5 和 6,那么我们确实不需要另一个 oauth 客户端来执行此操作。 我们仍然需要考虑,将来我们可能想要添加到帐户应用程序的每个功能都不能使用访问令牌作为唯一的授权手段。

对。 这对我来说很有意义。 这也是“sudo 模式”的更好基础,例如,在重新输入密码后,用户可以在帐户应用程序中_only_ 执行操作。 所以是的,OAuth 客户端和帐户应用程序可以做的事情之间可能存在一些重叠,但这种重叠对我来说似乎并不大。 我认为将内容专用于帐户应用程序很有价值。

好吧,听起来不错。
@htdvisser你有什么反对意见吗? 如果没有,您能否将我指向相关文件/包进行授权,因为我想您很快就没有时间处理这个问题(?)。

正如我之前评论过的,我们的/api/v3/*端点不接受 cookie 身份验证,因为它们启用了 CORS。 如果您想开始接受 cookie 身份验证,则需要仔细查看我们的 CORS 标头,因为我们真的不希望攻击者向这些端点发出经过 cookie 身份验证的跨域请求。


我们的 API 都是 gRPC,身份验证是通过Authorization标头完成的,该标头作为请求元数据传播到 gRPC。 会话身份验证的实现可能如下所示:

  • SessionToken类型添加到pkg/auth/auth.go
  • Session模型添加一个秘密部分,类似于我们对 API 密钥和访问令牌所做的事情。
  • 添加一个中间件,从 cookie 中提取会话 ID 和会话秘密,并将其作为 SessionToken 转发到Authorization标头中
  • SessionToken作为caseswitch tokenType {中的pkg/identityserver/entity_access.go

这里要考虑的一件事是,这也意味着帐户应用程序和 v3 API 需要从同一来源提供服务。 否则,cookie 身份验证将不起作用,因为身份验证上下文包含不同的来源。
不确定这是多么可接受。 至少在实践中,我们似乎在部署中使用了相同的来源。

是的,它们将来自同一来源。

@kschiffer请让我们知道如何在这里解锁进度。

我在这里写了一个总结: https :

好的,让我们在这里继续对话。

@kschiffer经过一段时间的研究:

  • oauth 应用程序的前端部分基本上只包含授权屏幕

是的

  • 我认为为此保留is.oauth.ui.*配置非常烦人
    [...]
  • 我也有点不确定我们如何在不破坏 CC 的情况下更改堆栈配置的确切限制
  • 我在这里找到一个可行的解决方案有点不走运,真的需要一些输入

我们不能破坏 V3 中的配置,但我们可以引入新配置,弃用旧配置,使用旧配置作为后备,并提交标记为bump/major的 TODO 问题以删除旧配置。

所以我的建议是引入新的配置,完全替代并启用新的帐户应用程序。 为了向后兼容,它应该在没有用户指定这个新配置的情况下工作,即通过is.oauth.ui.*依赖合理的默认值和旧配置。

@kschiffer这里的状态是什么?

目前正在将我的工作重新建立在新的脚手架上,这里正在进行:#3453

接下来是重新定位、修复和 PRing 已验证的视图,并将当前设计调整为新品牌。

@kschiffer这里的状态是什么?

帐户应用程序已在 3.11 中引入。 目前仍然缺少的是:

  • 账号切换#488
  • 会话管理
  • 授权管理(iirc 这还包括添加 API 端点)

行。 https://github.com/TheThingsNetwork/lorawan-stack/issues/488似乎已经关闭。

这一直是个大问题。 您能否为上述问题提交一两个新问题以替换此问题,以便可以关闭?

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

htdvisser picture htdvisser  ·  9评论

adriansmares picture adriansmares  ·  8评论

ecities picture ecities  ·  5评论

adriansmares picture adriansmares  ·  9评论

johanstokking picture johanstokking  ·  6评论