ForcePilot/backend/package/yuxi/external_systems/integrations/microsoft365/credentials.py

55 lines
2.2 KiB
Python
Raw Normal View History

"""Microsoft 365 厂商专属凭证 Pydantic 模型。
定义两个 ``AuthCredential`` 子类分别对应应用权限client_credentials
委托权限authorization_code + PKCE两种认证方式
字段与 ``token_refresh.py`` 中刷新策略函数读取的 ``auth_config`` 字段一一对齐
- ``Microsoft365ClientCredential`` ``_refresh_microsoft365_client_credentials``
- ``Microsoft365AuthCodeCredential`` ``_refresh_microsoft365_authorization_code``
``cloud`` 字段不在凭证中它属于 ``connection_config`` ``cloud_endpoints.py``
模块注释由刷新策略从 ``auth_config["connection_config"]["cloud"]`` 读取
``scope`` 也不在凭证中它由刷新策略根据 ``cloud`` 推导为
``{graph_host}/.default``
"""
from __future__ import annotations
from pydantic import ConfigDict
from yuxi.external_systems.framework.auth_plugins.credentials import AuthCredential
class Microsoft365ClientCredential(AuthCredential):
"""Microsoft 365 应用权限凭证client_credentials 流)。
scope ``cloud_endpoints`` 推导为 ``{graph_host}/.default``不暴露为凭证字段
cloud ``connection_config`` 读取不放在凭证中见模块注释
"""
model_config = ConfigDict(populate_by_name=True, extra="ignore")
auth_type: str = "microsoft365_client_credentials"
tenant_id: str
client_id: str
client_secret: str
class Microsoft365AuthCodeCredential(AuthCredential):
"""Microsoft 365 委托权限凭证authorization_code + PKCE
凭证存储的是首次授权码交换后回填的 ``refresh_token``用于后续刷新
``code_verifier`` 仅在首次 token 交换时使用刷新阶段不携带
首次授权码交换由前端 PKCE 流程完成交换成功后 ``refresh_token`` 持久化到本凭证
"""
model_config = ConfigDict(populate_by_name=True, extra="ignore")
auth_type: str = "microsoft365_authorization_code"
tenant_id: str
client_id: str
client_secret: str = "" # 公开客户端SPA/移动端)可为空
refresh_token: str # 首次授权码交换后回填,后续刷新使用
code_verifier: str | None = None # 仅首次 token 交换使用,刷新阶段不携带