@mcp-abap-adt/auth-broker 2.2.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,144 +1,119 @@
1
1
  /**
2
- * Main AuthBroker class for managing JWT tokens based on destinations
2
+ * AuthBroker: tokens for a destination, from a provider, kept in a session store.
3
+ *
4
+ * The broker orchestrates and nothing more. It resolves what the stores know
5
+ * about a destination, hands it to the provider, asks the provider for a token
6
+ * and writes the answer back. Whether a token is still valid, whether to use the
7
+ * refresh token or log in, and how a login is conducted (browser, headless,
8
+ * pasted code) are the provider's decisions — made by its strategy — and the
9
+ * broker does not repeat or override any of them.
3
10
  */
4
- import type { ITokenRefresher } from '@mcp-abap-adt/interfaces-auth';
11
+ import type { IRefreshableTokenProvider, ITokenRefresher } from '@mcp-abap-adt/interfaces-auth';
5
12
  import type { ILogger } from '@mcp-abap-adt/interfaces-utils';
6
- import type { ITokenProvider } from './providers';
7
13
  import type { IAuthorizationConfig, IConnectionConfig, IServiceKeyStore, ISessionStore } from './stores/interfaces';
8
14
  /**
9
- * Configuration object for AuthBroker constructor
15
+ * Builds the provider for one destination, from what the stores hold for it.
16
+ *
17
+ * - `authConfig`: the UAA credentials — from the session when it holds them,
18
+ * else from the service key — with the refresh token the session stored, or
19
+ * `null` when neither store has credentials (a SAML flow needs none).
20
+ * - `connConfig`: the session's connection config, with `serviceUrl` resolved
21
+ * and the last token the session stored, so the provider can reuse it while
22
+ * it is valid.
23
+ *
24
+ * Called once per destination; the broker keeps the provider it returns.
25
+ */
26
+ export type TokenProviderFactory = (destination: string, authConfig: IAuthorizationConfig | null, connConfig: IConnectionConfig) => IRefreshableTokenProvider;
27
+ /**
28
+ * Configuration object for the AuthBroker constructor
10
29
  */
11
30
  export interface AuthBrokerConfig {
12
- /** Session store (required) - stores and retrieves session data */
31
+ /** Session store (required) — where tokens and the refresh token are kept */
13
32
  sessionStore: ISessionStore;
14
- /** Service key store (optional) - stores and retrieves service keys */
33
+ /** Service key store (optional) — UAA credentials and the service URL */
15
34
  serviceKeyStore?: IServiceKeyStore;
16
- /** Token provider (required) - handles token refresh and authentication flows through browser-based authorization (e.g., XSUAA provider) */
17
- tokenProvider: ITokenProvider;
18
35
  /**
19
- * Allow browser-based authentication (optional, default: true)
20
- * When false, getToken() will throw BROWSER_AUTH_REQUIRED error instead of blocking on browser auth.
21
- * Use this for headless/non-interactive environments (e.g., MCP stdio transport).
36
+ * The token provider, or a factory building one per destination.
37
+ *
38
+ * An instance is used as given, for every destination. A factory is seeded
39
+ * with what the stores hold for the destination (see `TokenProviderFactory`).
22
40
  */
23
- allowBrowserAuth?: boolean;
41
+ provider: IRefreshableTokenProvider | TokenProviderFactory;
24
42
  }
25
43
  /**
26
- * AuthBroker manages JWT authentication tokens for destinations
44
+ * AuthBroker manages authentication tokens for destinations
27
45
  */
