@mcp-abap-adt/auth-providers 2.2.2 → 3.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 (37) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +231 -13
  3. package/dist/__tests__/integration/stand/formLogin.d.ts +68 -0
  4. package/dist/__tests__/integration/stand/formLogin.d.ts.map +1 -0
  5. package/dist/__tests__/integration/stand/formLogin.js +194 -0
  6. package/dist/auth/callbackServer.js +2 -2
  7. package/dist/auth/passcodeAuth.d.ts +25 -0
  8. package/dist/auth/passcodeAuth.d.ts.map +1 -0
  9. package/dist/auth/passcodeAuth.js +62 -0
  10. package/dist/auth/samlBearerAssertion.d.ts +24 -0
  11. package/dist/auth/samlBearerAssertion.d.ts.map +1 -0
  12. package/dist/auth/samlBearerAssertion.js +101 -0
  13. package/dist/index.d.ts +3 -3
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +3 -2
  16. package/dist/providers/Saml2BearerProvider.d.ts.map +1 -1
  17. package/dist/providers/Saml2BearerProvider.js +4 -1
  18. package/dist/providers/UaaPasscodeProvider.d.ts +43 -0
  19. package/dist/providers/UaaPasscodeProvider.d.ts.map +1 -0
  20. package/dist/providers/UaaPasscodeProvider.js +86 -0
  21. package/dist/providers/index.d.ts +2 -2
  22. package/dist/providers/index.d.ts.map +1 -1
  23. package/dist/providers/index.js +3 -3
  24. package/dist/strategies/index.d.ts +1 -1
  25. package/dist/strategies/index.d.ts.map +1 -1
  26. package/dist/strategies/index.js +2 -1
  27. package/dist/strategies/manualStrategies.d.ts +7 -0
  28. package/dist/strategies/manualStrategies.d.ts.map +1 -1
  29. package/dist/strategies/manualStrategies.js +21 -0
  30. package/package.json +10 -5
  31. package/bin/auth-device-flow.ts +0 -114
  32. package/dist/auth/deviceFlowAuth.d.ts +0 -43
  33. package/dist/auth/deviceFlowAuth.d.ts.map +0 -1
  34. package/dist/auth/deviceFlowAuth.js +0 -168
  35. package/dist/providers/DeviceFlowProvider.d.ts +0 -32
  36. package/dist/providers/DeviceFlowProvider.d.ts.map +0 -1
  37. package/dist/providers/DeviceFlowProvider.js +0 -86
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/auth-providers",
3
- "version": "2.2.2",
3
+ "version": "3.0.0",
4
4
  "description": "Token providers for MCP ABAP ADT auth-broker",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -40,8 +40,7 @@
40
40
  },
41
41
  "bin": {
42
42
  "auth-authorization-code": "./bin/auth-authorization-code.ts",
43
- "auth-client-credentials": "./bin/auth-client-credentials.ts",
44
- "auth-device-flow": "./bin/auth-device-flow.ts"
43
+ "auth-client-credentials": "./bin/auth-client-credentials.ts"
45
44
  },
46
45
  "scripts": {
47
46
  "chrono": "./tools/version-stats.sh",
@@ -53,15 +52,20 @@
53
52
  "build:fast": "npx tsc -p tsconfig.json",
54
53
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
55
54
  "test:check": "npx tsc --noEmit",
56
- "prepublishOnly": "npm run build"
55
+ "prepublishOnly": "npm run build",
56
+ "stand:up": "tests/stand/up.sh",
57
+ "stand:down": "tests/stand/down.sh",
58
+ "test:stand": "tests/stand/run.sh",
59
+ "test:xsuaa": "tests/xsuaa/run.sh"
57
60
  },
58
61
  "engines": {
59
- "node": ">=18.2.0"
62
+ "node": "^22 || ^24"
60
63
  },
