OAuthTokenResolver
OAuthTokenResolver
파이프라인 실행 시점에 OAuth 액세스 토큰을 해석하고, 다운스트림 컴포넌트(SharePoint·Google Drive의 retriever/fetcher 등)로 내보내 주는 컴포넌트예요.
출처: 문서
본문
OAuthTokenResolver는 파이프라인이 실행될 때 OAuth 액세스 토큰을 해석하고 access_token 출력 소켓으로 내보내요. MSSharePointRetriever, MSSharePointFetcher, GoogleDriveRetriever, GoogleDriveFetcher 같은 다운스트림 컴포넌트는 일반 연결로 이 토큰을 받아서, 어떻게 얻었는지는 알 필요가 없어요.
Resolver 자체는 얇은 래퍼예요. 실제 토큰을 얻는 작업은 토큰이 어디서 오는지를 정하는 **플러그형 토큰 소스(token source)**에 위임되죠. 이 분리 덕분에 파이프라인 나머지를 건드리지 않고 인증 전략(refresh-token 그랜트, 요청별 토큰 교환, 정적 장기 토큰)을 바꿔끼울 수 있어요.
토큰 소스
Resolver에 token_source 파라미터로 토큰 소스를 넘겨요. 모든 소스는 haystack_integrations.utils.oauth에서 임포트할 수 있어요.
| 소스 | 언제 쓰나 | 요청별 입력 |
|---|---|---|
OAuthRefreshTokenSource |
저장된 refresh token을 기반으로 한 단일 고정 ID가 있고, 그 소스가 짧은 수명의 액세스 토큰으로 교환해서 캐시하게 하려 할 때 | 없음 |
OAuthTokenExchangeSource |
여러 사용자(또는 여러 레플리카)를 서비스하면서, 영구 저장 없이 들어오는 요청별 사용자 어설션을 다운스트림 토큰으로 교환하려 할 때. RFC 8693 토큰 교환과 Microsoft의 on-behalf-of 흐름을 구현해요. | subject_token |
OAuthStaticTokenSource |
프로바이더가 만료되지 않는 토큰을 발급하고, 이를 대역 외(out of band)로 관리할 때(예: Slack, Notion) | 없음 |
구성한 소스가 요청별 자격 증명을 필요로 하면(OAuthTokenExchangeSource는 requires_subject_token = True로 설정), Resolver는 필수 subject_token 실행 입력을 선언해요. 이는 컨트롤러가 주입한 자격 증명(예: 들어오는 사용자 어설션)으로, 최종 사용자가 고르는 값이 아니에요. 구성 전용 소스(OAuthRefreshTokenSource, OAuthStaticTokenSource)에서는 Resolver가 실행 입력을 선언하지 않고 소스 노드로 동작해요.
Scopes는 프로바이더별로 달라요: 요청하는 OAuth scope는 다운스트림 서비스에 따라 달라져요. Microsoft Graph는
https://graph.microsoft.com/Files.Read.All같은 scope가, Google Drive는https://www.googleapis.com/auth/drive.readonly같은 scope가 필요해요. 정확한 scope 값은 항상 아이덴티티 프로바이더 문서를 확인하세요.
설치
OAuth 통합을 설치해요.
pip install oauth-haystack
더 알아보기 (Learn more)
단독으로 쓰기
저장된 refresh token으로 토큰을 해석하려면 OAuthRefreshTokenSource를 써요. refresh token은 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_source=OAuthRefreshTokenSource(
token_url="https://login.microsoftonline.com/common/oauth2/v2.0/token",
client_id="aaa-bbb-ccc",
refresh_token=Secret.from_env_var("MS_REFRESH_TOKEN"),
scopes=[
"https://graph.microsoft.com/Files.Read.All",
"offline_access",
],
),
)
access_token = resolver.run()["access_token"]
장기·만료 없는 토큰을 발급하는 프로바이더라면 OAuthStaticTokenSource를 써요.
from haystack.utils import Secret
from haystack_integrations.components.connectors.oauth import OAuthTokenResolver
from haystack_integrations.utils.oauth import OAuthStaticTokenSource
resolver = OAuthTokenResolver(
token_source=OAuthStaticTokenSource(token=Secret.from_env_var("SERVICE_TOKEN")),
)
access_token = resolver.run()["access_token"]
멀티 유저 백엔드에서는 OAuthTokenExchangeSource를 써요. 그러면 Resolver가 요청별 subject_token을 필요로 해요.
from haystack_integrations.components.connectors.oauth import OAuthTokenResolver
from haystack_integrations.utils.oauth import OAuthTokenExchangeSource
resolver = OAuthTokenResolver(
token_source=OAuthTokenExchangeSource(
token_url="https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token",
client_id="aaa-bbb-ccc",
subject_token_param="assertion",
grant_type="urn: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` is the incoming per-request user assertion, injected by your application.
access_token = resolver.run(subject_token="<incoming-user-assertion>")["access_token"]
파이프라인에서 쓰기
파이프라인에서는 Resolver의 access_token 출력을 하나 이상의 다운스트림 컴포넌트의 access_token 입력에 연결해요. 아래 예제는 Resolver를 MSSharePointRetriever에 연결해서, 실행 시점에는 검색어만 있으면 SharePoint를 검색하게 만들어요.
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_source=OAuthRefreshTokenSource(
token_url="https://login.microsoftonline.com/common/oauth2/v2.0/token",
client_id="aaa-bbb-ccc",
refresh_token=Secret.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_k=5))
pipeline.connect("resolver.access_token", "retriever.access_token")
result = pipeline.run({"retriever": {"query": "quarterly roadmap"}})
documents = result["retriever"]["documents"]
하나의 access_token 출력을 여러 다운스트림 입력에 연결할 수 있어요. 같은 토큰을 retriever와 fetcher 양쪽에 공급하는 전체 retrieve-then-fetch 파이프라인은 MSSharePointFetcher와 GoogleDriveFetcher 페이지를 참고하세요.