如何以及为什么要为FastAPI oAuth2作用域提供标量作用域?

z9smfwbn  于 2023-01-16  发布在  其他
关注(0)|答案(1)|浏览(184)

我在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.我有一个"范围",我相信这可能是必不可少的提供安全计划的工作。

  1. fastapi.security.oauth2.OAuth2模型需要为其model属性提供fastapi.openapi.models.OAuth2模型。
  2. fastapi.openapi.models.OAuth2模型需要为其flows属性提供一个fastapi.openapi.models.OAuthFlows模型。
  3. OAuthFlows型号包含OAuthFlow<Type>型号之一,OAuthFlow<Type>型号是fastapi.openapi.models.OAuthFlow的子类。
  4. OAuthFlow基类是存储"作用域"的地方:scopes: Dict[str, str] = {}
    在回到OAuthFlow的路上,我似乎找不到一句关于OAuth2PasswordBearer的行为和用法的话,甚至代码也完全没有任何关于这些类的内联文档。
  • 但是从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类 * 确实 * 将 * 标量 * 作用域存储为空格分隔的字符串,为什么有两种方法来存储作用域?它们如何交互(如果有的话)?

9cbw7uwe

9cbw7uwe1#

在提出这个问题之后,我在FastAPI高级用户指南中找到了我遗漏的几行代码,它们可以参考oAuth2教程,并添加一些使用作用域的示例代码:

示例代码中有一行定义了两个作用域:
scopes={"me": "Read information about the current user.", "items": "Read items."},
实际的 scope 似乎放在scopes字典的 key 中,而 value 似乎是任意的描述性文本,可能在某个适当的地方被推出(错误消息、异常,或者至少在OpenAPI文档中)。
scopes参数接收一个dict,其中每个范围作为键,描述作为值
因此,对于我的特定问题,似乎可以肯定我可以提供如下范围:
scopes = {"api://a12b34cd-5e67-89f0-a12b-c3de456f78ab/.default": "access"}
对于SecurityScopes中的标量作用域;当作用域由用户处理、嵌入到令牌中或根据所需的作用域检查传入的作用域时,不提供描述性文本,并且需要迭代地检查作用域,因此作用域列表如最初预期的那样是适当和有用的。我还没有找到SecurityScopesOAuthFlow中的作用域dict交互的任何地方。
这是一个比我想象中简单得多的问题,但我认为这是一个示例,它演示了为什么内联文档 * 不是 * 反模式,正如我听说一些狂热分子现在所拥护的那样。
为了使代码独立,避免在指南中进行精细的跟踪,添加注解会有所帮助:

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

:—)

相关问题