61
64
  "dependencies": {
62
65
  "@mcp-abap-adt/interfaces-auth": "^1.2.0",
63
66
  "@mcp-abap-adt/interfaces-auth-sap": "^1.0.0",
64
67
  "@mcp-abap-adt/interfaces-utils": "^1.1.0",
68
+ "@xmldom/xmldom": "^0.9.12",
65
69
  "axios": "^1.13.5",
66
70
  "express": "^5.1.0",
67
71
  "open": "^11.0.0"
@@ -69,6 +73,7 @@
69
73
  "devDependencies": {
70
74
  "@biomejs/biome": "^2.3.14",
71
75
  "@jest/globals": "^30.2.0",
76
+ "@mcp-abap-adt/auth-mocks": "^0.3.0",
72
77
  "@mcp-abap-adt/auth-stores": "^1.0.1",
73
78
  "@mcp-abap-adt/logger": "^0.4.0",
74
79
  "@types/express": "^5.0.5",
@@ -1,114 +0,0 @@
1
- #!/usr/bin/env tsx
2
- /**
3
- * Device Flow Provider Test Command
4
- */
5
-
6
- import { DeviceFlowProvider } from '../src/providers/DeviceFlowProvider';
7
- import {
8
- getUaaCredentials,
9
- parseEnvFile,
10
- parseServiceKey,
11
- writeEnvFile,
12
- } from './utils/parseConfig';
13
-
14
- async function main() {
15
- const args = process.argv.slice(2);
16
- let serviceKeyPath: string | undefined;
17
- let inputEnvPath: string | undefined;
18
- let outputEnvPath: string | undefined;
19
- let scope: string | undefined;
20
-
21
- for (let i = 0; i < args.length; i++) {
22
- const arg = args[i];
23
- if (arg === '--service-key' && args[i + 1]) {
24
- serviceKeyPath = args[++i];
25
- } else if (arg === '--input-env' && args[i + 1]) {
26
- inputEnvPath = args[++i];
27
- } else if (arg === '--output-env' && args[i + 1]) {
28
- outputEnvPath = args[++i];
29
- } else if (arg === '--scope' && args[i + 1]) {
30
- scope = args[++i];
31
- } else if (arg === '--help' || arg === '-h') {
32
- console.log(`
33
- Usage: auth-device-flow [options]
34
-
35
- Options:
36
- --service-key <path> Path to service key JSON file
37
- --input-env <path> Path to .env file for reading existing tokens (for refresh)
38
- --output-env <path> Path to .env file for saving tokens
39
- --scope <scope> Optional scope (space-separated)
40
- --help, -h Show this help message
41
- `);
42
- process.exit(0);
43
- }
44
- }
45
-
46
- if (!serviceKeyPath && !inputEnvPath) {
47
- console.error('❌ Error: Either --service-key or --input-env must be provided');
48
- process.exit(1);
49
- }
50
-
51
- if (!outputEnvPath) {
52
- console.error('❌ Error: --output-env is required to save tokens');
53
- process.exit(1);
54
- }
55
-
56
- try {
57
- // Read config from service key or input env
58
- const serviceKey = serviceKeyPath ? parseServiceKey(serviceKeyPath) : undefined;
59
- const inputEnv = inputEnvPath ? parseEnvFile(inputEnvPath) : undefined;
60
- const { uaaUrl, clientId, clientSecret } = getUaaCredentials(serviceKey, inputEnv);
61
-
62
- // Read existing tokens from input env if provided
63
- const existingAccessToken = inputEnv?.AUTHORIZATION_TOKEN;
64
- const existingRefreshToken = inputEnv?.REFRESH_TOKEN;
65
-
66
- const provider = new DeviceFlowProvider({
67
- uaaUrl,
68
- clientId,
69
- clientSecret,
70
- scope,
71
- accessToken: existingAccessToken,
72
- refreshToken: existingRefreshToken,
73
- });
74
-
75
- console.log('🔐 Getting tokens using Device Flow...');
76
- if (serviceKeyPath) {
77
- console.log(`📁 Service Key: ${serviceKeyPath}`);
78
- }
79
- if (inputEnvPath) {
80
- console.log(`📁 Input Env: ${inputEnvPath}`);
81
- }
82
- console.log(`💾 Output Env: ${outputEnvPath}\n`);
83
-
84
- const result = await provider.getTokens();
85
-
86
- // Save tokens to output env file
87
- writeEnvFile(outputEnvPath, {
88
- authorizationToken: result.authorizationToken,
89
- refreshToken: result.refreshToken,
90
- uaaUrl,
91
- clientId,
92
- clientSecret,
93
- });
94
-
95
- console.log('✅ Tokens obtained and saved successfully!');
96
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
97
- console.log(`🔑 Authorization Token: ${result.authorizationToken.substring(0, 50)}...`);
98
- if (result.refreshToken) {
99
- console.log(`🔄 Refresh Token: ${result.refreshToken.substring(0, 50)}...`);
100
- }
101
- console.log(`📋 Auth Type: ${result.authType}`);
102
- if (result.expiresIn) {
103
- console.log(`⏰ Expires In: ${result.expiresIn} seconds`);
104
- }
105
- console.log(`💾 Saved to: ${outputEnvPath}`);
106
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
107
- } catch (error) {
108
- console.error('❌ Error:', error instanceof Error ? error.message : String(error));
109
- process.exit(1);
110
- }
111
- }
112
-
113
- main();
114
-
@@ -1,43 +0,0 @@
1
- /**
2
- * Device Flow authentication
3
- *
4
- * OAuth2 Device Flow for devices without browser or input capabilities.
5
- * User authorizes on another device by entering a code.
6
- */
7
- import type { ILogger } from '@mcp-abap-adt/interfaces-utils';
8
- export interface DeviceFlowResult {
9
- deviceCode: string;
10
- userCode: string;
11
- verificationUri: string;
12
- verificationUriComplete?: string;
13
- expiresIn: number;
14
- interval?: number;
15
- }
16
- export interface DeviceFlowTokens {
17
- accessToken: string;
18
- refreshToken?: string;
19
- expiresIn?: number;
20
- }
21
- /**
22
- * Initiate device flow - get device code and user code
23
- * @param uaaUrl UAA URL
24
- * @param clientId Client ID
25
- * @param scope Optional scope (space-separated)
26
- * @param logger Optional logger
27
- * @returns Promise that resolves to device flow result
28
- * @internal - Internal function, not exported from package
29
- */
30
- export declare function initiateDeviceFlow(uaaUrl: string, clientId: string, scope?: string, logger?: ILogger): Promise<DeviceFlowResult>;
31
- /**
32
- * Poll for tokens using device code
33
- * @param uaaUrl UAA URL
34
- * @param clientId Client ID
35
- * @param clientSecret Client secret (optional for public clients)
36
- * @param deviceCode Device code from initiateDeviceFlow
37
- * @param interval Polling interval in seconds
38
- * @param logger Optional logger
39
- * @returns Promise that resolves to tokens
40
- * @internal - Internal function, not exported from package
41
- */
42
- export declare function pollForDeviceTokens(uaaUrl: string, clientId: string, clientSecret: string | undefined, deviceCode: string, interval?: number, logger?: ILogger): Promise<DeviceFlowTokens>;
43
- //# sourceMappingURL=deviceFlowAuth.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deviceFlowAuth.d.ts","sourceRoot":"","sources":["../../src/auth/deviceFlowAuth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAG9D,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,gBAAgB,CAAC,CA4D3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,MAAU,EACpB,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,gBAAgB,CAAC,CAoG3B"}
@@ -1,168 +0,0 @@
1
- "use strict";
2
- /**
3
- * Device Flow authentication
4
- *
5
- * OAuth2 Device Flow for devices without browser or input capabilities.
6
- * User authorizes on another device by entering a code.
7
- */
8
- var __importDefault = (this && this.__importDefault) || function (mod) {
9
- return (mod && mod.__esModule) ? mod : { "default": mod };
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.initiateDeviceFlow = initiateDeviceFlow;
13
- exports.pollForDeviceTokens = pollForDeviceTokens;
14
- const axios_1 = __importDefault(require("axios"));
15
- /**
16
- * Initiate device flow - get device code and user code
17
- * @param uaaUrl UAA URL
18
- * @param clientId Client ID
19
- * @param scope Optional scope (space-separated)
20
- * @param logger Optional logger
21
- * @returns Promise that resolves to device flow result
22
- * @internal - Internal function, not exported from package
23
- */
24
- async function initiateDeviceFlow(uaaUrl, clientId, scope, logger) {
25
- try {
26
- const deviceUrl = `${uaaUrl}/oauth/device_authorization`;
27
- const params = new URLSearchParams();
28
- params.append('client_id', clientId);
29
- if (scope) {
30
- params.append('scope', scope);
31
- }
32
- logger?.info(`Initiating device flow: ${deviceUrl}`);
33
- const response = await (0, axios_1.default)({
34
- method: 'post',
35
- url: deviceUrl,
36
- headers: {
37
- 'Content-Type': 'application/x-www-form-urlencoded',
38
- },
39
- data: params.toString(),
40
- timeout: 30000,
41
- });
42
- if (response.data?.device_code &&
43
- response.data?.user_code &&
44
- response.data?.verification_uri) {
45
- return {
46
- deviceCode: response.data.device_code,
47
- userCode: response.data.user_code,
48
- verificationUri: response.data.verification_uri,
49
- verificationUriComplete: response.data.verification_uri_complete,
50
- expiresIn: response.data.expires_in || 1800, // Default 30 minutes
51
- interval: response.data.interval || 5, // Default 5 seconds
52
- };
53
- }
54
- else {
55
- throw new Error('Response does not contain required device flow fields');
56
- }
57
- }
58
- catch (error) {
59
- if (error &&
60
- typeof error === 'object' &&
61
- 'response' in error &&
62
- error.response &&
63
- typeof error.response === 'object' &&
64
- 'status' in error.response &&
65
- 'data' in error.response) {
66
- const axiosError = error;
67
- throw new Error(`Device flow initiation failed (${axiosError.response.status}): ${JSON.stringify(axiosError.response.data)}`);
68
- }
69
- else {
70
- const errorMessage = error instanceof Error ? error.message : String(error);
71
- throw new Error(`Device flow initiation failed: ${errorMessage}`);
72
- }
73
- }
74
- }
75
- /**
76
- * Poll for tokens using device code
77
- * @param uaaUrl UAA URL
78
- * @param clientId Client ID
79
- * @param clientSecret Client secret (optional for public clients)
80
- * @param deviceCode Device code from initiateDeviceFlow
81
- * @param interval Polling interval in seconds
82
- * @param logger Optional logger
83
- * @returns Promise that resolves to tokens
84
- * @internal - Internal function, not exported from package
85
- */
86
- async function pollForDeviceTokens(uaaUrl, clientId, clientSecret, deviceCode, interval = 5, logger) {
87
- const tokenUrl = `${uaaUrl}/oauth/token`;
88
- const params = new URLSearchParams();
89
- params.append('grant_type', 'urn:ietf:params:oauth:grant-type:device_code');
90
- params.append('device_code', deviceCode);
91
- params.append('client_id', clientId);
92
- const headers = {
93
- 'Content-Type': 'application/x-www-form-urlencoded',
94
- };
95
- // Add client secret if provided (for confidential clients)
96
- if (clientSecret) {
97
- const authString = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
98
- headers.Authorization = `Basic ${authString}`;
99
- }
100
- // Poll until authorization is complete or expires
101
- const maxAttempts = 120; // 10 minutes max (120 * 5 seconds)
102
- let attempts = 0;
103
- while (attempts < maxAttempts) {
104
- try {
105
- logger?.debug(`Polling for device tokens (attempt ${attempts + 1})`);
106
- const response = await (0, axios_1.default)({
107
- method: 'post',
108
- url: tokenUrl,
109
- headers,
110
- data: params.toString(),
111
- timeout: 30000,
112
- });
113
- if (response.data?.access_token) {
114
- logger?.info('Device flow authorization successful');
115
- return {
116
- accessToken: response.data.access_token,
117
- refreshToken: response.data.refresh_token,
118
- expiresIn: response.data.expires_in,
119
- };
120
- }
121
- else {
122
- throw new Error('Response does not contain access_token');
123
- }
124
- }
125
- catch (error) {
126
- // Check if it's an "authorization_pending" error (expected during polling)
127
- if (error &&
128
- typeof error === 'object' &&
129
- 'response' in error &&
130
- error.response &&
131
- typeof error.response === 'object' &&
132
- 'status' in error.response &&
133
- 'data' in error.response) {
134
- const axiosError = error;
135
- if (axiosError.response.data?.error === 'authorization_pending') {
136
- // Still waiting for user authorization - continue polling
137
- attempts++;
138
- if (attempts >= maxAttempts) {
139
- throw new Error('Device flow authorization timeout - user did not authorize in time');
140
- }
141
- // Wait for interval before next poll
142
- await new Promise((resolve) => setTimeout(resolve, interval * 1000));
143
- continue;
144
- }
145
- else if (axiosError.response.data?.error === 'slow_down') {
146
- // Server requests slower polling - increase interval by 5 seconds
147
- interval += 5;
148
- attempts++;
149
- if (attempts >= maxAttempts) {
150
- throw new Error('Device flow authorization timeout - user did not authorize in time');
151
- }
152
- await new Promise((resolve) => setTimeout(resolve, interval * 1000));
153
- continue;
154
- }
155
- else if (axiosError.response.data?.error === 'expired_token') {
156
- throw new Error('Device code expired - please restart device flow');
157
- }
158
- else if (axiosError.response.data?.error === 'access_denied') {
159
- throw new Error('User denied device authorization');
160
- }
161
- }
162
- // Other error - rethrow
163
- const errorMessage = error instanceof Error ? error.message : String(error);
164
- throw new Error(`Device flow polling failed: ${errorMessage}`);
165
- }
166
- }
167
- throw new Error('Device flow authorization timeout - maximum polling attempts reached');
168
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * Device Flow Token Provider
3
- *
4
- * Uses OAuth2 Device Flow for devices without browser or input capabilities.
5
- * User authorizes on another device by entering a code.
6
- */
7
- import type { ITokenResult, OAuth2GrantType } from '@mcp-abap-adt/interfaces-auth';
8
- import type { ILogger } from '@mcp-abap-adt/interfaces-utils';
9
- import { BaseTokenProvider } from './BaseTokenProvider';
10
- export interface DeviceFlowProviderConfig {
11
- uaaUrl: string;
12
- clientId: string;
13
- clientSecret?: string;
14
- scope?: string;
15
- accessToken?: string;
16
- refreshToken?: string;
17
- logger?: ILogger;
18
- }
19
- /**
20
- * Device Flow token provider
21
- *
22
- * Uses OAuth2 Device Flow - user authorizes on another device.
23
- * Supports refresh token if provided by server.
24
- */
25
- export declare class DeviceFlowProvider extends BaseTokenProvider {
26
- private config;
27
- constructor(config: DeviceFlowProviderConfig);
28
- protected getAuthType(): OAuth2GrantType;
29
- protected performLogin(): Promise<ITokenResult>;
30
- protected performRefresh(): Promise<ITokenResult>;
31
- }
32
- //# sourceMappingURL=DeviceFlowProvider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DeviceFlowProvider.d.ts","sourceRoot":"","sources":["../../src/providers/DeviceFlowProvider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EAChB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAO9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,iBAAiB;IACvD,OAAO,CAAC,MAAM,CAA2B;gBAE7B,MAAM,EAAE,wBAAwB;IAc5C,SAAS,CAAC,WAAW,IAAI,eAAe;cAOxB,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC;cAyCrC,cAAc,IAAI,OAAO,CAAC,YAAY,CAAC;CA2BxD"}
@@ -1,86 +0,0 @@
1
- "use strict";
2
- /**
3
- * Device Flow Token Provider
4
- *
5
- * Uses OAuth2 Device Flow for devices without browser or input capabilities.
6
- * User authorizes on another device by entering a code.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.DeviceFlowProvider = void 0;
10
- const interfaces_auth_1 = require("@mcp-abap-adt/interfaces-auth");
11
- const announce_1 = require("../auth/announce");
12
- const deviceFlowAuth_1 = require("../auth/deviceFlowAuth");
13
- const tokenRefresher_1 = require("../auth/tokenRefresher");
14
- const BaseTokenProvider_1 = require("./BaseTokenProvider");
15
- /**
16
- * Device Flow token provider
17
- *
18
- * Uses OAuth2 Device Flow - user authorizes on another device.
19
- * Supports refresh token if provided by server.
20
- */
21
- class DeviceFlowProvider extends BaseTokenProvider_1.BaseTokenProvider {
22
- config;
23
- constructor(config) {
24
- super();
25
- this.config = config;
26
- this.logger = config.logger;
27
- if (config.accessToken) {
28
- this.authorizationToken = config.accessToken;
29
- this.expiresAt = this.parseExpirationFromJWT(config.accessToken);
30
- }
31
- if (config.refreshToken) {
32
- this.refreshToken = config.refreshToken;
33
- }
34
- }
35
- getAuthType() {
36
- // Device Flow is not a standard grant type in OAuth2 spec
37
- // We'll use a custom type or map it to authorization_code
38
- // For now, using authorization_code as it's similar
39
- return interfaces_auth_1.AUTH_TYPE_AUTHORIZATION_CODE;
40
- }
41
- async performLogin() {
42
- // Initiate device flow
43
- const deviceFlow = await (0, deviceFlowAuth_1.initiateDeviceFlow)(this.config.uaaUrl, this.config.clientId, this.config.scope, this.logger);
44
- // Display user code and verification URI. This is a prompt the user must
45
- // see to complete the flow, not a log line — it goes to the logger when
46
- // there is one and to stderr otherwise, never to stdout.
47
- const announce = (0, announce_1.announcer)(this.logger);
48
- announce('Device Flow Authorization');
49
- announce(`Go to: ${deviceFlow.verificationUri}`);
50
- if (deviceFlow.verificationUriComplete) {
51
- announce(`Or use complete URL: ${deviceFlow.verificationUriComplete}`);
52
- }
53
- announce(`Enter code: ${deviceFlow.userCode}`);
54
- announce('Waiting for authorization...');
55
- // Poll for tokens
56
- const result = await (0, deviceFlowAuth_1.pollForDeviceTokens)(this.config.uaaUrl, this.config.clientId, this.config.clientSecret, deviceFlow.deviceCode, deviceFlow.interval, this.logger);
57
- const expiresIn = this.calculateExpiresIn(result.accessToken);
58
- return {
59
- authorizationToken: result.accessToken,
60
- refreshToken: result.refreshToken,
61
- authType: interfaces_auth_1.AUTH_TYPE_AUTHORIZATION_CODE, // Device flow maps to authorization_code
62
- expiresIn,
63
- };
64
- }
65
- async performRefresh() {
66
- if (!this.refreshToken) {
67
- // No refresh token - re-authenticate with device flow
68
- return await this.performLogin();
69
- }
70
- try {
71
- const result = await (0, tokenRefresher_1.refreshJwtToken)(this.refreshToken, this.config.uaaUrl, this.config.clientId, this.config.clientSecret || '');
72
- const expiresIn = this.calculateExpiresIn(result.accessToken);
73
- return {
74
- authorizationToken: result.accessToken,
75
- refreshToken: result.refreshToken || this.refreshToken,
76
- authType: interfaces_auth_1.AUTH_TYPE_AUTHORIZATION_CODE,
77
- expiresIn,
78
- };
79
- }
80
- catch (_error) {
81
- // Refresh failed - try device flow login
82
- return await this.performLogin();
83
- }
84
- }
85
- }
86
- exports.DeviceFlowProvider = DeviceFlowProvider;