@mcp-abap-adt/auth-providers 1.1.0 → 2.0.0

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.
Files changed (63) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/README.md +376 -61
  3. package/bin/auth-authorization-code.ts +5 -3
  4. package/dist/__tests__/helpers/netHelpers.d.ts +16 -0
  5. package/dist/__tests__/helpers/netHelpers.d.ts.map +1 -1
  6. package/dist/__tests__/helpers/netHelpers.js +29 -0
  7. package/dist/auth/announce.d.ts +11 -0
  8. package/dist/auth/announce.d.ts.map +1 -0
  9. package/dist/auth/announce.js +19 -0
  10. package/dist/auth/browserAuth.d.ts +22 -16
  11. package/dist/auth/browserAuth.d.ts.map +1 -1
  12. package/dist/auth/browserAuth.js +101 -536
  13. package/dist/auth/callbackServer.d.ts +46 -0
  14. package/dist/auth/callbackServer.d.ts.map +1 -0
  15. package/dist/auth/callbackServer.js +332 -0
  16. package/dist/auth/oidcBrowserAuth.d.ts +4 -3
  17. package/dist/auth/oidcBrowserAuth.d.ts.map +1 -1
  18. package/dist/auth/oidcBrowserAuth.js +25 -134
  19. package/dist/auth/saml2Auth.d.ts +2 -2
  20. package/dist/auth/saml2Auth.d.ts.map +1 -1
  21. package/dist/auth/saml2Auth.js +21 -141
  22. package/dist/index.d.ts +6 -0
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +21 -1
  25. package/dist/providers/AuthorizationCodeProvider.d.ts +7 -3
  26. package/dist/providers/AuthorizationCodeProvider.d.ts.map +1 -1
  27. package/dist/providers/AuthorizationCodeProvider.js +51 -41
  28. package/dist/providers/DeviceFlowProvider.d.ts +2 -1
  29. package/dist/providers/DeviceFlowProvider.d.ts.map +1 -1
  30. package/dist/providers/DeviceFlowProvider.js +13 -10
  31. package/dist/providers/OidcBrowserProvider.d.ts +4 -7
  32. package/dist/providers/OidcBrowserProvider.d.ts.map +1 -1
  33. package/dist/providers/OidcBrowserProvider.js +54 -57
  34. package/dist/providers/OidcDeviceFlowProvider.d.ts.map +1 -1
  35. package/dist/providers/OidcDeviceFlowProvider.js +9 -7
  36. package/dist/providers/Saml2BearerProvider.d.ts +2 -2
  37. package/dist/providers/Saml2BearerProvider.d.ts.map +1 -1
  38. package/dist/providers/Saml2BearerProvider.js +3 -0
  39. package/dist/providers/Saml2PureProvider.d.ts +2 -2
  40. package/dist/providers/Saml2PureProvider.d.ts.map +1 -1
  41. package/dist/providers/Saml2PureProvider.js +3 -0
  42. package/dist/providers/saml2Utils.d.ts +12 -12
  43. package/dist/providers/saml2Utils.d.ts.map +1 -1
  44. package/dist/providers/saml2Utils.js +46 -26
  45. package/dist/strategies/BrowserCallbackStrategy.d.ts +64 -0
  46. package/dist/strategies/BrowserCallbackStrategy.d.ts.map +1 -0
  47. package/dist/strategies/BrowserCallbackStrategy.js +210 -0
  48. package/dist/strategies/asOidcResult.d.ts +11 -0
  49. package/dist/strategies/asOidcResult.d.ts.map +1 -0
  50. package/dist/strategies/asOidcResult.js +30 -0
  51. package/dist/strategies/codeStrategies.d.ts +22 -0
  52. package/dist/strategies/codeStrategies.d.ts.map +1 -0
  53. package/dist/strategies/codeStrategies.js +39 -0
  54. package/dist/strategies/index.d.ts +8 -0
  55. package/dist/strategies/index.d.ts.map +1 -0
  56. package/dist/strategies/index.js +18 -0
  57. package/dist/strategies/manualStrategies.d.ts +20 -0
  58. package/dist/strategies/manualStrategies.d.ts.map +1 -0
  59. package/dist/strategies/manualStrategies.js +77 -0
  60. package/package.json +4 -4
  61. package/dist/auth/manualInput.d.ts +0 -5
  62. package/dist/auth/manualInput.d.ts.map +0 -1
  63. package/dist/auth/manualInput.js +0 -19