28
46
  export declare class AuthBroker {
29
- private browser;
30
- private logger;
31
- private serviceKeyStore;
32
- private sessionStore;
33
- private tokenProvider;
34
- private allowBrowserAuth;
35
- /**
36
- * Create a new AuthBroker instance
37
- * @param config Configuration object with stores and token provider
38
- * - sessionStore: Store for session data (required)
39
- * - serviceKeyStore: Store for service keys (optional)
40
- * - tokenProvider: Token provider implementing ITokenProvider interface (required) - handles browser-based authorization
41
- * @param browser Optional browser name for authentication (chrome, edge, firefox, system, headless, none).
42
- * Default: 'system' (system default browser).
43
- * Use 'headless' for SSH/remote sessions - logs URL and waits for manual callback.
44
- * Use 'none' for automated tests - logs URL and rejects immediately.
45
- * @param logger Optional logger instance implementing ILogger interface. If not provided, uses no-op logger.
46
- */
47
- constructor(config: AuthBrokerConfig, browser?: string, logger?: ILogger);
47
+ private readonly logger;
48
+ private readonly serviceKeyStore;
49
+ private readonly sessionStore;
50
+ private readonly provider;
51
+ private readonly providers;
48
52
  /**
49
- * Load session data (connection and authorization configs)
53
+ * @param config Stores and the provider (instance or factory)
54
+ * @param logger Optional logger. Nothing the broker logs contains a token.
50
55
  */
51
- private loadSessionData;
56
+ constructor(config: AuthBrokerConfig, logger?: ILogger);
52
57
  /**
53
- * Get serviceUrl from session or service key store
58
+ * A token for the destination: the provider's current one, which it refreshes
59
+ * or obtains by login when it judges the cached one unusable.
60
+ *
61
+ * The result is written to the session store. Errors from the provider
62
+ * (its typed errors included) propagate unchanged.
54
63
  */
55
- private getServiceUrl;
64
+ getToken(destination: string): Promise<string>;
56
65
  /**
57
- * Get UAA credentials from session or service key
66
+ * A new token for the destination, never the cached one — for a caller whose
67
+ * token the server has just refused. Calls the provider's `refreshTokens()`,
68
+ * writes the result to the session store and returns it.
58
69
  */
59
- private getAuthorizationConfigFromServiceKey;
70
+ refreshToken(destination: string): Promise<string>;
71
+ private obtain;
72
+ private providerFor;
60
73
  /**
61
- * Save token and config to session
74
+ * The credentials the provider is built with: the session's own when it holds
75
+ * them, else the service key's, carrying the refresh token the session
76
+ * stored. The session keeps a refresh token without credentials when the
77
+ * credentials came from the service key, since the broker does not copy the
78
+ * client secret into it; `loadSession` is where such a token is read.
62
79
  */
63
- private saveTokenToSession;
64
- private requestTokens;
65
- private persistTokenResult;
80
+ private resolveAuthorizationConfig;
81
+ private resolveServiceUrl;
66
82
  /**
67
- * Get authentication token for destination.
68
- * Uses tokenProvider for all authentication operations (browser-based authorization).
69
- *
70
- * **Flow:**
71
- * **Step 0: Initialize Session with Token (if needed)**
72
- * - Check if session has `authorizationToken` AND UAA credentials
73
- * - If both are empty AND serviceKeyStore is available:
74
- * - Get UAA credentials from service key
75
- * - Use tokenProvider for browser-based authentication
76
- * - Save token and refresh token to session
77
- *
78
- * **Step 1: Token Validation**
79
- * - If token exists in session, validate it (if provider supports validation)
80
- * - If valid → return token
81
- * - If invalid or no token → continue to refresh
83
+ * Writes the result by its type: a SAML result is session cookies, anything
84
+ * else a bearer token. The refresh token is written only when the result has
85
+ * one, so a provider that returns none does not erase the stored one.
82
86
  *
83
- * **Step 2: Refresh Token Flow**
84
- * - Check if refresh token exists in session
85
- * - If refresh token exists:
86
- * - Use tokenProvider to refresh token (browser-based or refresh grant)
87
- * - Save new token to session
88
- * - Return new token
89
- * - Otherwise → proceed to Step 3
90
- *
91
- * **Step 3: New Token Flow**
92
- * - Get UAA credentials from session or service key
93
- * - Use tokenProvider for browser-based authentication
94
- * - Save new token to session
95
- * - Return new token
96
- *
97
- * **Important Notes:**
98
- * - All authentication is handled by tokenProvider (e.g., XSUAA provider)
99
- * - Provider uses browser-based authorization to ensure proper role assignment
100
- * - Direct UAA HTTP requests are not used to avoid role assignment issues
101
- *
102
- * @param destination Destination name (e.g., "TRIAL")
103
- * @returns Promise that resolves to JWT token string
104
- * @throws Error if session initialization fails or authentication failed
87
+ * `ITokenResult.expiresAt` has no field in `IConnectionConfig` to go to; the
88
+ * provider seeded with the stored token reads the expiry from the JWT itself.
105
89
  */
106
- getToken(destination: string): Promise<string>;
90
+ private persist;
107
91
  /**
108
- * Force refresh token for destination.
109
- * Uses refresh token from session if available, otherwise uses UAA credentials from session or service key.
110
- * @param destination Destination name (e.g., "TRIAL")
111
- * @returns Promise that resolves to new JWT token string
92
+ * A store read where absence is an answer and anything else is not.
93
+ *
94
+ * A store says "nothing here" with `null`, or with `FILE_NOT_FOUND`, and the
95
+ * flow goes on to the next source. Any other failure — a service key that is
96
+ * not valid JSON, a file the process may not read — is a different problem
97
+ * with a different fix, and reaches the caller as the store raised it. It
98
+ * used to be logged and answered as absent, so the caller saw only the
99
+ * consequence ("missing required field 'serviceUrl'") and went looking for a
100
+ * file that was there.
112
101
  */
113
- refreshToken(destination: string): Promise<string>;
102
+ private read;
114
103
  /**
115
- * Get authorization configuration for destination
116
- * @param destination Destination name (e.g., "TRIAL")
117
- * @returns Promise that resolves to IAuthorizationConfig or null if not found
104
+ * Authorization configuration for the destination: the session's, else the
105
+ * service key's, else null.
118
106
  */
119
107
  getAuthorizationConfig(destination: string): Promise<IAuthorizationConfig | null>;
120
108
  /**
121
- * Get connection configuration for destination
122
- * @param destination Destination name (e.g., "TRIAL")
123
- * @returns Promise that resolves to IConnectionConfig or null if not found
109
+ * Connection configuration for the destination: the session's, else the
110
+ * service key's (which has URLs but no token), else null.
124
111
  */
125
112
  getConnectionConfig(destination: string): Promise<IConnectionConfig | null>;
126
113
  /**
127
- * Create a token refresher for a specific destination.
128
- *
129
- * The token refresher is designed to be injected into JwtAbapConnection via DI,
130
- * allowing the connection to handle token refresh transparently without knowing
131
- * about authentication internals.
132
- *
133
- * **Usage:**
134
- * ```typescript
135
- * const broker = new AuthBroker(config);
136
- * const tokenRefresher = broker.createTokenRefresher('TRIAL');
137
- * const connection = new JwtAbapConnection(config, tokenRefresher);
138
- * ```
139
- *
140
- * @param destination Destination name (e.g., "TRIAL")
141
- * @returns ITokenRefresher implementation for the given destination
114
+ * An `ITokenRefresher` for one destination, for injection into a connection:
115
+ * `getToken()` is the broker's `getToken`, `refreshToken()` its forced
116
+ * `refreshToken`.
142
117
  */
143
118
  createTokenRefresher(destination: string): ITokenRefresher;
144
119
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACd,MAAM,qBAAqB,CAAC;AA8D7B;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,YAAY,EAAE,aAAa,CAAC;IAC5B,uEAAuE;IACvE,eAAe,CAAC,EAAE,gBAAgB,CAAC;IACnC,4IAA4I;IAC5I,aAAa,EAAE,cAAc,CAAC;IAC9B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,gBAAgB,CAAU;IAElC;;;;;;;;;;;OAWG;gBACS,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO;IAsFxE;;OAEG;YACW,eAAe;IA0D7B;;OAEG;YACW,aAAa;IAoD3B;;OAEG;YACW,oCAAoC;IA4ClD;;OAEG;YACW,kBAAkB;YA4ClB,aAAa;YA0Db,kBAAkB;IAkDhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAsLpD;;;;;OAKG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASxD;;;;OAIG;IACG,sBAAsB,CAC1B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAoEvC;;;;OAIG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAuEpC;;;;;;;;;;;;;;;;OAgBG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe;CAqB3D"}
1
+ {"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,yBAAyB,EACzB,eAAe,EAEhB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAS7B;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,oBAAoB,GAAG,IAAI,EACvC,UAAU,EAAE,iBAAiB,KAC1B,yBAAyB,CAAC;AAE/B;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,YAAY,EAAE,aAAa,CAAC;IAC5B,yEAAyE;IACzE,eAAe,CAAC,EAAE,gBAAgB,CAAC;IACnC;;;;;OAKG;IACH,QAAQ,EAAE,yBAAyB,GAAG,oBAAoB,CAAC;CAC5D;AAUD;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+B;IAC/D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmD;IAC5E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgD;IAE1E;;;OAGG;gBACS,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,OAAO;IA2DtD;;;;;;OAMG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIpD;;;;OAIG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAI1C,MAAM;YA2BN,WAAW;IA4BzB;;;;;;OAMG;YACW,0BAA0B;YAiC1B,iBAAiB;IAuB/B;;;;;;;OAOG;YACW,OAAO;IAoDrB;;;;;;;;;;OAUG;YACW,IAAI;IAgBlB;;;OAGG;IACG,sBAAsB,CAC1B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAkBvC;;;OAGG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAkBpC;;;;OAIG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe;CAM3D"}