Token导航 LogoToken导航TokenDH.com
MCP Abap Adt Auth Broker logo
安全风控未说明官方级别未说明来源级核验

MCP Abap Adt Auth Broker

MCP Server

MCP ABAP ADT服务器的JWT认证代理,基于目标头管理认证令牌,自动从.env文件加载令牌并在需要时使用服务密钥刷新。

工具数

0

提示词数

0

GitHub Stars

2

资源数

0
安全认证TypeScriptClineCline

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

fr0ster

提供方

fr0ster

最后核验

2026/5/17 20:20

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

详细介绍

@mcp-abap-adt/auth代理

![Stand With Ukraine](https://stand-with-ukraine.pp.ua)

MCP ABAP ADT服务器的JWT身份验证代理。基于目标标头管理身份验证令牌,自动从以下位置加载令牌 .env 文件,并在需要时使用服务密钥刷新它们。

特性

  • 🔐 基于目标的身份验证:基于以下内容加载令牌 x-mcp-destination 头球
  • 📁 环境文件支持:自动从以下位置加载令牌 {destination}.env 文件
  • 🔄 自动令牌刷新:使用来自的服务密钥刷新过期的令牌 {destination}.json 文件
  • 令牌验证:通过提供者验证令牌(如果 validateToken 已实施)
  • 💾 令牌缓存:内存缓存可提高性能
  • 🔧 可配置的基本路径:自定义位置 .env.json 文件已存储

安装

npm install @mcp-abap-adt/auth-broker

用法

基本用法(需要提供程序)

AuthBroker需要为目标配置令牌提供程序:

import { AuthBroker, AbapSessionStore } from '@mcp-abap-adt/auth-broker';
import { AuthorizationCodeProvider } from '@mcp-abap-adt/auth-providers';

const tokenProvider = new AuthorizationCodeProvider({
  uaaUrl: 'https://...authentication...hana.ondemand.com',
  clientId: '...',
  clientSecret: '...',
  browser: 'system',
});

const broker = new AuthBroker({
  sessionStore: new AbapSessionStore('/path/to/destinations'),
  tokenProvider,
});

const token = await broker.getToken('TRIAL');

完整配置(所有依赖项)

为了获得最大的灵活性,请提供所有三个依赖关系:

import {
  AuthBroker,
  AbapServiceKeyStore,
  AbapSessionStore,
} from '@mcp-abap-adt/auth-broker';
import { AuthorizationCodeProvider } from '@mcp-abap-adt/auth-providers';

const broker = new AuthBroker({
  sessionStore: new AbapSessionStore('/path/to/destinations'),
  serviceKeyStore: new AbapServiceKeyStore('/path/to/destinations'), // optional
  tokenProvider: new AuthorizationCodeProvider({
    uaaUrl: 'https://...authentication...hana.ondemand.com',
    clientId: '...',
    clientSecret: '...',
    browser: 'system',
  }),
}, 'chrome', logger);

// Disable browser authentication for headless/stdio environments (e.g., MCP with Cline)
const brokerNoBrowser = new AuthBroker({
  sessionStore: new AbapSessionStore('/path/to/destinations'),
  serviceKeyStore: new AbapServiceKeyStore('/path/to/destinations'),
  tokenProvider: new AuthorizationCodeProvider({
    uaaUrl: 'https://...authentication...hana.ondemand.com',
    clientId: '...',
    clientSecret: '...',
    browser: 'none',
  }),
  allowBrowserAuth: false, // Throws BROWSER_AUTH_REQUIRED if browser auth needed
}, 'chrome', logger);

会话+服务密钥(用于初始化)

如果需要从服务密钥初始化会话,请从服务密钥auth-config创建提供程序:

const broker = new AuthBroker({
  sessionStore: new AbapSessionStore('/path/to/destinations'),
  serviceKeyStore: new AbapServiceKeyStore('/path/to/destinations'),
  tokenProvider: new AuthorizationCodeProvider({
    uaaUrl: 'https://...authentication...hana.ondemand.com',
    clientId: '...',
    clientSecret: '...',
    browser: 'system',
  }),
});

内存会话存储

对于测试或临时会话:

import { AuthBroker, SafeAbapSessionStore } from '@mcp-abap-adt/auth-broker';

const broker = new AuthBroker({
  sessionStore: new SafeAbapSessionStore(), // In-memory, data lost after restart
});

自定义浏览器身份验证端口

为了避免与浏览器身份验证的端口冲突:

const broker = new AuthBroker({
  sessionStore: new AbapSessionStore('/path/to/destinations'),
  serviceKeyStore: new AbapServiceKeyStore('/path/to/destinations'),
  tokenProvider: new AuthorizationCodeProvider({
    uaaUrl: 'https://...authentication...hana.ondemand.com',
    clientId: '...',
    clientSecret: '...',
    browser: 'system',
    redirectPort: 4001,
  }),
}, 'chrome');

获取代币

const token = await broker.getToken('TRIAL');

// Force refresh token
const newToken = await broker.refreshToken('TRIAL');

为DI创建令牌刷新器

createTokenRefresher() 方法创建一个 ITokenRefresher 可以注入到连接中的实现。这使得连接能够透明地处理令牌刷新,而无需了解身份验证内部。

import { AuthBroker } from '@mcp-abap-adt/auth-broker';
import { JwtAbapConnection } from '@mcp-abap-adt/connection';

// Create broker
const broker = new AuthBroker({
  sessionStore: mySessionStore,
  serviceKeyStore: myServiceKeyStore,
  tokenProvider: myTokenProvider,
});

// Create token refresher for specific destination
const tokenRefresher = broker.createTokenRefresher('TRIAL');

// Inject into connection (connection can handle 401/403 automatically)
const connection = new JwtAbapConnection(config, tokenRefresher);

// Token refresher methods:
// - getToken(): Returns cached token if valid, otherwise refreshes
// - refreshToken(): Forces token refresh and saves to session store

代币更新的好处:

  • 🔄 透明刷新:连接自动处理401/403错误
  • 🧩 依赖注入:明确区分关注点
  • 💾 自动持久化:刷新后保存到会话存储的令牌
  • 🎯 目的地范围:每次复习都必须前往特定目的地

配置

环境变量

配置变量

  • AUTH_BROKER_PATH -用于搜索的冒号/分号分隔路径 .env.json 文件(默认:当前工作目录)

调试变量

  • DEBUG_BROKER -启用调试日志记录 auth-broker 包(简称)

- 吃起来 true 启用日志记录(默认值: false) - 启用后,记录身份验证步骤、令牌操作和错误详细信息 - 可以通过设置明确禁用 false - 例子: DEBUG_BROKER=true npm test

  • DEBUG_AUTH_BROKER -长名称(向后兼容)

- 同 DEBUG_BROKER,但名称较长 - 例子: DEBUG_AUTH_BROKER=true npm test

  • LOG_LEVEL -控制日志详细程度

- 价值观: debug, info, warn, error (默认值: info) - debug -所有消息,包括详细的调试信息 - info -信息性消息、警告和错误 - warn -仅警告和错误 - error -仅错误 - 例子: LOG_LEVEL=debug DEBUG_BROKER=true npm test

  • DEBUG -启用调试的替代方法

- 吃起来 true 启用所有调试日志记录 - 或设置为包含以下内容的字符串 brokerauth-broker 仅启用此程序包 - 例子: DEBUG=true npm testDEBUG=broker npm testDEBUG=auth-broker npm test

备注:对于调试相关包:

  • DEBUG_STORES (短)或 DEBUG_AUTH_STORES (long)-启用日志记录 @mcp-abap-adt/auth-stores 包裹
  • DEBUG_PROVIDER (短)或 DEBUG_AUTH_PROVIDERS (long)-启用日志记录 @mcp-abap-adt/auth-providers 包裹

传统支持: DEBUG_AUTH_LOG 仍然支持向后兼容性(相当于 DEBUG_BROKER=true LOG_LEVEL=debug)

日志记录功能

启用日志记录时(通过 DEBUG_BROKER=trueDEBUG_AUTH_BROKER=true),代理提供详细的结构化日志记录:

记录的内容:

  • 代理初始化:配置详细信息、存储、令牌提供程序、浏览器设置
  • 令牌检索:会话状态检查、令牌存在、刷新令牌可用性
  • 代币操作:通过提供者请求令牌,收到带有过期信息的令牌
  • 令牌持久性:使用格式化的令牌值和到期日期将令牌保存到会话
  • 错误上下文:详细的错误信息,包括文件路径、错误代码、缺少的字段

日志记录功能:

  • 令牌格式:为了安全性和可读性,令牌以截断格式记录(前25个字符和后25个字符,跳过中间)
  • 日期格式:过期日期以可读格式记录(例如,“2025-12-25 19:21:27 UTC”),而不是原始时间戳
  • 结构化日志:用途 DefaultLogger@mcp-abap-adt/logger 使用图标和级别前缀进行正确格式化
  • 日志级别:通过控制 LOG_LEVELAUTH_LOG_LEVEL 环境变量(错误、警告、信息、调试)

输出示例 DEBUG_BROKER=true LOG_LEVEL=info:

[INFO] ℹ️ [AUTH-BROKER] Broker initialized: hasServiceKeyStore(true), hasSessionStore(true), hasTokenProvider(true), browser(system), allowBrowserAuth(true)
[INFO] ℹ️ [AUTH-BROKER] Getting token for destination: TRIAL
[INFO] ℹ️ [AUTH-BROKER] Session check for TRIAL: hasToken(true), hasAuthConfig(true), hasServiceUrl(true), serviceUrl(https://...abap...), authorizationToken(eyJ0eXAiOiJKV1QiLCJqaWQiO...Q5ti7aYmEzItIDuLp7axNYo6w), hasRefreshToken(true)
[INFO] ℹ️ [AUTH-BROKER] Requesting tokens for TRIAL via session
[INFO] ℹ️ [AUTH-BROKER] Tokens received for TRIAL: authorizationToken(eyJ0eXAiOiJKV1QiLCJqaWQiO...Q5ti7aYmEzItIDuLp7axNYo6w), hasRefreshToken(true), authType(authorization_code), expiresIn(43199), expiresAt(2025-12-26 20:15:30 UTC)
[INFO] ℹ️ [AUTH-BROKER] Saving tokens to session for TRIAL: serviceUrl(https://...abap...), authorizationToken(eyJ0eXAiOiJKV1QiLCJqaWQiO...Q5ti7aYmEzItIDuLp7axNYo6w), hasRefreshToken(true), expiresAt(2025-12-26 20:15:30 UTC)
[INFO] ℹ️ [AUTH-BROKER] Token retrieved for TRIAL (via session): authorizationToken(eyJ0eXAiOiJKV1QiLCJqaWQiO...Q5ti7aYmEzItIDuLp7axNYo6w)

备注:只有当向代理构造函数显式提供记录器时,日志记录才有效。如果没有传递记录器,代理将不会向控制台输出任何内容。

文件结构

ABAP环境文件({destination}.env)

对于ABAP连接,请使用 SAP_* 环境变量:

SAP_URL=https://your-system.abap.us10.hana.ondemand.com
SAP_CLIENT=100
SAP_JWT_TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
SAP_REFRESH_TOKEN=refresh_token_string
SAP_UAA_URL=https://your-account.authentication.us10.hana.ondemand.com
SAP_UAA_CLIENT_ID=client_id
SAP_UAA_CLIENT_SECRET=client_secret

XSUAA环境文件({destination}.env)

对于XSUAA连接(范围缩小),使用 XSUAA_* 环境变量:

XSUAA_MCP_URL=https://your-mcp-server.cfapps.eu10.hana.ondemand.com
XSUAA_JWT_TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
XSUAA_REFRESH_TOKEN=refresh_token_string
XSUAA_UAA_URL=https://your-account.authentication.eu10.hana.ondemand.com
XSUAA_UAA_CLIENT_ID=client_id
XSUAA_UAA_CLIENT_SECRET=client_secret

备注: XSUAA_MCP_URL 是可选的-它不是身份验证的一部分,只需要发出请求。令牌和UAA凭据足以进行身份验证。

BTP环境文件({destination}.env)

对于BTP连接(ABAP系统的完整范围),请使用 BTP_* 环境变量:

BTP_ABAP_URL=https://your-system.abap.us10.hana.ondemand.com
BTP_JWT_TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
BTP_REFRESH_TOKEN=refresh_token_string
BTP_UAA_URL=https://your-account.authentication.eu10.hana.ondemand.com
BTP_UAA_CLIENT_ID=client_id
BTP_UAA_CLIENT_SECRET=client_secret
BTP_SAP_CLIENT=100
BTP_LANGUAGE=EN

备注: BTP_ABAP_URL 是必需的-它是ABAP系统URL。所有参数(令牌除外)都来自服务密钥。

ABAP的服务密钥文件({destination}.json)

标准ABAP服务密钥格式:

{
  "url": "https://your-system.abap.us10.hana.ondemand.com",
  "uaa": {
    "url": "https://your-account.authentication.us10.hana.ondemand.com",
    "clientid": "your_client_id",
    "clientsecret": "your_client_secret"
  }
}

XSUAA的服务密钥文件({destination}.json)

直接XSUAA服务密钥格式(来自BTP):

{
  "url": "https://your-account.authentication.eu10.hana.ondemand.com",
  "apiurl": "https://api.authentication.eu10.hana.ondemand.com",
  "clientid": "your_client_id",
  "clientsecret": "your_client_secret"
}

备注:对于XSUAA服务密钥, apiurl 优先于 url 用于UAA授权(如果存在)。

XSUAA与BTP身份验证

此软件包支持两种类型的BTP身份验证:

XSUAA(缩小范围)

  • 目的:访问范围有限的BTP服务
  • 服务密钥:仅包含UAA凭据(无ABAP URL)
  • 会话存储: XsuaaSessionStore (使用 XSUAA_* 环境变量)
  • 认证:客户端凭据授予类型(无需浏览器)
  • MCP网址:可选,单独提供(来自YAML配置 mcp_url、参数或请求标头)
  • 用例:以减少的权限访问MCP服务器等BTP服务

BTP(ABAP的完整范围)

  • 目的:以完整角色和范围访问ABAP系统
  • 服务密钥:包含UAA凭据和ABAP URL
  • 会话存储: BtpSessionStore (使用 BTP_* 环境变量)
  • 认证:基于浏览器的OAuth2(如ABAP)或刷新令牌
  • ABAP网址:必填,来自服务密钥或YAML配置
  • 用例:以完全权限访问BTP中的ABAP系统

责任和设计原则

核心开发原则

仅接口通信该方案遵循一个基本的发展原则: 所有与外部依赖关系的交互都只能通过接口进行代码知道 没有超出接口中定义的内容.

这意味着:

  • 不知道具体的实现类(例如。, AbapSessionStore, AuthorizationCodeProvider)
  • 不了解接口中未定义的内部数据结构或方法
  • 不假设接口契约之外的实现行为
  • 不访问接口中未明确定义的属性或方法

这一原则确保:

  • 松散结合: AuthBroker 与具体实现解耦
  • 灵活性:无需修改即可添加新实现 AuthBroker
  • 可测试性:易于模拟测试依赖关系
  • 可维护性:对实现的更改不会影响 AuthBroker

包装责任

@mcp-abap-adt/auth-broker 包定义 接口 并提供 编排逻辑 用于身份验证。确实如此 实现具体的存储或令牌获取机制-这些由单独的包提供(@mcp-abap-adt/auth-stores, @mcp-abap-adt/auth-providers).

AuthBroker做什么

  • 协调身份验证流程:使用提供的存储和提供程序协调令牌检索、验证和刷新
  • 管理令牌生命周期:处理令牌缓存、验证和自动刷新
  • 仅适用于接口:用途 IServiceKeyStore, ISessionStore,以及 ITokenProvider 不知道具体实现的接口
  • 供应商代表:通话 tokenProvider.getTokens() 获取代币
  • 代表到商店:将令牌和连接配置保存到 sessionStore

AuthBroker不做什么

  • 不实施存储:文件I/O、解析和存储逻辑由以下具体存储实现处理 @mcp-abap-adt/auth-stores
  • 不实施代币获取:OAuth2流、刷新令牌逻辑和客户端凭据由来自的具体提供者实现处理 @mcp-abap-adt/auth-providers

消费者责任

消费者 (应用程序使用 AuthBroker)负责:

  1. 选择合适的实施方式:选择正确的 IServiceKeyStore, ISessionStore,以及 ITokenProvider 基于用例的实现:

- ABAP系统:使用 AbapServiceKeyStore, AbapSessionStore (或 SafeAbapSessionStore),以及 AuthorizationCodeProvider - BTP系统:使用 AbapServiceKeyStore, BtpSessionStore (或 SafeBtpSessionStore),以及 AuthorizationCodeProvider - XSUAA服务:使用 XsuaaServiceKeyStore, XsuaaSessionStore (或 SafeXsuaaSessionStore),以及 ClientCredentialsProvider

  1. 确保完整配置:如果会话存储需要 serviceUrl (例如。, AbapSessionStore 需要 sapUrl),消费者必须确保:

- 会话是通过以下方式创建的 serviceUrl 打电话之前 AuthBroker.getToken(),或 - 会话存储实现处理 serviceUrl 内部检索(例如,从 serviceKeyStore)

  1. 了解店铺要求:不同的会话存储实现有不同的要求:

- AbapSessionStore:需要 sapUrl (地图到 serviceUrlIConnectionConfig) - BtpSessionStore:不需要 serviceUrl (使用 mcpUrl 相反) - XsuaaSessionStore:不需要 serviceUrl (MCP URL是可选的)

门店职责

混凝土 ISessionStore 实施负责:

  • 处理自己的数据格式:每个商店都知道其内部数据格式(例如。, AbapSessionData, BtpBaseSessionData)
  • 格式之间的转换:转换 IConfig/IConnectionConfig 以及内部存储格式
  • 管理必填字段:如果商店需要 serviceUrl (例如。, AbapSessionStore),它应该:

- 从以下位置检索 serviceKeyStore 如果未提供 IConnectionConfig,或 - 使用当前会话中的现有值(如果可用),或者 - 如果两者都不可用,则抛出错误(取决于实现)

供应商责任

混凝土 ITokenProvider 实施负责:

  • 获取代币:使用OAuth2流、刷新令牌或客户端凭据来获取JWT令牌
  • 管理令牌生命周期:根据需要进行缓存、验证、刷新和重新身份验证

设计原则

  1. 仅接口通信 (核心原则):所有与外部依赖的交互都会发生 仅通过接口代码知道 没有超出接口中定义的内容 (参见 核心开发原则 以上)
  2. 依赖倒置原理(DIP): AuthBroker 取决于抽象(IServiceKeyStore, ISessionStore, ITokenProvider),而非具体实现
  3. 单一责任:每个组成部分都有一个明确的责任:

- AuthBroker:编排和令牌生命周期管理 - ISessionStore:会话数据存储和检索 - ITokenProvider:代币获取 - IServiceKeyStore:服务密钥存储和检索

  1. 接口隔离:接口集中且最小化,只包含其特定目的所需的内容
  2. 开闭原则:可以添加新的存储和提供程序实现,而无需修改 AuthBroker

API

AuthBroker

构造函数

new AuthBroker(
  config: {
    sessionStore: ISessionStore;        // required
    serviceKeyStore?: IServiceKeyStore; // optional
    tokenProvider: ITokenProvider;      // required
    allowBrowserAuth?: boolean;         // optional
  }, 
  browser?: string, 
  logger?: ILogger
)

参数:

  • config -配置对象:

- sessionStore - 必需 -存储会话数据。必须包含初始会话 serviceUrl - serviceKeyStore - 可选的 -存放维修钥匙。仅需要从服务密钥初始化会话 - tokenProvider - 必需 -用于令牌获取和刷新的令牌提供者 - allowBrowserAuth - 可选的 -何时 false,投掷 BROWSER_AUTH_REQUIRED 而不是启动浏览器身份验证

  • browser -用于身份验证的可选浏览器名称(chrome, edge, firefox, system, headless, none).违约: system

- 使用 'headless' 对于SSH/远程会话-记录URL并等待手动回调 - 使用 'none' 用于自动测试-记录URL并立即拒绝 - 对于XSUAA,不使用浏览器(client_credentials授权类型)-使用 'none'

  • logger -可选记录器实例。如果没有提供,则不使用操作记录器

何时提供每种依赖关系:

  • sessionStore (必填):总是需要的。必须包含初始会话 serviceUrl
  • serviceKeyStore (可选):

- 如果需要从服务密钥初始化会话(步骤0),则需要此项 - 如果会话已包含授权配置和令牌,则不需要

  • tokenProvider (必填):

- 用于所有令牌获取和刷新流程 - 必须配置目标的身份验证参数(例如,UAA凭据)

可用实现:

  • ABAP: AbapServiceKeyStore(directory, defaultServiceUrl?, logger?), AbapSessionStore(directory, defaultServiceUrl?, logger?), SafeAbapSessionStore(defaultServiceUrl?, logger?), AuthorizationCodeProvider(...)
  • XSUAA (缩小范围): XsuaaServiceKeyStore(directory, logger?), XsuaaSessionStore(directory, defaultServiceUrl, logger?), SafeXsuaaSessionStore(defaultServiceUrl, logger?), ClientCredentialsProvider(...)
  • 业务流程平台 (ABAP的全部范围): AbapServiceKeyStore(directory, defaultServiceUrl?, logger?), BtpSessionStore(directory, defaultServiceUrl, logger?), SafeBtpSessionStore(defaultServiceUrl, logger?), AuthorizationCodeProvider(...)

方法

getToken(destination: string): Promise

获取目标的身份验证令牌。实现一个三步流程:

步骤0:使用令牌初始化会话(如果需要)

  • 检查会话是否具有 authorizationToken 和授权配置
  • 如果两者都缺失 serviceKeyStore 可用:

- 从服务密钥加载授权配置 - 用途 tokenProvider.getTokens() 获取代币 - 将令牌持久化到会话

  • 否则→ 进入步骤1

步骤1:令牌刷新/重新认证

  • 如果会话具有授权配置:

- 用途 tokenProvider.getTokens() 刷新或重新验证 - 将令牌持久化到会话 - 返回新令牌

  • 如果失败(或没有会话身份验证配置) serviceKeyStore 可用:

- 从服务密钥加载授权配置 - 用途 tokenProvider.getTokens() 获取代币 - 将令牌持久化到会话

  • 如果全部失败→ 抛出错误

重要提示:

  • 所有身份验证都由注入的提供者(authorization_code或client_credentials)处理。
  • tokenProvider 所有令牌获取和刷新流程都需要。
  • 经纪人总是打电话 provider.getTokens() -提供者在内部处理令牌生命周期(验证、刷新、登录)。消费者不需要知道代币问题。
  • 提供者根据令牌状态决定是返回缓存令牌、刷新还是执行登录。
  • 存储错误得到妥善处理:如果服务密钥文件丢失或格式错误,代理会记录错误并继续使用回退机制(会话存储数据或基于提供者的身份验证)

错误处理

代理为所有外部操作实现了全面的错误处理,将所有注入的依赖关系视为不受信任的:

import { STORE_ERROR_CODES } from '@mcp-abap-adt/interfaces';

try {
  const token = await broker.getToken('TRIAL');
} catch (error: any) {
  // Broker handles errors internally where possible, but critical errors propagate
  console.error('Failed to get token:', error.message);
}

错误类别 (由代理以优雅的降级方式处理):

1.会话存储错误 (读取会话文件):

  • STORE_ERROR_CODES.FILE_NOT_FOUND -会话文件丢失(已记录,尝试serviceKeyStore回退)
  • STORE_ERROR_CODES.PARSE_ERROR -会话文件已损坏(使用文件路径记录,尝试回退)
  • 保存令牌时写入失败(记录和抛出-严重)

2.ServiceKeyStore错误 (读取服务密钥文件):

  • STORE_ERROR_CODES.FILE_NOT_FOUND -服务密钥文件丢失(已记录,继续会话数据)
  • STORE_ERROR_CODES.PARSE_ERROR -服务密钥中的JSON无效(记录文件路径和原因)
  • STORE_ERROR_CODES.INVALID_CONFIG -缺少必填字段(记录时缺少字段名)
  • STORE_ERROR_CODES.STORAGE_ERROR -权限/写入错误(已记录)

3.令牌提供者错误 (网络操作):

  • 网络错误: ECONNREFUSED, ETIMEDOUT, ENOTFOUND (记录,抛出描述性消息)
  • VALIDATION_ERROR -缺少必需的身份验证字段(用字段名记录,throws)
  • BROWSER_AUTH_ERROR -浏览器身份验证失败或取消(记录、抛出)
  • REFRESH_ERROR -UAA服务器上的令牌刷新失败(已记录,抛出)

4.浏览器身份验证禁用错误 (当 allowBrowserAuth: false):

  • BROWSER_AUTH_REQUIRED -浏览器身份验证是必需的,但已禁用。投掷时间:

- 步骤0:会话中没有令牌和UAA凭据,服务密钥存在,但需要浏览器身份验证 - 步骤2b:刷新令牌已过期/无效,新令牌需要浏览器身份验证 - 错误包括 destination 上下文属性 - 用例:浏览器无法打开的非交互式环境(MCP stdio、Cline)

防御性设计原则:

  • 所有外部操作都包含在try-catch中:文件可能丢失/损坏,网络可能出现故障
  • 优雅降级:存储错误触发回退机制(serviceKey→ 会话→ 供应商)
  • 详细的错误上下文:日志包括文件路径、错误代码、缺少调试字段
  • 严重错误快速失败:写入失败和提供程序错误立即抛出(无法恢复)
  • 没有关于注入依赖关系的假设:所有被视为可能不可靠的商店/供应商

处理的错误场景示例:

  • 会话文件在操作过程中被删除→ 使用服务密钥
  • 服务密钥的JSON无效→ 日志解析错误,使用会话数据
  • 令牌刷新期间网络超时→ 记录超时,抛出描述性错误
  • 文件权限被拒绝→ 记录文件路径错误,抛出

refreshToken(destination: string): Promise

强制刷新目标令牌。呼叫 getToken() 运行完整的刷新流并保存更新的令牌。

clearCache(destination: string): void

清除特定目标的缓存令牌。

clearAllCache(): void

清除所有缓存的令牌。

令牌提供商

该软件包使用 ITokenProvider 令牌获取接口。提供程序实现在 @mcp-abap-adt/auth-providers:

  • ClientCredentialsProvider -用于XSUAA身份验证(范围缩小)

- 使用client_credentials授权类型 - 无需浏览器交互 - 未提供刷新令牌

  • AuthorizationCodeProvider -用于BTP/ABAP身份验证(全范围)

- 构造函数接受可选 browserAuthPort?: number 参数(默认值:3001) - 如果请求的端口正在使用中,则自动查找可用端口(防止 EADDRINUSE 错误) - 身份验证完成后,服务器正确关闭所有连接并释放端口 - 在与其他服务(例如代理服务器)一起运行时,使用自定义端口以避免冲突 - 使用基于浏览器的OAuth2流(如果没有刷新令牌) - 使用刷新令牌(如果可用) - 提供刷新令牌以供将来使用

示例用法:

import {
  AuthBroker,
  XsuaaServiceKeyStore,
  XsuaaSessionStore,
  AbapServiceKeyStore,
  BtpSessionStore
} from '@mcp-abap-adt/auth-broker';
import {
  ClientCredentialsProvider,
  AuthorizationCodeProvider,
} from '@mcp-abap-adt/auth-providers';

// XSUAA authentication
const xsuaaBroker = new AuthBroker({
  sessionStore: new XsuaaSessionStore('/path/to/sessions', 'https://mcp.example.com'),
  tokenProvider: new ClientCredentialsProvider({
    uaaUrl: 'https://auth.example.com',
    clientId: '...',
    clientSecret: '...',
  }),
});

// XSUAA authentication - with service key initialization
const xsuaaBrokerWithServiceKey = new AuthBroker({
  sessionStore: new XsuaaSessionStore('/path/to/sessions', 'https://mcp.example.com'),
  serviceKeyStore: new XsuaaServiceKeyStore('/path/to/keys'),
  tokenProvider: new ClientCredentialsProvider({
    uaaUrl: 'https://auth.example.com',
    clientId: '...',
    clientSecret: '...',
  }),
}, 'none');

// BTP authentication
const btpBroker = new AuthBroker({
  sessionStore: new BtpSessionStore('/path/to/sessions', 'https://abap.example.com'),
  tokenProvider: new AuthorizationCodeProvider({
    uaaUrl: 'https://auth.example.com',
    clientId: '...',
    clientSecret: '...',
    browser: 'system',
  }),
});

// BTP authentication - with service key and provider (for browser auth)
const btpBrokerFull = new AuthBroker({
  sessionStore: new BtpSessionStore('/path/to/sessions', 'https://abap.example.com'),
  serviceKeyStore: new AbapServiceKeyStore('/path/to/keys'),
  tokenProvider: new AuthorizationCodeProvider({
    uaaUrl: 'https://auth.example.com',
    clientId: '...',
    clientSecret: '...',
    browser: 'system',
  }),
});

CLI:mcp身份验证

生成或刷新 .env/使用AuthBroker+存储的JSON输出:

mcp-auth  [options]
mcp-auth --service-key 
 --output 
 [--env 
] [--type abap|xsuaa] [--credential] [--browser auto|none|system|chrome|edge|firefox] [--format json|env]

备注:已发布的CLI编译为 dist/bin 并且不需要 tsx 在运行时。要使用repo,请运行 npm installnpm run build.

身份验证流程:

  • 违约: authorization_code (基于浏览器的OAuth2)
  • --credential: client_credentials (clientId/clientSecret,无浏览器)

浏览器选项(用于authorization_code):

  • auto (默认):尝试打开浏览器,回退到显示URL
  • none:在控制台中显示URL并等待回调(无浏览器)
  • system/chrome/edge/firefox:打开特定浏览器

示例:

# Auth code (default via service key)
mcp-auth auth-code --service-key ./abap.json --output ./abap.env --type abap

# OIDC SSO (device flow example)
mcp-auth oidc --flow device --issuer https://issuer --client-id my-client --output ./sso.env --type xsuaa

# SAML2 pure (cookie)
mcp-auth saml2-pure --idp-sso-url https://idp/sso --sp-entity-id my-sp --output ./saml.env --type abap

# SAML2 bearer (in progress, requires --dev)
mcp-auth saml2-bearer --dev --service-key ./mcp.json --assertion  --output ./sso.env --type xsuaa

# ABAP: authorization_code (default, opens browser)
mcp-auth --service-key ./abap.json --output ./abap.env --type abap

# ABAP: authorization_code (show URL in console, no browser)
mcp-auth --service-key ./abap.json --output ./abap.env --type abap --browser none

# XSUAA: authorization_code (default)
mcp-auth --service-key ./mcp.json --output ./mcp.env --type xsuaa

# XSUAA: client_credentials (special cases)
mcp-auth --service-key ./mcp.json --output ./mcp.env --type xsuaa --credential

# Using existing .env for refresh token
mcp-auth --env ./mcp.env --service-key ./mcp.json --output ./mcp.env --type xsuaa

CLI:mcp-sso

通过SSO提供程序(OIDC/SAML)获取令牌并生成 .env/JSON输出:

mcp-sso  [options]
mcp-sso --protocol  --flow  --output 
 [--type abap|xsuaa] [--format env|json] [--env 
] [--config 
]

支持的流量:

  • OIDC: browser, device, password, token_exchange
  • SAML2: bearer, pure

示例:

# OIDC browser flow
mcp-sso oidc --flow browser --issuer https://issuer --client-id my-client --output ./sso.env --type xsuaa

# OIDC browser flow (manual code / OOB)
mcp-sso oidc --flow browser --token-endpoint https://issuer/token --client-id my-client --code  --redirect-uri urn:ietf:wg:oauth:2.0:oob --output ./sso.env --type xsuaa

# OIDC device flow
mcp-sso oidc --flow device --issuer https://issuer --client-id my-client --output ./sso.env --type xsuaa

# OIDC password flow
mcp-sso oidc --flow password --token-endpoint https://issuer/oauth/token --client-id my-client --username user --password pass --output ./sso.env --type xsuaa

# OIDC token exchange
mcp-sso oidc --flow token_exchange --issuer https://issuer --client-id my-client --subject-token  --output ./sso.env --type xsuaa

# SAML bearer flow (assertion -> token)
mcp-sso bearer --idp-sso-url https://idp/sso --sp-entity-id my-sp --token-endpoint https://uaa.example/oauth/token --assertion  --output ./sso.env --type xsuaa

# SAML pure flow (cookie)
mcp-sso saml2 --flow pure --idp-sso-url https://idp/sso --sp-entity-id my-sp --assertion  --cookie "SAP_SESSION=..." --output ./sso.env --type abap

SAML令牌别名(XSUAA): 如果您的IdP需要令牌别名端点,请传递SAML元数据XML:

mcp-sso bearer --saml-metadata ./saml-sp.xml --assertion  --service-key ./service-key.json --output ./sso.env --type xsuaa

本地密钥斗篷(OIDC+SAML测试)

用于本地测试 mcp-sso,包括一个可运行的Keycloak设置 (OIDC浏览器/密码/设备+SAML断言捕获)。

cd tests/keycloak
docker compose up -d

然后使用:

node dist/bin/mcp-sso.js \
  oidc \
  --flow browser \
  --issuer http://localhost:8080/realms/mcp-sso \
  --client-id mcp-sso-cli \
  --scopes openid,profile,email \
  --output /tmp/keycloak.env \
  --type xsuaa

tests/keycloak/README.md 用于设备流和SAML示例。

XSUAA演示(CAP)

用于测试XSUAA流的最小CAP应用程序包含在 tests/sso-demo. 它使 authorization_codesaml2-bearer 赠款类型和提供 简单 CatalogService。参见 tests/sso-demo/readme.md 用于部署步骤。

配置文件: 您可以通过提供程序配置传递JSON文件:

{
  "protocol": "oidc",
  "flow": "device",
  "issuerUrl": "https://issuer",
  "clientId": "my-client",
  "scopes": ["openid", "profile"]
}

实用程序脚本

生成 .env 服务密钥中的文件:

npm run generate-env  [service-key-path] [session-path]

测试

测试位于 src/__tests__/ 并使用Jest作为测试运行器。

运行测试

# Run all tests
npm test

# Run specific test file (all tests in that file)
npm test -- getToken.test.ts
npm test -- refreshToken.test.ts

# Run specific test by name/pattern
npm test -- getToken.test.ts -t "Test 1"
npm test -- getToken.test.ts -t "Test 2"
npm test -- getToken.test.ts -t "Test 3"

# Run test group (e.g., all getToken tests)
npm test -- getToken.test.ts

# Note: Test 2 requires Test 1 to pass first (test1Passed flag)
# To run Test 2 alone, you may need to run all tests in the file:
npm test -- getToken.test.ts

测试结构

测试设计为按顺序运行(保证 maxWorkers: 1maxConcurrency: 1jest.config.js):

  1. 测试1:验证不存在的目标的错误处理(NO_EXISTS)

- 要求: NO_EXISTS.json 不应该存在

  1. 测试2:当服务密钥存在但 .env 文件没有

- 要求: TRIAL.json 必须存在, TRIAL.env 不应该存在 - 将打开浏览器进行OAuth身份验证

  1. 测试3:使用现有测试令牌刷新 .env 文件

- 要求: TRIAL.jsonTRIAL.env 必须存在 - 如果满足以下条件,可以独立运行 .env 文件存在(手动创建或由测试2创建)

测试设置

  1. 复制 tests/test-config.yaml.templatetests/test-config.yaml
  2. 填写配置值(路径、目的地、XSUAA的MCP URL)
  3. 将服务密钥文件放入已配置的 service_keys_dir:

- {destination}.json 对于ABAP测试(例如。, trial.json) - {btp_destination}.json 对于XSUAA测试(例如。, btp.json)

如果缺少所需文件或配置包含占位符,测试将自动跳过。

文档

完整的文档可在 docs/ 目录:

docs/README.md 查看完整的文档索引。

贡献者

感谢所有贡献者!看 贡献者.md 查看完整列表。

许可证

麻省理工学院

目录标签

目录标签

安全认证TypeScriptClineJWT认证本地部署令牌管理ABAP开发自动化刷新

支持客户端

Cline

接入字段

传输方式(transport,传输协议)

未说明

鉴权方式(authType,认证方式)

oauth

工具数量(toolCount,工具数)

0

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

未说明oauth部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

仍需确认:installCommand

来源信息

继续浏览同类 MCP