@@ -1,3 +1,19 @@
1
1
  export declare function getAvailablePort(): Promise<number>;
2
2
  export declare function canListenOnLocalhost(): Promise<boolean>;
3
+ /**
4
+ * Whether a login in this test could own `port` — and therefore whether
5
+ * asserting that it released the port means anything.
6
+ *
7
+ * A release assertion is a claim about our own cleanup. When an unrelated
8
+ * process already holds the port, the login fails at the probe, never binds
9
+ * anything, and cannot release anything: the port is still held afterwards,
10
+ * the code is behaving exactly as it should, and the assertion fails anyway.
11
+ * That is a test reporting on what else is running on the machine.
12
+ *
13
+ * So the gate is placed *before* the login rather than the assertion being
14
+ * widened until it always passes — a `toBe(true)` relaxed into "free or held"
15
+ * would also pass when our own cleanup leaked, which is the one thing these
16
+ * cases exist to catch.
17
+ */
18
+ export declare function canOwnPort(port: number, context: string): Promise<boolean>;
3
19
  //# sourceMappingURL=netHelpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"netHelpers.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/netHelpers.ts"],"names":[],"mappings":"AAEA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAcxD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAQ7D"}
1
+ {"version":3,"file":"netHelpers.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/netHelpers.ts"],"names":[],"mappings":"AAEA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAcxD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAQ7D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAclB"}
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.getAvailablePort = getAvailablePort;
37
37
  exports.canListenOnLocalhost = canListenOnLocalhost;
38
+ exports.canOwnPort = canOwnPort;
38
39
  const net = __importStar(require("node:net"));
39
40
  async function getAvailablePort() {
40
41
  return new Promise((resolve, reject) => {
@@ -61,3 +62,31 @@ async function canListenOnLocalhost() {
61
62
  });
62
63
  });
63
64
  }
