【问题标题】:Api design with authorization from one service to another授权从一项服务到另一项服务的 API 设计
【发布时间】:2022-10-24 05:13:13
【问题描述】:

我正在创建一个 Shopify 应用程序,它有自己的 Shopify oAuth。我已经构建了一个外部 NodeJS 应用程序来处理所有设置,通过 api 处理所有仪表板分析等。

我需要将这两个服务连接在一起。在 Shopify 上安装应用程序后,我的外部服务上有一个端点,可以在我的表中创建 shop。虽然现在我需要只允许该商店能够查看他们的数据/更新它,而不是修改请求以获取其他商店信息。也不允许公众查看这些端点。

我正在考虑在 NodeJS(外部)应用程序上生成一个 Api 令牌并将其保存在 Shopify Database(另一个存储数据库)中,然后在每个请求中传递它并在外部应用程序端进行验证。我喜欢这种方法,但我也觉得它不安全,因为有人可以窃取令牌。

[您实际上也没有“创建”一个帐户,您只需安装应用程序,然后应用程序发出 Api 请求以获取新的“商店”条目] 我正在考虑为此使用 JWT,但可能不能。

另一种选择是结合 Api 令牌并在外部 NodeJS 上创建 1 个管理员用户,以便需要传递带有 Api 令牌的 Bearer 令牌。这提供了 1 层额外的安全性,因为他们“需要”至少在 Shopify 中安装此应用程序。

我可以研究哪些建议?

【问题讨论】:

    标签: node.js api security design-patterns


    【解决方案1】:

    Shopify 的docs 推荐了许多库来使用他们的 OAuth,我建议您使用其中的一个,直到您更熟悉 OAuth 工作流程。他们还提供了一个template project,它已经在一个快速服务器中连接了这个。根据您在外部项目中所处的位置,您可能会考虑从该项目开始并将现有代码移入其中,但如果没有,web/middleware 部分将为您提供如何操作的示例。

    要回答您的具体问题,我认为您可能误解了 OAuth 的工作原理,因为您自己可能不会生成任何令牌。那里有很多冗长的解释(这里有一些:What exactly is OAuth (Open Authorization)?),但对于一个非常基本的概要,让我们首先考虑一个非常简单的传统身份验证工作流程:

    • 用户在您的站点上注册,您将他们的用户名和密码的哈希值存储在一个表中,例如users
    • 当用户尝试登录时,他们会发送用户名和密码。您可以对照您的 users 表检查它,如果匹配,您将生成一个身份验证令牌。然后将此令牌与用户名一起存储在一个表中,例如auth_tokens
    • 对于后续请求,它们包含此身份验证令牌作为标头。对于每个请求,您都在auth_tokens 表中查找令牌,如果它在那里(并且尚未过期),您假设请求来自您与令牌一起存储的用户名并相应地限制访问

    使用 OAuth,您可以将所有这些都卸载给第三方。这有点过于简单,但有效地工作如下:

    • 第三方用户注册
    • 当用户尝试登录您的站点时,您将他们重定向到第三方,然后他们就可以登录了
    • 第三方给他们一个令牌并将他们重定向回您的网站
    • 您的应用程序使用令牌调用第三方,如果它有效,第三方会为您提供他们的用户名(和一些其他信息)。您信任第三方,因此您相信他们的请求来自该用户并相应地限制访问

    对于 shopify,“其他信息”将包括商店,然后您的应用可以选择仅向他们显示该商店的信息。

    https://github.com/Shopify/shopify-api-node/blob/main/src/auth/session/types.ts


    基于 cmets 的编辑: 如果我理解正确,您的意思是,在 Shopify 中进行某项操作后,您还希望同一个人使用您的核心应用程序来更新此外部服务中的内容,而中间没有 Shopify,并且您想验证它是同一个人。

    如果是这样,您对令牌的犹豫是正确的。您实际上会分发一个永久有效的密码并将其存储在不安全的地方。有 2 个更好的选择。

    1. 我对此一无所知,但看起来 Shopify 也可以选择成为您的核心应用程序的 OAuth 提供者。 https://shopify.dev/api/multipass。这与“使用 Google 登录”选项基本相同。这样,您就可以将 Shopify 的代币用于一切。

    2. 您的应用程序可以有自己的登录名,您需要将您的user 与他们的相关联。一种简单的方法是使用电子邮件地址。嵌套在您从 Shopify 获得的会话令牌中,您拥有 onlineAccessInfo

      export interface OnlineAccessInfo {
        expires_in: number;
        associated_user_scope: string;
        associated_user: {
          ...
          id: number;
          email: string;
          email_verified: boolean;
          ...
        };
      }
      

      当请求来自 Shopify 时,您需要记录此信息。如果他们已经验证了地址(email_verified 字段是 true),并且您已经验证了地址,那么您可以假设他们是同一个人。您可以要求他们使用相同的电子邮件在您的网站上注册,或者如果他们没有,您可以单独验证。

    【讨论】:

    • 我知道 Shopify 有一个部分是随快递服务器一起提供的,尽管我的核心应用程序(不是 Shopify)最终也需要连接到这个外部服务。基本上在 oAuth 之后,我想在我的自定义 NodeJs 应用程序/create/shop 上点击一个 Api,然后我正在考虑生成一个令牌(存储它)并将其存储在 Shopify 创建的本地 .sqlite 数据库中。然后 Shopify 应用程序上的每个请求(即更新字段)都会传递该令牌以验证该商店在我的外部服务中的真实性,然后执行 x。我只是担心这种方法是一种不好的安全做法
    • 基本上它“提出了内部服务到授权通信的设计模式”
    • 见编辑。希望能帮助到你!
    猜你喜欢
    • 2021-05-30
    • 2016-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    相关资源
    最近更新 更多