@sap-ux/backend-proxy-middleware-cf 0.0.99 → 0.1.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.
- package/README.md +62 -174
- package/dist/approuter/approuter.d.ts +27 -0
- package/dist/approuter/approuter.js +38 -0
- package/dist/approuter/extensions.d.ts +29 -0
- package/dist/approuter/extensions.js +90 -0
- package/dist/config/config.d.ts +10 -0
- package/dist/config/config.js +35 -0
- package/dist/config/constants.d.ts +10 -0
- package/dist/config/constants.js +13 -0
- package/dist/config/env.d.ts +32 -0
- package/dist/config/env.js +129 -0
- package/dist/index.d.ts +1 -1
- package/dist/middleware.js +88 -21
- package/dist/platform/bas.d.ts +19 -0
- package/dist/platform/bas.js +39 -0
- package/dist/platform/xssecurity.d.ts +10 -0
- package/dist/platform/xssecurity.js +51 -0
- package/dist/proxy/proxy.d.ts +22 -0
- package/dist/proxy/proxy.js +99 -0
- package/dist/proxy/routes.d.ts +18 -0
- package/dist/proxy/routes.js +103 -0
- package/dist/proxy/utils.d.ts +65 -0
- package/dist/proxy/utils.js +114 -0
- package/dist/types.d.ts +146 -49
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +25 -0
- package/package.json +12 -12
- package/ui5.yaml +1 -1
- package/dist/proxy.d.ts +0 -42
- package/dist/proxy.js +0 -91
- package/dist/token/factory.d.ts +0 -41
- package/dist/token/factory.js +0 -97
- package/dist/token/index.d.ts +0 -3
- package/dist/token/index.js +0 -8
- package/dist/token/provider.d.ts +0 -42
- package/dist/token/provider.js +0 -109
- package/dist/validation.d.ts +0 -11
- package/dist/validation.js +0 -30
package/dist/token/factory.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createManagerFromServiceKeys = createManagerFromServiceKeys;
|
|
4
|
-
exports.createManagerFromDirectCredentials = createManagerFromDirectCredentials;
|
|
5
|
-
exports.createTokenProvider = createTokenProvider;
|
|
6
|
-
exports.createManagerFromCfAdpProject = createManagerFromCfAdpProject;
|
|
7
|
-
const adp_tooling_1 = require("@sap-ux/adp-tooling");
|
|
8
|
-
const project_access_1 = require("@sap-ux/project-access");
|
|
9
|
-
const provider_1 = require("./provider");
|
|
10
|
-
const OAUTH_TOKEN_PATH = '/oauth/token';
|
|
11
|
-
/**
|
|
12
|
-
* Constructs the OAuth token endpoint URL from a base URL.
|
|
13
|
-
*
|
|
14
|
-
* @param {string} baseUrl - Base URL of the OAuth service.
|
|
15
|
-
* @returns {string} Full token endpoint URL.
|
|
16
|
-
*/
|
|
17
|
-
function buildTokenEndpoint(baseUrl) {
|
|
18
|
-
return `${baseUrl}${OAUTH_TOKEN_PATH}`;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Creates an OAuthTokenProvider from service keys (extracted from Cloud Foundry service instance).
|
|
22
|
-
*
|
|
23
|
-
* @param {ServiceKeys} serviceKeys - Service keys containing UAA information.
|
|
24
|
-
* @param {ToolsLogger} logger - Logger instance.
|
|
25
|
-
* @returns {OAuthTokenProvider} OAuthTokenProvider instance.
|
|
26
|
-
* @throws {Error} If service keys are invalid.
|
|
27
|
-
*/
|
|
28
|
-
function createManagerFromServiceKeys(serviceKeys, logger) {
|
|
29
|
-
const { uaa } = serviceKeys.credentials;
|
|
30
|
-
if (!uaa?.url) {
|
|
31
|
-
throw new Error('Invalid credentials: missing UAA URL');
|
|
32
|
-
}
|
|
33
|
-
if (!uaa?.clientid) {
|
|
34
|
-
throw new Error('Invalid credentials: missing client ID');
|
|
35
|
-
}
|
|
36
|
-
if (!uaa?.clientsecret) {
|
|
37
|
-
throw new Error('Invalid credentials: missing client secret');
|
|
38
|
-
}
|
|
39
|
-
const tokenEndpoint = buildTokenEndpoint(uaa.url);
|
|
40
|
-
return new provider_1.OAuthTokenProvider(uaa.clientid, uaa.clientsecret, tokenEndpoint, logger);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Creates an OAuthTokenProvider from direct OAuth credentials (provided in configuration).
|
|
44
|
-
*
|
|
45
|
-
* @param {string} clientId - OAuth2 client ID.
|
|
46
|
-
* @param {string} clientSecret - OAuth2 client secret.
|
|
47
|
-
* @param {string} baseUrl - Base URL for the OAuth service (token endpoint will be constructed as {baseUrl}/oauth/token).
|
|
48
|
-
* @param {ToolsLogger} logger - Logger instance.
|
|
49
|
-
* @returns {OAuthTokenProvider} OAuthTokenProvider instance.
|
|
50
|
-
*/
|
|
51
|
-
function createManagerFromDirectCredentials(clientId, clientSecret, baseUrl, logger) {
|
|
52
|
-
const tokenEndpoint = buildTokenEndpoint(baseUrl);
|
|
53
|
-
return new provider_1.OAuthTokenProvider(clientId, clientSecret, tokenEndpoint, logger);
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Creates an OAuth token provider based on configuration.
|
|
57
|
-
*
|
|
58
|
-
* @param {CfOAuthMiddlewareConfig} config - Configuration options.
|
|
59
|
-
* @param {ToolsLogger} logger - Logger instance.
|
|
60
|
-
* @returns {Promise<OAuthTokenProvider>} Token provider instance.
|
|
61
|
-
* @throws {Error} If token provider cannot be created.
|
|
62
|
-
*/
|
|
63
|
-
async function createTokenProvider(config, logger) {
|
|
64
|
-
if (config.credentials) {
|
|
65
|
-
logger.info('Initializing backend proxy middleware (CF) with provided credentials');
|
|
66
|
-
const { clientId, clientSecret, url } = config.credentials;
|
|
67
|
-
return createManagerFromDirectCredentials(clientId, clientSecret, url, logger);
|
|
68
|
-
}
|
|
69
|
-
logger.info('Attempting to auto-detect CF ADP project for OAuth credentials');
|
|
70
|
-
const tokenProvider = await createManagerFromCfAdpProject(process.cwd(), logger);
|
|
71
|
-
logger.info('CF ADP project detected, OAuth middleware enabled');
|
|
72
|
-
return tokenProvider;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Creates an OAuthTokenProvider from CF ADP project configuration (auto-detection).
|
|
76
|
-
*
|
|
77
|
-
* @param {string} projectPath - Path to the project root.
|
|
78
|
-
* @param {ToolsLogger} logger - Logger instance.
|
|
79
|
-
* @returns {Promise<OAuthTokenProvider>} Token provider instance.
|
|
80
|
-
*/
|
|
81
|
-
async function createManagerFromCfAdpProject(projectPath, logger) {
|
|
82
|
-
const buildTask = (0, adp_tooling_1.extractCfBuildTask)(await (0, project_access_1.readUi5Yaml)(projectPath, project_access_1.FileName.Ui5Yaml));
|
|
83
|
-
const name = buildTask.serviceInstanceName;
|
|
84
|
-
const guid = buildTask.serviceInstanceGuid;
|
|
85
|
-
if (!name || !guid) {
|
|
86
|
-
throw new Error('No service instance name or guid found in CF adaptation project build task');
|
|
87
|
-
}
|
|
88
|
-
const credentials = await (0, adp_tooling_1.getOrCreateServiceKeys)({
|
|
89
|
-
name,
|
|
90
|
-
guid
|
|
91
|
-
}, logger);
|
|
92
|
-
if (!credentials || credentials.length === 0) {
|
|
93
|
-
throw new Error('No service keys found for CF ADP project');
|
|
94
|
-
}
|
|
95
|
-
return createManagerFromServiceKeys(credentials[0], logger);
|
|
96
|
-
}
|
|
97
|
-
//# sourceMappingURL=factory.js.map
|
package/dist/token/index.d.ts
DELETED
package/dist/token/index.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createTokenProvider = exports.OAuthTokenProvider = void 0;
|
|
4
|
-
var provider_1 = require("./provider");
|
|
5
|
-
Object.defineProperty(exports, "OAuthTokenProvider", { enumerable: true, get: function () { return provider_1.OAuthTokenProvider; } });
|
|
6
|
-
var factory_1 = require("./factory");
|
|
7
|
-
Object.defineProperty(exports, "createTokenProvider", { enumerable: true, get: function () { return factory_1.createTokenProvider; } });
|
|
8
|
-
//# sourceMappingURL=index.js.map
|
package/dist/token/provider.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
-
import type { ToolsLogger } from '@sap-ux/logger';
|
|
3
|
-
/**
|
|
4
|
-
* Provides OAuth2 tokens with caching and automatic refresh.
|
|
5
|
-
*/
|
|
6
|
-
export declare class OAuthTokenProvider {
|
|
7
|
-
private readonly clientId;
|
|
8
|
-
private readonly clientSecret;
|
|
9
|
-
private readonly tokenEndpoint;
|
|
10
|
-
private readonly logger;
|
|
11
|
-
private token;
|
|
12
|
-
private tokenExpiry;
|
|
13
|
-
private tokenFetchPromise;
|
|
14
|
-
/**
|
|
15
|
-
* Creates a new OAuthTokenProvider instance.
|
|
16
|
-
*
|
|
17
|
-
* @param {string} clientId - OAuth2 client ID.
|
|
18
|
-
* @param {string} clientSecret - OAuth2 client secret.
|
|
19
|
-
* @param {string} tokenEndpoint - OAuth2 token endpoint URL.
|
|
20
|
-
* @param {ToolsLogger} logger - Logger instance.
|
|
21
|
-
*/
|
|
22
|
-
constructor(clientId: string, clientSecret: string, tokenEndpoint: string, logger: ToolsLogger);
|
|
23
|
-
/**
|
|
24
|
-
* Get a valid OAuth token, refreshing if necessary.
|
|
25
|
-
*
|
|
26
|
-
* @returns {Promise<string>} The access token.
|
|
27
|
-
*/
|
|
28
|
-
private getAccessToken;
|
|
29
|
-
/**
|
|
30
|
-
* Fetches a new OAuth2 token from the token endpoint.
|
|
31
|
-
*
|
|
32
|
-
* @returns {Promise<string>} The access token.
|
|
33
|
-
*/
|
|
34
|
-
private fetchToken;
|
|
35
|
-
/**
|
|
36
|
-
* Creates an Express middleware function that adds OAuth Bearer token to requests.
|
|
37
|
-
*
|
|
38
|
-
* @returns {RequestHandler} Express middleware function.
|
|
39
|
-
*/
|
|
40
|
-
createTokenMiddleware(): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
41
|
-
}
|
|
42
|
-
//# sourceMappingURL=provider.d.ts.map
|
package/dist/token/provider.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.OAuthTokenProvider = void 0;
|
|
7
|
-
const axios_1 = __importDefault(require("axios"));
|
|
8
|
-
/**
|
|
9
|
-
* Number of seconds before token expiry to refresh the token (safety buffer).
|
|
10
|
-
*/
|
|
11
|
-
const TOKEN_REFRESH_BUFFER_SECONDS = 60;
|
|
12
|
-
/**
|
|
13
|
-
* Provides OAuth2 tokens with caching and automatic refresh.
|
|
14
|
-
*/
|
|
15
|
-
class OAuthTokenProvider {
|
|
16
|
-
clientId;
|
|
17
|
-
clientSecret;
|
|
18
|
-
tokenEndpoint;
|
|
19
|
-
logger;
|
|
20
|
-
token = null;
|
|
21
|
-
tokenExpiry = 0;
|
|
22
|
-
tokenFetchPromise = null;
|
|
23
|
-
/**
|
|
24
|
-
* Creates a new OAuthTokenProvider instance.
|
|
25
|
-
*
|
|
26
|
-
* @param {string} clientId - OAuth2 client ID.
|
|
27
|
-
* @param {string} clientSecret - OAuth2 client secret.
|
|
28
|
-
* @param {string} tokenEndpoint - OAuth2 token endpoint URL.
|
|
29
|
-
* @param {ToolsLogger} logger - Logger instance.
|
|
30
|
-
*/
|
|
31
|
-
constructor(clientId, clientSecret, tokenEndpoint, logger) {
|
|
32
|
-
this.clientId = clientId;
|
|
33
|
-
this.clientSecret = clientSecret;
|
|
34
|
-
this.tokenEndpoint = tokenEndpoint;
|
|
35
|
-
this.logger = logger;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Get a valid OAuth token, refreshing if necessary.
|
|
39
|
-
*
|
|
40
|
-
* @returns {Promise<string>} The access token.
|
|
41
|
-
*/
|
|
42
|
-
async getAccessToken() {
|
|
43
|
-
if (this.token && Date.now() < this.tokenExpiry) {
|
|
44
|
-
return this.token;
|
|
45
|
-
}
|
|
46
|
-
// If a token fetch is already in progress, wait for it
|
|
47
|
-
if (this.tokenFetchPromise) {
|
|
48
|
-
return this.tokenFetchPromise;
|
|
49
|
-
}
|
|
50
|
-
this.tokenFetchPromise = this.fetchToken();
|
|
51
|
-
try {
|
|
52
|
-
const token = await this.tokenFetchPromise;
|
|
53
|
-
return token;
|
|
54
|
-
}
|
|
55
|
-
finally {
|
|
56
|
-
// Clear the promise so future requests can start a new fetch if needed
|
|
57
|
-
this.tokenFetchPromise = null;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Fetches a new OAuth2 token from the token endpoint.
|
|
62
|
-
*
|
|
63
|
-
* @returns {Promise<string>} The access token.
|
|
64
|
-
*/
|
|
65
|
-
async fetchToken() {
|
|
66
|
-
try {
|
|
67
|
-
this.logger.debug('Fetching new OAuth2 token...');
|
|
68
|
-
const formData = new URLSearchParams({
|
|
69
|
-
grant_type: 'client_credentials',
|
|
70
|
-
client_id: this.clientId,
|
|
71
|
-
client_secret: this.clientSecret
|
|
72
|
-
});
|
|
73
|
-
const response = await axios_1.default.post(this.tokenEndpoint, formData.toString(), {
|
|
74
|
-
headers: {
|
|
75
|
-
'Content-Type': 'application/x-www-form-urlencoded'
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
this.token = response.data.access_token;
|
|
79
|
-
const expiresIn = response.data.expires_in ?? 3600;
|
|
80
|
-
this.tokenExpiry = Date.now() + (expiresIn - TOKEN_REFRESH_BUFFER_SECONDS) * 1000;
|
|
81
|
-
this.logger.debug(`OAuth2 token obtained successfully (expires in ${expiresIn}s)`);
|
|
82
|
-
return this.token ?? '';
|
|
83
|
-
}
|
|
84
|
-
catch (e) {
|
|
85
|
-
throw new Error(`Failed to fetch OAuth2 token: ${e.message}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Creates an Express middleware function that adds OAuth Bearer token to requests.
|
|
90
|
-
*
|
|
91
|
-
* @returns {RequestHandler} Express middleware function.
|
|
92
|
-
*/
|
|
93
|
-
createTokenMiddleware() {
|
|
94
|
-
return async (req, _res, next) => {
|
|
95
|
-
this.logger.debug(`Token middleware: req.url=${req.url}, req.originalUrl=${req.originalUrl}`);
|
|
96
|
-
try {
|
|
97
|
-
const token = await this.getAccessToken();
|
|
98
|
-
req.headers.authorization = `Bearer ${token}`;
|
|
99
|
-
this.logger.debug(`Added Bearer token to request: ${req.url}`);
|
|
100
|
-
}
|
|
101
|
-
catch (e) {
|
|
102
|
-
this.logger.error(`Failed to get access token: ${e.message}`);
|
|
103
|
-
}
|
|
104
|
-
next();
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
exports.OAuthTokenProvider = OAuthTokenProvider;
|
|
109
|
-
//# sourceMappingURL=provider.js.map
|
package/dist/validation.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { ToolsLogger } from '@sap-ux/logger';
|
|
2
|
-
import type { CfOAuthMiddlewareConfig } from './types';
|
|
3
|
-
/**
|
|
4
|
-
* Validates the middleware configuration.
|
|
5
|
-
*
|
|
6
|
-
* @param {CfOAuthMiddlewareConfig} config - Configuration to validate.
|
|
7
|
-
* @param {ToolsLogger} logger - Logger instance.
|
|
8
|
-
* @throws {Error} If configuration is invalid.
|
|
9
|
-
*/
|
|
10
|
-
export declare function validateConfig(config: CfOAuthMiddlewareConfig, logger: ToolsLogger): Promise<void>;
|
|
11
|
-
//# sourceMappingURL=validation.d.ts.map
|
package/dist/validation.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateConfig = validateConfig;
|
|
4
|
-
const adp_tooling_1 = require("@sap-ux/adp-tooling");
|
|
5
|
-
/**
|
|
6
|
-
* Validates the middleware configuration.
|
|
7
|
-
*
|
|
8
|
-
* @param {CfOAuthMiddlewareConfig} config - Configuration to validate.
|
|
9
|
-
* @param {ToolsLogger} logger - Logger instance.
|
|
10
|
-
* @throws {Error} If configuration is invalid.
|
|
11
|
-
*/
|
|
12
|
-
async function validateConfig(config, logger) {
|
|
13
|
-
if (!config.backends || !Array.isArray(config.backends) || config.backends.length === 0) {
|
|
14
|
-
throw new Error('Backend proxy middleware (CF) requires "backends" array configuration.');
|
|
15
|
-
}
|
|
16
|
-
// Validate each backend
|
|
17
|
-
for (const backend of config.backends) {
|
|
18
|
-
if (!backend.url) {
|
|
19
|
-
throw new Error('Backend proxy middleware (CF) requires url for each backend.');
|
|
20
|
-
}
|
|
21
|
-
if (!backend.paths || !Array.isArray(backend.paths) || backend.paths.length === 0) {
|
|
22
|
-
throw new Error(`Backend proxy middleware (CF) has no paths configured for URL: ${backend.url}`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const cfConfig = (0, adp_tooling_1.loadCfConfig)(logger);
|
|
26
|
-
if (!(await (0, adp_tooling_1.isLoggedInCf)(cfConfig, logger))) {
|
|
27
|
-
throw new Error('User is not logged in to Cloud Foundry.');
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=validation.js.map
|