@dataflint/mcp-server 1.0.15 → 1.0.17
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/dist/auth/secrets/aws-secrets-provider.d.ts.map +1 -1
- package/dist/auth/secrets/aws-secrets-provider.js +3 -1
- package/dist/auth/secrets/aws-secrets-provider.js.map +1 -1
- package/dist/auth.d.ts +47 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +302 -0
- package/dist/auth.js.map +1 -0
- package/dist/dataflint-server-service.d.ts +3 -6
- package/dist/dataflint-server-service.d.ts.map +1 -1
- package/dist/dataflint-server-service.js +48 -133
- package/dist/dataflint-server-service.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -11
- package/dist/index.js.map +1 -1
- package/dist/request-context.d.ts +0 -20
- package/dist/request-context.d.ts.map +1 -1
- package/dist/request-context.js +1 -31
- package/dist/request-context.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +14 -16
- package/dist/server.js.map +1 -1
- package/dist/standalone/config.d.ts +7 -13
- package/dist/standalone/config.d.ts.map +1 -1
- package/dist/standalone/config.js +1387 -280
- package/dist/standalone/config.js.map +7 -1
- package/dist/standalone/logger.js +2 -2
- package/dist/standalone/logger.js.map +1 -1
- package/dist/standalone/server.d.ts.map +1 -1
- package/dist/standalone/server.js +25 -45
- package/dist/standalone/server.js.map +1 -1
- package/dist/standalone/stdio-transport.d.ts +1 -2
- package/dist/standalone/stdio-transport.d.ts.map +1 -1
- package/dist/standalone/stdio-transport.js +4 -3
- package/dist/standalone/stdio-transport.js.map +1 -1
- package/dist/tools/base.d.ts +16 -0
- package/dist/tools/base.d.ts.map +1 -1
- package/dist/tools/base.js +16 -0
- package/dist/tools/base.js.map +1 -1
- package/dist/tools/core-tools.d.ts.map +1 -1
- package/dist/tools/core-tools.js +4 -4
- package/dist/tools/core-tools.js.map +1 -1
- package/dist/tools/expertise-tools.d.ts.map +1 -1
- package/dist/tools/expertise-tools.js +5 -5
- package/dist/tools/expertise-tools.js.map +1 -1
- package/dist/tools/findings-tools.d.ts.map +1 -1
- package/dist/tools/findings-tools.js +4 -4
- package/dist/tools/findings-tools.js.map +1 -1
- package/dist/tools/highlight-tools.d.ts.map +1 -1
- package/dist/tools/highlight-tools.js +8 -10
- package/dist/tools/highlight-tools.js.map +1 -1
- package/dist/tools/listing-tools.d.ts.map +1 -1
- package/dist/tools/listing-tools.js +1 -1
- package/dist/tools/listing-tools.js.map +1 -1
- package/dist/types.d.ts +13 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -5
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
|
@@ -1,317 +1,1424 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
|
|
28
|
+
// dist/auth/customer-auth-configs.js
|
|
29
|
+
var require_customer_auth_configs = __commonJS({
|
|
30
|
+
"dist/auth/customer-auth-configs.js"(exports2) {
|
|
31
|
+
"use strict";
|
|
32
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
33
|
+
exports2.customerAuthConfigs = void 0;
|
|
34
|
+
exports2.customerAuthConfigs = {
|
|
35
|
+
// Customer domain hash → Auth0 configuration
|
|
36
|
+
"857064adfec4e0e5e37be8afef397155db006bb6009d1b395388d9174eb40795": {
|
|
37
|
+
clientId: "CWvpqujjEV2aoRSDVWFSh1U6HQALygB0",
|
|
38
|
+
domainProducer: (customerDomain) => `https://dataflint-${customerDomain}.us.auth0.com/`
|
|
39
|
+
},
|
|
40
|
+
cafe6e0af028d729afd3c4a386482621af90e8e117b1216f2bbc08e86a5e9445: {
|
|
41
|
+
clientId: "HRLICLhE0BP4AeZ8dSPAoDHFmMZVacxi"
|
|
42
|
+
},
|
|
43
|
+
"1613f29ea956158d2ad56a10780feb45d78755819565e76c4bf0d9069d17aab9": {
|
|
44
|
+
clientId: "CnyJJKVqes0Y0uU57GreAeaPbJlm4l4w"
|
|
45
|
+
},
|
|
46
|
+
eae8e3404182477f008479b38a6629ee86b23cefe2c418c5dc5c2f0d02af5475: {
|
|
47
|
+
clientId: "etY3z44ssWohe77PEBIMPzktW4BmvWGT"
|
|
48
|
+
},
|
|
49
|
+
// dataflint-demo (added from commit f38928c)
|
|
50
|
+
cc1677626e05d82b301cc83c22a850eac849555e704f288083108d79f600cea1: {
|
|
51
|
+
clientId: "u9W23NGvlV58W2N9WXMMhsM12bKK8oGI"
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
17
55
|
});
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
56
|
+
|
|
57
|
+
// dist/auth/types.js
|
|
58
|
+
var require_types = __commonJS({
|
|
59
|
+
"dist/auth/types.js"(exports2) {
|
|
60
|
+
"use strict";
|
|
61
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
62
|
+
exports2.M2MType = exports2.AuthStrategyType = void 0;
|
|
63
|
+
var AuthStrategyType;
|
|
64
|
+
(function(AuthStrategyType2) {
|
|
65
|
+
AuthStrategyType2["SERVICE_ACCOUNT"] = "service_account";
|
|
66
|
+
AuthStrategyType2["AUTH0_M2M"] = "auth0_m2m";
|
|
67
|
+
AuthStrategyType2["AUTH0_USER"] = "auth0_user";
|
|
68
|
+
})(AuthStrategyType || (exports2.AuthStrategyType = AuthStrategyType = {}));
|
|
69
|
+
var M2MType;
|
|
70
|
+
(function(M2MType2) {
|
|
71
|
+
M2MType2["NONE"] = "none";
|
|
72
|
+
M2MType2["SERVICE_ACCOUNT"] = "service_account";
|
|
73
|
+
M2MType2["AUTH0_M2M"] = "auth0_m2m";
|
|
74
|
+
})(M2MType || (exports2.M2MType = M2MType = {}));
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// dist/auth/auth0-service.js
|
|
79
|
+
var require_auth0_service = __commonJS({
|
|
80
|
+
"dist/auth/auth0-service.js"(exports2) {
|
|
81
|
+
"use strict";
|
|
82
|
+
var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
83
|
+
if (k2 === void 0) k2 = k;
|
|
84
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
85
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
86
|
+
desc = { enumerable: true, get: function() {
|
|
87
|
+
return m[k];
|
|
88
|
+
} };
|
|
89
|
+
}
|
|
90
|
+
Object.defineProperty(o, k2, desc);
|
|
91
|
+
}) : (function(o, m, k, k2) {
|
|
92
|
+
if (k2 === void 0) k2 = k;
|
|
93
|
+
o[k2] = m[k];
|
|
94
|
+
}));
|
|
95
|
+
var __setModuleDefault2 = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
96
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
97
|
+
}) : function(o, v) {
|
|
98
|
+
o["default"] = v;
|
|
99
|
+
});
|
|
100
|
+
var __importStar2 = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
101
|
+
var ownKeys = function(o) {
|
|
102
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
103
|
+
var ar = [];
|
|
104
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
105
|
+
return ar;
|
|
24
106
|
};
|
|
25
107
|
return ownKeys(o);
|
|
26
|
-
|
|
27
|
-
|
|
108
|
+
};
|
|
109
|
+
return function(mod) {
|
|
28
110
|
if (mod && mod.__esModule) return mod;
|
|
29
111
|
var result = {};
|
|
30
|
-
if (mod != null)
|
|
31
|
-
|
|
112
|
+
if (mod != null) {
|
|
113
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding2(result, mod, k[i]);
|
|
114
|
+
}
|
|
115
|
+
__setModuleDefault2(result, mod);
|
|
32
116
|
return result;
|
|
117
|
+
};
|
|
118
|
+
})();
|
|
119
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
120
|
+
exports2.Auth0Service = void 0;
|
|
121
|
+
var http = __importStar2(require("http"));
|
|
122
|
+
var openid_client_1 = require("openid-client");
|
|
123
|
+
var url_1 = require("url");
|
|
124
|
+
var AUTH_DISCOVERY_TIMEOUT_MS = 1e4;
|
|
125
|
+
openid_client_1.custom.setHttpOptionsDefaults({
|
|
126
|
+
timeout: AUTH_DISCOVERY_TIMEOUT_MS
|
|
127
|
+
});
|
|
128
|
+
var noopLogger = {
|
|
129
|
+
info: () => {
|
|
130
|
+
},
|
|
131
|
+
warn: () => {
|
|
132
|
+
},
|
|
133
|
+
error: () => {
|
|
134
|
+
},
|
|
135
|
+
debug: () => {
|
|
136
|
+
}
|
|
33
137
|
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
authDomain: zod_1.z.string().optional(),
|
|
62
|
-
clientId: zod_1.z.string().optional(),
|
|
63
|
-
audience: zod_1.z.string().optional(),
|
|
64
|
-
scope: zod_1.z.string().optional(),
|
|
65
|
-
credentialsPath: zod_1.z.string().optional(),
|
|
66
|
-
adminCompanyDomain: zod_1.z.string().optional(),
|
|
67
|
-
customerDomain: zod_1.z.string().optional(),
|
|
68
|
-
m2mTokenPath: zod_1.z.string().optional(),
|
|
69
|
-
m2mSecretName: zod_1.z.string().optional(),
|
|
70
|
-
tenantId: zod_1.z.string().optional(),
|
|
71
|
-
})
|
|
72
|
-
.strict();
|
|
73
|
-
class StandaloneConfigService {
|
|
74
|
-
config;
|
|
75
|
-
credentialsPath;
|
|
76
|
-
m2mMode;
|
|
77
|
-
constructor(config = {}) {
|
|
78
|
-
this.config = this.mergeWithDefaults(config);
|
|
79
|
-
this.m2mMode = this.detectM2MMode();
|
|
80
|
-
this.validateM2MConfig();
|
|
81
|
-
this.credentialsPath =
|
|
82
|
-
config.credentialsPath || this.defaultCredentialsPath();
|
|
83
|
-
this.ensureDataflintDirectory();
|
|
84
|
-
}
|
|
85
|
-
defaultCredentialsPath() {
|
|
86
|
-
const hash = crypto
|
|
87
|
-
.createHash("sha256")
|
|
88
|
-
.update(this.config.clientId || DEFAULT_CLIENT_ID_FOR_HASH)
|
|
89
|
-
.digest("hex")
|
|
90
|
-
.substring(0, HASH_PREFIX_LENGTH);
|
|
91
|
-
return path.join(os.homedir(), ".dataflint", `credentials-${hash}.json`);
|
|
92
|
-
}
|
|
93
|
-
ensureDataflintDirectory() {
|
|
94
|
-
const dir = path.dirname(this.credentialsPath);
|
|
95
|
-
if (!fs.existsSync(dir)) {
|
|
96
|
-
fs.mkdirSync(dir, { recursive: true, mode: CREDENTIALS_DIR_MODE });
|
|
138
|
+
var Auth0Service = class {
|
|
139
|
+
config;
|
|
140
|
+
redirectUri;
|
|
141
|
+
callbackPort;
|
|
142
|
+
client = null;
|
|
143
|
+
issuer = null;
|
|
144
|
+
initialized = false;
|
|
145
|
+
openUrlHandler;
|
|
146
|
+
logger;
|
|
147
|
+
constructor(openUrlHandler, configProvider, logger, callbackPort = 11334) {
|
|
148
|
+
this.logger = logger || noopLogger;
|
|
149
|
+
this.openUrlHandler = openUrlHandler;
|
|
150
|
+
this.config = {
|
|
151
|
+
...configProvider(),
|
|
152
|
+
scope: configProvider().scope || "openid profile email"
|
|
153
|
+
};
|
|
154
|
+
this.callbackPort = callbackPort;
|
|
155
|
+
this.redirectUri = `http://localhost:${callbackPort}/callback`;
|
|
156
|
+
this.logger.info(`Auth0Service initialized for domain: ${this.config.domain}`);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Initialize the Auth0 client by discovering the issuer metadata
|
|
160
|
+
*/
|
|
161
|
+
async initialize() {
|
|
162
|
+
if (this.initialized) {
|
|
163
|
+
this.logger.debug("Auth0 client already initialized");
|
|
164
|
+
return;
|
|
97
165
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
166
|
+
try {
|
|
167
|
+
const issuerUrl = this.config.domain.startsWith("http") ? this.config.domain : `https://${this.config.domain}`;
|
|
168
|
+
this.logger.info(`Attempting to discover Auth0 issuer at: ${issuerUrl}`);
|
|
169
|
+
this.logger.debug(`Discovery URL will be: ${issuerUrl}`);
|
|
170
|
+
this.issuer = await openid_client_1.Issuer.discover(issuerUrl);
|
|
171
|
+
this.logger.info(`Auth0 issuer discovered successfully: ${this.issuer.issuer}`);
|
|
172
|
+
this.client = new this.issuer.Client({
|
|
173
|
+
client_id: this.config.clientId,
|
|
174
|
+
redirect_uris: [this.redirectUri],
|
|
175
|
+
response_types: ["code"],
|
|
176
|
+
token_endpoint_auth_method: "none"
|
|
177
|
+
// Public client, no client secret required
|
|
178
|
+
});
|
|
179
|
+
this.initialized = true;
|
|
180
|
+
this.logger.info("Auth0 client initialized successfully");
|
|
181
|
+
} catch (error) {
|
|
182
|
+
this.logger.error("Failed to initialize Auth0 client", error);
|
|
183
|
+
this.logger.error(`Auth0 domain: ${this.config.domain}`);
|
|
184
|
+
this.logger.error(`Client ID: ${this.config.clientId}`);
|
|
185
|
+
this.logger.error(`Constructed issuer URL: ${this.config.domain.startsWith("http") ? this.config.domain : `https://${this.config.domain}`}`);
|
|
186
|
+
if (error instanceof Error) {
|
|
187
|
+
if (error.message.includes("404") || error.message.includes("Not Found")) {
|
|
188
|
+
throw new Error(`Auth0 domain '${this.config.domain}' not found. Please verify your Auth0 domain configuration. The discovery endpoint ${this.config.domain} returned 404.`);
|
|
189
|
+
} else if (error.message.includes("ENOTFOUND") || error.message.includes("getaddrinfo")) {
|
|
190
|
+
throw new Error(`Cannot connect to Auth0 domain '${this.config.domain}'. Please check your internet connection and verify the domain is correct.`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
throw new Error(`Auth0 initialization failed: ${error}`);
|
|
117
194
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Start the authentication flow
|
|
198
|
+
*/
|
|
199
|
+
async authenticate() {
|
|
200
|
+
if (!this.client) {
|
|
201
|
+
await this.initialize();
|
|
202
|
+
}
|
|
203
|
+
if (!this.client) {
|
|
204
|
+
throw new Error("Auth0 client not initialized");
|
|
123
205
|
}
|
|
124
|
-
const
|
|
206
|
+
const codeVerifier = openid_client_1.generators.codeVerifier();
|
|
207
|
+
const codeChallenge = openid_client_1.generators.codeChallenge(codeVerifier);
|
|
208
|
+
const authUrl = this.client.authorizationUrl({
|
|
209
|
+
scope: this.config.scope,
|
|
210
|
+
code_challenge: codeChallenge,
|
|
211
|
+
code_challenge_method: "S256",
|
|
212
|
+
...this.config.audience && { audience: this.config.audience }
|
|
213
|
+
});
|
|
214
|
+
this.logger.info("Opening browser for authentication...");
|
|
125
215
|
try {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
216
|
+
await this.openUrlHandler(authUrl);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
this.logger.error("Failed to open browser", error);
|
|
219
|
+
this.logger.info(`Please manually navigate to: ${authUrl}`);
|
|
220
|
+
}
|
|
221
|
+
return new Promise((resolve, reject) => {
|
|
222
|
+
const server = http.createServer(async (req, res) => {
|
|
223
|
+
var _a;
|
|
224
|
+
try {
|
|
225
|
+
if (!((_a = req.url) == null ? void 0 : _a.startsWith("/callback"))) {
|
|
226
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
227
|
+
res.end("Not Found");
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const callbackUrl = new url_1.URL(`http://localhost:${this.callbackPort}${req.url}`);
|
|
231
|
+
const params = this.client.callbackParams(callbackUrl.toString());
|
|
232
|
+
const tokenSet = await this.client.callback(this.redirectUri, params, {
|
|
233
|
+
code_verifier: codeVerifier
|
|
234
|
+
});
|
|
235
|
+
const authResult = this.processTokenSet(tokenSet);
|
|
236
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
237
|
+
res.end(`
|
|
238
|
+
<html>
|
|
239
|
+
<body style="font-family: Arial, sans-serif; text-align: center; padding: 50px;">
|
|
240
|
+
<h2 style="color: #4CAF50;">Authentication Successful!</h2>
|
|
241
|
+
<p>You can now close this tab and return to VS Code/Cursor.</p>
|
|
242
|
+
<script>
|
|
243
|
+
setTimeout(() => {
|
|
244
|
+
window.close();
|
|
245
|
+
}, 3000);
|
|
246
|
+
</script>
|
|
247
|
+
</body>
|
|
248
|
+
</html>
|
|
249
|
+
`);
|
|
250
|
+
server.close();
|
|
251
|
+
resolve(authResult);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
this.logger.error("Authentication callback error", error);
|
|
254
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
255
|
+
res.end(`
|
|
256
|
+
<html>
|
|
257
|
+
<body style="font-family: Arial, sans-serif; text-align: center; padding: 50px;">
|
|
258
|
+
<h2 style="color: #f44336;">Authentication Failed</h2>
|
|
259
|
+
<p>Error: ${error}</p>
|
|
260
|
+
<p>Please try again.</p>
|
|
261
|
+
</body>
|
|
262
|
+
</html>
|
|
263
|
+
`);
|
|
264
|
+
server.close();
|
|
265
|
+
reject(error);
|
|
131
266
|
}
|
|
132
|
-
|
|
267
|
+
});
|
|
268
|
+
server.listen(this.callbackPort, () => {
|
|
269
|
+
this.logger.info(`Listening for Auth0 callback on http://localhost:${this.callbackPort}/callback`);
|
|
270
|
+
});
|
|
271
|
+
setTimeout(() => {
|
|
272
|
+
server.close();
|
|
273
|
+
reject(new Error("Authentication timeout - no response received within 5 minutes"));
|
|
274
|
+
}, 3e5);
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Get user information using the access token
|
|
279
|
+
*/
|
|
280
|
+
async getUserInfo(accessToken) {
|
|
281
|
+
if (!this.client) {
|
|
282
|
+
throw new Error("Auth0 client not initialized");
|
|
133
283
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
284
|
+
try {
|
|
285
|
+
this.logger.info("Fetching user information...");
|
|
286
|
+
const userInfo = await this.client.userinfo(accessToken);
|
|
287
|
+
this.logger.info("User information retrieved successfully");
|
|
288
|
+
this.logger.debug(`User ID: ${userInfo.sub}`);
|
|
289
|
+
return userInfo;
|
|
290
|
+
} catch (error) {
|
|
291
|
+
this.logger.error("Failed to get user info", error);
|
|
292
|
+
throw error;
|
|
137
293
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Refresh the access token using refresh token
|
|
297
|
+
*/
|
|
298
|
+
async refreshToken(refreshToken) {
|
|
299
|
+
if (!this.client) {
|
|
300
|
+
throw new Error("Auth0 client not initialized");
|
|
301
|
+
}
|
|
302
|
+
try {
|
|
303
|
+
this.logger.info("Refreshing access token...");
|
|
304
|
+
const tokenSet = await this.client.refresh(refreshToken);
|
|
305
|
+
const result = this.processTokenSet(tokenSet);
|
|
306
|
+
this.logger.info("Token refresh completed successfully");
|
|
307
|
+
return result;
|
|
308
|
+
} catch (error) {
|
|
309
|
+
this.logger.error("Token refresh failed", error);
|
|
310
|
+
throw error;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Process token set and return structured result
|
|
315
|
+
*/
|
|
316
|
+
processTokenSet(tokenSet) {
|
|
317
|
+
var _a;
|
|
318
|
+
const result = {
|
|
319
|
+
accessToken: tokenSet.access_token,
|
|
320
|
+
idToken: tokenSet.id_token,
|
|
321
|
+
refreshToken: tokenSet.refresh_token
|
|
151
322
|
};
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
logger.info(`Auth0 Domain: ${customerConfig.domain}`);
|
|
170
|
-
logger.info(`Client ID: ${customerConfig.clientId.substring(0, 8)}...`);
|
|
171
|
-
// Return customer-specific configuration
|
|
172
|
-
// Customer config takes precedence over everything else
|
|
173
|
-
return {
|
|
174
|
-
serverUrl: customerConfig.serverUrl,
|
|
175
|
-
authDomain: customerConfig.domain,
|
|
176
|
-
clientId: customerConfig.clientId,
|
|
177
|
-
audience: customerConfig.audience,
|
|
178
|
-
scope: DEFAULT_SCOPE,
|
|
179
|
-
// Credentials path only configurable via CLI argument for security
|
|
180
|
-
credentialsPath: config.credentialsPath,
|
|
181
|
-
adminCompanyDomain: config.adminCompanyDomain ||
|
|
182
|
-
envConfig.adminCompanyDomain ||
|
|
183
|
-
fileConfig.adminCompanyDomain ||
|
|
184
|
-
DEFAULT_ADMIN_COMPANY_DOMAIN,
|
|
185
|
-
customerDomain: customerDomain,
|
|
186
|
-
m2mTokenPath: config.m2mTokenPath ||
|
|
187
|
-
envConfig.m2mTokenPath ||
|
|
188
|
-
fileConfig.m2mTokenPath,
|
|
189
|
-
m2mSecretName: config.m2mSecretName ||
|
|
190
|
-
envConfig.m2mSecretName ||
|
|
191
|
-
fileConfig.m2mSecretName,
|
|
192
|
-
tenantId: config.tenantId ||
|
|
193
|
-
envConfig.tenantId ||
|
|
194
|
-
fileConfig.tenantId,
|
|
195
|
-
};
|
|
323
|
+
if (tokenSet.expires_at) {
|
|
324
|
+
result.expiresAt = new Date(tokenSet.expires_at * 1e3);
|
|
325
|
+
}
|
|
326
|
+
this.logger.info("Authentication tokens processed successfully");
|
|
327
|
+
this.logger.debug(`Access Token: ${(_a = result.accessToken) == null ? void 0 : _a.substring(0, 20)}...`);
|
|
328
|
+
this.logger.debug(`ID Token: ${result.idToken ? "Present" : "Not provided"}`);
|
|
329
|
+
this.logger.debug(`Refresh Token: ${result.refreshToken ? "Present" : "Not provided"}`);
|
|
330
|
+
this.logger.debug(`Expires At: ${result.expiresAt}`);
|
|
331
|
+
return result;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Check if a token is expired
|
|
335
|
+
*/
|
|
336
|
+
isTokenExpired(authResult) {
|
|
337
|
+
if (!authResult.expiresAt) {
|
|
338
|
+
this.logger.debug("No expiration time available, considering token valid");
|
|
339
|
+
return false;
|
|
196
340
|
}
|
|
197
|
-
|
|
198
|
-
|
|
341
|
+
const expiresAt = authResult.expiresAt instanceof Date ? authResult.expiresAt : new Date(authResult.expiresAt);
|
|
342
|
+
const now = /* @__PURE__ */ new Date();
|
|
343
|
+
const buffer = 5 * 60 * 1e3;
|
|
344
|
+
const isExpired = expiresAt.getTime() - buffer < now.getTime();
|
|
345
|
+
if (isExpired) {
|
|
346
|
+
this.logger.warn("Access token is expired or will expire soon");
|
|
347
|
+
} else {
|
|
348
|
+
this.logger.debug("Access token is still valid");
|
|
349
|
+
}
|
|
350
|
+
return isExpired;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Logout (revoke tokens if supported)
|
|
354
|
+
*/
|
|
355
|
+
async logout(accessToken) {
|
|
356
|
+
if (!this.client) {
|
|
357
|
+
throw new Error("Auth0 client not initialized");
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
await this.client.revoke(accessToken);
|
|
361
|
+
this.logger.info("Token revoked successfully");
|
|
362
|
+
} catch (error) {
|
|
363
|
+
this.logger.error("Failed to revoke token", error);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
exports2.Auth0Service = Auth0Service;
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// dist/auth/auth0-m2m-service.js
|
|
372
|
+
var require_auth0_m2m_service = __commonJS({
|
|
373
|
+
"dist/auth/auth0-m2m-service.js"(exports2) {
|
|
374
|
+
"use strict";
|
|
375
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
376
|
+
exports2.Auth0M2MService = void 0;
|
|
377
|
+
var types_1 = require_types();
|
|
378
|
+
var noopLogger = {
|
|
379
|
+
info: () => {
|
|
380
|
+
},
|
|
381
|
+
warn: () => {
|
|
382
|
+
},
|
|
383
|
+
error: () => {
|
|
384
|
+
},
|
|
385
|
+
debug: () => {
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
var Auth0M2MService = class _Auth0M2MService {
|
|
389
|
+
credentials;
|
|
390
|
+
tenantId;
|
|
391
|
+
tokenCache = null;
|
|
392
|
+
logger;
|
|
393
|
+
initialized = false;
|
|
394
|
+
/**
|
|
395
|
+
* Token expiry buffer in milliseconds (5 minutes)
|
|
396
|
+
* Tokens will be refreshed this long before actual expiration
|
|
397
|
+
*/
|
|
398
|
+
static EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
|
|
399
|
+
constructor(credentials, tenantId, logger) {
|
|
400
|
+
this.credentials = credentials;
|
|
401
|
+
this.tenantId = tenantId;
|
|
402
|
+
this.logger = logger || noopLogger;
|
|
403
|
+
const clientIdPrefix = credentials.client_id.substring(0, 8);
|
|
404
|
+
this.logger.info(`Auth0M2MService created for client: ${clientIdPrefix}...`);
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Get the strategy type identifier
|
|
408
|
+
*/
|
|
409
|
+
getType() {
|
|
410
|
+
return types_1.AuthStrategyType.AUTH0_M2M;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Initialize the M2M service
|
|
414
|
+
* Validates credentials format and performs initial token fetch
|
|
415
|
+
*/
|
|
416
|
+
async initialize() {
|
|
417
|
+
if (this.initialized) {
|
|
418
|
+
this.logger.debug("Auth0M2MService already initialized");
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
this.logger.info("Initializing Auth0M2MService...");
|
|
422
|
+
if (!this.credentials.client_id || !this.credentials.client_secret) {
|
|
423
|
+
throw new Error("M2M credentials missing client_id or client_secret");
|
|
424
|
+
}
|
|
425
|
+
if (!this.credentials.domain) {
|
|
426
|
+
throw new Error("M2M credentials missing domain");
|
|
427
|
+
}
|
|
428
|
+
if (!this.credentials.audience) {
|
|
429
|
+
throw new Error("M2M credentials missing audience");
|
|
430
|
+
}
|
|
431
|
+
await this.fetchNewToken();
|
|
432
|
+
this.initialized = true;
|
|
433
|
+
this.logger.info("Auth0M2MService initialized successfully");
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Get a valid access token, fetching a new one if cache is expired
|
|
437
|
+
*/
|
|
438
|
+
async getToken() {
|
|
439
|
+
const now = Date.now();
|
|
440
|
+
if (this.tokenCache && now < this.tokenCache.expiresAt - _Auth0M2MService.EXPIRY_BUFFER_MS) {
|
|
441
|
+
this.logger.debug("Using cached M2M token");
|
|
442
|
+
return this.tokenCache.accessToken;
|
|
443
|
+
}
|
|
444
|
+
this.logger.info("M2M token expired or not cached, fetching new token...");
|
|
445
|
+
await this.fetchNewToken();
|
|
446
|
+
return this.tokenCache.accessToken;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Force refresh the token by clearing cache and fetching a new one
|
|
450
|
+
*/
|
|
451
|
+
async refreshToken() {
|
|
452
|
+
this.logger.info("Force refreshing M2M token...");
|
|
453
|
+
this.tokenCache = null;
|
|
454
|
+
await this.fetchNewToken();
|
|
455
|
+
this.logger.info("M2M token refreshed");
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Check if currently authenticated (credentials are valid)
|
|
459
|
+
*/
|
|
460
|
+
async isAuthenticated() {
|
|
461
|
+
try {
|
|
462
|
+
await this.getToken();
|
|
463
|
+
return true;
|
|
464
|
+
} catch {
|
|
465
|
+
return false;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Get user information for the M2M client
|
|
470
|
+
* Returns synthetic user info since M2M clients don't have traditional user profiles
|
|
471
|
+
*/
|
|
472
|
+
async getUserInfo() {
|
|
473
|
+
const clientIdPrefix = this.credentials.client_id.substring(0, 8);
|
|
199
474
|
return {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
DEFAULT_SERVER_URL,
|
|
204
|
-
authDomain: config.authDomain ||
|
|
205
|
-
envConfig.authDomain ||
|
|
206
|
-
fileConfig.authDomain ||
|
|
207
|
-
DEFAULT_AUTH_DOMAIN,
|
|
208
|
-
clientId: config.clientId ||
|
|
209
|
-
envConfig.clientId ||
|
|
210
|
-
fileConfig.clientId ||
|
|
211
|
-
DEFAULT_PUBLIC_CLIENT_ID,
|
|
212
|
-
audience: config.audience ||
|
|
213
|
-
envConfig.audience ||
|
|
214
|
-
fileConfig.audience ||
|
|
215
|
-
DEFAULT_AUDIENCE,
|
|
216
|
-
scope: config.scope ||
|
|
217
|
-
envConfig.scope ||
|
|
218
|
-
fileConfig.scope ||
|
|
219
|
-
DEFAULT_SCOPE,
|
|
220
|
-
adminCompanyDomain: config.adminCompanyDomain ||
|
|
221
|
-
envConfig.adminCompanyDomain ||
|
|
222
|
-
fileConfig.adminCompanyDomain ||
|
|
223
|
-
DEFAULT_ADMIN_COMPANY_DOMAIN,
|
|
224
|
-
// Credentials path only configurable via CLI argument for security
|
|
225
|
-
credentialsPath: config.credentialsPath,
|
|
226
|
-
customerDomain: undefined,
|
|
227
|
-
m2mTokenPath: config.m2mTokenPath ||
|
|
228
|
-
envConfig.m2mTokenPath ||
|
|
229
|
-
fileConfig.m2mTokenPath,
|
|
230
|
-
m2mSecretName: config.m2mSecretName ||
|
|
231
|
-
envConfig.m2mSecretName ||
|
|
232
|
-
fileConfig.m2mSecretName,
|
|
233
|
-
tenantId: config.tenantId || envConfig.tenantId || fileConfig.tenantId,
|
|
475
|
+
sub: `m2m-client-${clientIdPrefix}`,
|
|
476
|
+
name: "M2M Client",
|
|
477
|
+
...this.tenantId && { tenant_id: this.tenantId }
|
|
234
478
|
};
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Get the tenant ID associated with this M2M client
|
|
482
|
+
*/
|
|
483
|
+
getTenantId() {
|
|
484
|
+
return this.tenantId;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Fetch a new token from Auth0 using client credentials grant
|
|
488
|
+
*/
|
|
489
|
+
async fetchNewToken() {
|
|
490
|
+
const domain = this.credentials.domain.startsWith("http") ? this.credentials.domain : `https://${this.credentials.domain}`;
|
|
491
|
+
const tokenUrl = `${domain.replace(/\/$/, "")}/oauth/token`;
|
|
492
|
+
this.logger.debug(`Fetching M2M token from: ${tokenUrl}`);
|
|
493
|
+
const requestBody = {
|
|
494
|
+
grant_type: "client_credentials",
|
|
495
|
+
client_id: this.credentials.client_id,
|
|
496
|
+
client_secret: this.credentials.client_secret,
|
|
497
|
+
audience: this.credentials.audience
|
|
498
|
+
};
|
|
499
|
+
try {
|
|
500
|
+
const response = await fetch(tokenUrl, {
|
|
501
|
+
method: "POST",
|
|
502
|
+
headers: {
|
|
503
|
+
"Content-Type": "application/json"
|
|
504
|
+
},
|
|
505
|
+
body: JSON.stringify(requestBody)
|
|
506
|
+
});
|
|
507
|
+
if (!response.ok) {
|
|
508
|
+
this.logger.error(`M2M token request failed: ${response.status}`);
|
|
509
|
+
throw new Error(`Auth0 M2M token request failed with status ${response.status}`);
|
|
510
|
+
}
|
|
511
|
+
const tokenResponse = await response.json();
|
|
512
|
+
if (!tokenResponse.access_token) {
|
|
513
|
+
throw new Error("Auth0 response missing access_token");
|
|
514
|
+
}
|
|
515
|
+
const expiresIn = tokenResponse.expires_in || 3600;
|
|
516
|
+
const expiresAt = Date.now() + expiresIn * 1e3;
|
|
517
|
+
this.tokenCache = {
|
|
518
|
+
accessToken: tokenResponse.access_token,
|
|
519
|
+
expiresAt
|
|
520
|
+
};
|
|
521
|
+
const expiresInMinutes = Math.floor(expiresIn / 60);
|
|
522
|
+
this.logger.info(`M2M token obtained${this.tenantId ? ` for tenant ${this.tenantId}` : ""}: expires in ${expiresInMinutes} minutes`);
|
|
523
|
+
} catch (error) {
|
|
524
|
+
this.tokenCache = null;
|
|
525
|
+
if (error instanceof Error) {
|
|
526
|
+
this.logger.error("Failed to fetch M2M token", error);
|
|
527
|
+
throw error;
|
|
528
|
+
}
|
|
529
|
+
throw new Error(`Failed to fetch M2M token: ${error}`);
|
|
240
530
|
}
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
exports2.Auth0M2MService = Auth0M2MService;
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
// dist/auth/service-account-service.js
|
|
538
|
+
var require_service_account_service = __commonJS({
|
|
539
|
+
"dist/auth/service-account-service.js"(exports2) {
|
|
540
|
+
"use strict";
|
|
541
|
+
var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
542
|
+
if (k2 === void 0) k2 = k;
|
|
543
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
544
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
545
|
+
desc = { enumerable: true, get: function() {
|
|
546
|
+
return m[k];
|
|
547
|
+
} };
|
|
548
|
+
}
|
|
549
|
+
Object.defineProperty(o, k2, desc);
|
|
550
|
+
}) : (function(o, m, k, k2) {
|
|
551
|
+
if (k2 === void 0) k2 = k;
|
|
552
|
+
o[k2] = m[k];
|
|
553
|
+
}));
|
|
554
|
+
var __setModuleDefault2 = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
555
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
556
|
+
}) : function(o, v) {
|
|
557
|
+
o["default"] = v;
|
|
558
|
+
});
|
|
559
|
+
var __importStar2 = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
560
|
+
var ownKeys = function(o) {
|
|
561
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
562
|
+
var ar = [];
|
|
563
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
564
|
+
return ar;
|
|
565
|
+
};
|
|
566
|
+
return ownKeys(o);
|
|
567
|
+
};
|
|
568
|
+
return function(mod) {
|
|
569
|
+
if (mod && mod.__esModule) return mod;
|
|
570
|
+
var result = {};
|
|
571
|
+
if (mod != null) {
|
|
572
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding2(result, mod, k[i]);
|
|
573
|
+
}
|
|
574
|
+
__setModuleDefault2(result, mod);
|
|
575
|
+
return result;
|
|
576
|
+
};
|
|
577
|
+
})();
|
|
578
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
579
|
+
exports2.ServiceAccountService = void 0;
|
|
580
|
+
var fs2 = __importStar2(require("fs"));
|
|
581
|
+
var types_1 = require_types();
|
|
582
|
+
var noopLogger = {
|
|
583
|
+
info: () => {
|
|
584
|
+
},
|
|
585
|
+
warn: () => {
|
|
586
|
+
},
|
|
587
|
+
error: () => {
|
|
588
|
+
},
|
|
589
|
+
debug: () => {
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
var ServiceAccountService = class {
|
|
593
|
+
tokenPath;
|
|
594
|
+
tenantId;
|
|
595
|
+
tokenCache = null;
|
|
596
|
+
logger;
|
|
597
|
+
constructor(tokenPath, tenantId, logger) {
|
|
598
|
+
this.tokenPath = tokenPath;
|
|
599
|
+
this.tenantId = tenantId;
|
|
600
|
+
this.logger = logger || noopLogger;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Get the strategy type identifier
|
|
604
|
+
*/
|
|
605
|
+
getType() {
|
|
606
|
+
return types_1.AuthStrategyType.SERVICE_ACCOUNT;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Initialize the service account strategy
|
|
610
|
+
* Validates that the token file exists and is readable
|
|
611
|
+
*/
|
|
612
|
+
async initialize() {
|
|
613
|
+
this.logger.info(`Initializing ServiceAccountService with token path: ${this.tokenPath}`);
|
|
614
|
+
if (!fs2.existsSync(this.tokenPath)) {
|
|
615
|
+
throw new Error(`Service account token file not found: ${this.tokenPath}`);
|
|
255
616
|
}
|
|
256
|
-
|
|
257
|
-
|
|
617
|
+
await this.getToken();
|
|
618
|
+
this.logger.info("ServiceAccountService initialized successfully");
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Get a valid access token, reading from file if cache is expired
|
|
622
|
+
*/
|
|
623
|
+
async getToken() {
|
|
624
|
+
const now = Date.now();
|
|
625
|
+
const bufferMs = 5 * 60 * 1e3;
|
|
626
|
+
if (this.tokenCache && now < this.tokenCache.expiresAt - bufferMs) {
|
|
627
|
+
this.logger.debug("Using cached service account token");
|
|
628
|
+
return this.tokenCache.token;
|
|
258
629
|
}
|
|
259
|
-
|
|
260
|
-
|
|
630
|
+
const rawToken = this.readTokenFromFile();
|
|
631
|
+
this.validateAndCacheToken(rawToken);
|
|
632
|
+
return this.tokenCache.token;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Force refresh the token by clearing cache and re-reading from file
|
|
636
|
+
*/
|
|
637
|
+
async refreshToken() {
|
|
638
|
+
this.logger.info("Refreshing service account token...");
|
|
639
|
+
this.tokenCache = null;
|
|
640
|
+
await this.getToken();
|
|
641
|
+
this.logger.info("Service account token refreshed");
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Check if currently authenticated (token file exists and is valid)
|
|
645
|
+
*/
|
|
646
|
+
async isAuthenticated() {
|
|
647
|
+
try {
|
|
648
|
+
await this.getToken();
|
|
649
|
+
return true;
|
|
650
|
+
} catch {
|
|
651
|
+
return false;
|
|
261
652
|
}
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Get user information for the service account
|
|
656
|
+
* Returns synthetic user info since service accounts don't have traditional user profiles
|
|
657
|
+
*/
|
|
658
|
+
async getUserInfo() {
|
|
262
659
|
return {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
scope: this.config.scope ?? DEFAULT_SCOPE,
|
|
660
|
+
sub: "m2m-service-account",
|
|
661
|
+
name: "M2M Service Account",
|
|
662
|
+
...this.tenantId && { tenant_id: this.tenantId }
|
|
267
663
|
};
|
|
268
|
-
|
|
269
|
-
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Get the tenant ID associated with this service account
|
|
667
|
+
*/
|
|
668
|
+
getTenantId() {
|
|
669
|
+
return this.tenantId;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Read the token from the file system
|
|
673
|
+
*/
|
|
674
|
+
readTokenFromFile() {
|
|
675
|
+
return fs2.readFileSync(this.tokenPath, "utf8");
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Validate the token format and cache it with expiration
|
|
679
|
+
*/
|
|
680
|
+
validateAndCacheToken(rawToken) {
|
|
681
|
+
const token = rawToken.trim();
|
|
682
|
+
if (!token) {
|
|
683
|
+
throw new Error("Service account token is empty");
|
|
684
|
+
}
|
|
685
|
+
const parts = token.split(".");
|
|
686
|
+
if (parts.length !== 3) {
|
|
687
|
+
throw new Error(`Invalid JWT format: expected 3 parts, got ${parts.length}`);
|
|
688
|
+
}
|
|
689
|
+
const expiresAt = this.extractExpiration(token);
|
|
690
|
+
const now = Date.now();
|
|
691
|
+
const expiresIn = Math.floor((expiresAt - now) / 1e3);
|
|
692
|
+
if (expiresAt <= now) {
|
|
693
|
+
throw new Error("Service account token is expired");
|
|
694
|
+
}
|
|
695
|
+
this.logger.info(`Service account token loaded${this.tenantId ? ` for tenant ${this.tenantId}` : ""}: expires in ${expiresIn}s (${new Date(expiresAt).toISOString()})`);
|
|
696
|
+
this.tokenCache = {
|
|
697
|
+
token,
|
|
698
|
+
expiresAt
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Extract expiration time from JWT payload
|
|
703
|
+
*/
|
|
704
|
+
extractExpiration(token) {
|
|
705
|
+
const parts = token.split(".");
|
|
270
706
|
try {
|
|
271
|
-
|
|
707
|
+
const payload = parts[1];
|
|
708
|
+
const decoded = Buffer.from(payload, "base64url").toString("utf8");
|
|
709
|
+
const parsed = JSON.parse(decoded);
|
|
710
|
+
if (typeof parsed.exp === "number") {
|
|
711
|
+
return parsed.exp * 1e3;
|
|
712
|
+
}
|
|
713
|
+
this.logger.warn("JWT missing 'exp' field, using fallback expiration");
|
|
714
|
+
return Date.now() + 3e5;
|
|
715
|
+
} catch (error) {
|
|
716
|
+
this.logger.warn(`Failed to parse JWT expiration: ${error}, using fallback expiration`);
|
|
717
|
+
return Date.now() + 3e5;
|
|
272
718
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
exports2.ServiceAccountService = ServiceAccountService;
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
// dist/auth/secrets/aws-secrets-provider.js
|
|
726
|
+
var require_aws_secrets_provider = __commonJS({
|
|
727
|
+
"dist/auth/secrets/aws-secrets-provider.js"(exports2) {
|
|
728
|
+
"use strict";
|
|
729
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
730
|
+
exports2.AWSSecretsProvider = void 0;
|
|
731
|
+
var noopLogger = {
|
|
732
|
+
info: () => {
|
|
733
|
+
},
|
|
734
|
+
warn: () => {
|
|
735
|
+
},
|
|
736
|
+
error: () => {
|
|
737
|
+
},
|
|
738
|
+
debug: () => {
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
var AWSSecretsProvider = class {
|
|
742
|
+
logger;
|
|
743
|
+
region;
|
|
744
|
+
constructor(logger) {
|
|
745
|
+
this.logger = logger || noopLogger;
|
|
746
|
+
this.region = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION;
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Get the provider name for logging
|
|
750
|
+
*/
|
|
751
|
+
getName() {
|
|
752
|
+
return "AWS Secrets Manager";
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Check if running in AWS environment with credentials available
|
|
756
|
+
*/
|
|
757
|
+
async isAvailable() {
|
|
758
|
+
const hasRegion = !!(process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION);
|
|
759
|
+
const hasExecutionEnv = !!process.env.AWS_EXECUTION_ENV;
|
|
760
|
+
const hasCredentials = !!(process.env.AWS_ACCESS_KEY_ID || process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI || process.env.AWS_WEB_IDENTITY_TOKEN_FILE);
|
|
761
|
+
const isAWSEnvironment = hasRegion && (hasExecutionEnv || hasCredentials);
|
|
762
|
+
if (isAWSEnvironment) {
|
|
763
|
+
this.logger.debug("AWS environment detected");
|
|
764
|
+
} else {
|
|
765
|
+
this.logger.debug("Not in AWS environment");
|
|
766
|
+
}
|
|
767
|
+
return isAWSEnvironment;
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Load Auth0 M2M credentials from AWS Secrets Manager
|
|
771
|
+
*
|
|
772
|
+
* @param secretName - The name or ARN of the secret in Secrets Manager
|
|
773
|
+
* @returns M2M credentials or null if not found
|
|
774
|
+
*/
|
|
775
|
+
async loadAuth0M2MCredentials(secretName) {
|
|
776
|
+
this.logger.info(`Loading M2M credentials from AWS Secrets Manager: ${secretName}`);
|
|
777
|
+
try {
|
|
778
|
+
const { SecretsManagerClient, GetSecretValueCommand } = (
|
|
779
|
+
// @ts-expect-error - @aws-sdk/client-secrets-manager is an optional runtime dependency
|
|
780
|
+
await import("@aws-sdk/client-secrets-manager")
|
|
781
|
+
);
|
|
782
|
+
const client = new SecretsManagerClient({
|
|
783
|
+
region: this.region
|
|
784
|
+
});
|
|
785
|
+
const command = new GetSecretValueCommand({
|
|
786
|
+
SecretId: secretName
|
|
787
|
+
});
|
|
788
|
+
const response = await client.send(command);
|
|
789
|
+
if (!response.SecretString) {
|
|
790
|
+
this.logger.error("Secret value is empty or binary");
|
|
791
|
+
return null;
|
|
792
|
+
}
|
|
793
|
+
const secretValue = JSON.parse(response.SecretString);
|
|
794
|
+
if (!secretValue.client_id || !secretValue.client_secret || !secretValue.audience || !secretValue.domain) {
|
|
795
|
+
this.logger.error("Secret missing required fields (client_id, client_secret, audience, domain)");
|
|
796
|
+
return null;
|
|
797
|
+
}
|
|
798
|
+
this.logger.info("M2M credentials loaded from AWS Secrets Manager");
|
|
799
|
+
return {
|
|
800
|
+
client_id: secretValue.client_id,
|
|
801
|
+
client_secret: secretValue.client_secret,
|
|
802
|
+
audience: secretValue.audience,
|
|
803
|
+
domain: secretValue.domain
|
|
804
|
+
};
|
|
805
|
+
} catch (error) {
|
|
806
|
+
if (error instanceof Error) {
|
|
807
|
+
if (error.name === "ResourceNotFoundException") {
|
|
808
|
+
this.logger.warn(`Secret not found: ${secretName}`);
|
|
809
|
+
return null;
|
|
810
|
+
}
|
|
811
|
+
if (error.message.includes("Cannot find module")) {
|
|
812
|
+
this.logger.warn("AWS SDK not available - @aws-sdk/client-secrets-manager not installed");
|
|
813
|
+
return null;
|
|
278
814
|
}
|
|
279
|
-
|
|
280
|
-
|
|
815
|
+
this.logger.error("Failed to load secret from AWS", error);
|
|
816
|
+
}
|
|
817
|
+
return null;
|
|
281
818
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
exports2.AWSSecretsProvider = AWSSecretsProvider;
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
// dist/auth/secrets/local-file-secrets-provider.js
|
|
826
|
+
var require_local_file_secrets_provider = __commonJS({
|
|
827
|
+
"dist/auth/secrets/local-file-secrets-provider.js"(exports2) {
|
|
828
|
+
"use strict";
|
|
829
|
+
var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
830
|
+
if (k2 === void 0) k2 = k;
|
|
831
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
832
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
833
|
+
desc = { enumerable: true, get: function() {
|
|
834
|
+
return m[k];
|
|
835
|
+
} };
|
|
836
|
+
}
|
|
837
|
+
Object.defineProperty(o, k2, desc);
|
|
838
|
+
}) : (function(o, m, k, k2) {
|
|
839
|
+
if (k2 === void 0) k2 = k;
|
|
840
|
+
o[k2] = m[k];
|
|
841
|
+
}));
|
|
842
|
+
var __setModuleDefault2 = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
843
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
844
|
+
}) : function(o, v) {
|
|
845
|
+
o["default"] = v;
|
|
846
|
+
});
|
|
847
|
+
var __importStar2 = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
848
|
+
var ownKeys = function(o) {
|
|
849
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
850
|
+
var ar = [];
|
|
851
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
852
|
+
return ar;
|
|
853
|
+
};
|
|
854
|
+
return ownKeys(o);
|
|
855
|
+
};
|
|
856
|
+
return function(mod) {
|
|
857
|
+
if (mod && mod.__esModule) return mod;
|
|
858
|
+
var result = {};
|
|
859
|
+
if (mod != null) {
|
|
860
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding2(result, mod, k[i]);
|
|
861
|
+
}
|
|
862
|
+
__setModuleDefault2(result, mod);
|
|
863
|
+
return result;
|
|
864
|
+
};
|
|
865
|
+
})();
|
|
866
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
867
|
+
exports2.LocalFileSecretsProvider = void 0;
|
|
868
|
+
var fs2 = __importStar2(require("fs"));
|
|
869
|
+
var path2 = __importStar2(require("path"));
|
|
870
|
+
var os2 = __importStar2(require("os"));
|
|
871
|
+
var noopLogger = {
|
|
872
|
+
info: () => {
|
|
873
|
+
},
|
|
874
|
+
warn: () => {
|
|
875
|
+
},
|
|
876
|
+
error: () => {
|
|
877
|
+
},
|
|
878
|
+
debug: () => {
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
var LocalFileSecretsProvider = class {
|
|
882
|
+
logger;
|
|
883
|
+
environment;
|
|
884
|
+
secretFilePath;
|
|
885
|
+
constructor(environment, logger) {
|
|
886
|
+
this.logger = logger || noopLogger;
|
|
887
|
+
this.environment = environment;
|
|
888
|
+
this.secretFilePath = path2.join(os2.homedir(), ".dataflint", `m2m_secret.${environment}.json`);
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Get the provider name for logging
|
|
892
|
+
*/
|
|
893
|
+
getName() {
|
|
894
|
+
return "Local File";
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Check if the local secret file exists
|
|
898
|
+
*/
|
|
899
|
+
async isAvailable() {
|
|
900
|
+
const exists = fs2.existsSync(this.secretFilePath);
|
|
901
|
+
if (exists) {
|
|
902
|
+
this.logger.debug(`Local M2M secret file found: ${this.secretFilePath}`);
|
|
903
|
+
} else {
|
|
904
|
+
this.logger.debug(`Local M2M secret file not found: ${this.secretFilePath}`);
|
|
905
|
+
}
|
|
906
|
+
return exists;
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Load Auth0 M2M credentials from local file
|
|
910
|
+
*
|
|
911
|
+
* @param _secretName - Ignored, uses environment-based file path
|
|
912
|
+
* @returns M2M credentials or null if not found or invalid
|
|
913
|
+
*/
|
|
914
|
+
async loadAuth0M2MCredentials(_secretName) {
|
|
915
|
+
this.logger.info(`Loading M2M credentials from local file: ${this.secretFilePath}`);
|
|
293
916
|
try {
|
|
294
|
-
|
|
917
|
+
if (!fs2.existsSync(this.secretFilePath)) {
|
|
918
|
+
this.logger.debug("Local secret file does not exist");
|
|
919
|
+
return null;
|
|
920
|
+
}
|
|
921
|
+
const stats = fs2.statSync(this.secretFilePath);
|
|
922
|
+
const mode = stats.mode & 511;
|
|
923
|
+
if (mode !== 384) {
|
|
924
|
+
this.logger.warn(`Secret file has insecure permissions: ${mode.toString(8)}. Should be 600.`);
|
|
925
|
+
}
|
|
926
|
+
const content = fs2.readFileSync(this.secretFilePath, "utf8");
|
|
927
|
+
const secretValue = JSON.parse(content);
|
|
928
|
+
if (!secretValue.client_id || !secretValue.client_secret || !secretValue.audience || !secretValue.domain) {
|
|
929
|
+
this.logger.error("Local secret file missing required fields (client_id, client_secret, audience, domain)");
|
|
930
|
+
return null;
|
|
931
|
+
}
|
|
932
|
+
this.logger.info("M2M credentials loaded from local file");
|
|
933
|
+
return {
|
|
934
|
+
client_id: secretValue.client_id,
|
|
935
|
+
client_secret: secretValue.client_secret,
|
|
936
|
+
audience: secretValue.audience,
|
|
937
|
+
domain: secretValue.domain
|
|
938
|
+
};
|
|
939
|
+
} catch (error) {
|
|
940
|
+
if (error instanceof SyntaxError) {
|
|
941
|
+
this.logger.error("Failed to parse local secret file as JSON");
|
|
942
|
+
} else {
|
|
943
|
+
this.logger.error("Failed to load local secret file", error);
|
|
944
|
+
}
|
|
945
|
+
return null;
|
|
295
946
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Get the path to the secret file (for diagnostics)
|
|
950
|
+
*/
|
|
951
|
+
getSecretFilePath() {
|
|
952
|
+
return this.secretFilePath;
|
|
953
|
+
}
|
|
954
|
+
};
|
|
955
|
+
exports2.LocalFileSecretsProvider = LocalFileSecretsProvider;
|
|
956
|
+
}
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
// dist/auth/secrets/secrets-provider.js
|
|
960
|
+
var require_secrets_provider = __commonJS({
|
|
961
|
+
"dist/auth/secrets/secrets-provider.js"(exports2) {
|
|
962
|
+
"use strict";
|
|
963
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
964
|
+
exports2.SecretsProvider = void 0;
|
|
965
|
+
var aws_secrets_provider_1 = require_aws_secrets_provider();
|
|
966
|
+
var local_file_secrets_provider_1 = require_local_file_secrets_provider();
|
|
967
|
+
var noopLogger = {
|
|
968
|
+
info: () => {
|
|
969
|
+
},
|
|
970
|
+
warn: () => {
|
|
971
|
+
},
|
|
972
|
+
error: () => {
|
|
973
|
+
},
|
|
974
|
+
debug: () => {
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
var SecretsProvider = class {
|
|
978
|
+
logger;
|
|
979
|
+
providers;
|
|
980
|
+
environment;
|
|
981
|
+
constructor(environment, logger) {
|
|
982
|
+
this.logger = logger || noopLogger;
|
|
983
|
+
this.environment = environment;
|
|
984
|
+
this.providers = [
|
|
985
|
+
new aws_secrets_provider_1.AWSSecretsProvider(logger),
|
|
986
|
+
new local_file_secrets_provider_1.LocalFileSecretsProvider(environment, logger)
|
|
987
|
+
];
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Get the provider name for logging
|
|
991
|
+
*/
|
|
992
|
+
getName() {
|
|
993
|
+
return "Composite Secrets Provider";
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Check if any provider is available
|
|
997
|
+
*/
|
|
998
|
+
async isAvailable() {
|
|
999
|
+
for (const provider of this.providers) {
|
|
1000
|
+
if (await provider.isAvailable()) {
|
|
1001
|
+
this.logger.debug(`Secrets provider available: ${provider.getName()}`);
|
|
1002
|
+
return true;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
this.logger.debug("No secrets providers available");
|
|
1006
|
+
return false;
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Load Auth0 M2M credentials from the first available provider
|
|
1010
|
+
*
|
|
1011
|
+
* @param secretName - The name of the secret (used for AWS, ignored for local file)
|
|
1012
|
+
* @returns M2M credentials or null if not found in any provider
|
|
1013
|
+
*/
|
|
1014
|
+
async loadAuth0M2MCredentials(secretName) {
|
|
1015
|
+
this.logger.info("Attempting to load M2M credentials...");
|
|
1016
|
+
for (const provider of this.providers) {
|
|
1017
|
+
const providerName = provider.getName();
|
|
1018
|
+
if (!await provider.isAvailable()) {
|
|
1019
|
+
this.logger.debug(`Provider not available: ${providerName}`);
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
1022
|
+
this.logger.info(`Trying provider: ${providerName}`);
|
|
1023
|
+
const credentials = await provider.loadAuth0M2MCredentials(secretName);
|
|
1024
|
+
if (credentials) {
|
|
1025
|
+
this.logger.info(`M2M credentials loaded from: ${providerName}`);
|
|
1026
|
+
return credentials;
|
|
1027
|
+
}
|
|
1028
|
+
this.logger.debug(`No credentials found in provider: ${providerName}`);
|
|
303
1029
|
}
|
|
1030
|
+
this.logger.info("No M2M credentials found in any provider");
|
|
1031
|
+
return null;
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Get the default secret name for M2M credentials based on environment
|
|
1035
|
+
*
|
|
1036
|
+
* @param environment - The environment (prod, staging, local)
|
|
1037
|
+
* @returns The default secret name
|
|
1038
|
+
*/
|
|
1039
|
+
static getDefaultSecretName(environment) {
|
|
1040
|
+
return `auth0_m2m_databricks_loader_${environment}`;
|
|
1041
|
+
}
|
|
1042
|
+
};
|
|
1043
|
+
exports2.SecretsProvider = SecretsProvider;
|
|
1044
|
+
}
|
|
1045
|
+
});
|
|
1046
|
+
|
|
1047
|
+
// dist/auth/secrets/index.js
|
|
1048
|
+
var require_secrets = __commonJS({
|
|
1049
|
+
"dist/auth/secrets/index.js"(exports2) {
|
|
1050
|
+
"use strict";
|
|
1051
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1052
|
+
exports2.SecretsProvider = exports2.LocalFileSecretsProvider = exports2.AWSSecretsProvider = void 0;
|
|
1053
|
+
var aws_secrets_provider_1 = require_aws_secrets_provider();
|
|
1054
|
+
Object.defineProperty(exports2, "AWSSecretsProvider", { enumerable: true, get: function() {
|
|
1055
|
+
return aws_secrets_provider_1.AWSSecretsProvider;
|
|
1056
|
+
} });
|
|
1057
|
+
var local_file_secrets_provider_1 = require_local_file_secrets_provider();
|
|
1058
|
+
Object.defineProperty(exports2, "LocalFileSecretsProvider", { enumerable: true, get: function() {
|
|
1059
|
+
return local_file_secrets_provider_1.LocalFileSecretsProvider;
|
|
1060
|
+
} });
|
|
1061
|
+
var secrets_provider_1 = require_secrets_provider();
|
|
1062
|
+
Object.defineProperty(exports2, "SecretsProvider", { enumerable: true, get: function() {
|
|
1063
|
+
return secrets_provider_1.SecretsProvider;
|
|
1064
|
+
} });
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
|
|
1068
|
+
// dist/auth/auth-strategy-factory.js
|
|
1069
|
+
var require_auth_strategy_factory = __commonJS({
|
|
1070
|
+
"dist/auth/auth-strategy-factory.js"(exports2) {
|
|
1071
|
+
"use strict";
|
|
1072
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1073
|
+
exports2.AuthStrategyFactory = void 0;
|
|
1074
|
+
var types_1 = require_types();
|
|
1075
|
+
var service_account_service_1 = require_service_account_service();
|
|
1076
|
+
var auth0_m2m_service_1 = require_auth0_m2m_service();
|
|
1077
|
+
var secrets_1 = require_secrets();
|
|
1078
|
+
var noopLogger = {
|
|
1079
|
+
info: () => {
|
|
1080
|
+
},
|
|
1081
|
+
warn: () => {
|
|
1082
|
+
},
|
|
1083
|
+
error: () => {
|
|
1084
|
+
},
|
|
1085
|
+
debug: () => {
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
var AuthStrategyFactory = class {
|
|
1089
|
+
configProvider;
|
|
1090
|
+
logger;
|
|
1091
|
+
constructor(configProvider, logger) {
|
|
1092
|
+
this.configProvider = configProvider;
|
|
1093
|
+
this.logger = logger || noopLogger;
|
|
1094
|
+
}
|
|
1095
|
+
async createStrategy() {
|
|
1096
|
+
const m2mMode = this.configProvider.getM2MMode();
|
|
1097
|
+
switch (m2mMode.type) {
|
|
1098
|
+
case types_1.M2MType.SERVICE_ACCOUNT:
|
|
1099
|
+
return this.buildServiceAccountStrategy(m2mMode);
|
|
1100
|
+
case types_1.M2MType.AUTH0_M2M:
|
|
1101
|
+
return await this.buildAuth0M2MStrategy(m2mMode);
|
|
1102
|
+
default:
|
|
1103
|
+
this.logger.info("Using interactive OAuth flow");
|
|
1104
|
+
return {
|
|
1105
|
+
strategy: null,
|
|
1106
|
+
strategyType: types_1.AuthStrategyType.AUTH0_USER
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
buildServiceAccountStrategy(mode) {
|
|
1111
|
+
this.logger.info(`Service Account mode: ${mode.tokenPath}`);
|
|
1112
|
+
return {
|
|
1113
|
+
strategy: new service_account_service_1.ServiceAccountService(mode.tokenPath, mode.tenantId, this.logger),
|
|
1114
|
+
strategyType: types_1.AuthStrategyType.SERVICE_ACCOUNT
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
async buildAuth0M2MStrategy(mode) {
|
|
1118
|
+
const secretsProvider = new secrets_1.SecretsProvider(this.configProvider.getEnvironment(), this.logger);
|
|
1119
|
+
if (!await secretsProvider.isAvailable()) {
|
|
1120
|
+
throw new Error(`Auth0 M2M mode requires a secrets provider. M2M_AUTH0_SECRET_NAME is set to "${mode.secretName}" but no secrets provider is available. Ensure AWS credentials are configured or use Service Account mode instead.`);
|
|
1121
|
+
}
|
|
1122
|
+
const credentials = await secretsProvider.loadAuth0M2MCredentials(mode.secretName);
|
|
1123
|
+
if (!credentials) {
|
|
1124
|
+
throw new Error(`Auth0 M2M credentials not found: "${mode.secretName}". Ensure the secret exists and contains valid Auth0 M2M credentials.`);
|
|
1125
|
+
}
|
|
1126
|
+
this.logger.info(`Auth0 M2M mode: ${mode.secretName}`);
|
|
1127
|
+
return {
|
|
1128
|
+
strategy: new auth0_m2m_service_1.Auth0M2MService(credentials, mode.tenantId, this.logger),
|
|
1129
|
+
strategyType: types_1.AuthStrategyType.AUTH0_M2M
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
async isM2MAvailable() {
|
|
1133
|
+
const mode = this.configProvider.getM2MMode();
|
|
1134
|
+
if (mode.type === types_1.M2MType.SERVICE_ACCOUNT) {
|
|
1135
|
+
return true;
|
|
1136
|
+
}
|
|
1137
|
+
if (mode.type === types_1.M2MType.AUTH0_M2M) {
|
|
1138
|
+
const secretsProvider = new secrets_1.SecretsProvider(this.configProvider.getEnvironment(), this.logger);
|
|
1139
|
+
return secretsProvider.isAvailable();
|
|
1140
|
+
}
|
|
1141
|
+
return false;
|
|
1142
|
+
}
|
|
1143
|
+
};
|
|
1144
|
+
exports2.AuthStrategyFactory = AuthStrategyFactory;
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1147
|
+
|
|
1148
|
+
// dist/auth/index.js
|
|
1149
|
+
var require_auth = __commonJS({
|
|
1150
|
+
"dist/auth/index.js"(exports2) {
|
|
1151
|
+
"use strict";
|
|
1152
|
+
var __createBinding2 = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
1153
|
+
if (k2 === void 0) k2 = k;
|
|
1154
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
1155
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
1156
|
+
desc = { enumerable: true, get: function() {
|
|
1157
|
+
return m[k];
|
|
1158
|
+
} };
|
|
1159
|
+
}
|
|
1160
|
+
Object.defineProperty(o, k2, desc);
|
|
1161
|
+
}) : (function(o, m, k, k2) {
|
|
1162
|
+
if (k2 === void 0) k2 = k;
|
|
1163
|
+
o[k2] = m[k];
|
|
1164
|
+
}));
|
|
1165
|
+
var __setModuleDefault2 = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
1166
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
1167
|
+
}) : function(o, v) {
|
|
1168
|
+
o["default"] = v;
|
|
1169
|
+
});
|
|
1170
|
+
var __importStar2 = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
1171
|
+
var ownKeys = function(o) {
|
|
1172
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
1173
|
+
var ar = [];
|
|
1174
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
1175
|
+
return ar;
|
|
1176
|
+
};
|
|
1177
|
+
return ownKeys(o);
|
|
1178
|
+
};
|
|
1179
|
+
return function(mod) {
|
|
1180
|
+
if (mod && mod.__esModule) return mod;
|
|
1181
|
+
var result = {};
|
|
1182
|
+
if (mod != null) {
|
|
1183
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding2(result, mod, k[i]);
|
|
1184
|
+
}
|
|
1185
|
+
__setModuleDefault2(result, mod);
|
|
1186
|
+
return result;
|
|
1187
|
+
};
|
|
1188
|
+
})();
|
|
1189
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1190
|
+
exports2.SecretsProvider = exports2.LocalFileSecretsProvider = exports2.AWSSecretsProvider = exports2.AuthStrategyFactory = exports2.ServiceAccountService = exports2.Auth0M2MService = exports2.Auth0Service = exports2.M2MType = exports2.AuthStrategyType = exports2.customerAuthConfigs = void 0;
|
|
1191
|
+
exports2.getCustomerAuthConfig = getCustomerAuthConfig;
|
|
1192
|
+
var crypto2 = __importStar2(require("node:crypto"));
|
|
1193
|
+
var customer_auth_configs_1 = require_customer_auth_configs();
|
|
1194
|
+
Object.defineProperty(exports2, "customerAuthConfigs", { enumerable: true, get: function() {
|
|
1195
|
+
return customer_auth_configs_1.customerAuthConfigs;
|
|
1196
|
+
} });
|
|
1197
|
+
function getCustomerAuthConfig(customerDomain) {
|
|
1198
|
+
var _a;
|
|
1199
|
+
const customerHash = crypto2.createHash("sha256").update(customerDomain).digest("hex");
|
|
1200
|
+
const customerConfig = customer_auth_configs_1.customerAuthConfigs[customerHash];
|
|
1201
|
+
if (!customerConfig) {
|
|
1202
|
+
return null;
|
|
1203
|
+
}
|
|
1204
|
+
return {
|
|
1205
|
+
// Use custom Auth0 domain if domainProducer is defined, otherwise use default
|
|
1206
|
+
domain: ((_a = customerConfig.domainProducer) == null ? void 0 : _a.call(customerConfig, customerDomain)) || "https://dataflint.us.auth0.com/",
|
|
1207
|
+
// Customer-specific Auth0 client ID
|
|
1208
|
+
clientId: customerConfig.clientId,
|
|
1209
|
+
// Customer-specific API audience
|
|
1210
|
+
audience: `https://api.${customerDomain}.dataflint.io`,
|
|
1211
|
+
// Customer-specific server URL
|
|
1212
|
+
serverUrl: `https://api.${customerDomain}.dataflint.io`
|
|
1213
|
+
};
|
|
304
1214
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
1215
|
+
var types_1 = require_types();
|
|
1216
|
+
Object.defineProperty(exports2, "AuthStrategyType", { enumerable: true, get: function() {
|
|
1217
|
+
return types_1.AuthStrategyType;
|
|
1218
|
+
} });
|
|
1219
|
+
Object.defineProperty(exports2, "M2MType", { enumerable: true, get: function() {
|
|
1220
|
+
return types_1.M2MType;
|
|
1221
|
+
} });
|
|
1222
|
+
var auth0_service_1 = require_auth0_service();
|
|
1223
|
+
Object.defineProperty(exports2, "Auth0Service", { enumerable: true, get: function() {
|
|
1224
|
+
return auth0_service_1.Auth0Service;
|
|
1225
|
+
} });
|
|
1226
|
+
var auth0_m2m_service_1 = require_auth0_m2m_service();
|
|
1227
|
+
Object.defineProperty(exports2, "Auth0M2MService", { enumerable: true, get: function() {
|
|
1228
|
+
return auth0_m2m_service_1.Auth0M2MService;
|
|
1229
|
+
} });
|
|
1230
|
+
var service_account_service_1 = require_service_account_service();
|
|
1231
|
+
Object.defineProperty(exports2, "ServiceAccountService", { enumerable: true, get: function() {
|
|
1232
|
+
return service_account_service_1.ServiceAccountService;
|
|
1233
|
+
} });
|
|
1234
|
+
var auth_strategy_factory_1 = require_auth_strategy_factory();
|
|
1235
|
+
Object.defineProperty(exports2, "AuthStrategyFactory", { enumerable: true, get: function() {
|
|
1236
|
+
return auth_strategy_factory_1.AuthStrategyFactory;
|
|
1237
|
+
} });
|
|
1238
|
+
var secrets_1 = require_secrets();
|
|
1239
|
+
Object.defineProperty(exports2, "AWSSecretsProvider", { enumerable: true, get: function() {
|
|
1240
|
+
return secrets_1.AWSSecretsProvider;
|
|
1241
|
+
} });
|
|
1242
|
+
Object.defineProperty(exports2, "LocalFileSecretsProvider", { enumerable: true, get: function() {
|
|
1243
|
+
return secrets_1.LocalFileSecretsProvider;
|
|
1244
|
+
} });
|
|
1245
|
+
Object.defineProperty(exports2, "SecretsProvider", { enumerable: true, get: function() {
|
|
1246
|
+
return secrets_1.SecretsProvider;
|
|
1247
|
+
} });
|
|
1248
|
+
}
|
|
1249
|
+
});
|
|
1250
|
+
|
|
1251
|
+
// dist/standalone/config.js
|
|
1252
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
1253
|
+
if (k2 === void 0) k2 = k;
|
|
1254
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
1255
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
1256
|
+
desc = { enumerable: true, get: function() {
|
|
1257
|
+
return m[k];
|
|
1258
|
+
} };
|
|
1259
|
+
}
|
|
1260
|
+
Object.defineProperty(o, k2, desc);
|
|
1261
|
+
}) : (function(o, m, k, k2) {
|
|
1262
|
+
if (k2 === void 0) k2 = k;
|
|
1263
|
+
o[k2] = m[k];
|
|
1264
|
+
}));
|
|
1265
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
1266
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
1267
|
+
}) : function(o, v) {
|
|
1268
|
+
o["default"] = v;
|
|
1269
|
+
});
|
|
1270
|
+
var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
|
|
1271
|
+
var ownKeys = function(o) {
|
|
1272
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
1273
|
+
var ar = [];
|
|
1274
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
1275
|
+
return ar;
|
|
1276
|
+
};
|
|
1277
|
+
return ownKeys(o);
|
|
1278
|
+
};
|
|
1279
|
+
return function(mod) {
|
|
1280
|
+
if (mod && mod.__esModule) return mod;
|
|
1281
|
+
var result = {};
|
|
1282
|
+
if (mod != null) {
|
|
1283
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
1284
|
+
}
|
|
1285
|
+
__setModuleDefault(result, mod);
|
|
1286
|
+
return result;
|
|
1287
|
+
};
|
|
1288
|
+
})();
|
|
1289
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1290
|
+
exports.StandaloneConfigService = void 0;
|
|
1291
|
+
var fs = __importStar(require("fs"));
|
|
1292
|
+
var path = __importStar(require("path"));
|
|
1293
|
+
var os = __importStar(require("os"));
|
|
1294
|
+
var crypto = __importStar(require("crypto"));
|
|
1295
|
+
var index_js_1 = require_auth();
|
|
1296
|
+
var StandaloneConfigService = class {
|
|
1297
|
+
config;
|
|
1298
|
+
credentialsPath;
|
|
1299
|
+
constructor(config = {}) {
|
|
1300
|
+
this.config = this.mergeWithDefaults(config);
|
|
1301
|
+
if (config.credentialsPath) {
|
|
1302
|
+
this.credentialsPath = config.credentialsPath;
|
|
1303
|
+
} else {
|
|
1304
|
+
const clientIdHash = crypto.createHash("sha256").update(this.config.clientId).digest("hex").substring(0, 8);
|
|
1305
|
+
this.credentialsPath = path.join(os.homedir(), ".dataflint", `credentials-${clientIdHash}.json`);
|
|
1306
|
+
}
|
|
1307
|
+
this.ensureDataflintDirectory();
|
|
1308
|
+
}
|
|
1309
|
+
ensureDataflintDirectory() {
|
|
1310
|
+
const dataflintDir = path.dirname(this.credentialsPath);
|
|
1311
|
+
if (!fs.existsSync(dataflintDir)) {
|
|
1312
|
+
fs.mkdirSync(dataflintDir, { recursive: true, mode: 448 });
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
mergeWithDefaults(config) {
|
|
1316
|
+
const envConfig = {
|
|
1317
|
+
serverUrl: process.env.DATAFLINT_SERVER_URL,
|
|
1318
|
+
authDomain: process.env.DATAFLINT_AUTH_DOMAIN,
|
|
1319
|
+
clientId: process.env.DATAFLINT_CLIENT_ID,
|
|
1320
|
+
audience: process.env.DATAFLINT_AUDIENCE,
|
|
1321
|
+
scope: process.env.DATAFLINT_SCOPE,
|
|
1322
|
+
adminCompanyDomain: process.env.DATAFLINT_ADMIN_COMPANY_DOMAIN,
|
|
1323
|
+
customerDomain: process.env.DATAFLINT_CUSTOMER_DOMAIN
|
|
1324
|
+
};
|
|
1325
|
+
const configFilePath = path.join(os.homedir(), ".dataflint", "config.json");
|
|
1326
|
+
let fileConfig = {};
|
|
1327
|
+
if (fs.existsSync(configFilePath)) {
|
|
1328
|
+
try {
|
|
1329
|
+
const fileContent = fs.readFileSync(configFilePath, "utf8");
|
|
1330
|
+
fileConfig = JSON.parse(fileContent);
|
|
1331
|
+
} catch (error) {
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
const customerDomain = config.customerDomain || envConfig.customerDomain || fileConfig.customerDomain;
|
|
1335
|
+
if (customerDomain) {
|
|
1336
|
+
console.error(`[CONFIG] Customer domain detected: ${customerDomain}`);
|
|
1337
|
+
const customerConfig = (0, index_js_1.getCustomerAuthConfig)(customerDomain);
|
|
1338
|
+
if (!customerConfig) {
|
|
1339
|
+
console.error(`[CONFIG] ERROR: Unknown customer domain: ${customerDomain}`);
|
|
1340
|
+
throw new Error(`Unknown customer domain: "${customerDomain}". This customer is not registered in the system. Please check the domain name or contact support.`);
|
|
1341
|
+
}
|
|
1342
|
+
console.error(`[CONFIG] Using customer-specific configuration:`);
|
|
1343
|
+
console.error(`[CONFIG] - Server URL: ${customerConfig.serverUrl}`);
|
|
1344
|
+
console.error(`[CONFIG] - Auth0 Domain: ${customerConfig.domain}`);
|
|
1345
|
+
console.error(`[CONFIG] - Client ID: ${customerConfig.clientId.substring(0, 8)}...`);
|
|
1346
|
+
return {
|
|
1347
|
+
serverUrl: customerConfig.serverUrl,
|
|
1348
|
+
authDomain: customerConfig.domain,
|
|
1349
|
+
clientId: customerConfig.clientId,
|
|
1350
|
+
audience: customerConfig.audience,
|
|
1351
|
+
scope: "openid profile email offline_access",
|
|
1352
|
+
// Credentials path only configurable via CLI argument for security
|
|
1353
|
+
credentialsPath: config.credentialsPath,
|
|
1354
|
+
adminCompanyDomain: config.adminCompanyDomain || envConfig.adminCompanyDomain || fileConfig.adminCompanyDomain || "none",
|
|
1355
|
+
customerDomain
|
|
1356
|
+
};
|
|
308
1357
|
}
|
|
309
|
-
|
|
310
|
-
|
|
1358
|
+
console.error(`[CONFIG] No customer domain - using default/explicit configuration`);
|
|
1359
|
+
return {
|
|
1360
|
+
serverUrl: config.serverUrl || envConfig.serverUrl || fileConfig.serverUrl || "https://api.dataflint.io",
|
|
1361
|
+
authDomain: config.authDomain || envConfig.authDomain || fileConfig.authDomain || "https://dataflint.us.auth0.com/",
|
|
1362
|
+
clientId: config.clientId || envConfig.clientId || fileConfig.clientId || "1NdbhkYoLyqQWtevBNal1BozB9pSZe3g",
|
|
1363
|
+
audience: config.audience || envConfig.audience || fileConfig.audience || "https://api.dataflint.io",
|
|
1364
|
+
scope: config.scope || envConfig.scope || fileConfig.scope || "openid profile email offline_access",
|
|
1365
|
+
adminCompanyDomain: config.adminCompanyDomain || envConfig.adminCompanyDomain || fileConfig.adminCompanyDomain || "none",
|
|
1366
|
+
// Credentials path only configurable via CLI argument for security
|
|
1367
|
+
credentialsPath: config.credentialsPath,
|
|
1368
|
+
customerDomain: void 0
|
|
1369
|
+
};
|
|
1370
|
+
}
|
|
1371
|
+
// IConfigService interface implementation
|
|
1372
|
+
getServerUrl() {
|
|
1373
|
+
return this.config.serverUrl;
|
|
1374
|
+
}
|
|
1375
|
+
getEnvironment() {
|
|
1376
|
+
return "prod";
|
|
1377
|
+
}
|
|
1378
|
+
getCustomerDomain() {
|
|
1379
|
+
return this.config.customerDomain || null;
|
|
1380
|
+
}
|
|
1381
|
+
getAdminCompanyDomain() {
|
|
1382
|
+
return this.config.adminCompanyDomain || "none";
|
|
1383
|
+
}
|
|
1384
|
+
getAuthConfig() {
|
|
1385
|
+
return {
|
|
1386
|
+
domain: this.config.authDomain,
|
|
1387
|
+
clientId: this.config.clientId,
|
|
1388
|
+
audience: this.config.audience,
|
|
1389
|
+
scope: this.config.scope || "openid profile email offline_access"
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
async getAuthSecret() {
|
|
1393
|
+
try {
|
|
1394
|
+
if (fs.existsSync(this.credentialsPath)) {
|
|
1395
|
+
const content = fs.readFileSync(this.credentialsPath, "utf8");
|
|
1396
|
+
return content;
|
|
1397
|
+
}
|
|
1398
|
+
return void 0;
|
|
1399
|
+
} catch (error) {
|
|
1400
|
+
return void 0;
|
|
311
1401
|
}
|
|
312
|
-
|
|
313
|
-
|
|
1402
|
+
}
|
|
1403
|
+
async setAuthSecret(value) {
|
|
1404
|
+
this.ensureDataflintDirectory();
|
|
1405
|
+
fs.writeFileSync(this.credentialsPath, value, {
|
|
1406
|
+
mode: 384,
|
|
1407
|
+
encoding: "utf8"
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
async deleteAuthSecret() {
|
|
1411
|
+
try {
|
|
1412
|
+
if (fs.existsSync(this.credentialsPath)) {
|
|
1413
|
+
fs.unlinkSync(this.credentialsPath);
|
|
1414
|
+
}
|
|
1415
|
+
} catch (error) {
|
|
314
1416
|
}
|
|
315
|
-
}
|
|
1417
|
+
}
|
|
1418
|
+
getSendSourceCode() {
|
|
1419
|
+
const envValue = process.env.DATAFLINT_SEND_SOURCE_CODE;
|
|
1420
|
+
return (envValue == null ? void 0 : envValue.toLowerCase()) === "true";
|
|
1421
|
+
}
|
|
1422
|
+
};
|
|
316
1423
|
exports.StandaloneConfigService = StandaloneConfigService;
|
|
317
|
-
//# sourceMappingURL=config.js.map
|
|
1424
|
+
//# sourceMappingURL=config.js.map
|