@mcp-z/oauth-microsoft 1.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.
- package/LICENSE +21 -0
- package/README.md +98 -0
- package/dist/cjs/index.d.cts +16 -0
- package/dist/cjs/index.d.ts +16 -0
- package/dist/cjs/index.js +112 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/lib/dcr-router.d.cts +44 -0
- package/dist/cjs/lib/dcr-router.d.ts +44 -0
- package/dist/cjs/lib/dcr-router.js +1227 -0
- package/dist/cjs/lib/dcr-router.js.map +1 -0
- package/dist/cjs/lib/dcr-utils.d.cts +160 -0
- package/dist/cjs/lib/dcr-utils.d.ts +160 -0
- package/dist/cjs/lib/dcr-utils.js +860 -0
- package/dist/cjs/lib/dcr-utils.js.map +1 -0
- package/dist/cjs/lib/dcr-verify.d.cts +53 -0
- package/dist/cjs/lib/dcr-verify.d.ts +53 -0
- package/dist/cjs/lib/dcr-verify.js +193 -0
- package/dist/cjs/lib/dcr-verify.js.map +1 -0
- package/dist/cjs/lib/fetch-with-timeout.d.cts +14 -0
- package/dist/cjs/lib/fetch-with-timeout.d.ts +14 -0
- package/dist/cjs/lib/fetch-with-timeout.js +257 -0
- package/dist/cjs/lib/fetch-with-timeout.js.map +1 -0
- package/dist/cjs/lib/token-verifier.d.cts +44 -0
- package/dist/cjs/lib/token-verifier.d.ts +44 -0
- package/dist/cjs/lib/token-verifier.js +253 -0
- package/dist/cjs/lib/token-verifier.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/providers/dcr.d.cts +110 -0
- package/dist/cjs/providers/dcr.d.ts +110 -0
- package/dist/cjs/providers/dcr.js +600 -0
- package/dist/cjs/providers/dcr.js.map +1 -0
- package/dist/cjs/providers/device-code.d.cts +179 -0
- package/dist/cjs/providers/device-code.d.ts +179 -0
- package/dist/cjs/providers/device-code.js +896 -0
- package/dist/cjs/providers/device-code.js.map +1 -0
- package/dist/cjs/providers/loopback-oauth.d.cts +125 -0
- package/dist/cjs/providers/loopback-oauth.d.ts +125 -0
- package/dist/cjs/providers/loopback-oauth.js +1325 -0
- package/dist/cjs/providers/loopback-oauth.js.map +1 -0
- package/dist/cjs/schemas/index.d.cts +20 -0
- package/dist/cjs/schemas/index.d.ts +20 -0
- package/dist/cjs/schemas/index.js +37 -0
- package/dist/cjs/schemas/index.js.map +1 -0
- package/dist/cjs/setup/config.d.cts +113 -0
- package/dist/cjs/setup/config.d.ts +113 -0
- package/dist/cjs/setup/config.js +246 -0
- package/dist/cjs/setup/config.js.map +1 -0
- package/dist/cjs/types.d.cts +188 -0
- package/dist/cjs/types.d.ts +188 -0
- package/dist/cjs/types.js +18 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/index.d.ts +16 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lib/dcr-router.d.ts +44 -0
- package/dist/esm/lib/dcr-router.js +556 -0
- package/dist/esm/lib/dcr-router.js.map +1 -0
- package/dist/esm/lib/dcr-utils.d.ts +160 -0
- package/dist/esm/lib/dcr-utils.js +270 -0
- package/dist/esm/lib/dcr-utils.js.map +1 -0
- package/dist/esm/lib/dcr-verify.d.ts +53 -0
- package/dist/esm/lib/dcr-verify.js +53 -0
- package/dist/esm/lib/dcr-verify.js.map +1 -0
- package/dist/esm/lib/fetch-with-timeout.d.ts +14 -0
- package/dist/esm/lib/fetch-with-timeout.js +30 -0
- package/dist/esm/lib/fetch-with-timeout.js.map +1 -0
- package/dist/esm/lib/token-verifier.d.ts +44 -0
- package/dist/esm/lib/token-verifier.js +53 -0
- package/dist/esm/lib/token-verifier.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/providers/dcr.d.ts +110 -0
- package/dist/esm/providers/dcr.js +235 -0
- package/dist/esm/providers/dcr.js.map +1 -0
- package/dist/esm/providers/device-code.d.ts +179 -0
- package/dist/esm/providers/device-code.js +417 -0
- package/dist/esm/providers/device-code.js.map +1 -0
- package/dist/esm/providers/loopback-oauth.d.ts +125 -0
- package/dist/esm/providers/loopback-oauth.js +643 -0
- package/dist/esm/providers/loopback-oauth.js.map +1 -0
- package/dist/esm/schemas/index.d.ts +20 -0
- package/dist/esm/schemas/index.js +18 -0
- package/dist/esm/schemas/index.js.map +1 -0
- package/dist/esm/setup/config.d.ts +113 -0
- package/dist/esm/setup/config.js +268 -0
- package/dist/esm/setup/config.js.map +1 -0
- package/dist/esm/types.d.ts +188 -0
- package/dist/esm/types.js +8 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,1325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loopback OAuth Implementation for Microsoft (RFC 8252)
|
|
3
|
+
*
|
|
4
|
+
* Implements OAuth 2.0 Authorization Code Flow with PKCE using loopback interface redirection.
|
|
5
|
+
* Uses ephemeral local server with OS-assigned port (RFC 8252 Section 8.3).
|
|
6
|
+
* Eliminates port conflicts by using port 0, allowing unlimited concurrent servers.
|
|
7
|
+
*
|
|
8
|
+
* Flow:
|
|
9
|
+
* 1. Check token cache (memory + storage)
|
|
10
|
+
* 2. If cache miss: Start ephemeral server on port 0
|
|
11
|
+
* 3. Generate auth URL with dynamic redirect (localhost:{assigned-port})
|
|
12
|
+
* 4. Open browser or print URL (headless flag controls behavior)
|
|
13
|
+
* 5. Handle callback, exchange code for token
|
|
14
|
+
* 6. Cache token to storage
|
|
15
|
+
* 7. Close ephemeral server
|
|
16
|
+
*/ "use strict";
|
|
17
|
+
Object.defineProperty(exports, "__esModule", {
|
|
18
|
+
value: true
|
|
19
|
+
});
|
|
20
|
+
function _export(target, all) {
|
|
21
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
_export(exports, {
|
|
27
|
+
get LoopbackOAuthProvider () {
|
|
28
|
+
return LoopbackOAuthProvider;
|
|
29
|
+
},
|
|
30
|
+
get createMicrosoftFileAuth () {
|
|
31
|
+
return createMicrosoftFileAuth;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
var _oauth = require("@mcp-z/oauth");
|
|
35
|
+
var _http = /*#__PURE__*/ _interop_require_wildcard(require("http"));
|
|
36
|
+
var _open = /*#__PURE__*/ _interop_require_default(require("open"));
|
|
37
|
+
var _fetchwithtimeoutts = require("../lib/fetch-with-timeout.js");
|
|
38
|
+
var _typests = require("../types.js");
|
|
39
|
+
function _array_like_to_array(arr, len) {
|
|
40
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
41
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
42
|
+
return arr2;
|
|
43
|
+
}
|
|
44
|
+
function _array_without_holes(arr) {
|
|
45
|
+
if (Array.isArray(arr)) return _array_like_to_array(arr);
|
|
46
|
+
}
|
|
47
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
48
|
+
try {
|
|
49
|
+
var info = gen[key](arg);
|
|
50
|
+
var value = info.value;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
reject(error);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (info.done) {
|
|
56
|
+
resolve(value);
|
|
57
|
+
} else {
|
|
58
|
+
Promise.resolve(value).then(_next, _throw);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function _async_to_generator(fn) {
|
|
62
|
+
return function() {
|
|
63
|
+
var self = this, args = arguments;
|
|
64
|
+
return new Promise(function(resolve, reject) {
|
|
65
|
+
var gen = fn.apply(self, args);
|
|
66
|
+
function _next(value) {
|
|
67
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
68
|
+
}
|
|
69
|
+
function _throw(err) {
|
|
70
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
71
|
+
}
|
|
72
|
+
_next(undefined);
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function _class_call_check(instance, Constructor) {
|
|
77
|
+
if (!(instance instanceof Constructor)) {
|
|
78
|
+
throw new TypeError("Cannot call a class as a function");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function _define_property(obj, key, value) {
|
|
82
|
+
if (key in obj) {
|
|
83
|
+
Object.defineProperty(obj, key, {
|
|
84
|
+
value: value,
|
|
85
|
+
enumerable: true,
|
|
86
|
+
configurable: true,
|
|
87
|
+
writable: true
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
obj[key] = value;
|
|
91
|
+
}
|
|
92
|
+
return obj;
|
|
93
|
+
}
|
|
94
|
+
function _instanceof(left, right) {
|
|
95
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
96
|
+
return !!right[Symbol.hasInstance](left);
|
|
97
|
+
} else {
|
|
98
|
+
return left instanceof right;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function _interop_require_default(obj) {
|
|
102
|
+
return obj && obj.__esModule ? obj : {
|
|
103
|
+
default: obj
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
107
|
+
if (typeof WeakMap !== "function") return null;
|
|
108
|
+
var cacheBabelInterop = new WeakMap();
|
|
109
|
+
var cacheNodeInterop = new WeakMap();
|
|
110
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
111
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
112
|
+
})(nodeInterop);
|
|
113
|
+
}
|
|
114
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
115
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
116
|
+
return obj;
|
|
117
|
+
}
|
|
118
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
119
|
+
return {
|
|
120
|
+
default: obj
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
124
|
+
if (cache && cache.has(obj)) {
|
|
125
|
+
return cache.get(obj);
|
|
126
|
+
}
|
|
127
|
+
var newObj = {
|
|
128
|
+
__proto__: null
|
|
129
|
+
};
|
|
130
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
131
|
+
for(var key in obj){
|
|
132
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
133
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
134
|
+
if (desc && (desc.get || desc.set)) {
|
|
135
|
+
Object.defineProperty(newObj, key, desc);
|
|
136
|
+
} else {
|
|
137
|
+
newObj[key] = obj[key];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
newObj.default = obj;
|
|
142
|
+
if (cache) {
|
|
143
|
+
cache.set(obj, newObj);
|
|
144
|
+
}
|
|
145
|
+
return newObj;
|
|
146
|
+
}
|
|
147
|
+
function _iterable_to_array(iter) {
|
|
148
|
+
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
149
|
+
}
|
|
150
|
+
function _non_iterable_spread() {
|
|
151
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
152
|
+
}
|
|
153
|
+
function _object_spread(target) {
|
|
154
|
+
for(var i = 1; i < arguments.length; i++){
|
|
155
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
156
|
+
var ownKeys = Object.keys(source);
|
|
157
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
158
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
159
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
ownKeys.forEach(function(key) {
|
|
163
|
+
_define_property(target, key, source[key]);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return target;
|
|
167
|
+
}
|
|
168
|
+
function ownKeys(object, enumerableOnly) {
|
|
169
|
+
var keys = Object.keys(object);
|
|
170
|
+
if (Object.getOwnPropertySymbols) {
|
|
171
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
172
|
+
if (enumerableOnly) {
|
|
173
|
+
symbols = symbols.filter(function(sym) {
|
|
174
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
keys.push.apply(keys, symbols);
|
|
178
|
+
}
|
|
179
|
+
return keys;
|
|
180
|
+
}
|
|
181
|
+
function _object_spread_props(target, source) {
|
|
182
|
+
source = source != null ? source : {};
|
|
183
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
184
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
185
|
+
} else {
|
|
186
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
187
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
return target;
|
|
191
|
+
}
|
|
192
|
+
function _to_consumable_array(arr) {
|
|
193
|
+
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
|
|
194
|
+
}
|
|
195
|
+
function _type_of(obj) {
|
|
196
|
+
"@swc/helpers - typeof";
|
|
197
|
+
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
198
|
+
}
|
|
199
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
200
|
+
if (!o) return;
|
|
201
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
202
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
203
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
204
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
205
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
206
|
+
}
|
|
207
|
+
function _ts_generator(thisArg, body) {
|
|
208
|
+
var f, y, t, _ = {
|
|
209
|
+
label: 0,
|
|
210
|
+
sent: function() {
|
|
211
|
+
if (t[0] & 1) throw t[1];
|
|
212
|
+
return t[1];
|
|
213
|
+
},
|
|
214
|
+
trys: [],
|
|
215
|
+
ops: []
|
|
216
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
|
|
217
|
+
return d(g, "next", {
|
|
218
|
+
value: verb(0)
|
|
219
|
+
}), d(g, "throw", {
|
|
220
|
+
value: verb(1)
|
|
221
|
+
}), d(g, "return", {
|
|
222
|
+
value: verb(2)
|
|
223
|
+
}), typeof Symbol === "function" && d(g, Symbol.iterator, {
|
|
224
|
+
value: function() {
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
227
|
+
}), g;
|
|
228
|
+
function verb(n) {
|
|
229
|
+
return function(v) {
|
|
230
|
+
return step([
|
|
231
|
+
n,
|
|
232
|
+
v
|
|
233
|
+
]);
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function step(op) {
|
|
237
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
238
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
239
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
240
|
+
if (y = 0, t) op = [
|
|
241
|
+
op[0] & 2,
|
|
242
|
+
t.value
|
|
243
|
+
];
|
|
244
|
+
switch(op[0]){
|
|
245
|
+
case 0:
|
|
246
|
+
case 1:
|
|
247
|
+
t = op;
|
|
248
|
+
break;
|
|
249
|
+
case 4:
|
|
250
|
+
_.label++;
|
|
251
|
+
return {
|
|
252
|
+
value: op[1],
|
|
253
|
+
done: false
|
|
254
|
+
};
|
|
255
|
+
case 5:
|
|
256
|
+
_.label++;
|
|
257
|
+
y = op[1];
|
|
258
|
+
op = [
|
|
259
|
+
0
|
|
260
|
+
];
|
|
261
|
+
continue;
|
|
262
|
+
case 7:
|
|
263
|
+
op = _.ops.pop();
|
|
264
|
+
_.trys.pop();
|
|
265
|
+
continue;
|
|
266
|
+
default:
|
|
267
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
268
|
+
_ = 0;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
272
|
+
_.label = op[1];
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
276
|
+
_.label = t[1];
|
|
277
|
+
t = op;
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
if (t && _.label < t[2]) {
|
|
281
|
+
_.label = t[2];
|
|
282
|
+
_.ops.push(op);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
if (t[2]) _.ops.pop();
|
|
286
|
+
_.trys.pop();
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
op = body.call(thisArg, _);
|
|
290
|
+
} catch (e) {
|
|
291
|
+
op = [
|
|
292
|
+
6,
|
|
293
|
+
e
|
|
294
|
+
];
|
|
295
|
+
y = 0;
|
|
296
|
+
} finally{
|
|
297
|
+
f = t = 0;
|
|
298
|
+
}
|
|
299
|
+
if (op[0] & 5) throw op[1];
|
|
300
|
+
return {
|
|
301
|
+
value: op[0] ? op[1] : void 0,
|
|
302
|
+
done: true
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
var LoopbackOAuthProvider = /*#__PURE__*/ function() {
|
|
307
|
+
"use strict";
|
|
308
|
+
function LoopbackOAuthProvider(config) {
|
|
309
|
+
_class_call_check(this, LoopbackOAuthProvider);
|
|
310
|
+
this.config = config;
|
|
311
|
+
}
|
|
312
|
+
var _proto = LoopbackOAuthProvider.prototype;
|
|
313
|
+
/**
|
|
314
|
+
* Get access token from Keyv using compound key
|
|
315
|
+
*
|
|
316
|
+
* @param accountId - Account identifier (email address). Required for loopback OAuth.
|
|
317
|
+
* @returns Access token for API requests
|
|
318
|
+
*/ _proto.getAccessToken = function getAccessToken(accountId) {
|
|
319
|
+
return _async_to_generator(function() {
|
|
320
|
+
var _this_config, logger, service, tokenStore, effectiveAccountId, _tmp, storedToken, refreshedToken, error, headless, _this_config1, clientId, tenantId, scope, existingAccounts, hasOtherAccounts, authUrl, hint, baseDescriptor, descriptor, _ref, token, email;
|
|
321
|
+
return _ts_generator(this, function(_state) {
|
|
322
|
+
switch(_state.label){
|
|
323
|
+
case 0:
|
|
324
|
+
_this_config = this.config, logger = _this_config.logger, service = _this_config.service, tokenStore = _this_config.tokenStore;
|
|
325
|
+
if (!(accountId !== null && accountId !== void 0)) return [
|
|
326
|
+
3,
|
|
327
|
+
1
|
|
328
|
+
];
|
|
329
|
+
_tmp = accountId;
|
|
330
|
+
return [
|
|
331
|
+
3,
|
|
332
|
+
3
|
|
333
|
+
];
|
|
334
|
+
case 1:
|
|
335
|
+
return [
|
|
336
|
+
4,
|
|
337
|
+
(0, _oauth.getActiveAccount)(tokenStore, {
|
|
338
|
+
service: service
|
|
339
|
+
})
|
|
340
|
+
];
|
|
341
|
+
case 2:
|
|
342
|
+
_tmp = _state.sent();
|
|
343
|
+
_state.label = 3;
|
|
344
|
+
case 3:
|
|
345
|
+
effectiveAccountId = _tmp;
|
|
346
|
+
if (!effectiveAccountId) return [
|
|
347
|
+
3,
|
|
348
|
+
9
|
|
349
|
+
];
|
|
350
|
+
logger.debug('Getting access token', {
|
|
351
|
+
service: service,
|
|
352
|
+
accountId: effectiveAccountId
|
|
353
|
+
});
|
|
354
|
+
return [
|
|
355
|
+
4,
|
|
356
|
+
(0, _oauth.getToken)(tokenStore, {
|
|
357
|
+
accountId: effectiveAccountId,
|
|
358
|
+
service: service
|
|
359
|
+
})
|
|
360
|
+
];
|
|
361
|
+
case 4:
|
|
362
|
+
storedToken = _state.sent();
|
|
363
|
+
if (storedToken && this.isTokenValid(storedToken)) {
|
|
364
|
+
logger.debug('Using stored access token', {
|
|
365
|
+
accountId: effectiveAccountId
|
|
366
|
+
});
|
|
367
|
+
return [
|
|
368
|
+
2,
|
|
369
|
+
storedToken.accessToken
|
|
370
|
+
];
|
|
371
|
+
}
|
|
372
|
+
if (!(storedToken === null || storedToken === void 0 ? void 0 : storedToken.refreshToken)) return [
|
|
373
|
+
3,
|
|
374
|
+
9
|
|
375
|
+
];
|
|
376
|
+
_state.label = 5;
|
|
377
|
+
case 5:
|
|
378
|
+
_state.trys.push([
|
|
379
|
+
5,
|
|
380
|
+
8,
|
|
381
|
+
,
|
|
382
|
+
9
|
|
383
|
+
]);
|
|
384
|
+
logger.info('Refreshing expired access token', {
|
|
385
|
+
accountId: effectiveAccountId
|
|
386
|
+
});
|
|
387
|
+
return [
|
|
388
|
+
4,
|
|
389
|
+
this.refreshAccessToken(storedToken.refreshToken)
|
|
390
|
+
];
|
|
391
|
+
case 6:
|
|
392
|
+
refreshedToken = _state.sent();
|
|
393
|
+
return [
|
|
394
|
+
4,
|
|
395
|
+
(0, _oauth.setToken)(tokenStore, {
|
|
396
|
+
accountId: effectiveAccountId,
|
|
397
|
+
service: service
|
|
398
|
+
}, refreshedToken)
|
|
399
|
+
];
|
|
400
|
+
case 7:
|
|
401
|
+
_state.sent();
|
|
402
|
+
return [
|
|
403
|
+
2,
|
|
404
|
+
refreshedToken.accessToken
|
|
405
|
+
];
|
|
406
|
+
case 8:
|
|
407
|
+
error = _state.sent();
|
|
408
|
+
logger.info('Token refresh failed, starting new OAuth flow', {
|
|
409
|
+
accountId: effectiveAccountId,
|
|
410
|
+
error: _instanceof(error, Error) ? error.message : String(error)
|
|
411
|
+
});
|
|
412
|
+
return [
|
|
413
|
+
3,
|
|
414
|
+
9
|
|
415
|
+
];
|
|
416
|
+
case 9:
|
|
417
|
+
// No valid token or no account - check if we can start OAuth flow
|
|
418
|
+
headless = this.config.headless;
|
|
419
|
+
if (!headless) return [
|
|
420
|
+
3,
|
|
421
|
+
11
|
|
422
|
+
];
|
|
423
|
+
// In headless mode (production), cannot start OAuth flow
|
|
424
|
+
// Throw AuthRequiredError with auth_url descriptor for MCP tool response
|
|
425
|
+
_this_config1 = this.config, clientId = _this_config1.clientId, tenantId = _this_config1.tenantId, scope = _this_config1.scope;
|
|
426
|
+
return [
|
|
427
|
+
4,
|
|
428
|
+
this.getExistingAccounts()
|
|
429
|
+
];
|
|
430
|
+
case 10:
|
|
431
|
+
existingAccounts = _state.sent();
|
|
432
|
+
hasOtherAccounts = effectiveAccountId ? existingAccounts.length > 0 && !existingAccounts.includes(effectiveAccountId) : existingAccounts.length > 0;
|
|
433
|
+
// Build informational OAuth URL for headless mode
|
|
434
|
+
// Note: No redirect_uri included - user must use account-add tool which starts proper ephemeral server
|
|
435
|
+
authUrl = new URL("https://login.microsoftonline.com/".concat(tenantId, "/oauth2/v2.0/authorize"));
|
|
436
|
+
authUrl.searchParams.set('client_id', clientId);
|
|
437
|
+
authUrl.searchParams.set('response_type', 'code');
|
|
438
|
+
authUrl.searchParams.set('scope', scope);
|
|
439
|
+
authUrl.searchParams.set('response_mode', 'query');
|
|
440
|
+
authUrl.searchParams.set('prompt', 'select_account');
|
|
441
|
+
if (hasOtherAccounts) {
|
|
442
|
+
hint = "Existing ".concat(service, " accounts found. Use account-list to view, account-switch to change account, or account-add to add new account");
|
|
443
|
+
} else if (effectiveAccountId) {
|
|
444
|
+
hint = "Use account-add to authenticate ".concat(effectiveAccountId);
|
|
445
|
+
} else {
|
|
446
|
+
hint = 'Use account-add to authenticate interactively';
|
|
447
|
+
}
|
|
448
|
+
baseDescriptor = {
|
|
449
|
+
kind: 'auth_url',
|
|
450
|
+
provider: 'microsoft',
|
|
451
|
+
url: authUrl.toString(),
|
|
452
|
+
hint: hint
|
|
453
|
+
};
|
|
454
|
+
descriptor = effectiveAccountId ? _object_spread_props(_object_spread({}, baseDescriptor), {
|
|
455
|
+
accountId: effectiveAccountId
|
|
456
|
+
}) : baseDescriptor;
|
|
457
|
+
throw new _typests.AuthRequiredError(descriptor);
|
|
458
|
+
case 11:
|
|
459
|
+
// Interactive mode - start ephemeral OAuth flow
|
|
460
|
+
logger.info('Starting ephemeral OAuth flow', {
|
|
461
|
+
service: service,
|
|
462
|
+
headless: headless
|
|
463
|
+
});
|
|
464
|
+
return [
|
|
465
|
+
4,
|
|
466
|
+
this.performEphemeralOAuthFlow()
|
|
467
|
+
];
|
|
468
|
+
case 12:
|
|
469
|
+
_ref = _state.sent(), token = _ref.token, email = _ref.email;
|
|
470
|
+
// Store token with email as accountId
|
|
471
|
+
return [
|
|
472
|
+
4,
|
|
473
|
+
(0, _oauth.setToken)(tokenStore, {
|
|
474
|
+
accountId: email,
|
|
475
|
+
service: service
|
|
476
|
+
}, token)
|
|
477
|
+
];
|
|
478
|
+
case 13:
|
|
479
|
+
_state.sent();
|
|
480
|
+
// Register account in account management system
|
|
481
|
+
return [
|
|
482
|
+
4,
|
|
483
|
+
(0, _oauth.addAccount)(tokenStore, {
|
|
484
|
+
service: service,
|
|
485
|
+
accountId: email
|
|
486
|
+
})
|
|
487
|
+
];
|
|
488
|
+
case 14:
|
|
489
|
+
_state.sent();
|
|
490
|
+
// Set as active account so subsequent getAccessToken() calls find it
|
|
491
|
+
return [
|
|
492
|
+
4,
|
|
493
|
+
(0, _oauth.setActiveAccount)(tokenStore, {
|
|
494
|
+
service: service,
|
|
495
|
+
accountId: email
|
|
496
|
+
})
|
|
497
|
+
];
|
|
498
|
+
case 15:
|
|
499
|
+
_state.sent();
|
|
500
|
+
// Store account metadata (email, added timestamp)
|
|
501
|
+
return [
|
|
502
|
+
4,
|
|
503
|
+
(0, _oauth.setAccountInfo)(tokenStore, {
|
|
504
|
+
service: service,
|
|
505
|
+
accountId: email
|
|
506
|
+
}, {
|
|
507
|
+
email: email,
|
|
508
|
+
addedAt: new Date().toISOString()
|
|
509
|
+
})
|
|
510
|
+
];
|
|
511
|
+
case 16:
|
|
512
|
+
_state.sent();
|
|
513
|
+
logger.info('OAuth flow completed', {
|
|
514
|
+
service: service,
|
|
515
|
+
accountId: email
|
|
516
|
+
});
|
|
517
|
+
return [
|
|
518
|
+
2,
|
|
519
|
+
token.accessToken
|
|
520
|
+
];
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
}).call(this);
|
|
524
|
+
};
|
|
525
|
+
/**
|
|
526
|
+
* Convert to Microsoft Graph-compatible auth provider
|
|
527
|
+
*
|
|
528
|
+
* @param accountId - Account identifier for multi-account support (e.g., 'user@example.com')
|
|
529
|
+
* @returns Auth provider configured for the specified account
|
|
530
|
+
*/ _proto.toAuthProvider = function toAuthProvider(accountId) {
|
|
531
|
+
var _this = this;
|
|
532
|
+
// Capture accountId in closure to pass to getAccessToken
|
|
533
|
+
var getToken = function() {
|
|
534
|
+
return _this.getAccessToken(accountId);
|
|
535
|
+
};
|
|
536
|
+
return {
|
|
537
|
+
getAccessToken: getToken
|
|
538
|
+
};
|
|
539
|
+
};
|
|
540
|
+
/**
|
|
541
|
+
* Authenticate new account with OAuth flow
|
|
542
|
+
* Triggers account selection, stores token, registers account
|
|
543
|
+
*
|
|
544
|
+
* @returns Email address of newly authenticated account
|
|
545
|
+
* @throws Error in headless mode (cannot open browser for OAuth)
|
|
546
|
+
*/ _proto.authenticateNewAccount = function authenticateNewAccount() {
|
|
547
|
+
return _async_to_generator(function() {
|
|
548
|
+
var _this_config, logger, headless, service, tokenStore, _ref, token, email;
|
|
549
|
+
return _ts_generator(this, function(_state) {
|
|
550
|
+
switch(_state.label){
|
|
551
|
+
case 0:
|
|
552
|
+
_this_config = this.config, logger = _this_config.logger, headless = _this_config.headless, service = _this_config.service, tokenStore = _this_config.tokenStore;
|
|
553
|
+
if (headless) {
|
|
554
|
+
throw new Error('Cannot authenticate new account in headless mode - interactive OAuth required');
|
|
555
|
+
}
|
|
556
|
+
logger.info('Starting new account authentication', {
|
|
557
|
+
service: service
|
|
558
|
+
});
|
|
559
|
+
return [
|
|
560
|
+
4,
|
|
561
|
+
this.performEphemeralOAuthFlow()
|
|
562
|
+
];
|
|
563
|
+
case 1:
|
|
564
|
+
_ref = _state.sent(), token = _ref.token, email = _ref.email;
|
|
565
|
+
// Store token
|
|
566
|
+
return [
|
|
567
|
+
4,
|
|
568
|
+
(0, _oauth.setToken)(tokenStore, {
|
|
569
|
+
accountId: email,
|
|
570
|
+
service: service
|
|
571
|
+
}, token)
|
|
572
|
+
];
|
|
573
|
+
case 2:
|
|
574
|
+
_state.sent();
|
|
575
|
+
// Register account
|
|
576
|
+
return [
|
|
577
|
+
4,
|
|
578
|
+
(0, _oauth.addAccount)(tokenStore, {
|
|
579
|
+
service: service,
|
|
580
|
+
accountId: email
|
|
581
|
+
})
|
|
582
|
+
];
|
|
583
|
+
case 3:
|
|
584
|
+
_state.sent();
|
|
585
|
+
// Set as active account
|
|
586
|
+
return [
|
|
587
|
+
4,
|
|
588
|
+
(0, _oauth.setActiveAccount)(tokenStore, {
|
|
589
|
+
service: service,
|
|
590
|
+
accountId: email
|
|
591
|
+
})
|
|
592
|
+
];
|
|
593
|
+
case 4:
|
|
594
|
+
_state.sent();
|
|
595
|
+
// Store account metadata
|
|
596
|
+
return [
|
|
597
|
+
4,
|
|
598
|
+
(0, _oauth.setAccountInfo)(tokenStore, {
|
|
599
|
+
service: service,
|
|
600
|
+
accountId: email
|
|
601
|
+
}, {
|
|
602
|
+
email: email,
|
|
603
|
+
addedAt: new Date().toISOString()
|
|
604
|
+
})
|
|
605
|
+
];
|
|
606
|
+
case 5:
|
|
607
|
+
_state.sent();
|
|
608
|
+
logger.info('New account authenticated', {
|
|
609
|
+
service: service,
|
|
610
|
+
email: email
|
|
611
|
+
});
|
|
612
|
+
return [
|
|
613
|
+
2,
|
|
614
|
+
email
|
|
615
|
+
];
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
}).call(this);
|
|
619
|
+
};
|
|
620
|
+
/**
|
|
621
|
+
* Get user email from Microsoft Graph API (pure query)
|
|
622
|
+
* Used to query email for existing authenticated account
|
|
623
|
+
*
|
|
624
|
+
* @param accountId - Account identifier to get email for
|
|
625
|
+
* @returns User's email address
|
|
626
|
+
*/ _proto.getUserEmail = function getUserEmail(accountId) {
|
|
627
|
+
return _async_to_generator(function() {
|
|
628
|
+
var _userInfo_mail, token, response, _, _1, _2, userInfo;
|
|
629
|
+
return _ts_generator(this, function(_state) {
|
|
630
|
+
switch(_state.label){
|
|
631
|
+
case 0:
|
|
632
|
+
return [
|
|
633
|
+
4,
|
|
634
|
+
this.getAccessToken(accountId)
|
|
635
|
+
];
|
|
636
|
+
case 1:
|
|
637
|
+
token = _state.sent();
|
|
638
|
+
return [
|
|
639
|
+
4,
|
|
640
|
+
(0, _fetchwithtimeoutts.fetchWithTimeout)('https://graph.microsoft.com/v1.0/me', {
|
|
641
|
+
headers: {
|
|
642
|
+
Authorization: "Bearer ".concat(token)
|
|
643
|
+
}
|
|
644
|
+
})
|
|
645
|
+
];
|
|
646
|
+
case 2:
|
|
647
|
+
response = _state.sent();
|
|
648
|
+
if (!!response.ok) return [
|
|
649
|
+
3,
|
|
650
|
+
4
|
|
651
|
+
];
|
|
652
|
+
_ = Error.bind;
|
|
653
|
+
_2 = (_1 = "Failed to get user info: ".concat(response.status, " ")).concat;
|
|
654
|
+
return [
|
|
655
|
+
4,
|
|
656
|
+
response.text()
|
|
657
|
+
];
|
|
658
|
+
case 3:
|
|
659
|
+
throw new (_.apply(Error, [
|
|
660
|
+
void 0,
|
|
661
|
+
_2.apply(_1, [
|
|
662
|
+
_state.sent()
|
|
663
|
+
])
|
|
664
|
+
]));
|
|
665
|
+
case 4:
|
|
666
|
+
return [
|
|
667
|
+
4,
|
|
668
|
+
response.json()
|
|
669
|
+
];
|
|
670
|
+
case 5:
|
|
671
|
+
userInfo = _state.sent();
|
|
672
|
+
return [
|
|
673
|
+
2,
|
|
674
|
+
(_userInfo_mail = userInfo.mail) !== null && _userInfo_mail !== void 0 ? _userInfo_mail : userInfo.userPrincipalName
|
|
675
|
+
];
|
|
676
|
+
}
|
|
677
|
+
});
|
|
678
|
+
}).call(this);
|
|
679
|
+
};
|
|
680
|
+
/**
|
|
681
|
+
* Check for existing accounts in token storage (incremental OAuth detection)
|
|
682
|
+
*
|
|
683
|
+
* Uses key-utils helper for forward compatibility with key format changes.
|
|
684
|
+
*
|
|
685
|
+
* @returns Array of account IDs that have tokens for this service
|
|
686
|
+
*/ _proto.getExistingAccounts = function getExistingAccounts() {
|
|
687
|
+
return _async_to_generator(function() {
|
|
688
|
+
var _this_config, service, tokenStore;
|
|
689
|
+
return _ts_generator(this, function(_state) {
|
|
690
|
+
_this_config = this.config, service = _this_config.service, tokenStore = _this_config.tokenStore;
|
|
691
|
+
return [
|
|
692
|
+
2,
|
|
693
|
+
(0, _oauth.listAccountIds)(tokenStore, service)
|
|
694
|
+
];
|
|
695
|
+
});
|
|
696
|
+
}).call(this);
|
|
697
|
+
};
|
|
698
|
+
_proto.isTokenValid = function isTokenValid(token) {
|
|
699
|
+
if (!token.expiresAt) return true; // No expiry = assume valid
|
|
700
|
+
return Date.now() < token.expiresAt - 60000; // 1 minute buffer
|
|
701
|
+
};
|
|
702
|
+
/**
|
|
703
|
+
* Fetch user email from Microsoft Graph using access token
|
|
704
|
+
* Called during OAuth flow to get email for accountId
|
|
705
|
+
*
|
|
706
|
+
* @param accessToken - Fresh access token from OAuth exchange
|
|
707
|
+
* @returns User's email address (mail field or userPrincipalName fallback)
|
|
708
|
+
*/ _proto.fetchUserEmailFromToken = function fetchUserEmailFromToken(accessToken) {
|
|
709
|
+
return _async_to_generator(function() {
|
|
710
|
+
var _userInfo_mail, logger, response, errorText, userInfo, email;
|
|
711
|
+
return _ts_generator(this, function(_state) {
|
|
712
|
+
switch(_state.label){
|
|
713
|
+
case 0:
|
|
714
|
+
logger = this.config.logger;
|
|
715
|
+
return [
|
|
716
|
+
4,
|
|
717
|
+
(0, _fetchwithtimeoutts.fetchWithTimeout)('https://graph.microsoft.com/v1.0/me', {
|
|
718
|
+
headers: {
|
|
719
|
+
Authorization: "Bearer ".concat(accessToken)
|
|
720
|
+
}
|
|
721
|
+
})
|
|
722
|
+
];
|
|
723
|
+
case 1:
|
|
724
|
+
response = _state.sent();
|
|
725
|
+
if (!!response.ok) return [
|
|
726
|
+
3,
|
|
727
|
+
3
|
|
728
|
+
];
|
|
729
|
+
return [
|
|
730
|
+
4,
|
|
731
|
+
response.text()
|
|
732
|
+
];
|
|
733
|
+
case 2:
|
|
734
|
+
errorText = _state.sent();
|
|
735
|
+
throw new Error("Failed to fetch user email: HTTP ".concat(response.status, " - ").concat(errorText));
|
|
736
|
+
case 3:
|
|
737
|
+
return [
|
|
738
|
+
4,
|
|
739
|
+
response.json()
|
|
740
|
+
];
|
|
741
|
+
case 4:
|
|
742
|
+
userInfo = _state.sent();
|
|
743
|
+
email = (_userInfo_mail = userInfo.mail) !== null && _userInfo_mail !== void 0 ? _userInfo_mail : userInfo.userPrincipalName;
|
|
744
|
+
logger.debug('Fetched user email from Graph API', {
|
|
745
|
+
email: email
|
|
746
|
+
});
|
|
747
|
+
return [
|
|
748
|
+
2,
|
|
749
|
+
email
|
|
750
|
+
];
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
}).call(this);
|
|
754
|
+
};
|
|
755
|
+
_proto.performEphemeralOAuthFlow = function performEphemeralOAuthFlow() {
|
|
756
|
+
return _async_to_generator(function() {
|
|
757
|
+
var _this, _this_config, clientId, tenantId, scope, headless, logger, configRedirectUri, targetHost, targetPort, targetProtocol, callbackPath, useConfiguredUri, parsed;
|
|
758
|
+
return _ts_generator(this, function(_state) {
|
|
759
|
+
_this = this;
|
|
760
|
+
_this_config = this.config, clientId = _this_config.clientId, tenantId = _this_config.tenantId, scope = _this_config.scope, headless = _this_config.headless, logger = _this_config.logger, configRedirectUri = _this_config.redirectUri;
|
|
761
|
+
// Parse redirectUri if provided to extract host, protocol, port, and path
|
|
762
|
+
targetHost = 'localhost'; // Default: localhost (Microsoft requires exact match with registered redirect URI)
|
|
763
|
+
targetPort = 0; // Default: OS-assigned ephemeral port
|
|
764
|
+
targetProtocol = 'http:'; // Default: http
|
|
765
|
+
callbackPath = '/callback'; // Default callback path
|
|
766
|
+
useConfiguredUri = false;
|
|
767
|
+
if (configRedirectUri) {
|
|
768
|
+
try {
|
|
769
|
+
parsed = new URL(configRedirectUri);
|
|
770
|
+
// Use configured redirect URI as-is for production deployments
|
|
771
|
+
targetHost = parsed.hostname;
|
|
772
|
+
targetProtocol = parsed.protocol;
|
|
773
|
+
// Extract port from URL (use default ports if not specified)
|
|
774
|
+
if (parsed.port) {
|
|
775
|
+
targetPort = Number.parseInt(parsed.port, 10);
|
|
776
|
+
} else {
|
|
777
|
+
targetPort = parsed.protocol === 'https:' ? 443 : 80;
|
|
778
|
+
}
|
|
779
|
+
// Extract path (default to /callback if URL has no path or just '/')
|
|
780
|
+
if (parsed.pathname && parsed.pathname !== '/') {
|
|
781
|
+
callbackPath = parsed.pathname;
|
|
782
|
+
}
|
|
783
|
+
useConfiguredUri = true;
|
|
784
|
+
logger.debug('Using configured redirect URI', {
|
|
785
|
+
host: targetHost,
|
|
786
|
+
protocol: targetProtocol,
|
|
787
|
+
port: targetPort,
|
|
788
|
+
path: callbackPath,
|
|
789
|
+
redirectUri: configRedirectUri
|
|
790
|
+
});
|
|
791
|
+
} catch (error) {
|
|
792
|
+
logger.warn('Failed to parse redirectUri, using ephemeral defaults', {
|
|
793
|
+
redirectUri: configRedirectUri,
|
|
794
|
+
error: _instanceof(error, Error) ? error.message : String(error)
|
|
795
|
+
});
|
|
796
|
+
// Continue with defaults (127.0.0.1, port 0, http, /callback)
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return [
|
|
800
|
+
2,
|
|
801
|
+
new Promise(function(resolve, reject) {
|
|
802
|
+
// Generate PKCE challenge
|
|
803
|
+
var _generatePKCE = (0, _oauth.generatePKCE)(), codeVerifier = _generatePKCE.verifier, codeChallenge = _generatePKCE.challenge;
|
|
804
|
+
var server = null;
|
|
805
|
+
var serverPort;
|
|
806
|
+
var finalRedirectUri; // Will be set in server.listen callback
|
|
807
|
+
// Create ephemeral server with OS-assigned port (RFC 8252)
|
|
808
|
+
server = _http.createServer(function(req, res) {
|
|
809
|
+
return _async_to_generator(function() {
|
|
810
|
+
var url, code, _$error, tokenResponse, cachedToken, email, exchangeError;
|
|
811
|
+
return _ts_generator(this, function(_state) {
|
|
812
|
+
switch(_state.label){
|
|
813
|
+
case 0:
|
|
814
|
+
if (!req.url) {
|
|
815
|
+
res.writeHead(400, {
|
|
816
|
+
'Content-Type': 'text/html'
|
|
817
|
+
});
|
|
818
|
+
res.end((0, _oauth.getErrorTemplate)('Invalid request'));
|
|
819
|
+
server === null || server === void 0 ? void 0 : server.close();
|
|
820
|
+
reject(new Error('Invalid request: missing URL'));
|
|
821
|
+
return [
|
|
822
|
+
2
|
|
823
|
+
];
|
|
824
|
+
}
|
|
825
|
+
url = new URL(req.url, "http://localhost:".concat(serverPort));
|
|
826
|
+
if (!(url.pathname === callbackPath)) return [
|
|
827
|
+
3,
|
|
828
|
+
6
|
|
829
|
+
];
|
|
830
|
+
code = url.searchParams.get('code');
|
|
831
|
+
_$error = url.searchParams.get('error');
|
|
832
|
+
if (_$error) {
|
|
833
|
+
res.writeHead(400, {
|
|
834
|
+
'Content-Type': 'text/html'
|
|
835
|
+
});
|
|
836
|
+
res.end((0, _oauth.getErrorTemplate)(_$error));
|
|
837
|
+
server === null || server === void 0 ? void 0 : server.close();
|
|
838
|
+
reject(new Error("OAuth error: ".concat(_$error)));
|
|
839
|
+
return [
|
|
840
|
+
2
|
|
841
|
+
];
|
|
842
|
+
}
|
|
843
|
+
if (!code) {
|
|
844
|
+
res.writeHead(400, {
|
|
845
|
+
'Content-Type': 'text/html'
|
|
846
|
+
});
|
|
847
|
+
res.end((0, _oauth.getErrorTemplate)('No authorization code received'));
|
|
848
|
+
server === null || server === void 0 ? void 0 : server.close();
|
|
849
|
+
reject(new Error('No authorization code received'));
|
|
850
|
+
return [
|
|
851
|
+
2
|
|
852
|
+
];
|
|
853
|
+
}
|
|
854
|
+
_state.label = 1;
|
|
855
|
+
case 1:
|
|
856
|
+
_state.trys.push([
|
|
857
|
+
1,
|
|
858
|
+
4,
|
|
859
|
+
,
|
|
860
|
+
5
|
|
861
|
+
]);
|
|
862
|
+
return [
|
|
863
|
+
4,
|
|
864
|
+
this.exchangeCodeForToken(code, codeVerifier, finalRedirectUri)
|
|
865
|
+
];
|
|
866
|
+
case 2:
|
|
867
|
+
tokenResponse = _state.sent();
|
|
868
|
+
// Build cached token
|
|
869
|
+
cachedToken = _object_spread({
|
|
870
|
+
accessToken: tokenResponse.access_token
|
|
871
|
+
}, tokenResponse.refresh_token !== undefined && {
|
|
872
|
+
refreshToken: tokenResponse.refresh_token
|
|
873
|
+
}, tokenResponse.expires_in !== undefined && {
|
|
874
|
+
expiresAt: Date.now() + tokenResponse.expires_in * 1000
|
|
875
|
+
}, tokenResponse.scope !== undefined && {
|
|
876
|
+
scope: tokenResponse.scope
|
|
877
|
+
});
|
|
878
|
+
return [
|
|
879
|
+
4,
|
|
880
|
+
this.fetchUserEmailFromToken(tokenResponse.access_token)
|
|
881
|
+
];
|
|
882
|
+
case 3:
|
|
883
|
+
email = _state.sent();
|
|
884
|
+
res.writeHead(200, {
|
|
885
|
+
'Content-Type': 'text/html'
|
|
886
|
+
});
|
|
887
|
+
res.end((0, _oauth.getSuccessTemplate)());
|
|
888
|
+
server === null || server === void 0 ? void 0 : server.close();
|
|
889
|
+
resolve({
|
|
890
|
+
token: cachedToken,
|
|
891
|
+
email: email
|
|
892
|
+
});
|
|
893
|
+
return [
|
|
894
|
+
3,
|
|
895
|
+
5
|
|
896
|
+
];
|
|
897
|
+
case 4:
|
|
898
|
+
exchangeError = _state.sent();
|
|
899
|
+
logger.error('Token exchange failed', {
|
|
900
|
+
error: _instanceof(exchangeError, Error) ? exchangeError.message : String(exchangeError)
|
|
901
|
+
});
|
|
902
|
+
res.writeHead(500, {
|
|
903
|
+
'Content-Type': 'text/html'
|
|
904
|
+
});
|
|
905
|
+
res.end((0, _oauth.getErrorTemplate)('Token exchange failed'));
|
|
906
|
+
server === null || server === void 0 ? void 0 : server.close();
|
|
907
|
+
reject(exchangeError);
|
|
908
|
+
return [
|
|
909
|
+
3,
|
|
910
|
+
5
|
|
911
|
+
];
|
|
912
|
+
case 5:
|
|
913
|
+
return [
|
|
914
|
+
3,
|
|
915
|
+
7
|
|
916
|
+
];
|
|
917
|
+
case 6:
|
|
918
|
+
res.writeHead(404, {
|
|
919
|
+
'Content-Type': 'text/plain'
|
|
920
|
+
});
|
|
921
|
+
res.end('Not Found');
|
|
922
|
+
_state.label = 7;
|
|
923
|
+
case 7:
|
|
924
|
+
return [
|
|
925
|
+
2
|
|
926
|
+
];
|
|
927
|
+
}
|
|
928
|
+
});
|
|
929
|
+
}).call(_this);
|
|
930
|
+
});
|
|
931
|
+
// Listen on targetPort (0 for OS assignment, or custom port from redirectUri)
|
|
932
|
+
server.listen(targetPort, targetHost, function() {
|
|
933
|
+
var address = server === null || server === void 0 ? void 0 : server.address();
|
|
934
|
+
if (!address || typeof address === 'string') {
|
|
935
|
+
server === null || server === void 0 ? void 0 : server.close();
|
|
936
|
+
reject(new Error('Failed to start ephemeral server'));
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
serverPort = address.port;
|
|
940
|
+
// Construct final redirect URI
|
|
941
|
+
if (useConfiguredUri && configRedirectUri) {
|
|
942
|
+
// Use configured redirect URI as-is for production
|
|
943
|
+
finalRedirectUri = configRedirectUri;
|
|
944
|
+
} else {
|
|
945
|
+
// Construct ephemeral redirect URI with actual server port
|
|
946
|
+
finalRedirectUri = "".concat(targetProtocol, "//").concat(targetHost, ":").concat(serverPort).concat(callbackPath);
|
|
947
|
+
}
|
|
948
|
+
// Build Microsoft auth URL
|
|
949
|
+
var authUrl = new URL("https://login.microsoftonline.com/".concat(tenantId, "/oauth2/v2.0/authorize"));
|
|
950
|
+
authUrl.searchParams.set('client_id', clientId);
|
|
951
|
+
authUrl.searchParams.set('redirect_uri', finalRedirectUri);
|
|
952
|
+
authUrl.searchParams.set('response_type', 'code');
|
|
953
|
+
authUrl.searchParams.set('scope', scope);
|
|
954
|
+
authUrl.searchParams.set('response_mode', 'query');
|
|
955
|
+
authUrl.searchParams.set('code_challenge', codeChallenge);
|
|
956
|
+
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
957
|
+
authUrl.searchParams.set('prompt', 'select_account');
|
|
958
|
+
logger.info('Ephemeral OAuth server started', {
|
|
959
|
+
port: serverPort,
|
|
960
|
+
headless: headless
|
|
961
|
+
});
|
|
962
|
+
if (headless) {
|
|
963
|
+
// Headless mode: Print auth URL to stderr (stdout is MCP protocol)
|
|
964
|
+
console.error('\n🔐 OAuth Authorization Required');
|
|
965
|
+
console.error('📋 Please visit this URL in your browser:\n');
|
|
966
|
+
console.error(" ".concat(authUrl.toString(), "\n"));
|
|
967
|
+
console.error('⏳ Waiting for authorization...\n');
|
|
968
|
+
} else {
|
|
969
|
+
// Interactive mode: Open browser automatically
|
|
970
|
+
logger.info('Opening browser for OAuth authorization');
|
|
971
|
+
(0, _open.default)(authUrl.toString()).catch(function(error) {
|
|
972
|
+
logger.info('Failed to open browser automatically', {
|
|
973
|
+
error: error.message
|
|
974
|
+
});
|
|
975
|
+
console.error('\n🔐 OAuth Authorization Required');
|
|
976
|
+
console.error(" ".concat(authUrl.toString(), "\n"));
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
// Timeout after 5 minutes
|
|
981
|
+
setTimeout(function() {
|
|
982
|
+
if (server) {
|
|
983
|
+
server.close();
|
|
984
|
+
reject(new Error('OAuth flow timed out after 5 minutes'));
|
|
985
|
+
}
|
|
986
|
+
}, 5 * 60 * 1000);
|
|
987
|
+
})
|
|
988
|
+
];
|
|
989
|
+
});
|
|
990
|
+
}).call(this);
|
|
991
|
+
};
|
|
992
|
+
_proto.exchangeCodeForToken = function exchangeCodeForToken(code, codeVerifier, redirectUri) {
|
|
993
|
+
return _async_to_generator(function() {
|
|
994
|
+
var _this_config, clientId, clientSecret, tenantId, tokenUrl, params, body, response, errorText;
|
|
995
|
+
return _ts_generator(this, function(_state) {
|
|
996
|
+
switch(_state.label){
|
|
997
|
+
case 0:
|
|
998
|
+
_this_config = this.config, clientId = _this_config.clientId, clientSecret = _this_config.clientSecret, tenantId = _this_config.tenantId;
|
|
999
|
+
tokenUrl = "https://login.microsoftonline.com/".concat(tenantId, "/oauth2/v2.0/token");
|
|
1000
|
+
params = {
|
|
1001
|
+
code: code,
|
|
1002
|
+
client_id: clientId,
|
|
1003
|
+
redirect_uri: redirectUri,
|
|
1004
|
+
grant_type: 'authorization_code',
|
|
1005
|
+
code_verifier: codeVerifier
|
|
1006
|
+
};
|
|
1007
|
+
// Only include client_secret for confidential clients
|
|
1008
|
+
if (clientSecret) {
|
|
1009
|
+
params.client_secret = clientSecret;
|
|
1010
|
+
}
|
|
1011
|
+
body = new URLSearchParams(params);
|
|
1012
|
+
return [
|
|
1013
|
+
4,
|
|
1014
|
+
(0, _fetchwithtimeoutts.fetchWithTimeout)(tokenUrl, {
|
|
1015
|
+
method: 'POST',
|
|
1016
|
+
headers: {
|
|
1017
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
1018
|
+
},
|
|
1019
|
+
body: body.toString()
|
|
1020
|
+
})
|
|
1021
|
+
];
|
|
1022
|
+
case 1:
|
|
1023
|
+
response = _state.sent();
|
|
1024
|
+
if (!!response.ok) return [
|
|
1025
|
+
3,
|
|
1026
|
+
3
|
|
1027
|
+
];
|
|
1028
|
+
return [
|
|
1029
|
+
4,
|
|
1030
|
+
response.text()
|
|
1031
|
+
];
|
|
1032
|
+
case 2:
|
|
1033
|
+
errorText = _state.sent();
|
|
1034
|
+
throw new Error("Token exchange failed: ".concat(response.status, " ").concat(errorText));
|
|
1035
|
+
case 3:
|
|
1036
|
+
return [
|
|
1037
|
+
4,
|
|
1038
|
+
response.json()
|
|
1039
|
+
];
|
|
1040
|
+
case 4:
|
|
1041
|
+
return [
|
|
1042
|
+
2,
|
|
1043
|
+
_state.sent()
|
|
1044
|
+
];
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
}).call(this);
|
|
1048
|
+
};
|
|
1049
|
+
_proto.refreshAccessToken = function refreshAccessToken(refreshToken) {
|
|
1050
|
+
return _async_to_generator(function() {
|
|
1051
|
+
var _this_config, clientId, clientSecret, tenantId, scope, tokenUrl, params, body, response, errorText, tokenResponse;
|
|
1052
|
+
return _ts_generator(this, function(_state) {
|
|
1053
|
+
switch(_state.label){
|
|
1054
|
+
case 0:
|
|
1055
|
+
_this_config = this.config, clientId = _this_config.clientId, clientSecret = _this_config.clientSecret, tenantId = _this_config.tenantId, scope = _this_config.scope;
|
|
1056
|
+
tokenUrl = "https://login.microsoftonline.com/".concat(tenantId, "/oauth2/v2.0/token");
|
|
1057
|
+
params = {
|
|
1058
|
+
refresh_token: refreshToken,
|
|
1059
|
+
client_id: clientId,
|
|
1060
|
+
grant_type: 'refresh_token',
|
|
1061
|
+
scope: scope
|
|
1062
|
+
};
|
|
1063
|
+
// Only include client_secret for confidential clients
|
|
1064
|
+
if (clientSecret) {
|
|
1065
|
+
params.client_secret = clientSecret;
|
|
1066
|
+
}
|
|
1067
|
+
body = new URLSearchParams(params);
|
|
1068
|
+
return [
|
|
1069
|
+
4,
|
|
1070
|
+
(0, _fetchwithtimeoutts.fetchWithTimeout)(tokenUrl, {
|
|
1071
|
+
method: 'POST',
|
|
1072
|
+
headers: {
|
|
1073
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
1074
|
+
},
|
|
1075
|
+
body: body.toString()
|
|
1076
|
+
})
|
|
1077
|
+
];
|
|
1078
|
+
case 1:
|
|
1079
|
+
response = _state.sent();
|
|
1080
|
+
if (!!response.ok) return [
|
|
1081
|
+
3,
|
|
1082
|
+
3
|
|
1083
|
+
];
|
|
1084
|
+
return [
|
|
1085
|
+
4,
|
|
1086
|
+
response.text()
|
|
1087
|
+
];
|
|
1088
|
+
case 2:
|
|
1089
|
+
errorText = _state.sent();
|
|
1090
|
+
throw new Error("Token refresh failed: ".concat(response.status, " ").concat(errorText));
|
|
1091
|
+
case 3:
|
|
1092
|
+
return [
|
|
1093
|
+
4,
|
|
1094
|
+
response.json()
|
|
1095
|
+
];
|
|
1096
|
+
case 4:
|
|
1097
|
+
tokenResponse = _state.sent();
|
|
1098
|
+
return [
|
|
1099
|
+
2,
|
|
1100
|
+
_object_spread({
|
|
1101
|
+
accessToken: tokenResponse.access_token,
|
|
1102
|
+
refreshToken: refreshToken
|
|
1103
|
+
}, tokenResponse.expires_in !== undefined && {
|
|
1104
|
+
expiresAt: Date.now() + tokenResponse.expires_in * 1000
|
|
1105
|
+
}, tokenResponse.scope !== undefined && {
|
|
1106
|
+
scope: tokenResponse.scope
|
|
1107
|
+
})
|
|
1108
|
+
];
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
}).call(this);
|
|
1112
|
+
};
|
|
1113
|
+
/**
|
|
1114
|
+
* Create auth middleware for single-user context (single active account per service)
|
|
1115
|
+
*
|
|
1116
|
+
* Single-user mode:
|
|
1117
|
+
* - Maintains per-service active accounts in storage
|
|
1118
|
+
* - Supports backchannel account override via extra._meta.accountId
|
|
1119
|
+
* - Automatically enhances output schemas with auth_required branch
|
|
1120
|
+
*
|
|
1121
|
+
* Example:
|
|
1122
|
+
* ```typescript
|
|
1123
|
+
* const loopback = new LoopbackOAuthProvider({ service: 'outlook', ... });
|
|
1124
|
+
* const middleware = loopback.authMiddleware();
|
|
1125
|
+
* const tools = toolFactories.map(f => f()).map(middleware.withToolAuth);
|
|
1126
|
+
* const resources = resourceFactories.map(f => f()).map(middleware.withResourceAuth);
|
|
1127
|
+
* const prompts = promptFactories.map(f => f()).map(middleware.withPromptAuth);
|
|
1128
|
+
* ```
|
|
1129
|
+
*
|
|
1130
|
+
* @returns Object with withToolAuth, withResourceAuth, withPromptAuth methods
|
|
1131
|
+
*/ _proto.authMiddleware = function authMiddleware() {
|
|
1132
|
+
var _this = this;
|
|
1133
|
+
var _this_config = this.config, service = _this_config.service, tokenStore = _this_config.tokenStore, logger = _this_config.logger;
|
|
1134
|
+
// Shared wrapper logic - extracts extra parameter from specified position
|
|
1135
|
+
// Generic T captures the actual module type; handler is cast from unknown to callable
|
|
1136
|
+
var wrapAtPosition = function(module, extraPosition) {
|
|
1137
|
+
var _this1 = _this;
|
|
1138
|
+
var operation = module.name;
|
|
1139
|
+
var originalHandler = module.handler;
|
|
1140
|
+
var wrappedHandler = function() {
|
|
1141
|
+
for(var _len = arguments.length, allArgs = new Array(_len), _key = 0; _key < _len; _key++){
|
|
1142
|
+
allArgs[_key] = arguments[_key];
|
|
1143
|
+
}
|
|
1144
|
+
return _async_to_generator(function() {
|
|
1145
|
+
var extra, accountId, _ref, _extra__meta, _tmp, error, effectiveAccountId, _tmp1, auth, error1, authRequiredResponse;
|
|
1146
|
+
return _ts_generator(this, function(_state) {
|
|
1147
|
+
switch(_state.label){
|
|
1148
|
+
case 0:
|
|
1149
|
+
if (allArgs.length <= extraPosition) {
|
|
1150
|
+
// Arg-less tool pattern: keep args as-is, create separate extra object
|
|
1151
|
+
extra = allArgs[0] && _type_of(allArgs[0]) === 'object' ? {} : {};
|
|
1152
|
+
allArgs[extraPosition] = extra;
|
|
1153
|
+
} else {
|
|
1154
|
+
extra = allArgs[extraPosition] || {};
|
|
1155
|
+
allArgs[extraPosition] = extra;
|
|
1156
|
+
}
|
|
1157
|
+
_state.label = 1;
|
|
1158
|
+
case 1:
|
|
1159
|
+
_state.trys.push([
|
|
1160
|
+
1,
|
|
1161
|
+
13,
|
|
1162
|
+
,
|
|
1163
|
+
14
|
|
1164
|
+
]);
|
|
1165
|
+
_state.label = 2;
|
|
1166
|
+
case 2:
|
|
1167
|
+
_state.trys.push([
|
|
1168
|
+
2,
|
|
1169
|
+
6,
|
|
1170
|
+
,
|
|
1171
|
+
7
|
|
1172
|
+
]);
|
|
1173
|
+
if (!((_ref = (_extra__meta = extra._meta) === null || _extra__meta === void 0 ? void 0 : _extra__meta.accountId) !== null && _ref !== void 0)) return [
|
|
1174
|
+
3,
|
|
1175
|
+
3
|
|
1176
|
+
];
|
|
1177
|
+
_tmp = _ref;
|
|
1178
|
+
return [
|
|
1179
|
+
3,
|
|
1180
|
+
5
|
|
1181
|
+
];
|
|
1182
|
+
case 3:
|
|
1183
|
+
return [
|
|
1184
|
+
4,
|
|
1185
|
+
(0, _oauth.getActiveAccount)(tokenStore, {
|
|
1186
|
+
service: service
|
|
1187
|
+
})
|
|
1188
|
+
];
|
|
1189
|
+
case 4:
|
|
1190
|
+
_tmp = _state.sent();
|
|
1191
|
+
_state.label = 5;
|
|
1192
|
+
case 5:
|
|
1193
|
+
accountId = _tmp;
|
|
1194
|
+
return [
|
|
1195
|
+
3,
|
|
1196
|
+
7
|
|
1197
|
+
];
|
|
1198
|
+
case 6:
|
|
1199
|
+
error = _state.sent();
|
|
1200
|
+
if (_instanceof(error, Error) && (error.code === 'REQUIRES_AUTHENTICATION' || error.name === 'AccountManagerError')) {
|
|
1201
|
+
accountId = undefined;
|
|
1202
|
+
} else {
|
|
1203
|
+
throw error;
|
|
1204
|
+
}
|
|
1205
|
+
return [
|
|
1206
|
+
3,
|
|
1207
|
+
7
|
|
1208
|
+
];
|
|
1209
|
+
case 7:
|
|
1210
|
+
// Eagerly validate token exists or trigger OAuth flow
|
|
1211
|
+
return [
|
|
1212
|
+
4,
|
|
1213
|
+
this.getAccessToken(accountId)
|
|
1214
|
+
];
|
|
1215
|
+
case 8:
|
|
1216
|
+
_state.sent();
|
|
1217
|
+
if (!(accountId !== null && accountId !== void 0)) return [
|
|
1218
|
+
3,
|
|
1219
|
+
9
|
|
1220
|
+
];
|
|
1221
|
+
_tmp1 = accountId;
|
|
1222
|
+
return [
|
|
1223
|
+
3,
|
|
1224
|
+
11
|
|
1225
|
+
];
|
|
1226
|
+
case 9:
|
|
1227
|
+
return [
|
|
1228
|
+
4,
|
|
1229
|
+
(0, _oauth.getActiveAccount)(tokenStore, {
|
|
1230
|
+
service: service
|
|
1231
|
+
})
|
|
1232
|
+
];
|
|
1233
|
+
case 10:
|
|
1234
|
+
_tmp1 = _state.sent();
|
|
1235
|
+
_state.label = 11;
|
|
1236
|
+
case 11:
|
|
1237
|
+
effectiveAccountId = _tmp1;
|
|
1238
|
+
if (!effectiveAccountId) {
|
|
1239
|
+
throw new Error("No account found after OAuth flow for service ".concat(service));
|
|
1240
|
+
}
|
|
1241
|
+
auth = this.toAuthProvider(effectiveAccountId);
|
|
1242
|
+
// Inject authContext and logger into extra
|
|
1243
|
+
extra.authContext = {
|
|
1244
|
+
auth: auth,
|
|
1245
|
+
accountId: effectiveAccountId
|
|
1246
|
+
};
|
|
1247
|
+
extra.logger = logger;
|
|
1248
|
+
return [
|
|
1249
|
+
4,
|
|
1250
|
+
originalHandler.apply(void 0, _to_consumable_array(allArgs))
|
|
1251
|
+
];
|
|
1252
|
+
case 12:
|
|
1253
|
+
// Call original handler with all args
|
|
1254
|
+
return [
|
|
1255
|
+
2,
|
|
1256
|
+
_state.sent()
|
|
1257
|
+
];
|
|
1258
|
+
case 13:
|
|
1259
|
+
error1 = _state.sent();
|
|
1260
|
+
// Token retrieval/refresh failed - return auth required
|
|
1261
|
+
if (_instanceof(error1, _typests.AuthRequiredError)) {
|
|
1262
|
+
logger.info('Authentication required', {
|
|
1263
|
+
service: service,
|
|
1264
|
+
tool: operation,
|
|
1265
|
+
descriptor: error1.descriptor
|
|
1266
|
+
});
|
|
1267
|
+
// Return auth_required response wrapped in { result } to match tool outputSchema pattern
|
|
1268
|
+
// Tools define outputSchema: z.object({ result: discriminatedUnion(...) }) where auth_required is a branch
|
|
1269
|
+
authRequiredResponse = {
|
|
1270
|
+
type: 'auth_required',
|
|
1271
|
+
provider: service,
|
|
1272
|
+
message: "Authentication required for ".concat(operation, ". Please authenticate with ").concat(service, "."),
|
|
1273
|
+
url: error1.descriptor.kind === 'auth_url' ? error1.descriptor.url : undefined
|
|
1274
|
+
};
|
|
1275
|
+
return [
|
|
1276
|
+
2,
|
|
1277
|
+
{
|
|
1278
|
+
content: [
|
|
1279
|
+
{
|
|
1280
|
+
type: 'text',
|
|
1281
|
+
text: JSON.stringify({
|
|
1282
|
+
result: authRequiredResponse
|
|
1283
|
+
})
|
|
1284
|
+
}
|
|
1285
|
+
],
|
|
1286
|
+
structuredContent: {
|
|
1287
|
+
result: authRequiredResponse
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
];
|
|
1291
|
+
}
|
|
1292
|
+
// Other errors - propagate
|
|
1293
|
+
throw error1;
|
|
1294
|
+
case 14:
|
|
1295
|
+
return [
|
|
1296
|
+
2
|
|
1297
|
+
];
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
}).call(_this1);
|
|
1301
|
+
};
|
|
1302
|
+
return _object_spread_props(_object_spread({}, module), {
|
|
1303
|
+
handler: wrappedHandler
|
|
1304
|
+
});
|
|
1305
|
+
};
|
|
1306
|
+
return {
|
|
1307
|
+
// Use structural constraints to avoid contravariance check on handler type.
|
|
1308
|
+
// wrapAtPosition is now generic and returns T directly.
|
|
1309
|
+
withToolAuth: function(module) {
|
|
1310
|
+
return wrapAtPosition(module, 1);
|
|
1311
|
+
},
|
|
1312
|
+
withResourceAuth: function(module) {
|
|
1313
|
+
return wrapAtPosition(module, 2);
|
|
1314
|
+
},
|
|
1315
|
+
withPromptAuth: function(module) {
|
|
1316
|
+
return wrapAtPosition(module, 0);
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
};
|
|
1320
|
+
return LoopbackOAuthProvider;
|
|
1321
|
+
}();
|
|
1322
|
+
function createMicrosoftFileAuth(config) {
|
|
1323
|
+
return new LoopbackOAuthProvider(config);
|
|
1324
|
+
}
|
|
1325
|
+
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|