65
+ /**
66
+ * Whether a login in this test could own `port` — and therefore whether
67
+ * asserting that it released the port means anything.
68
+ *
69
+ * A release assertion is a claim about our own cleanup. When an unrelated
70
+ * process already holds the port, the login fails at the probe, never binds
71
+ * anything, and cannot release anything: the port is still held afterwards,
72
+ * the code is behaving exactly as it should, and the assertion fails anyway.
73
+ * That is a test reporting on what else is running on the machine.
74
+ *
75
+ * So the gate is placed *before* the login rather than the assertion being
76
+ * widened until it always passes — a `toBe(true)` relaxed into "free or held"
77
+ * would also pass when our own cleanup leaked, which is the one thing these
78
+ * cases exist to catch.
79
+ */
80
+ async function canOwnPort(port, context) {
81
+ const free = await new Promise((resolve) => {
82
+ const probe = net.createServer();
83
+ probe.once('error', () => resolve(false));
84
+ probe.listen(port, () => probe.close(() => resolve(true)));
85
+ });
86
+ if (!free) {
87
+ console.warn(`⚠️ Port ${port} is held by another process — skipping the port-release ` +
88
+ `assertions in "${context}". A login that never bound the socket cannot ` +
89
+ 'release it; the remaining assertions in this case still run.');
90
+ }
91
+ return free;
92
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Where an essential, user-facing prompt goes.
3
+ *
4
+ * Prompts are not log lines: a device code or an authorization URL the user
5
+ * cannot see makes the flow impassable, so they must survive the absence of a
6
+ * logger. They must equally never reach stdout, which carries protocol traffic
7
+ * under an MCP or LSP stdio transport.
8
+ */
9
+ import type { ILogger } from '@mcp-abap-adt/interfaces';
10
+ export declare function announcer(logger?: ILogger): (msg: string) => void;
11
+ //# sourceMappingURL=announce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"announce.d.ts","sourceRoot":"","sources":["../../src/auth/announce.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAExD,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAKjE"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /**
3
+ * Where an essential, user-facing prompt goes.
4
+ *
5
+ * Prompts are not log lines: a device code or an authorization URL the user
6
+ * cannot see makes the flow impassable, so they must survive the absence of a
7
+ * logger. They must equally never reach stdout, which carries protocol traffic
8
+ * under an MCP or LSP stdio transport.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.announcer = announcer;
12
+ function announcer(logger) {
13
+ return (msg) => {
14
+ if (logger)
15
+ logger.info(msg);
16
+ else
17
+ process.stderr.write(`${msg}\n`);
18
+ };
19
+ }
@@ -2,9 +2,6 @@
2
2
  * Browser authentication - OAuth2 flow for obtaining tokens
3
3
  */
4
4
  import type { IAuthorizationConfig, ILogger } from '@mcp-abap-adt/interfaces';
5
- type BrowserAuthConfig = IAuthorizationConfig & {
6
- authorizationUrl?: string;
7
- };
8
5
  /**
9
6
  * Extract an OAuth2 authorization code from arbitrary pasted input.
10
7
  *
@@ -17,26 +14,35 @@ type BrowserAuthConfig = IAuthorizationConfig & {
17
14
  * @internal - Exported for testing and for manual-paste flows.
18
15
  */
19
16
  export declare function extractCode(input: string): string | null;
17
+ /**
18
+ * Build the OAuth2 authorization URL for a redirect URI that is already known.
19
+ *
20
+ * The URI is a parameter rather than a port because the port may have been
21
+ * chosen by the OS moments earlier — see `ICallbackServerOptions.port`.
22
+ */
23
+ export declare function getJwtAuthorizationUrl(authConfig: IAuthorizationConfig, redirectUri: string): string;
20
24
  /**
21
25
  * Exchange authorization code for tokens
22
26
  * @internal - Exported for testing
23
27
  */
24
- export declare function exchangeCodeForToken(authConfig: IAuthorizationConfig, code: string, port?: number, log?: ILogger | null): Promise<{
28
+ export declare function exchangeCodeForToken(authConfig: IAuthorizationConfig, code: string, redirectUri: string, log?: ILogger | null): Promise<{
25
29
  accessToken: string;
26
30
  refreshToken?: string;
27
31
  }>;
28
32
  /**
29
- * Start browser authentication flow
30
- * @param authConfig Authorization configuration with UAA credentials
31
- * @param browser Browser name (chrome, edge, firefox, system, none)
32
- * @param logger Optional logger instance. If not provided, uses default logger.
33
- * @param port Port for OAuth callback server (default: 3001)
34
- * @returns Promise that resolves to tokens
35
- * @internal - Internal function, not exported from package
33
+ * Open the authorization URL, or tell the user how to do it.
34
+ *
35
+ * Never awaited on the critical path by the caller: a launcher that hangs must
36
+ * not delay the login timeout or the release of the port. A launcher that fails
37
+ * is reported through the scope's `fail`, which is just another way for the
38
+ * scope to end.
36
39
  */
37
- export declare function startBrowserAuth(authConfig: BrowserAuthConfig, browser?: string, logger?: ILogger, port?: number): Promise<{
38
- accessToken: string;
39
- refreshToken?: string;
40
- }>;
41
- export {};
40
+ export declare function launchBrowser(authorizationUrl: string, browser: string, callbackUri: string, announce: (msg: string) => void, log: ILogger | null,
41
+ /**
42
+ * Extra guidance for 'none'/'headless', supplied only by a flow whose
43
+ * transport really offers another way in. The UAA callback server has a paste
44
+ * form on `/`; the OIDC and SAML ones do not, and promising one there sends
45
+ * the user to a 404.
46
+ */
47
+ remoteHint?: string): Promise<void>;
42
48
  //# sourceMappingURL=browserAuth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"browserAuth.d.ts","sourceRoot":"","sources":["../../src/auth/browserAuth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAI9E,KAAK,iBAAiB,GAAG,oBAAoB,GAAG;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAYF;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBxD;AAoBD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,oBAAoB,EAChC,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,MAAa,EACnB,GAAG,CAAC,EAAE,OAAO,GAAG,IAAI,GACnB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgDzD;AA6BD;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,iBAAiB,EAC7B,OAAO,GAAE,MAAiB,EAC1B,MAAM,CAAC,EAAE,OAAO,EAChB,IAAI,GAAE,MAAa,GAClB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAumBzD"}
1
+ {"version":3,"file":"browserAuth.d.ts","sourceRoot":"","sources":["../../src/auth/browserAuth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAa9E;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBxD;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,oBAAoB,EAChC,WAAW,EAAE,MAAM,GAClB,MAAM,CASR;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,oBAAoB,EAChC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,GAAG,CAAC,EAAE,OAAO,GAAG,IAAI,GACnB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA+CzD;AAeD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,gBAAgB,EAAE,MAAM,EACxB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC/B,GAAG,EAAE,OAAO,GAAG,IAAI;AACnB;;;;;GAKG;AACH,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAiGf"}