@mcp-z/oauth-google 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 +93 -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 +1189 -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 +107 -0
- package/dist/cjs/providers/dcr.d.ts +107 -0
- package/dist/cjs/providers/dcr.js +584 -0
- package/dist/cjs/providers/dcr.js.map +1 -0
- package/dist/cjs/providers/loopback-oauth.d.cts +119 -0
- package/dist/cjs/providers/loopback-oauth.d.ts +119 -0
- package/dist/cjs/providers/loopback-oauth.js +1334 -0
- package/dist/cjs/providers/loopback-oauth.js.map +1 -0
- package/dist/cjs/providers/service-account.d.cts +131 -0
- package/dist/cjs/providers/service-account.d.ts +131 -0
- package/dist/cjs/providers/service-account.js +800 -0
- package/dist/cjs/providers/service-account.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 +112 -0
- package/dist/cjs/setup/config.d.ts +112 -0
- package/dist/cjs/setup/config.js +236 -0
- package/dist/cjs/setup/config.js.map +1 -0
- package/dist/cjs/types.d.cts +173 -0
- package/dist/cjs/types.d.ts +173 -0
- package/dist/cjs/types.js +16 -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 +515 -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 +107 -0
- package/dist/esm/providers/dcr.js +242 -0
- package/dist/esm/providers/dcr.js.map +1 -0
- package/dist/esm/providers/loopback-oauth.d.ts +119 -0
- package/dist/esm/providers/loopback-oauth.js +639 -0
- package/dist/esm/providers/loopback-oauth.js.map +1 -0
- package/dist/esm/providers/service-account.d.ts +131 -0
- package/dist/esm/providers/service-account.js +353 -0
- package/dist/esm/providers/service-account.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 +112 -0
- package/dist/esm/setup/config.js +258 -0
- package/dist/esm/setup/config.js.map +1 -0
- package/dist/esm/types.d.ts +173 -0
- package/dist/esm/types.js +6 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,1189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DCR Router - OAuth 2.0 Authorization Server
|
|
3
|
+
*
|
|
4
|
+
* Implements OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591)
|
|
5
|
+
* and OAuth 2.0 Authorization Server endpoints (RFC 6749, RFC 8414, RFC 9728).
|
|
6
|
+
*
|
|
7
|
+
* Endpoints:
|
|
8
|
+
* - GET /.well-known/oauth-authorization-server (RFC 8414 metadata)
|
|
9
|
+
* - GET /.well-known/oauth-protected-resource (RFC 9728 metadata - root)
|
|
10
|
+
* - GET /.well-known/oauth-protected-resource/mcp (RFC 9728 metadata - sub-path)
|
|
11
|
+
* - POST /oauth/register (RFC 7591 client registration)
|
|
12
|
+
* - GET /oauth/authorize (RFC 6749 authorization endpoint)
|
|
13
|
+
* - POST /oauth/token (RFC 6749 token endpoint)
|
|
14
|
+
* - POST /oauth/revoke (RFC 7009 token revocation)
|
|
15
|
+
* - GET /oauth/verify (token verification for Resource Server)
|
|
16
|
+
*/ "use strict";
|
|
17
|
+
Object.defineProperty(exports, "__esModule", {
|
|
18
|
+
value: true
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(exports, "createDcrRouter", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function() {
|
|
23
|
+
return createDcrRouter;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
var _crypto = require("crypto");
|
|
27
|
+
var _express = /*#__PURE__*/ _interop_require_default(require("express"));
|
|
28
|
+
var _dcrts = require("../providers/dcr.js");
|
|
29
|
+
var _dcrutilsts = /*#__PURE__*/ _interop_require_wildcard(require("./dcr-utils.js"));
|
|
30
|
+
function _array_like_to_array(arr, len) {
|
|
31
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
32
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
33
|
+
return arr2;
|
|
34
|
+
}
|
|
35
|
+
function _array_with_holes(arr) {
|
|
36
|
+
if (Array.isArray(arr)) return arr;
|
|
37
|
+
}
|
|
38
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
39
|
+
try {
|
|
40
|
+
var info = gen[key](arg);
|
|
41
|
+
var value = info.value;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
reject(error);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (info.done) {
|
|
47
|
+
resolve(value);
|
|
48
|
+
} else {
|
|
49
|
+
Promise.resolve(value).then(_next, _throw);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function _async_to_generator(fn) {
|
|
53
|
+
return function() {
|
|
54
|
+
var self = this, args = arguments;
|
|
55
|
+
return new Promise(function(resolve, reject) {
|
|
56
|
+
var gen = fn.apply(self, args);
|
|
57
|
+
function _next(value) {
|
|
58
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
59
|
+
}
|
|
60
|
+
function _throw(err) {
|
|
61
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
62
|
+
}
|
|
63
|
+
_next(undefined);
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function _define_property(obj, key, value) {
|
|
68
|
+
if (key in obj) {
|
|
69
|
+
Object.defineProperty(obj, key, {
|
|
70
|
+
value: value,
|
|
71
|
+
enumerable: true,
|
|
72
|
+
configurable: true,
|
|
73
|
+
writable: true
|
|
74
|
+
});
|
|
75
|
+
} else {
|
|
76
|
+
obj[key] = value;
|
|
77
|
+
}
|
|
78
|
+
return obj;
|
|
79
|
+
}
|
|
80
|
+
function _instanceof(left, right) {
|
|
81
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
82
|
+
return !!right[Symbol.hasInstance](left);
|
|
83
|
+
} else {
|
|
84
|
+
return left instanceof right;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function _interop_require_default(obj) {
|
|
88
|
+
return obj && obj.__esModule ? obj : {
|
|
89
|
+
default: obj
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
93
|
+
if (typeof WeakMap !== "function") return null;
|
|
94
|
+
var cacheBabelInterop = new WeakMap();
|
|
95
|
+
var cacheNodeInterop = new WeakMap();
|
|
96
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
97
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
98
|
+
})(nodeInterop);
|
|
99
|
+
}
|
|
100
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
101
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
102
|
+
return obj;
|
|
103
|
+
}
|
|
104
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
105
|
+
return {
|
|
106
|
+
default: obj
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
110
|
+
if (cache && cache.has(obj)) {
|
|
111
|
+
return cache.get(obj);
|
|
112
|
+
}
|
|
113
|
+
var newObj = {
|
|
114
|
+
__proto__: null
|
|
115
|
+
};
|
|
116
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
117
|
+
for(var key in obj){
|
|
118
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
119
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
120
|
+
if (desc && (desc.get || desc.set)) {
|
|
121
|
+
Object.defineProperty(newObj, key, desc);
|
|
122
|
+
} else {
|
|
123
|
+
newObj[key] = obj[key];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
newObj.default = obj;
|
|
128
|
+
if (cache) {
|
|
129
|
+
cache.set(obj, newObj);
|
|
130
|
+
}
|
|
131
|
+
return newObj;
|
|
132
|
+
}
|
|
133
|
+
function _iterable_to_array_limit(arr, i) {
|
|
134
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
135
|
+
if (_i == null) return;
|
|
136
|
+
var _arr = [];
|
|
137
|
+
var _n = true;
|
|
138
|
+
var _d = false;
|
|
139
|
+
var _s, _e;
|
|
140
|
+
try {
|
|
141
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
142
|
+
_arr.push(_s.value);
|
|
143
|
+
if (i && _arr.length === i) break;
|
|
144
|
+
}
|
|
145
|
+
} catch (err) {
|
|
146
|
+
_d = true;
|
|
147
|
+
_e = err;
|
|
148
|
+
} finally{
|
|
149
|
+
try {
|
|
150
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
151
|
+
} finally{
|
|
152
|
+
if (_d) throw _e;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return _arr;
|
|
156
|
+
}
|
|
157
|
+
function _non_iterable_rest() {
|
|
158
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
159
|
+
}
|
|
160
|
+
function _object_spread(target) {
|
|
161
|
+
for(var i = 1; i < arguments.length; i++){
|
|
162
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
163
|
+
var ownKeys = Object.keys(source);
|
|
164
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
165
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
166
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
ownKeys.forEach(function(key) {
|
|
170
|
+
_define_property(target, key, source[key]);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return target;
|
|
174
|
+
}
|
|
175
|
+
function ownKeys(object, enumerableOnly) {
|
|
176
|
+
var keys = Object.keys(object);
|
|
177
|
+
if (Object.getOwnPropertySymbols) {
|
|
178
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
179
|
+
if (enumerableOnly) {
|
|
180
|
+
symbols = symbols.filter(function(sym) {
|
|
181
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
keys.push.apply(keys, symbols);
|
|
185
|
+
}
|
|
186
|
+
return keys;
|
|
187
|
+
}
|
|
188
|
+
function _object_spread_props(target, source) {
|
|
189
|
+
source = source != null ? source : {};
|
|
190
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
191
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
192
|
+
} else {
|
|
193
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
194
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return target;
|
|
198
|
+
}
|
|
199
|
+
function _sliced_to_array(arr, i) {
|
|
200
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
201
|
+
}
|
|
202
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
203
|
+
if (!o) return;
|
|
204
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
205
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
206
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
207
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
208
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
209
|
+
}
|
|
210
|
+
function _ts_generator(thisArg, body) {
|
|
211
|
+
var f, y, t, _ = {
|
|
212
|
+
label: 0,
|
|
213
|
+
sent: function() {
|
|
214
|
+
if (t[0] & 1) throw t[1];
|
|
215
|
+
return t[1];
|
|
216
|
+
},
|
|
217
|
+
trys: [],
|
|
218
|
+
ops: []
|
|
219
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
|
|
220
|
+
return d(g, "next", {
|
|
221
|
+
value: verb(0)
|
|
222
|
+
}), d(g, "throw", {
|
|
223
|
+
value: verb(1)
|
|
224
|
+
}), d(g, "return", {
|
|
225
|
+
value: verb(2)
|
|
226
|
+
}), typeof Symbol === "function" && d(g, Symbol.iterator, {
|
|
227
|
+
value: function() {
|
|
228
|
+
return this;
|
|
229
|
+
}
|
|
230
|
+
}), g;
|
|
231
|
+
function verb(n) {
|
|
232
|
+
return function(v) {
|
|
233
|
+
return step([
|
|
234
|
+
n,
|
|
235
|
+
v
|
|
236
|
+
]);
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function step(op) {
|
|
240
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
241
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
242
|
+
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;
|
|
243
|
+
if (y = 0, t) op = [
|
|
244
|
+
op[0] & 2,
|
|
245
|
+
t.value
|
|
246
|
+
];
|
|
247
|
+
switch(op[0]){
|
|
248
|
+
case 0:
|
|
249
|
+
case 1:
|
|
250
|
+
t = op;
|
|
251
|
+
break;
|
|
252
|
+
case 4:
|
|
253
|
+
_.label++;
|
|
254
|
+
return {
|
|
255
|
+
value: op[1],
|
|
256
|
+
done: false
|
|
257
|
+
};
|
|
258
|
+
case 5:
|
|
259
|
+
_.label++;
|
|
260
|
+
y = op[1];
|
|
261
|
+
op = [
|
|
262
|
+
0
|
|
263
|
+
];
|
|
264
|
+
continue;
|
|
265
|
+
case 7:
|
|
266
|
+
op = _.ops.pop();
|
|
267
|
+
_.trys.pop();
|
|
268
|
+
continue;
|
|
269
|
+
default:
|
|
270
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
271
|
+
_ = 0;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
275
|
+
_.label = op[1];
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
279
|
+
_.label = t[1];
|
|
280
|
+
t = op;
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
if (t && _.label < t[2]) {
|
|
284
|
+
_.label = t[2];
|
|
285
|
+
_.ops.push(op);
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
if (t[2]) _.ops.pop();
|
|
289
|
+
_.trys.pop();
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
op = body.call(thisArg, _);
|
|
293
|
+
} catch (e) {
|
|
294
|
+
op = [
|
|
295
|
+
6,
|
|
296
|
+
e
|
|
297
|
+
];
|
|
298
|
+
y = 0;
|
|
299
|
+
} finally{
|
|
300
|
+
f = t = 0;
|
|
301
|
+
}
|
|
302
|
+
if (op[0] & 5) throw op[1];
|
|
303
|
+
return {
|
|
304
|
+
value: op[0] ? op[1] : void 0,
|
|
305
|
+
done: true
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function createDcrRouter(config) {
|
|
310
|
+
var router = _express.default.Router();
|
|
311
|
+
var store = config.store, issuerUrl = config.issuerUrl, baseUrl = config.baseUrl, scopesSupported = config.scopesSupported, clientConfig = config.clientConfig;
|
|
312
|
+
router.use(_express.default.json());
|
|
313
|
+
router.use(_express.default.urlencoded({
|
|
314
|
+
extended: true
|
|
315
|
+
}));
|
|
316
|
+
/**
|
|
317
|
+
* OAuth Authorization Server Metadata (RFC 8414)
|
|
318
|
+
* GET /.well-known/oauth-authorization-server
|
|
319
|
+
*/ router.get('/.well-known/oauth-authorization-server', function(_req, res) {
|
|
320
|
+
var metadata = {
|
|
321
|
+
issuer: issuerUrl,
|
|
322
|
+
authorization_endpoint: "".concat(baseUrl, "/oauth/authorize"),
|
|
323
|
+
token_endpoint: "".concat(baseUrl, "/oauth/token"),
|
|
324
|
+
registration_endpoint: "".concat(baseUrl, "/oauth/register"),
|
|
325
|
+
revocation_endpoint: "".concat(baseUrl, "/oauth/revoke"),
|
|
326
|
+
scopes_supported: scopesSupported,
|
|
327
|
+
response_types_supported: [
|
|
328
|
+
'code'
|
|
329
|
+
],
|
|
330
|
+
grant_types_supported: [
|
|
331
|
+
'authorization_code',
|
|
332
|
+
'refresh_token'
|
|
333
|
+
],
|
|
334
|
+
token_endpoint_auth_methods_supported: [
|
|
335
|
+
'client_secret_basic',
|
|
336
|
+
'client_secret_post'
|
|
337
|
+
],
|
|
338
|
+
code_challenge_methods_supported: [
|
|
339
|
+
'S256',
|
|
340
|
+
'plain'
|
|
341
|
+
],
|
|
342
|
+
service_documentation: "".concat(baseUrl, "/docs")
|
|
343
|
+
};
|
|
344
|
+
res.json(metadata);
|
|
345
|
+
});
|
|
346
|
+
/**
|
|
347
|
+
* OAuth Protected Resource Metadata (RFC 9728 - Root)
|
|
348
|
+
* GET /.well-known/oauth-protected-resource
|
|
349
|
+
*/ router.get('/.well-known/oauth-protected-resource', function(_req, res) {
|
|
350
|
+
var metadata = {
|
|
351
|
+
resource: baseUrl,
|
|
352
|
+
authorization_servers: [
|
|
353
|
+
baseUrl
|
|
354
|
+
],
|
|
355
|
+
scopes_supported: scopesSupported,
|
|
356
|
+
bearer_methods_supported: [
|
|
357
|
+
'header'
|
|
358
|
+
]
|
|
359
|
+
};
|
|
360
|
+
res.json(metadata);
|
|
361
|
+
});
|
|
362
|
+
/**
|
|
363
|
+
* OAuth Protected Resource Metadata (RFC 9728 - Sub-path /mcp)
|
|
364
|
+
* GET /.well-known/oauth-protected-resource/mcp
|
|
365
|
+
*/ router.get('/.well-known/oauth-protected-resource/mcp', function(_req, res) {
|
|
366
|
+
var metadata = {
|
|
367
|
+
resource: "".concat(baseUrl, "/mcp"),
|
|
368
|
+
authorization_servers: [
|
|
369
|
+
baseUrl
|
|
370
|
+
],
|
|
371
|
+
scopes_supported: scopesSupported,
|
|
372
|
+
bearer_methods_supported: [
|
|
373
|
+
'header'
|
|
374
|
+
]
|
|
375
|
+
};
|
|
376
|
+
res.json(metadata);
|
|
377
|
+
});
|
|
378
|
+
/**
|
|
379
|
+
* Dynamic Client Registration (RFC 7591)
|
|
380
|
+
* POST /oauth/register
|
|
381
|
+
*/ router.post('/oauth/register', function(req, res) {
|
|
382
|
+
return _async_to_generator(function() {
|
|
383
|
+
var registrationRequest, client, error;
|
|
384
|
+
return _ts_generator(this, function(_state) {
|
|
385
|
+
switch(_state.label){
|
|
386
|
+
case 0:
|
|
387
|
+
_state.trys.push([
|
|
388
|
+
0,
|
|
389
|
+
2,
|
|
390
|
+
,
|
|
391
|
+
3
|
|
392
|
+
]);
|
|
393
|
+
registrationRequest = req.body;
|
|
394
|
+
return [
|
|
395
|
+
4,
|
|
396
|
+
_dcrutilsts.registerClient(store, registrationRequest)
|
|
397
|
+
];
|
|
398
|
+
case 1:
|
|
399
|
+
client = _state.sent();
|
|
400
|
+
res.status(201).json(client);
|
|
401
|
+
return [
|
|
402
|
+
3,
|
|
403
|
+
3
|
|
404
|
+
];
|
|
405
|
+
case 2:
|
|
406
|
+
error = _state.sent();
|
|
407
|
+
res.status(400).json({
|
|
408
|
+
error: 'invalid_client_metadata',
|
|
409
|
+
error_description: _instanceof(error, Error) ? error.message : 'Invalid registration request'
|
|
410
|
+
});
|
|
411
|
+
return [
|
|
412
|
+
3,
|
|
413
|
+
3
|
|
414
|
+
];
|
|
415
|
+
case 3:
|
|
416
|
+
return [
|
|
417
|
+
2
|
|
418
|
+
];
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
})();
|
|
422
|
+
});
|
|
423
|
+
/**
|
|
424
|
+
* OAuth Authorization Endpoint (RFC 6749 Section 3.1)
|
|
425
|
+
* GET /oauth/authorize
|
|
426
|
+
*
|
|
427
|
+
* Initiates Google OAuth flow, then generates DCR authorization code
|
|
428
|
+
*/ router.get('/oauth/authorize', function(req, res) {
|
|
429
|
+
return _async_to_generator(function() {
|
|
430
|
+
var _req_query, response_type, client_id, redirect_uri, _req_query_scope, scope, _req_query_state, state, code_challenge, code_challenge_method, client, isValidRedirect, googleState, dcrRequestState, googleAuthUrl;
|
|
431
|
+
return _ts_generator(this, function(_state) {
|
|
432
|
+
switch(_state.label){
|
|
433
|
+
case 0:
|
|
434
|
+
_req_query = req.query, response_type = _req_query.response_type, client_id = _req_query.client_id, redirect_uri = _req_query.redirect_uri, _req_query_scope = _req_query.scope, scope = _req_query_scope === void 0 ? '' : _req_query_scope, _req_query_state = _req_query.state, state = _req_query_state === void 0 ? '' : _req_query_state, code_challenge = _req_query.code_challenge, code_challenge_method = _req_query.code_challenge_method;
|
|
435
|
+
if (response_type !== 'code') {
|
|
436
|
+
return [
|
|
437
|
+
2,
|
|
438
|
+
res.status(400).json({
|
|
439
|
+
error: 'unsupported_response_type',
|
|
440
|
+
error_description: 'Only response_type=code is supported'
|
|
441
|
+
})
|
|
442
|
+
];
|
|
443
|
+
}
|
|
444
|
+
if (!client_id || typeof client_id !== 'string') {
|
|
445
|
+
return [
|
|
446
|
+
2,
|
|
447
|
+
res.status(400).json({
|
|
448
|
+
error: 'invalid_request',
|
|
449
|
+
error_description: 'client_id is required'
|
|
450
|
+
})
|
|
451
|
+
];
|
|
452
|
+
}
|
|
453
|
+
if (!redirect_uri || typeof redirect_uri !== 'string') {
|
|
454
|
+
return [
|
|
455
|
+
2,
|
|
456
|
+
res.status(400).json({
|
|
457
|
+
error: 'invalid_request',
|
|
458
|
+
error_description: 'redirect_uri is required'
|
|
459
|
+
})
|
|
460
|
+
];
|
|
461
|
+
}
|
|
462
|
+
return [
|
|
463
|
+
4,
|
|
464
|
+
_dcrutilsts.getClient(store, client_id)
|
|
465
|
+
];
|
|
466
|
+
case 1:
|
|
467
|
+
client = _state.sent();
|
|
468
|
+
if (!client) {
|
|
469
|
+
return [
|
|
470
|
+
2,
|
|
471
|
+
res.status(400).json({
|
|
472
|
+
error: 'invalid_client',
|
|
473
|
+
error_description: 'Unknown client_id'
|
|
474
|
+
})
|
|
475
|
+
];
|
|
476
|
+
}
|
|
477
|
+
return [
|
|
478
|
+
4,
|
|
479
|
+
_dcrutilsts.validateRedirectUri(store, client_id, redirect_uri)
|
|
480
|
+
];
|
|
481
|
+
case 2:
|
|
482
|
+
isValidRedirect = _state.sent();
|
|
483
|
+
if (!isValidRedirect) {
|
|
484
|
+
return [
|
|
485
|
+
2,
|
|
486
|
+
res.status(400).json({
|
|
487
|
+
error: 'invalid_request',
|
|
488
|
+
error_description: 'Invalid redirect_uri'
|
|
489
|
+
})
|
|
490
|
+
];
|
|
491
|
+
}
|
|
492
|
+
googleState = (0, _crypto.randomUUID)();
|
|
493
|
+
dcrRequestState = {
|
|
494
|
+
client_id: client_id,
|
|
495
|
+
redirect_uri: redirect_uri,
|
|
496
|
+
scope: typeof scope === 'string' ? scope : '',
|
|
497
|
+
state: typeof state === 'string' ? state : undefined,
|
|
498
|
+
code_challenge: typeof code_challenge === 'string' ? code_challenge : undefined,
|
|
499
|
+
code_challenge_method: typeof code_challenge_method === 'string' ? code_challenge_method : undefined,
|
|
500
|
+
created_at: Date.now(),
|
|
501
|
+
expires_at: Date.now() + 600000
|
|
502
|
+
};
|
|
503
|
+
return [
|
|
504
|
+
4,
|
|
505
|
+
store.set("dcr:google-state:".concat(googleState), dcrRequestState, 600000)
|
|
506
|
+
];
|
|
507
|
+
case 3:
|
|
508
|
+
_state.sent();
|
|
509
|
+
googleAuthUrl = new URL('https://accounts.google.com/o/oauth2/v2/auth');
|
|
510
|
+
googleAuthUrl.searchParams.set('client_id', clientConfig.clientId);
|
|
511
|
+
googleAuthUrl.searchParams.set('redirect_uri', "".concat(baseUrl, "/oauth/callback"));
|
|
512
|
+
googleAuthUrl.searchParams.set('response_type', 'code');
|
|
513
|
+
googleAuthUrl.searchParams.set('scope', typeof scope === 'string' ? scope : '');
|
|
514
|
+
googleAuthUrl.searchParams.set('state', googleState);
|
|
515
|
+
googleAuthUrl.searchParams.set('access_type', 'offline');
|
|
516
|
+
googleAuthUrl.searchParams.set('prompt', 'consent');
|
|
517
|
+
return [
|
|
518
|
+
2,
|
|
519
|
+
res.redirect(googleAuthUrl.toString())
|
|
520
|
+
];
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
})();
|
|
524
|
+
});
|
|
525
|
+
/**
|
|
526
|
+
* OAuth Callback Handler
|
|
527
|
+
* GET /oauth/callback
|
|
528
|
+
*
|
|
529
|
+
* Handles OAuth callback from Google, exchanges authorization code for tokens,
|
|
530
|
+
* and redirects back to client with DCR authorization code.
|
|
531
|
+
*/ router.get('/oauth/callback', function(req, res) {
|
|
532
|
+
return _async_to_generator(function() {
|
|
533
|
+
var _req_query, googleCode, googleState, error, dcrRequestState, tokenUrl, tokenParamsObj, tokenParams, tokenResponse, errorText, tokenData, providerTokens, dcrCode, authCode, clientRedirectUrl;
|
|
534
|
+
return _ts_generator(this, function(_state) {
|
|
535
|
+
switch(_state.label){
|
|
536
|
+
case 0:
|
|
537
|
+
_req_query = req.query, googleCode = _req_query.code, googleState = _req_query.state, error = _req_query.error;
|
|
538
|
+
if (error) {
|
|
539
|
+
return [
|
|
540
|
+
2,
|
|
541
|
+
res.status(400).json({
|
|
542
|
+
error: typeof error === 'string' ? error : 'access_denied',
|
|
543
|
+
error_description: 'Google OAuth authorization failed'
|
|
544
|
+
})
|
|
545
|
+
];
|
|
546
|
+
}
|
|
547
|
+
if (!googleCode || typeof googleCode !== 'string') {
|
|
548
|
+
return [
|
|
549
|
+
2,
|
|
550
|
+
res.status(400).json({
|
|
551
|
+
error: 'invalid_request',
|
|
552
|
+
error_description: 'Missing authorization code from Google'
|
|
553
|
+
})
|
|
554
|
+
];
|
|
555
|
+
}
|
|
556
|
+
if (!googleState || typeof googleState !== 'string') {
|
|
557
|
+
return [
|
|
558
|
+
2,
|
|
559
|
+
res.status(400).json({
|
|
560
|
+
error: 'invalid_request',
|
|
561
|
+
error_description: 'Missing state parameter'
|
|
562
|
+
})
|
|
563
|
+
];
|
|
564
|
+
}
|
|
565
|
+
return [
|
|
566
|
+
4,
|
|
567
|
+
store.get("dcr:google-state:".concat(googleState))
|
|
568
|
+
];
|
|
569
|
+
case 1:
|
|
570
|
+
dcrRequestState = _state.sent();
|
|
571
|
+
if (!dcrRequestState) {
|
|
572
|
+
return [
|
|
573
|
+
2,
|
|
574
|
+
res.status(400).json({
|
|
575
|
+
error: 'invalid_request',
|
|
576
|
+
error_description: 'Invalid or expired state parameter'
|
|
577
|
+
})
|
|
578
|
+
];
|
|
579
|
+
}
|
|
580
|
+
return [
|
|
581
|
+
4,
|
|
582
|
+
store.delete("dcr:google-state:".concat(googleState))
|
|
583
|
+
];
|
|
584
|
+
case 2:
|
|
585
|
+
_state.sent();
|
|
586
|
+
if (Date.now() > dcrRequestState.expires_at) {
|
|
587
|
+
return [
|
|
588
|
+
2,
|
|
589
|
+
res.status(400).json({
|
|
590
|
+
error: 'invalid_request',
|
|
591
|
+
error_description: 'DCR request state expired'
|
|
592
|
+
})
|
|
593
|
+
];
|
|
594
|
+
}
|
|
595
|
+
tokenUrl = 'https://oauth2.googleapis.com/token';
|
|
596
|
+
// Build token params - only include client_secret for confidential clients
|
|
597
|
+
// Public clients (Desktop apps) should NOT send client_secret at all
|
|
598
|
+
tokenParamsObj = {
|
|
599
|
+
code: googleCode,
|
|
600
|
+
client_id: clientConfig.clientId,
|
|
601
|
+
redirect_uri: "".concat(baseUrl, "/oauth/callback"),
|
|
602
|
+
grant_type: 'authorization_code'
|
|
603
|
+
};
|
|
604
|
+
if (clientConfig.clientSecret) {
|
|
605
|
+
tokenParamsObj.client_secret = clientConfig.clientSecret;
|
|
606
|
+
}
|
|
607
|
+
tokenParams = new URLSearchParams(tokenParamsObj);
|
|
608
|
+
return [
|
|
609
|
+
4,
|
|
610
|
+
fetch(tokenUrl, {
|
|
611
|
+
method: 'POST',
|
|
612
|
+
headers: {
|
|
613
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
614
|
+
},
|
|
615
|
+
body: tokenParams.toString()
|
|
616
|
+
})
|
|
617
|
+
];
|
|
618
|
+
case 3:
|
|
619
|
+
tokenResponse = _state.sent();
|
|
620
|
+
if (!!tokenResponse.ok) return [
|
|
621
|
+
3,
|
|
622
|
+
5
|
|
623
|
+
];
|
|
624
|
+
return [
|
|
625
|
+
4,
|
|
626
|
+
tokenResponse.text()
|
|
627
|
+
];
|
|
628
|
+
case 4:
|
|
629
|
+
errorText = _state.sent();
|
|
630
|
+
return [
|
|
631
|
+
2,
|
|
632
|
+
res.status(400).json({
|
|
633
|
+
error: 'server_error',
|
|
634
|
+
error_description: "Failed to exchange Google authorization code: ".concat(errorText)
|
|
635
|
+
})
|
|
636
|
+
];
|
|
637
|
+
case 5:
|
|
638
|
+
return [
|
|
639
|
+
4,
|
|
640
|
+
tokenResponse.json()
|
|
641
|
+
];
|
|
642
|
+
case 6:
|
|
643
|
+
tokenData = _state.sent();
|
|
644
|
+
// Create provider tokens from Google response
|
|
645
|
+
providerTokens = _object_spread_props(_object_spread({
|
|
646
|
+
accessToken: tokenData.access_token
|
|
647
|
+
}, tokenData.refresh_token && {
|
|
648
|
+
refreshToken: tokenData.refresh_token
|
|
649
|
+
}), {
|
|
650
|
+
expiresAt: Date.now() + tokenData.expires_in * 1000,
|
|
651
|
+
scope: tokenData.scope
|
|
652
|
+
});
|
|
653
|
+
dcrCode = (0, _crypto.randomUUID)();
|
|
654
|
+
authCode = _object_spread_props(_object_spread({
|
|
655
|
+
code: dcrCode,
|
|
656
|
+
client_id: dcrRequestState.client_id,
|
|
657
|
+
redirect_uri: dcrRequestState.redirect_uri,
|
|
658
|
+
scope: dcrRequestState.scope
|
|
659
|
+
}, dcrRequestState.code_challenge && {
|
|
660
|
+
code_challenge: dcrRequestState.code_challenge
|
|
661
|
+
}, dcrRequestState.code_challenge_method && {
|
|
662
|
+
code_challenge_method: dcrRequestState.code_challenge_method
|
|
663
|
+
}), {
|
|
664
|
+
providerTokens: providerTokens,
|
|
665
|
+
created_at: Date.now(),
|
|
666
|
+
expires_at: Date.now() + 600000
|
|
667
|
+
});
|
|
668
|
+
return [
|
|
669
|
+
4,
|
|
670
|
+
_dcrutilsts.setAuthCode(store, dcrCode, authCode)
|
|
671
|
+
];
|
|
672
|
+
case 7:
|
|
673
|
+
_state.sent();
|
|
674
|
+
clientRedirectUrl = new URL(dcrRequestState.redirect_uri);
|
|
675
|
+
clientRedirectUrl.searchParams.set('code', dcrCode);
|
|
676
|
+
if (dcrRequestState.state) {
|
|
677
|
+
clientRedirectUrl.searchParams.set('state', dcrRequestState.state);
|
|
678
|
+
}
|
|
679
|
+
return [
|
|
680
|
+
2,
|
|
681
|
+
res.redirect(clientRedirectUrl.toString())
|
|
682
|
+
];
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
})();
|
|
686
|
+
});
|
|
687
|
+
/**
|
|
688
|
+
* OAuth Token Endpoint (RFC 6749 Section 3.2)
|
|
689
|
+
* POST /oauth/token
|
|
690
|
+
*/ router.post('/oauth/token', function(req, res) {
|
|
691
|
+
return _async_to_generator(function() {
|
|
692
|
+
var client_id, client_secret, authHeader, base64Credentials, credentials, _credentials_split, id, secret, _req_body, grant_type, code, redirect_uri, refresh_token, code_verifier, isValidClient, authCode, _authCode_code_challenge_method, method, computedChallenge, accessToken, refreshTokenValue, tokenData, isValidClient1, tokenData1, refreshedProviderTokens, provider, error, newAccessToken, newTokenData;
|
|
693
|
+
return _ts_generator(this, function(_state) {
|
|
694
|
+
switch(_state.label){
|
|
695
|
+
case 0:
|
|
696
|
+
client_id = req.body.client_id;
|
|
697
|
+
client_secret = req.body.client_secret;
|
|
698
|
+
authHeader = req.headers.authorization;
|
|
699
|
+
if (authHeader && authHeader.startsWith('Basic ')) {
|
|
700
|
+
base64Credentials = authHeader.substring(6);
|
|
701
|
+
credentials = Buffer.from(base64Credentials, 'base64').toString('utf-8');
|
|
702
|
+
_credentials_split = _sliced_to_array(credentials.split(':'), 2), id = _credentials_split[0], secret = _credentials_split[1];
|
|
703
|
+
client_id = id;
|
|
704
|
+
client_secret = secret;
|
|
705
|
+
}
|
|
706
|
+
_req_body = req.body, grant_type = _req_body.grant_type, code = _req_body.code, redirect_uri = _req_body.redirect_uri, refresh_token = _req_body.refresh_token, code_verifier = _req_body.code_verifier;
|
|
707
|
+
if (!grant_type) {
|
|
708
|
+
return [
|
|
709
|
+
2,
|
|
710
|
+
res.status(400).json({
|
|
711
|
+
error: 'invalid_request',
|
|
712
|
+
error_description: 'grant_type is required'
|
|
713
|
+
})
|
|
714
|
+
];
|
|
715
|
+
}
|
|
716
|
+
if (!(grant_type === 'authorization_code')) return [
|
|
717
|
+
3,
|
|
718
|
+
9
|
|
719
|
+
];
|
|
720
|
+
if (!code || !client_id || !redirect_uri) {
|
|
721
|
+
return [
|
|
722
|
+
2,
|
|
723
|
+
res.status(400).json({
|
|
724
|
+
error: 'invalid_request',
|
|
725
|
+
error_description: 'code, client_id, and redirect_uri are required'
|
|
726
|
+
})
|
|
727
|
+
];
|
|
728
|
+
}
|
|
729
|
+
return [
|
|
730
|
+
4,
|
|
731
|
+
_dcrutilsts.validateClient(store, client_id, client_secret !== null && client_secret !== void 0 ? client_secret : '')
|
|
732
|
+
];
|
|
733
|
+
case 1:
|
|
734
|
+
isValidClient = _state.sent();
|
|
735
|
+
if (!isValidClient) {
|
|
736
|
+
return [
|
|
737
|
+
2,
|
|
738
|
+
res.status(401).json({
|
|
739
|
+
error: 'invalid_client',
|
|
740
|
+
error_description: 'Invalid client credentials'
|
|
741
|
+
})
|
|
742
|
+
];
|
|
743
|
+
}
|
|
744
|
+
return [
|
|
745
|
+
4,
|
|
746
|
+
_dcrutilsts.getAuthCode(store, code)
|
|
747
|
+
];
|
|
748
|
+
case 2:
|
|
749
|
+
authCode = _state.sent();
|
|
750
|
+
if (!authCode) {
|
|
751
|
+
return [
|
|
752
|
+
2,
|
|
753
|
+
res.status(400).json({
|
|
754
|
+
error: 'invalid_grant',
|
|
755
|
+
error_description: 'Invalid or expired authorization code'
|
|
756
|
+
})
|
|
757
|
+
];
|
|
758
|
+
}
|
|
759
|
+
if (authCode.client_id !== client_id || authCode.redirect_uri !== redirect_uri) {
|
|
760
|
+
return [
|
|
761
|
+
2,
|
|
762
|
+
res.status(400).json({
|
|
763
|
+
error: 'invalid_grant',
|
|
764
|
+
error_description: 'Authorization code mismatch'
|
|
765
|
+
})
|
|
766
|
+
];
|
|
767
|
+
}
|
|
768
|
+
if (!(Date.now() > authCode.expires_at)) return [
|
|
769
|
+
3,
|
|
770
|
+
4
|
|
771
|
+
];
|
|
772
|
+
return [
|
|
773
|
+
4,
|
|
774
|
+
_dcrutilsts.deleteAuthCode(store, code)
|
|
775
|
+
];
|
|
776
|
+
case 3:
|
|
777
|
+
_state.sent();
|
|
778
|
+
return [
|
|
779
|
+
2,
|
|
780
|
+
res.status(400).json({
|
|
781
|
+
error: 'invalid_grant',
|
|
782
|
+
error_description: 'Authorization code expired'
|
|
783
|
+
})
|
|
784
|
+
];
|
|
785
|
+
case 4:
|
|
786
|
+
if (authCode.code_challenge) {
|
|
787
|
+
;
|
|
788
|
+
if (!code_verifier) {
|
|
789
|
+
return [
|
|
790
|
+
2,
|
|
791
|
+
res.status(400).json({
|
|
792
|
+
error: 'invalid_request',
|
|
793
|
+
error_description: 'code_verifier is required for PKCE'
|
|
794
|
+
})
|
|
795
|
+
];
|
|
796
|
+
}
|
|
797
|
+
method = (_authCode_code_challenge_method = authCode.code_challenge_method) !== null && _authCode_code_challenge_method !== void 0 ? _authCode_code_challenge_method : 'plain';
|
|
798
|
+
computedChallenge = method === 'S256' ? (0, _crypto.createHash)('sha256').update(code_verifier).digest('base64url') : code_verifier;
|
|
799
|
+
if (computedChallenge !== authCode.code_challenge) {
|
|
800
|
+
return [
|
|
801
|
+
2,
|
|
802
|
+
res.status(400).json({
|
|
803
|
+
error: 'invalid_grant',
|
|
804
|
+
error_description: 'Invalid code_verifier'
|
|
805
|
+
})
|
|
806
|
+
];
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
return [
|
|
810
|
+
4,
|
|
811
|
+
_dcrutilsts.deleteAuthCode(store, code)
|
|
812
|
+
];
|
|
813
|
+
case 5:
|
|
814
|
+
_state.sent();
|
|
815
|
+
accessToken = (0, _crypto.randomUUID)();
|
|
816
|
+
refreshTokenValue = (0, _crypto.randomUUID)();
|
|
817
|
+
tokenData = {
|
|
818
|
+
access_token: accessToken,
|
|
819
|
+
token_type: 'Bearer',
|
|
820
|
+
expires_in: 3600,
|
|
821
|
+
refresh_token: refreshTokenValue,
|
|
822
|
+
scope: authCode.scope,
|
|
823
|
+
client_id: client_id,
|
|
824
|
+
providerTokens: authCode.providerTokens,
|
|
825
|
+
created_at: Date.now()
|
|
826
|
+
};
|
|
827
|
+
return [
|
|
828
|
+
4,
|
|
829
|
+
_dcrutilsts.setAccessToken(store, accessToken, tokenData)
|
|
830
|
+
];
|
|
831
|
+
case 6:
|
|
832
|
+
_state.sent();
|
|
833
|
+
return [
|
|
834
|
+
4,
|
|
835
|
+
_dcrutilsts.setRefreshToken(store, refreshTokenValue, tokenData)
|
|
836
|
+
];
|
|
837
|
+
case 7:
|
|
838
|
+
_state.sent();
|
|
839
|
+
return [
|
|
840
|
+
4,
|
|
841
|
+
_dcrutilsts.setProviderTokens(store, accessToken, authCode.providerTokens)
|
|
842
|
+
];
|
|
843
|
+
case 8:
|
|
844
|
+
_state.sent();
|
|
845
|
+
return [
|
|
846
|
+
2,
|
|
847
|
+
res.json({
|
|
848
|
+
access_token: tokenData.access_token,
|
|
849
|
+
token_type: tokenData.token_type,
|
|
850
|
+
expires_in: tokenData.expires_in,
|
|
851
|
+
refresh_token: tokenData.refresh_token,
|
|
852
|
+
scope: tokenData.scope
|
|
853
|
+
})
|
|
854
|
+
];
|
|
855
|
+
case 9:
|
|
856
|
+
if (!(grant_type === 'refresh_token')) return [
|
|
857
|
+
3,
|
|
858
|
+
18
|
|
859
|
+
];
|
|
860
|
+
if (!refresh_token || !client_id) {
|
|
861
|
+
return [
|
|
862
|
+
2,
|
|
863
|
+
res.status(400).json({
|
|
864
|
+
error: 'invalid_request',
|
|
865
|
+
error_description: 'refresh_token and client_id are required'
|
|
866
|
+
})
|
|
867
|
+
];
|
|
868
|
+
}
|
|
869
|
+
return [
|
|
870
|
+
4,
|
|
871
|
+
_dcrutilsts.validateClient(store, client_id, client_secret !== null && client_secret !== void 0 ? client_secret : '')
|
|
872
|
+
];
|
|
873
|
+
case 10:
|
|
874
|
+
isValidClient1 = _state.sent();
|
|
875
|
+
if (!isValidClient1) {
|
|
876
|
+
return [
|
|
877
|
+
2,
|
|
878
|
+
res.status(401).json({
|
|
879
|
+
error: 'invalid_client',
|
|
880
|
+
error_description: 'Invalid client credentials'
|
|
881
|
+
})
|
|
882
|
+
];
|
|
883
|
+
}
|
|
884
|
+
return [
|
|
885
|
+
4,
|
|
886
|
+
_dcrutilsts.getRefreshToken(store, refresh_token)
|
|
887
|
+
];
|
|
888
|
+
case 11:
|
|
889
|
+
tokenData1 = _state.sent();
|
|
890
|
+
if (!tokenData1 || tokenData1.client_id !== client_id) {
|
|
891
|
+
return [
|
|
892
|
+
2,
|
|
893
|
+
res.status(400).json({
|
|
894
|
+
error: 'invalid_grant',
|
|
895
|
+
error_description: 'Invalid refresh token'
|
|
896
|
+
})
|
|
897
|
+
];
|
|
898
|
+
}
|
|
899
|
+
refreshedProviderTokens = tokenData1.providerTokens;
|
|
900
|
+
if (!tokenData1.providerTokens.refreshToken) return [
|
|
901
|
+
3,
|
|
902
|
+
15
|
|
903
|
+
];
|
|
904
|
+
_state.label = 12;
|
|
905
|
+
case 12:
|
|
906
|
+
_state.trys.push([
|
|
907
|
+
12,
|
|
908
|
+
14,
|
|
909
|
+
,
|
|
910
|
+
15
|
|
911
|
+
]);
|
|
912
|
+
// Create DcrOAuthProvider instance to refresh Google tokens
|
|
913
|
+
provider = new _dcrts.DcrOAuthProvider(_object_spread_props(_object_spread({}, clientConfig), {
|
|
914
|
+
scope: tokenData1.scope,
|
|
915
|
+
verifyEndpoint: "".concat(baseUrl, "/oauth/verify"),
|
|
916
|
+
logger: {
|
|
917
|
+
info: console.log,
|
|
918
|
+
error: console.error,
|
|
919
|
+
warn: console.warn,
|
|
920
|
+
debug: function() {}
|
|
921
|
+
}
|
|
922
|
+
}));
|
|
923
|
+
return [
|
|
924
|
+
4,
|
|
925
|
+
provider.refreshAccessToken(tokenData1.providerTokens.refreshToken)
|
|
926
|
+
];
|
|
927
|
+
case 13:
|
|
928
|
+
// Refresh the Google access token
|
|
929
|
+
refreshedProviderTokens = _state.sent();
|
|
930
|
+
return [
|
|
931
|
+
3,
|
|
932
|
+
15
|
|
933
|
+
];
|
|
934
|
+
case 14:
|
|
935
|
+
error = _state.sent();
|
|
936
|
+
// If refresh fails, continue with existing tokens (they may still be valid)
|
|
937
|
+
console.warn('Provider token refresh failed, using existing tokens:', _instanceof(error, Error) ? error.message : String(error));
|
|
938
|
+
return [
|
|
939
|
+
3,
|
|
940
|
+
15
|
|
941
|
+
];
|
|
942
|
+
case 15:
|
|
943
|
+
newAccessToken = (0, _crypto.randomUUID)();
|
|
944
|
+
newTokenData = _object_spread_props(_object_spread({}, tokenData1), {
|
|
945
|
+
access_token: newAccessToken,
|
|
946
|
+
created_at: Date.now()
|
|
947
|
+
});
|
|
948
|
+
return [
|
|
949
|
+
4,
|
|
950
|
+
_dcrutilsts.setAccessToken(store, newAccessToken, newTokenData)
|
|
951
|
+
];
|
|
952
|
+
case 16:
|
|
953
|
+
_state.sent();
|
|
954
|
+
return [
|
|
955
|
+
4,
|
|
956
|
+
_dcrutilsts.setProviderTokens(store, newAccessToken, refreshedProviderTokens)
|
|
957
|
+
];
|
|
958
|
+
case 17:
|
|
959
|
+
_state.sent();
|
|
960
|
+
return [
|
|
961
|
+
2,
|
|
962
|
+
res.json({
|
|
963
|
+
access_token: newTokenData.access_token,
|
|
964
|
+
token_type: newTokenData.token_type,
|
|
965
|
+
expires_in: newTokenData.expires_in,
|
|
966
|
+
scope: newTokenData.scope
|
|
967
|
+
})
|
|
968
|
+
];
|
|
969
|
+
case 18:
|
|
970
|
+
return [
|
|
971
|
+
2,
|
|
972
|
+
res.status(400).json({
|
|
973
|
+
error: 'unsupported_grant_type',
|
|
974
|
+
error_description: 'Only authorization_code and refresh_token grants are supported'
|
|
975
|
+
})
|
|
976
|
+
];
|
|
977
|
+
}
|
|
978
|
+
});
|
|
979
|
+
})();
|
|
980
|
+
});
|
|
981
|
+
/**
|
|
982
|
+
* OAuth Token Revocation (RFC 7009)
|
|
983
|
+
* POST /oauth/revoke
|
|
984
|
+
*/ router.post('/oauth/revoke', function(req, res) {
|
|
985
|
+
return _async_to_generator(function() {
|
|
986
|
+
var _req_body, token, token_type_hint, client_id, client_secret, isValidClient;
|
|
987
|
+
return _ts_generator(this, function(_state) {
|
|
988
|
+
switch(_state.label){
|
|
989
|
+
case 0:
|
|
990
|
+
_req_body = req.body, token = _req_body.token, token_type_hint = _req_body.token_type_hint, client_id = _req_body.client_id, client_secret = _req_body.client_secret;
|
|
991
|
+
if (!token) {
|
|
992
|
+
return [
|
|
993
|
+
2,
|
|
994
|
+
res.status(400).json({
|
|
995
|
+
error: 'invalid_request',
|
|
996
|
+
error_description: 'token is required'
|
|
997
|
+
})
|
|
998
|
+
];
|
|
999
|
+
}
|
|
1000
|
+
if (!(client_id && client_secret)) return [
|
|
1001
|
+
3,
|
|
1002
|
+
2
|
|
1003
|
+
];
|
|
1004
|
+
return [
|
|
1005
|
+
4,
|
|
1006
|
+
_dcrutilsts.validateClient(store, client_id, client_secret)
|
|
1007
|
+
];
|
|
1008
|
+
case 1:
|
|
1009
|
+
isValidClient = _state.sent();
|
|
1010
|
+
if (!isValidClient) {
|
|
1011
|
+
return [
|
|
1012
|
+
2,
|
|
1013
|
+
res.status(401).json({
|
|
1014
|
+
error: 'invalid_client',
|
|
1015
|
+
error_description: 'Invalid client credentials'
|
|
1016
|
+
})
|
|
1017
|
+
];
|
|
1018
|
+
}
|
|
1019
|
+
_state.label = 2;
|
|
1020
|
+
case 2:
|
|
1021
|
+
if (!(token_type_hint === 'refresh_token')) return [
|
|
1022
|
+
3,
|
|
1023
|
+
4
|
|
1024
|
+
];
|
|
1025
|
+
return [
|
|
1026
|
+
4,
|
|
1027
|
+
_dcrutilsts.deleteRefreshToken(store, token)
|
|
1028
|
+
];
|
|
1029
|
+
case 3:
|
|
1030
|
+
_state.sent();
|
|
1031
|
+
return [
|
|
1032
|
+
3,
|
|
1033
|
+
11
|
|
1034
|
+
];
|
|
1035
|
+
case 4:
|
|
1036
|
+
if (!(token_type_hint === 'access_token')) return [
|
|
1037
|
+
3,
|
|
1038
|
+
7
|
|
1039
|
+
];
|
|
1040
|
+
return [
|
|
1041
|
+
4,
|
|
1042
|
+
_dcrutilsts.deleteAccessToken(store, token)
|
|
1043
|
+
];
|
|
1044
|
+
case 5:
|
|
1045
|
+
_state.sent();
|
|
1046
|
+
return [
|
|
1047
|
+
4,
|
|
1048
|
+
_dcrutilsts.deleteProviderTokens(store, token)
|
|
1049
|
+
];
|
|
1050
|
+
case 6:
|
|
1051
|
+
_state.sent();
|
|
1052
|
+
return [
|
|
1053
|
+
3,
|
|
1054
|
+
11
|
|
1055
|
+
];
|
|
1056
|
+
case 7:
|
|
1057
|
+
// No hint - try both
|
|
1058
|
+
return [
|
|
1059
|
+
4,
|
|
1060
|
+
_dcrutilsts.deleteRefreshToken(store, token)
|
|
1061
|
+
];
|
|
1062
|
+
case 8:
|
|
1063
|
+
_state.sent();
|
|
1064
|
+
return [
|
|
1065
|
+
4,
|
|
1066
|
+
_dcrutilsts.deleteAccessToken(store, token)
|
|
1067
|
+
];
|
|
1068
|
+
case 9:
|
|
1069
|
+
_state.sent();
|
|
1070
|
+
return [
|
|
1071
|
+
4,
|
|
1072
|
+
_dcrutilsts.deleteProviderTokens(store, token)
|
|
1073
|
+
];
|
|
1074
|
+
case 10:
|
|
1075
|
+
_state.sent();
|
|
1076
|
+
_state.label = 11;
|
|
1077
|
+
case 11:
|
|
1078
|
+
return [
|
|
1079
|
+
2,
|
|
1080
|
+
res.status(200).send()
|
|
1081
|
+
];
|
|
1082
|
+
}
|
|
1083
|
+
});
|
|
1084
|
+
})();
|
|
1085
|
+
});
|
|
1086
|
+
/**
|
|
1087
|
+
* Token Verification Endpoint
|
|
1088
|
+
* GET /oauth/verify
|
|
1089
|
+
*
|
|
1090
|
+
* Validates bearer tokens for Resource Server.
|
|
1091
|
+
* Returns AuthInfo with provider tokens for stateless DCR pattern.
|
|
1092
|
+
*/ router.get('/oauth/verify', function(req, res) {
|
|
1093
|
+
return _async_to_generator(function() {
|
|
1094
|
+
var authHeader, token, tokenData, now, expiresAt, authInfo;
|
|
1095
|
+
return _ts_generator(this, function(_state) {
|
|
1096
|
+
switch(_state.label){
|
|
1097
|
+
case 0:
|
|
1098
|
+
authHeader = req.headers.authorization;
|
|
1099
|
+
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
1100
|
+
return [
|
|
1101
|
+
2,
|
|
1102
|
+
res.status(401).json({
|
|
1103
|
+
error: 'invalid_request',
|
|
1104
|
+
error_description: 'Missing or invalid Authorization header'
|
|
1105
|
+
})
|
|
1106
|
+
];
|
|
1107
|
+
}
|
|
1108
|
+
token = authHeader.substring(7);
|
|
1109
|
+
return [
|
|
1110
|
+
4,
|
|
1111
|
+
_dcrutilsts.getAccessToken(store, token)
|
|
1112
|
+
];
|
|
1113
|
+
case 1:
|
|
1114
|
+
tokenData = _state.sent();
|
|
1115
|
+
if (!tokenData) {
|
|
1116
|
+
return [
|
|
1117
|
+
2,
|
|
1118
|
+
res.status(401).json({
|
|
1119
|
+
error: 'invalid_token',
|
|
1120
|
+
error_description: 'Unknown or expired access token'
|
|
1121
|
+
})
|
|
1122
|
+
];
|
|
1123
|
+
}
|
|
1124
|
+
now = Date.now();
|
|
1125
|
+
expiresAt = tokenData.created_at + tokenData.expires_in * 1000;
|
|
1126
|
+
if (!(now > expiresAt)) return [
|
|
1127
|
+
3,
|
|
1128
|
+
4
|
|
1129
|
+
];
|
|
1130
|
+
return [
|
|
1131
|
+
4,
|
|
1132
|
+
_dcrutilsts.deleteAccessToken(store, token)
|
|
1133
|
+
];
|
|
1134
|
+
case 2:
|
|
1135
|
+
_state.sent();
|
|
1136
|
+
return [
|
|
1137
|
+
4,
|
|
1138
|
+
_dcrutilsts.deleteProviderTokens(store, token)
|
|
1139
|
+
];
|
|
1140
|
+
case 3:
|
|
1141
|
+
_state.sent();
|
|
1142
|
+
return [
|
|
1143
|
+
2,
|
|
1144
|
+
res.status(401).json({
|
|
1145
|
+
error: 'invalid_token',
|
|
1146
|
+
error_description: 'Access token has expired'
|
|
1147
|
+
})
|
|
1148
|
+
];
|
|
1149
|
+
case 4:
|
|
1150
|
+
authInfo = {
|
|
1151
|
+
token: token,
|
|
1152
|
+
clientId: tokenData.client_id,
|
|
1153
|
+
scopes: tokenData.scope ? tokenData.scope.split(' ') : [],
|
|
1154
|
+
expiresAt: expiresAt,
|
|
1155
|
+
providerTokens: tokenData.providerTokens
|
|
1156
|
+
};
|
|
1157
|
+
return [
|
|
1158
|
+
2,
|
|
1159
|
+
res.json(authInfo)
|
|
1160
|
+
];
|
|
1161
|
+
}
|
|
1162
|
+
});
|
|
1163
|
+
})();
|
|
1164
|
+
});
|
|
1165
|
+
/**
|
|
1166
|
+
* Debug endpoint to list registered clients (development only)
|
|
1167
|
+
*/ router.get('/debug/clients', function(_req, res) {
|
|
1168
|
+
return _async_to_generator(function() {
|
|
1169
|
+
var clients;
|
|
1170
|
+
return _ts_generator(this, function(_state) {
|
|
1171
|
+
switch(_state.label){
|
|
1172
|
+
case 0:
|
|
1173
|
+
return [
|
|
1174
|
+
4,
|
|
1175
|
+
_dcrutilsts.listClients(store)
|
|
1176
|
+
];
|
|
1177
|
+
case 1:
|
|
1178
|
+
clients = _state.sent();
|
|
1179
|
+
return [
|
|
1180
|
+
2,
|
|
1181
|
+
res.json(clients)
|
|
1182
|
+
];
|
|
1183
|
+
}
|
|
1184
|
+
});
|
|
1185
|
+
})();
|
|
1186
|
+
});
|
|
1187
|
+
return router;
|
|
1188
|
+
}
|
|
1189
|
+
/* 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; }
|