【问题标题】:How and why to supply scalar scope to FastAPI oAuth2 scopes dict?如何以及为什么向 FastAPI oAuth2 范围字典提供标量范围?
【发布时间】:2023-01-12 11:08:34
【问题描述】:

我在 Python 3.9 中使用 FastAPI。我无法获得可用的 oAuth2 依赖项来处理我们特定的 Azure 令牌身份验证,而且我最初尝试使用 fastapi-azure-auth 似乎也不匹配。

因此,我目前正在对 fastapi.security.base.SecurityBase 进行子类化,以尝试创建我自己的身份验证依赖项。我使用 fastapi.security.oauth2.OAuth2fastapi.security.oauth2.OAuth2PasswordBearer 中的方法作为指导。

这些模型依赖于 fastapi.openapi.models.OAuth2fastapi.openapi.models.OAuthFlow 回到 Pydantic 的 BaseModel,除了初始化提供的字段外,大概没有发生任何事情。

我似乎能找到的关于将 OAuth2 与 FastAPI 结合使用的唯一信息似乎是对很棒的 FastAPI 安全小教程的重复剪切和粘贴,它只为一个简单的虚拟示例提供指导。

在这个阶段,我真的很想回答一个对我来说很困惑的问题。

  1. 我有一个“范围”,我认为它可能是安全方案发挥作用所必需的。
  2. fastapi.security.oauth2.OAuth2模型需要为其model属性提供fastapi.openapi.models.OAuth2模型。
  3. fastapi.openapi.models.OAuth2模型需要为其flows属性提供fastapi.openapi.models.OAuthFlows模型。
  4. OAuthFlows 模型包含 OAuthFlow<Type> 模型之一,它是 fastapi.openapi.models.OAuthFlow 的子类。
  5. OAuthFlow 基类是存储“作用域”的地方:scopes: Dict[str, str] = {}

    我似乎找不到关于 OAuth2PasswordBearer 的行为和用法的一句话,直到返回 OAuthFlow,甚至代码也完全没有任何这些类的任何在线文档。

    但是从 FastAPI 教程和 OpenAPI 文档中似乎可以清楚地看出,“作用域”是一个字符串;并且多个范围有时可以表示为使用空格作为分隔符的单个字符串。我无法避免得出这样的结论(以及我可以提供的作为范围的数据证实),“范围”是标量:单个值。

    https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/ 说:

    • OAuth2 规范将“范围”定义为由空格分隔的字符串列表。
    • 每个字符串的内容可以有任何格式,但不应包含空格。
    • 每个“范围”只是一个字符串(没有空格)。

    所以我的问题是:我们应该如何向OAuthFlow.scopes dict 提供标量值?

    我的范围(标量)看起来像这样:

    api://a12b34cd-5e67-89f0-a12b-c3de456f78ab/.default
    

    是否应将其作为键或值或两者提供,否则是否可以将其他键/值留空 ("")、None,或者应该在其中放置什么(为什么?)?

    此外,由于存在 fastapi.security.oauth2.SecurityScopes店铺标量范围作为空格分隔的字符串,为什么有两种存储范围的方法以及它们如何交互(如果有的话)?

【问题讨论】:

    标签: python oauth-2.0 fastapi openapi


    【解决方案1】:

    在提出这个问题之后,我在 FastAPI 高级用户指南中找到了几行我错过的内容。他们参考了 oAuth2 教程并添加了一些使用范围的示例代码:

    示例代码中有一行定义了两个范围:

    scopes={"me": "Read information about the current user.", "items": "Read items."},

    看来实际范围被放置在钥匙scopes 字典,以及价值似乎是任意的描述性文本,可能会在某个地方的适当位置被推出(错误消息、异常等)。 FastAPI 高级用户指南的这一部分说:

    scopes 参数接收一个字典,其中每个范围作为键,描述作为值

    因此,对于我的特定问题,似乎可以肯定我可以提供我的范围:

    scopes = {"api://a12b34cd-5e67-89f0-a12b-c3de456f78ab/.default": "access"}

    至于SecurityScopes中的标量范围;当用户处理范围、嵌入令牌或根据所需范围检查传入范围时,不提供描述性文本,并且需要反复检查范围,因此范围列表正如最初预期的那样是适当且有用的。我还没有找到SecurityScopesOAuthFlow 中的作用域字典交互的任何地方。

    事实证明这是一个比我想象的要简单得多的问题,但我认为这是一个说明为什么在线文档是不是一种反模式,正如我听到一些狂热分子现在所支持的那样。

    为了使代码独立存在,并避免通过指南进行精细跟踪,添加注释会有所帮助:

    class OAuthFlow(BaseModel):
        refreshUrl: Optional[str] = None
        scopes: Dict[str, str] = {}  # [<scope>: <description>]
    

    或者,现在,甚至:

    class OAuthFlow(BaseModel):
        refreshUrl: Optional[str] = None
        scopes: Dict[str, str] = {}  # https://stackoverflow.com/q/75091028/134044
    

    :-)

    【讨论】:

      猜你喜欢
      • 2021-02-24
      • 1970-01-01
      • 2023-01-03
      • 1970-01-01
      • 2021-10-05
      • 2016-10-30
      • 1970-01-01
      • 1970-01-01
      • 2022-11-25
      相关资源
      最近更新 更多