
Haystack OAuth 集成指南用 OAuthTokenResolver 为 SharePoint / Google Drive 管道在运行时解析访问令牌【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack本篇技术指南围绕 Haystack 生态的oauth-haystack集成展开核心讲解OAuthTokenResolver组件它如何在管道Pipeline运行时解析 OAuth 访问令牌并通过access_token输出接口馈送给下游的 SharePoint、Google Drive 检索器Retriever与抓取器Fetcher。读完本文你将掌握三种可插拔令牌源刷新令牌授权、按请求令牌交换、静态长寿命令牌的选型与配置能够把令牌从哪来这件事彻底与业务管道解耦并理解底层协议RFC 6749 与 RFC 8693、缓存与序列化机制的实现细节。为什么管道需要一个 OAuth 解析组件接入微软 SharePoint、Google Drive 等企业数据源时几乎所有的下游 API 调用都需要一个有效的 OAuth 2.0 访问令牌。直接把令牌硬编码进组件、或在每次调用时手工刷新都会带来两个问题令牌有生命周期访问令牌通常几十分钟就会过期需要凭 refresh token 或按请求交换去续期这个逻辑不该散落在业务代码里令牌来源与应用形态强耦合单租户固定身份、多用户 SaaS 后端、多副本部署各自需要的令牌获取方式完全不同。Haystack 的解法是把解析令牌抽象成一个独立的管道组件OAuthTokenResolver。下游组件例如MSSharePointRetriever、MSSharePointFetcher、GoogleDriveRetriever、GoogleDriveFetcher通过普通的连接消费access_token字符串完全不需要知道令牌是刷新来的、交换来的还是静态配置的。这样你就可以在不改动下游任何代码的前提下切换认证策略。组件概览薄包装 可插拔令牌源OAuthTokenResolver在管道运行时解析访问令牌并将其从access_token输出接口socket发出。它本身是一个薄包装真正从哪里取令牌的逻辑被委托给一个可插拔的token source令牌源。从 version-2.19 的 API 参考文档 可以看到所有令牌源都实现了统一的协议TokenSource配置型令牌源凭据在构造时固定requires_subject_token False运行时不接收任何输入因此OAuthTokenResolver在管道中表现为一个源节点source nodeSubjectTokenSource按请求交换型令牌源requires_subject_token True此时OAuthTokenResolver会声明一个必填的subject_token运行输入——这是由应用/控制器在每个请求注入的凭据例如传入的用户断言而不是终端用户自行选择的值。当前版本的组件文档对它在管道中的位置做了如下总结见 OAuthTokenResolver 组件页项目说明管道中最常见位置管道起点将access_token馈送给MSSharePointRetriever或GoogleDriveRetriever等下游组件必填初始化参数token_source解析访问令牌的策略例如OAuthRefreshTokenSource必填运行参数配置型令牌源无subject_token控制器注入的按请求凭据仅当令牌源要求时必填如OAuthTokenExchangeSource输出变量access_tokenbearer 令牌字符串包名oauth-haystack安装pip install oauth-haystack三种内置令牌源所有令牌源都可以从haystack_integrations.utils.oauth导入。官方组件文档给出的选型对照如下令牌源适用场景按请求输入OAuthRefreshTokenSource拥有单一固定身份与存储的 refresh token希望自动换取短期访问令牌并缓存无OAuthTokenExchangeSource服务多用户或运行多副本希望用传入的用户断言换取下游令牌无需持久化存储实现 RFC 8693 令牌交换与微软 on-behalf-of 流程subject_tokenOAuthStaticTokenSource提供商签发不过期的令牌且令牌在带外管理例如 Slack、Notion无注意scope 是提供商相关的。你申请的 OAuth scope 取决于下游服务微软 Graph 使用诸如https://graph.microsoft.com/Files.Read.All的 scopeGoogle Drive 则使用https://www.googleapis.com/auth/drive.readonly。确切的 scope 值请以身份提供商文档为准。独立使用三种令牌源的实战示例场景一固定身份 refresh token 授权OAuthRefreshTokenSource这是最典型的用法令牌源运行 RFC 6749 refresh-token grant凭存储的 refresh token 加上客户端凭据换取访问令牌并在进程内缓存到临近过期为止。refresh token 通过 Haystack 的 Secret API 从环境变量读取from haystack.utils import Secret from haystack_integrations.components.connectors.oauth import OAuthTokenResolver from haystack_integrations.utils.oauth import OAuthRefreshTokenSource resolver OAuthTokenResolver( token_sourceOAuthRefreshTokenSource( token_urlhttps://login.microsoftonline.com/common/oauth2/v2.0/token, client_idaaa-bbb-ccc, refresh_tokenSecret.from_env_var(MS_REFRESH_TOKEN), scopes[ https://graph.microsoft.com/Files.Read.All, offline_access, ], ), ) access_token resolver.run()[access_token]因为该令牌源是配置型的resolver.run()不需要任何参数返回的字典中只有一个access_token键。场景二静态长寿命令牌OAuthStaticTokenSource对于签发不过期令牌的提供商例如 Slack、Notion无需刷新流程令牌在带外管理直接原样返回即可from haystack.utils import Secret from haystack_integrations.components.connectors.oauth import OAuthTokenResolver from haystack_integrations.utils.oauth import OAuthStaticTokenSource resolver OAuthTokenResolver( token_sourceOAuthStaticTokenSource(tokenSecret.from_env_var(SERVICE_TOKEN)), ) access_token resolver.run()[access_token]如果提供商签发的是必须刷新的短期令牌则应改用OAuthRefreshTokenSource。场景三多用户后端 按请求令牌交换OAuthTokenExchangeSource在多用户场景下传入的用户断言本身就是用户身份令牌源把它交换成下游访问令牌整个过程不需要任何持久化存储。此时OAuthTokenResolver会声明必填的subject_token运行输入from haystack_integrations.components.connectors.oauth import OAuthTokenResolver from haystack_integrations.utils.oauth import OAuthTokenExchangeSource resolver OAuthTokenResolver( token_sourceOAuthTokenExchangeSource( token_urlhttps://login.microsoftonline.com/tenant/oauth2/v2.0/token, client_idaaa-bbb-ccc, subject_token_paramassertion, grant_typeurn:ietf:params:oauth:grant-type:jwt-bearer, scopes[https://graph.microsoft.com/Files.Read.All], extra_token_params{requested_token_use: on_behalf_of}, ), ) # subject_token 是应用注入的按请求用户断言。 access_token resolver.run(subject_tokenincoming-user-assertion)[access_token]注意这里通过配置表达了微软 on-behalf-of 流程的差异表单参数名改为assertionsubject_token_paramgrant type 改为 JWT bearer并追加requested_token_useon_behalf_of。在管道中使用一条只需 query 的 SharePoint 检索管道把 resolver 的access_token输出连接到下游组件的access_token输入即可。下面的例子来自 MSSharePointRetriever 组件页管道运行时只要求一个query令牌由 resolver 自动解析from haystack import Pipeline from haystack.utils import Secret from haystack_integrations.components.connectors.oauth import OAuthTokenResolver from haystack_integrations.utils.oauth import OAuthRefreshTokenSource from haystack_integrations.components.retrievers.microsoft_sharepoint import ( MSSharePointRetriever, ) pipeline Pipeline() pipeline.add_component( resolver, OAuthTokenResolver( token_sourceOAuthRefreshTokenSource( token_urlhttps://login.microsoftonline.com/common/oauth2/v2.0/token, client_idaaa-bbb-ccc, refresh_tokenSecret.from_env_var(MS_REFRESH_TOKEN), scopes[ https://graph.microsoft.com/Files.Read.All, https://graph.microsoft.com/Sites.Read.All, offline_access, ], ), ), ) pipeline.add_component(retriever, MSSharePointRetriever(top_k5)) pipeline.connect(resolver.access_token, retriever.access_token) result pipeline.run({retriever: {query: quarterly roadmap}}) documents result[retriever][documents]MSSharePointRetriever通过微软 Search (Graph) API 检索用户 SharePoint / OneDrive 内容令牌必须是**委托权限delegated permissions**的 Graph bearer 令牌。而OAuthTokenResolver发出的正是普通字符串两者通过一条connect直接对接Retriever 内部也接受Secret并自行解析。同一个access_token输出还可以同时连接到多个下游输入构建 retrieve-then-fetch 的完整流程抓取全文可参考 MSSharePointFetcher 与 GoogleDriveFetcher 页面。源码级解析OAuthTokenResolver 的完整 API以 version-2.19 的 API 参考 为准OAuthTokenResolver定义在haystack_integrations.components.connectors.oauth其完整接口如下。init__init__(token_source: TokenSource | SubjectTokenSource) - Nonetoken_source解析访问令牌的策略。若其requires_subject_token True如OAuthTokenExchangeSourceresolver 会声明必填的subject_token运行输入否则 resolver 不声明任何运行输入。抛出OAuthConfigError当token_source未实现令牌源协议时。run 与 run_asyncrun(**kwargs: Any) - dict[str, str] run_async(**kwargs: Any) - dict[str, str]kwargs当配置的令牌源需要按请求凭据时携带subject_token此时它被声明为必填输入由应用/控制器每请求注入配置型令牌源不声明输入kwargs为空。返回只含单个access_token键的字典值为 bearer 令牌字符串。抛出OAuthConfigError当令牌源要求subject_token但该值为缺失或为空时。run_async是异步版本签名与语义一致。API 参考中对令牌源特别提醒同步或异步模式请只使用同一个实例不要混用。序列化to_dict 与 from_dictto_dict() - dict[str, Any] from_dict(data: dict[str, Any]) - OAuthTokenResolverto_dict把组件序列化为字典配合 Haystack 的 管道序列化机制 使用。from_dict从字典反序列化。若序列化中的token_source类型无法导入抛出ImportError。深入理解三种令牌源OAuthRefreshTokenSourceRFC 6749 刷新授权定义于haystack_integrations.utils.oauth.sources负责对 OAuth token 端点运行 RFC 6749 refresh-token grant。它用存储的 refresh token 加上客户端凭据换取访问令牌并在进程内缓存到临近过期。若身份提供商在交换时轮换rotate了 refresh token新值仅在进程生命周期内保留并通过可选的on_rotate回调暴露出来便于你持久化。完整签名__init__( token_url: str, client_id: str, *, refresh_token: Secret Secret.from_env_var(OAUTH_REFRESH_TOKEN), client_secret: Secret | None None, scopes: list[str] | None None, scope_delimiter: str , expiry_buffer_seconds: int DEFAULT_EXPIRY_BUFFER_SECONDS, timeout: float DEFAULT_TIMEOUT_SECONDS, on_rotate: Callable[[str], None] | None None ) - None参数含义与默认值token_urlOAuth 2.0 token 端点。client_idOAuth 客户端标识。refresh_token要交换的 refresh token默认读取OAUTH_REFRESH_TOKEN环境变量。client_secret机密客户端confidential client的客户端密钥公开客户端可省略。scopes要申请的 OAuth scope 列表按scope_delimiter拼接。scope 的值是提供商相关的以身份提供商文档为准。scope_delimiter拼接 scope 的分隔符默认为空格部分提供商使用逗号。expiry_buffer_seconds在声明过期时间之前多少秒刷新缓存的访问令牌默认值见DEFAULT_EXPIRY_BUFFER_SECONDS。timeout请求 token 端点的超时秒数默认值见DEFAULT_TIMEOUT_SECONDS。on_rotate当提供商轮换 refresh token 时携带新值调用的可选回调。用它把轮换后的令牌持久化到可靠存储令牌源本身只在进程内保存。resolve()返回缓存的访问令牌若已过期则执行刷新授权获取新的resolve_async()是其异步对应。to_dict/from_dict支持序列化往返。部署注意该令牌源是单身份的——每个实例一个 refresh token进程内缓存不跨进程共享。在多副本部署中每个副本维护自己的缓存对于会轮换签发一次性refresh token 的提供商多个副本可能互相使彼此的令牌失效除非通过on_rotate把轮换结果持久化到共享存储并由单一持有者驱动刷新。OAuthTokenExchangeSourceRFC 8693 令牌交换与 on-behalf-of它通过在 OAuth token 端点交换按请求的 subject token 来解析访问令牌。实现 RFC 8693 令牌交换并可通过配置实现微软的 on-behalf-of 流程。与OAuthRefreshTokenSource不同它是无持久化存储的多用户方案按请求的subject_token传入的用户断言本身就是用户身份被实时交换成下游令牌。解析出的令牌按 subject token 在有界 LRU 内存缓存中缓存到临近过期。由于不持久化任何实例状态它同样适合多副本部署。完整签名__init__( token_url: str, client_id: str, *, client_secret: Secret | None None, grant_type: str DEFAULT_TOKEN_EXCHANGE_GRANT, subject_token_param: str subject_token, subject_token_type: str | None None, requested_token_type: str | None None, scopes: list[str] | None None, scope_delimiter: str , extra_token_params: dict[str, str] | None None, expiry_buffer_seconds: int DEFAULT_EXPIRY_BUFFER_SECONDS, cache_max_size: int DEFAULT_CACHE_MAX_SIZE, timeout: float DEFAULT_TIMEOUT_SECONDS ) - None参数要点grant_type作为grant_type表单参数发送的授权类型默认为 RFC 8693 令牌交换授权需按提供商期望设置例如微软 on-behalf-of 使用urn:ietf:params:oauth:grant-type:jwt-bearer。subject_token_param承载按请求 subject token 的表单参数名默认为subject_tokenRFC 8693部分提供商期望其他名称如assertion。subject_token_typeRFC 8693 中提供 subject token 类型的标识作为subject_token_type表单参数发送未设置时省略。RFC 8693 令牌交换要求它如urn:ietf:params:oauth:token-type:access_token微软 on-behalf-of 流程不使用。requested_token_type期望返回的令牌类型的 RFC 8693 标识作为requested_token_type表单参数发送未设置时省略可选。scopes/scope_delimiter与刷新源一致只有线上格式是标准化的RFC 6749 §3.3scope 值仍由提供商定义。extra_token_params每个请求原样附加的额外表单参数例如{requested_token_use: on_behalf_of}。它最后应用因此这里的任何键都会覆盖由其他参数推导出的对应表单参数如grant_type、subject_token_type、requested_token_type、scope或client_secret。expiry_buffer_seconds缓存访问令牌在声明过期前多少秒刷新。cache_max_size内存缓存保留的每用户令牌最大数量默认值见DEFAULT_CACHE_MAX_SIZE缓存满时淘汰最久未使用LRU的条目。timeout请求 token 端点的超时秒数。resolve(subject_token)把按请求的 subject token 交换为访问令牌按 subject token 缓存resolve_async为异步版本。OAuthStaticTokenSource原样返回长寿命令牌配置一个长寿命访问令牌并原样返回适合签发不过期令牌的提供商例如 Slack、Notion。它不接收按请求输入__init__(token: Secret) - Nonetoken即要返回的长寿命访问令牌。resolve()/resolve_async()均返回该配置令牌。协议层与异常体系TokenSource 与 SubjectTokenSource 协议两个协议都定义在haystack_integrations.utils.oauth.protocols各自要求实现resolve、resolve_async、to_dict、from_dictTokenSource无按请求输入凭据在构造时固定由OAuthRefreshTokenSource、OAuthStaticTokenSource实现类属性requires_subject_token Falseresolver 将其作为源节点运行。SubjectTokenSource按请求交换resolve(subject_token: str) - str由OAuthTokenExchangeSource实现类属性requires_subject_token True使 resolver 声明必填的subject_token运行输入。如果你想接入自定义令牌源实现其中一个协议即可resolver 对下游保持透明。异常层级定义于haystack_integrations.utils.oauth.errorsOAuthError基类ExceptionOAuth 集成抛出的所有错误的基类。OAuthConfigError基类OAuthErrorOAuth 组件或令牌源配置错误时抛出例如token_source未实现协议、或要求subject_token但缺失/为空。TokenRefreshError基类OAuthError无法在身份提供商处解析或刷新令牌时抛出。与 Secret API 结合安全的凭据管理所有令牌源中的敏感值refresh token、client secret、静态令牌都使用 Haystack 的Secret类型承载相关规范详见 Secret Management 文档环境变量式 Secret推荐Secret.from_env_var(MS_REFRESH_TOKEN)只把环境变量名写入序列化结果凭据值永不落盘OAuthRefreshTokenSource的refresh_token参数默认就是Secret.from_env_var(OAUTH_REFRESH_TOKEN)。令牌式 SecretSecret.from_token(...)直接内嵌令牌值但无法序列化——这是刻意的安全设计防止敏感数据意外暴露。解析在运行期通过resolve_value()取到真实值。选型与最佳实践综合 API 参考与组件文档选型时可以这样决策单一固定身份、有 refresh grant 支撑选OAuthRefreshTokenSource把 refresh token 存环境变量多副本场景务必用on_rotate把轮换结果持久化到共享存储并确保只有单一持有者驱动刷新。多用户或多副本后端选OAuthTokenExchangeSource按请求注入subject_token用grant_type、subject_token_param、extra_token_params表达微软 on-behalf-of 等提供商差异用cache_max_size控制内存占用。提供商签发不过期令牌选OAuthStaticTokenSource令牌在带外管理。最后提醒两点一是 scope 值以身份提供商文档为准微软 Graph 与 Google Drive 的 scope 完全不同见上文提示框二是run/run_async不要在同一实例上混用。围绕这套机制你还可以继续阅读 Microsoft SharePoint 集成参考、Google Drive 集成参考 以及 GoogleDriveRetriever 组件页把令牌解析与具体的检索、抓取管道完整串联起来。【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考