@backstage/plugin-auth-backend 0.4.8 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/README.md +6 -6
- package/dist/index.cjs.js +460 -353
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +152 -20
- package/package.json +8 -8
package/dist/index.cjs.js
CHANGED
|
@@ -17,12 +17,12 @@ var passportGoogleOauth20 = require('passport-google-oauth20');
|
|
|
17
17
|
var passportMicrosoft = require('passport-microsoft');
|
|
18
18
|
var got = require('got');
|
|
19
19
|
var OAuth2Strategy = require('passport-oauth2');
|
|
20
|
+
var openidClient = require('openid-client');
|
|
20
21
|
var passportOktaOauth = require('passport-okta-oauth');
|
|
21
22
|
var passportBitbucketOauth2 = require('passport-bitbucket-oauth2');
|
|
22
|
-
var fetch = require('
|
|
23
|
+
var fetch = require('node-fetch');
|
|
23
24
|
var NodeCache = require('node-cache');
|
|
24
25
|
var jose = require('jose');
|
|
25
|
-
var openidClient = require('openid-client');
|
|
26
26
|
var passportSaml = require('passport-saml');
|
|
27
27
|
var passportOneloginOauth = require('passport-onelogin-oauth');
|
|
28
28
|
var catalogClient = require('@backstage/catalog-client');
|
|
@@ -46,14 +46,12 @@ function _interopNamespace(e) {
|
|
|
46
46
|
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
47
47
|
Object.defineProperty(n, k, d.get ? d : {
|
|
48
48
|
enumerable: true,
|
|
49
|
-
get: function () {
|
|
50
|
-
return e[k];
|
|
51
|
-
}
|
|
49
|
+
get: function () { return e[k]; }
|
|
52
50
|
});
|
|
53
51
|
}
|
|
54
52
|
});
|
|
55
53
|
}
|
|
56
|
-
n[
|
|
54
|
+
n["default"] = e;
|
|
57
55
|
return Object.freeze(n);
|
|
58
56
|
}
|
|
59
57
|
|
|
@@ -88,7 +86,7 @@ const makeProfileInfo = (profile, idToken) => {
|
|
|
88
86
|
let displayName = (_b = (_a = profile.displayName) != null ? _a : profile.username) != null ? _b : profile.id;
|
|
89
87
|
if ((!email || !picture || !displayName) && idToken) {
|
|
90
88
|
try {
|
|
91
|
-
const decoded = jwtDecoder__default[
|
|
89
|
+
const decoded = jwtDecoder__default["default"](idToken);
|
|
92
90
|
if (!email && decoded.email) {
|
|
93
91
|
email = decoded.email;
|
|
94
92
|
}
|
|
@@ -112,16 +110,16 @@ const executeRedirectStrategy = async (req, providerStrategy, options) => {
|
|
|
112
110
|
return new Promise((resolve) => {
|
|
113
111
|
const strategy = Object.create(providerStrategy);
|
|
114
112
|
strategy.redirect = (url, status) => {
|
|
115
|
-
resolve({url, status: status != null ? status : void 0});
|
|
113
|
+
resolve({ url, status: status != null ? status : void 0 });
|
|
116
114
|
};
|
|
117
|
-
strategy.authenticate(req, {...options});
|
|
115
|
+
strategy.authenticate(req, { ...options });
|
|
118
116
|
});
|
|
119
117
|
};
|
|
120
118
|
const executeFrameHandlerStrategy = async (req, providerStrategy) => {
|
|
121
119
|
return new Promise((resolve, reject) => {
|
|
122
120
|
const strategy = Object.create(providerStrategy);
|
|
123
121
|
strategy.success = (result, privateInfo) => {
|
|
124
|
-
resolve({result, privateInfo});
|
|
122
|
+
resolve({ result, privateInfo });
|
|
125
123
|
};
|
|
126
124
|
strategy.fail = (info) => {
|
|
127
125
|
var _a;
|
|
@@ -193,7 +191,7 @@ const readState = (stateString) => {
|
|
|
193
191
|
return state;
|
|
194
192
|
};
|
|
195
193
|
const encodeState = (state) => {
|
|
196
|
-
const stateString = new URLSearchParams(pickBy__default[
|
|
194
|
+
const stateString = new URLSearchParams(pickBy__default["default"](state, (value) => value !== void 0)).toString();
|
|
197
195
|
return Buffer.from(stateString, "utf-8").toString("hex");
|
|
198
196
|
};
|
|
199
197
|
const verifyNonce = (req, providerId) => {
|
|
@@ -218,7 +216,7 @@ class OAuthEnvironmentHandler {
|
|
|
218
216
|
}
|
|
219
217
|
static mapConfig(config, factoryFunc) {
|
|
220
218
|
const envs = config.keys();
|
|
221
|
-
const handlers = new Map();
|
|
219
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
222
220
|
for (const env of envs) {
|
|
223
221
|
const envConfig = config.getConfig(env);
|
|
224
222
|
const handler = factoryFunc(envConfig);
|
|
@@ -227,22 +225,22 @@ class OAuthEnvironmentHandler {
|
|
|
227
225
|
return new OAuthEnvironmentHandler(handlers);
|
|
228
226
|
}
|
|
229
227
|
async start(req, res) {
|
|
230
|
-
const provider = this.getProviderForEnv(req
|
|
231
|
-
await
|
|
228
|
+
const provider = this.getProviderForEnv(req);
|
|
229
|
+
await provider.start(req, res);
|
|
232
230
|
}
|
|
233
231
|
async frameHandler(req, res) {
|
|
234
|
-
const provider = this.getProviderForEnv(req
|
|
235
|
-
await
|
|
232
|
+
const provider = this.getProviderForEnv(req);
|
|
233
|
+
await provider.frameHandler(req, res);
|
|
236
234
|
}
|
|
237
235
|
async refresh(req, res) {
|
|
238
236
|
var _a;
|
|
239
|
-
const provider = this.getProviderForEnv(req
|
|
240
|
-
await ((_a = provider
|
|
237
|
+
const provider = this.getProviderForEnv(req);
|
|
238
|
+
await ((_a = provider.refresh) == null ? void 0 : _a.call(provider, req, res));
|
|
241
239
|
}
|
|
242
240
|
async logout(req, res) {
|
|
243
241
|
var _a;
|
|
244
|
-
const provider = this.getProviderForEnv(req
|
|
245
|
-
await ((_a = provider
|
|
242
|
+
const provider = this.getProviderForEnv(req);
|
|
243
|
+
await ((_a = provider.logout) == null ? void 0 : _a.call(provider, req, res));
|
|
246
244
|
}
|
|
247
245
|
getRequestFromEnv(req) {
|
|
248
246
|
var _a, _b;
|
|
@@ -257,19 +255,16 @@ class OAuthEnvironmentHandler {
|
|
|
257
255
|
const env = readState(stateParams).env;
|
|
258
256
|
return env;
|
|
259
257
|
}
|
|
260
|
-
getProviderForEnv(req
|
|
258
|
+
getProviderForEnv(req) {
|
|
261
259
|
const env = this.getRequestFromEnv(req);
|
|
262
260
|
if (!env) {
|
|
263
261
|
throw new errors.InputError(`Must specify 'env' query to select environment`);
|
|
264
262
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
<br>
|
|
269
|
-
For this flow to work you need to supply a valid configuration for the "${env}" environment of provider.`);
|
|
270
|
-
return void 0;
|
|
263
|
+
const handler = this.handlers.get(env);
|
|
264
|
+
if (!handler) {
|
|
265
|
+
throw new errors.NotFoundError(`No configuration available for the '${env}' environment of this provider.`);
|
|
271
266
|
}
|
|
272
|
-
return
|
|
267
|
+
return handler;
|
|
273
268
|
}
|
|
274
269
|
}
|
|
275
270
|
|
|
@@ -290,11 +285,11 @@ const postMessageResponse = (res, appOrigin, response) => {
|
|
|
290
285
|
window.close();
|
|
291
286
|
}, 100); // same as the interval of the core-app-api lib/loginPopup.ts (to address race conditions)
|
|
292
287
|
`;
|
|
293
|
-
const hash = crypto__default[
|
|
288
|
+
const hash = crypto__default["default"].createHash("sha256").update(script).digest("base64");
|
|
294
289
|
res.setHeader("Content-Type", "text/html");
|
|
295
290
|
res.setHeader("X-Frame-Options", "sameorigin");
|
|
296
291
|
res.setHeader("Content-Security-Policy", `script-src 'sha256-${hash}'`);
|
|
297
|
-
res.end(`<html><body><script>${script}
|
|
292
|
+
res.end(`<html><body><script>${script}<\/script></body></html>`);
|
|
298
293
|
};
|
|
299
294
|
const ensuresXRequestedWith = (req) => {
|
|
300
295
|
const requiredHeader = req.header("X-Requested-With");
|
|
@@ -304,6 +299,25 @@ const ensuresXRequestedWith = (req) => {
|
|
|
304
299
|
return true;
|
|
305
300
|
};
|
|
306
301
|
|
|
302
|
+
function parseJwtPayload(token) {
|
|
303
|
+
const [_header, payload, _signature] = token.split(".");
|
|
304
|
+
return JSON.parse(Buffer.from(payload, "base64").toString());
|
|
305
|
+
}
|
|
306
|
+
function prepareBackstageIdentityResponse(result) {
|
|
307
|
+
const { sub, ent } = parseJwtPayload(result.token);
|
|
308
|
+
return {
|
|
309
|
+
...{
|
|
310
|
+
idToken: result.token,
|
|
311
|
+
...result
|
|
312
|
+
},
|
|
313
|
+
identity: {
|
|
314
|
+
type: "user",
|
|
315
|
+
userEntityRef: sub,
|
|
316
|
+
ownershipEntityRefs: ent != null ? ent : []
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
307
321
|
const THOUSAND_DAYS_MS = 1e3 * 24 * 60 * 60 * 1e3;
|
|
308
322
|
const TEN_MINUTES_MS = 600 * 1e3;
|
|
309
323
|
class OAuthAdapter {
|
|
@@ -355,7 +369,7 @@ class OAuthAdapter {
|
|
|
355
369
|
};
|
|
356
370
|
}
|
|
357
371
|
static fromConfig(config, handlers, options) {
|
|
358
|
-
const {origin: appOrigin} = new url.URL(config.appUrl);
|
|
372
|
+
const { origin: appOrigin } = new url.URL(config.appUrl);
|
|
359
373
|
const secure = config.baseUrl.startsWith("https://");
|
|
360
374
|
const url$1 = new url.URL(config.baseUrl);
|
|
361
375
|
const cookiePath = `${url$1.pathname}/${options.providerId}`;
|
|
@@ -379,11 +393,11 @@ class OAuthAdapter {
|
|
|
379
393
|
if (this.options.persistScopes) {
|
|
380
394
|
this.setScopesCookie(res, scope);
|
|
381
395
|
}
|
|
382
|
-
const nonce = crypto__default[
|
|
396
|
+
const nonce = crypto__default["default"].randomBytes(16).toString("base64");
|
|
383
397
|
this.setNonceCookie(res, nonce);
|
|
384
|
-
const state = {nonce, env, origin};
|
|
385
|
-
const forwardReq = Object.assign(req, {scope, state});
|
|
386
|
-
const {url, status} = await this.handlers.start(forwardReq);
|
|
398
|
+
const state = { nonce, env, origin };
|
|
399
|
+
const forwardReq = Object.assign(req, { scope, state });
|
|
400
|
+
const { url, status } = await this.handlers.start(forwardReq);
|
|
387
401
|
res.statusCode = status || 302;
|
|
388
402
|
res.setHeader("Location", url);
|
|
389
403
|
res.setHeader("Content-Length", "0");
|
|
@@ -405,7 +419,7 @@ class OAuthAdapter {
|
|
|
405
419
|
}
|
|
406
420
|
}
|
|
407
421
|
verifyNonce(req, this.options.providerId);
|
|
408
|
-
const {response, refreshToken} = await this.handlers.handler(req);
|
|
422
|
+
const { response, refreshToken } = await this.handlers.handler(req);
|
|
409
423
|
if (this.options.persistScopes) {
|
|
410
424
|
const grantedScopes = this.getScopesFromCookie(req, this.options.providerId);
|
|
411
425
|
response.providerInfo.scope = grantedScopes;
|
|
@@ -413,65 +427,62 @@ class OAuthAdapter {
|
|
|
413
427
|
if (refreshToken && !this.options.disableRefresh) {
|
|
414
428
|
this.setRefreshTokenCookie(res, refreshToken);
|
|
415
429
|
}
|
|
416
|
-
await this.populateIdentity(response.backstageIdentity);
|
|
430
|
+
const identity = await this.populateIdentity(response.backstageIdentity);
|
|
417
431
|
return postMessageResponse(res, appOrigin, {
|
|
418
432
|
type: "authorization_response",
|
|
419
|
-
response
|
|
433
|
+
response: { ...response, backstageIdentity: identity }
|
|
420
434
|
});
|
|
421
435
|
} catch (error) {
|
|
422
|
-
const {name, message} = errors.isError(error) ? error : new Error("Encountered invalid error");
|
|
436
|
+
const { name, message } = errors.isError(error) ? error : new Error("Encountered invalid error");
|
|
423
437
|
return postMessageResponse(res, appOrigin, {
|
|
424
438
|
type: "authorization_response",
|
|
425
|
-
error: {name, message}
|
|
439
|
+
error: { name, message }
|
|
426
440
|
});
|
|
427
441
|
}
|
|
428
442
|
}
|
|
429
443
|
async logout(req, res) {
|
|
430
444
|
if (!ensuresXRequestedWith(req)) {
|
|
431
|
-
|
|
432
|
-
return;
|
|
445
|
+
throw new errors.AuthenticationError("Invalid X-Requested-With header");
|
|
433
446
|
}
|
|
434
447
|
this.removeRefreshTokenCookie(res);
|
|
435
|
-
res.status(200).
|
|
448
|
+
res.status(200).end();
|
|
436
449
|
}
|
|
437
450
|
async refresh(req, res) {
|
|
438
451
|
var _a, _b;
|
|
439
452
|
if (!ensuresXRequestedWith(req)) {
|
|
440
|
-
|
|
441
|
-
return;
|
|
453
|
+
throw new errors.AuthenticationError("Invalid X-Requested-With header");
|
|
442
454
|
}
|
|
443
455
|
if (!this.handlers.refresh || this.options.disableRefresh) {
|
|
444
|
-
|
|
445
|
-
return;
|
|
456
|
+
throw new errors.InputError(`Refresh token is not supported for provider ${this.options.providerId}`);
|
|
446
457
|
}
|
|
447
458
|
try {
|
|
448
459
|
const refreshToken = req.cookies[`${this.options.providerId}-refresh-token`];
|
|
449
460
|
if (!refreshToken) {
|
|
450
|
-
throw new
|
|
461
|
+
throw new errors.InputError("Missing session cookie");
|
|
451
462
|
}
|
|
452
463
|
const scope = (_b = (_a = req.query.scope) == null ? void 0 : _a.toString()) != null ? _b : "";
|
|
453
|
-
const forwardReq = Object.assign(req, {scope, refreshToken});
|
|
464
|
+
const forwardReq = Object.assign(req, { scope, refreshToken });
|
|
454
465
|
const response = await this.handlers.refresh(forwardReq);
|
|
455
|
-
await this.populateIdentity(response.backstageIdentity);
|
|
466
|
+
const backstageIdentity = await this.populateIdentity(response.backstageIdentity);
|
|
456
467
|
if (response.providerInfo.refreshToken && response.providerInfo.refreshToken !== refreshToken) {
|
|
457
468
|
this.setRefreshTokenCookie(res, response.providerInfo.refreshToken);
|
|
458
469
|
}
|
|
459
|
-
res.status(200).json(response);
|
|
470
|
+
res.status(200).json({ ...response, backstageIdentity });
|
|
460
471
|
} catch (error) {
|
|
461
|
-
|
|
472
|
+
throw new errors.AuthenticationError("Refresh failed", error);
|
|
462
473
|
}
|
|
463
474
|
}
|
|
464
475
|
async populateIdentity(identity) {
|
|
465
476
|
if (!identity) {
|
|
466
|
-
return;
|
|
477
|
+
return void 0;
|
|
467
478
|
}
|
|
468
|
-
if (
|
|
469
|
-
|
|
470
|
-
claims: {sub: identity.id}
|
|
471
|
-
});
|
|
472
|
-
} else if (!identity.token && identity.idToken) {
|
|
473
|
-
identity.token = identity.idToken;
|
|
479
|
+
if (identity.token) {
|
|
480
|
+
return prepareBackstageIdentityResponse(identity);
|
|
474
481
|
}
|
|
482
|
+
const token = await this.options.tokenIssuer.issueToken({
|
|
483
|
+
claims: { sub: identity.id }
|
|
484
|
+
});
|
|
485
|
+
return prepareBackstageIdentityResponse({ ...identity, token });
|
|
475
486
|
}
|
|
476
487
|
}
|
|
477
488
|
|
|
@@ -488,9 +499,9 @@ class CatalogIdentityClient {
|
|
|
488
499
|
filter[`metadata.annotations.${key}`] = value;
|
|
489
500
|
}
|
|
490
501
|
const token = await this.tokenIssuer.issueToken({
|
|
491
|
-
claims: {sub: "backstage.io/auth-backend"}
|
|
502
|
+
claims: { sub: "backstage.io/auth-backend" }
|
|
492
503
|
});
|
|
493
|
-
const {items} = await this.catalogApi.getEntities({filter}, {token});
|
|
504
|
+
const { items } = await this.catalogApi.getEntities({ filter }, { token });
|
|
494
505
|
if (items.length !== 1) {
|
|
495
506
|
if (items.length > 1) {
|
|
496
507
|
throw new errors.ConflictError("User lookup resulted in multiple matches");
|
|
@@ -500,10 +511,8 @@ class CatalogIdentityClient {
|
|
|
500
511
|
}
|
|
501
512
|
return items[0];
|
|
502
513
|
}
|
|
503
|
-
async resolveCatalogMembership({
|
|
504
|
-
entityRefs,
|
|
505
|
-
logger
|
|
506
|
-
}) {
|
|
514
|
+
async resolveCatalogMembership(query) {
|
|
515
|
+
const { entityRefs, logger } = query;
|
|
507
516
|
const resolvedEntityRefs = entityRefs.map((ref) => {
|
|
508
517
|
try {
|
|
509
518
|
const parsedRef = catalogModel.parseEntityRef(ref.toLocaleLowerCase("en-US"), {
|
|
@@ -521,7 +530,7 @@ class CatalogIdentityClient {
|
|
|
521
530
|
"metadata.namespace": ref.namespace,
|
|
522
531
|
"metadata.name": ref.name
|
|
523
532
|
}));
|
|
524
|
-
const entities = await this.catalogApi.getEntities({filter}).then((r) => r.items);
|
|
533
|
+
const entities = await this.catalogApi.getEntities({ filter }).then((r) => r.items);
|
|
525
534
|
if (entityRefs.length !== entities.length) {
|
|
526
535
|
const foundEntityNames = entities.map(catalogModel.stringifyEntityRef);
|
|
527
536
|
const missingEntityNames = resolvedEntityRefs.map(catalogModel.stringifyEntityRef).filter((s) => !foundEntityNames.includes(s));
|
|
@@ -565,7 +574,7 @@ class GithubAuthProvider {
|
|
|
565
574
|
userProfileURL: options.userProfileUrl,
|
|
566
575
|
authorizationURL: options.authorizationUrl
|
|
567
576
|
}, (accessToken, refreshToken, params, fullProfile, done) => {
|
|
568
|
-
done(void 0, {fullProfile, params, accessToken}, {refreshToken});
|
|
577
|
+
done(void 0, { fullProfile, params, accessToken }, { refreshToken });
|
|
569
578
|
});
|
|
570
579
|
}
|
|
571
580
|
async start(req) {
|
|
@@ -575,7 +584,7 @@ class GithubAuthProvider {
|
|
|
575
584
|
});
|
|
576
585
|
}
|
|
577
586
|
async handler(req) {
|
|
578
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
587
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
579
588
|
return {
|
|
580
589
|
response: await this.handleResult(result),
|
|
581
590
|
refreshToken: privateInfo.refreshToken
|
|
@@ -596,7 +605,7 @@ class GithubAuthProvider {
|
|
|
596
605
|
});
|
|
597
606
|
}
|
|
598
607
|
async handleResult(result) {
|
|
599
|
-
const {profile} = await this.authHandler(result);
|
|
608
|
+
const { profile } = await this.authHandler(result);
|
|
600
609
|
const expiresInStr = result.params.expires_in;
|
|
601
610
|
const response = {
|
|
602
611
|
providerInfo: {
|
|
@@ -621,12 +630,12 @@ class GithubAuthProvider {
|
|
|
621
630
|
}
|
|
622
631
|
}
|
|
623
632
|
const githubDefaultSignInResolver = async (info, ctx) => {
|
|
624
|
-
const {fullProfile} = info.result;
|
|
633
|
+
const { fullProfile } = info.result;
|
|
625
634
|
const userId = fullProfile.username || fullProfile.id;
|
|
626
635
|
const token = await ctx.tokenIssuer.issueToken({
|
|
627
|
-
claims: {sub: userId, ent: [`user:default/${userId}`]}
|
|
636
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
628
637
|
});
|
|
629
|
-
return {id: userId, token};
|
|
638
|
+
return { id: userId, token };
|
|
630
639
|
};
|
|
631
640
|
const createGithubProvider = (options) => {
|
|
632
641
|
return ({
|
|
@@ -650,7 +659,7 @@ const createGithubProvider = (options) => {
|
|
|
650
659
|
catalogApi,
|
|
651
660
|
tokenIssuer
|
|
652
661
|
});
|
|
653
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile}) => ({
|
|
662
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
654
663
|
profile: makeProfileInfo(fullProfile)
|
|
655
664
|
});
|
|
656
665
|
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : githubDefaultSignInResolver;
|
|
@@ -660,7 +669,7 @@ const createGithubProvider = (options) => {
|
|
|
660
669
|
logger
|
|
661
670
|
});
|
|
662
671
|
const stateEncoder = (_c = options == null ? void 0 : options.stateEncoder) != null ? _c : async (req) => {
|
|
663
|
-
return {encodedState: encodeState(req.state)};
|
|
672
|
+
return { encodedState: encodeState(req.state) };
|
|
664
673
|
};
|
|
665
674
|
const provider = new GithubAuthProvider({
|
|
666
675
|
clientId,
|
|
@@ -685,15 +694,15 @@ const createGithubProvider = (options) => {
|
|
|
685
694
|
};
|
|
686
695
|
|
|
687
696
|
const gitlabDefaultSignInResolver = async (info, ctx) => {
|
|
688
|
-
const {profile, result} = info;
|
|
697
|
+
const { profile, result } = info;
|
|
689
698
|
let id = result.fullProfile.id;
|
|
690
699
|
if (profile.email) {
|
|
691
700
|
id = profile.email.split("@")[0];
|
|
692
701
|
}
|
|
693
702
|
const token = await ctx.tokenIssuer.issueToken({
|
|
694
|
-
claims: {sub: id, ent: [`user:default/${id}`]}
|
|
703
|
+
claims: { sub: id, ent: [`user:default/${id}`] }
|
|
695
704
|
});
|
|
696
|
-
return {id, token};
|
|
705
|
+
return { id, token };
|
|
697
706
|
};
|
|
698
707
|
const gitlabDefaultAuthHandler = async ({
|
|
699
708
|
fullProfile,
|
|
@@ -714,7 +723,7 @@ class GitlabAuthProvider {
|
|
|
714
723
|
callbackURL: options.callbackUrl,
|
|
715
724
|
baseURL: options.baseUrl
|
|
716
725
|
}, (accessToken, refreshToken, params, fullProfile, done) => {
|
|
717
|
-
done(void 0, {fullProfile, params, accessToken}, {
|
|
726
|
+
done(void 0, { fullProfile, params, accessToken }, {
|
|
718
727
|
refreshToken
|
|
719
728
|
});
|
|
720
729
|
});
|
|
@@ -726,7 +735,7 @@ class GitlabAuthProvider {
|
|
|
726
735
|
});
|
|
727
736
|
}
|
|
728
737
|
async handler(req) {
|
|
729
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
738
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
730
739
|
return {
|
|
731
740
|
response: await this.handleResult(result),
|
|
732
741
|
refreshToken: privateInfo.refreshToken
|
|
@@ -747,7 +756,7 @@ class GitlabAuthProvider {
|
|
|
747
756
|
});
|
|
748
757
|
}
|
|
749
758
|
async handleResult(result) {
|
|
750
|
-
const {profile} = await this.authHandler(result);
|
|
759
|
+
const { profile } = await this.authHandler(result);
|
|
751
760
|
const response = {
|
|
752
761
|
providerInfo: {
|
|
753
762
|
idToken: result.params.id_token,
|
|
@@ -848,14 +857,14 @@ class GoogleAuthProvider {
|
|
|
848
857
|
});
|
|
849
858
|
}
|
|
850
859
|
async handler(req) {
|
|
851
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
860
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
852
861
|
return {
|
|
853
862
|
response: await this.handleResult(result),
|
|
854
863
|
refreshToken: privateInfo.refreshToken
|
|
855
864
|
};
|
|
856
865
|
}
|
|
857
866
|
async refresh(req) {
|
|
858
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
867
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
859
868
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
860
869
|
return this.handleResult({
|
|
861
870
|
fullProfile,
|
|
@@ -865,7 +874,7 @@ class GoogleAuthProvider {
|
|
|
865
874
|
});
|
|
866
875
|
}
|
|
867
876
|
async handleResult(result) {
|
|
868
|
-
const {profile} = await this.authHandler(result);
|
|
877
|
+
const { profile } = await this.authHandler(result);
|
|
869
878
|
const response = {
|
|
870
879
|
providerInfo: {
|
|
871
880
|
idToken: result.params.id_token,
|
|
@@ -889,7 +898,7 @@ class GoogleAuthProvider {
|
|
|
889
898
|
}
|
|
890
899
|
}
|
|
891
900
|
const googleEmailSignInResolver = async (info, ctx) => {
|
|
892
|
-
const {profile} = info;
|
|
901
|
+
const { profile } = info;
|
|
893
902
|
if (!profile.email) {
|
|
894
903
|
throw new Error("Google profile contained no email");
|
|
895
904
|
}
|
|
@@ -899,11 +908,11 @@ const googleEmailSignInResolver = async (info, ctx) => {
|
|
|
899
908
|
}
|
|
900
909
|
});
|
|
901
910
|
const claims = getEntityClaims(entity);
|
|
902
|
-
const token = await ctx.tokenIssuer.issueToken({claims});
|
|
903
|
-
return {id: entity.metadata.name, entity, token};
|
|
911
|
+
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
912
|
+
return { id: entity.metadata.name, entity, token };
|
|
904
913
|
};
|
|
905
914
|
const googleDefaultSignInResolver = async (info, ctx) => {
|
|
906
|
-
const {profile} = info;
|
|
915
|
+
const { profile } = info;
|
|
907
916
|
if (!profile.email) {
|
|
908
917
|
throw new Error("Google profile contained no email");
|
|
909
918
|
}
|
|
@@ -920,9 +929,9 @@ const googleDefaultSignInResolver = async (info, ctx) => {
|
|
|
920
929
|
userId = profile.email.split("@")[0];
|
|
921
930
|
}
|
|
922
931
|
const token = await ctx.tokenIssuer.issueToken({
|
|
923
|
-
claims: {sub: userId, ent: [`user:default/${userId}`]}
|
|
932
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
924
933
|
});
|
|
925
|
-
return {id: userId, token};
|
|
934
|
+
return { id: userId, token };
|
|
926
935
|
};
|
|
927
936
|
const createGoogleProvider = (options) => {
|
|
928
937
|
return ({
|
|
@@ -941,7 +950,7 @@ const createGoogleProvider = (options) => {
|
|
|
941
950
|
catalogApi,
|
|
942
951
|
tokenIssuer
|
|
943
952
|
});
|
|
944
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile, params}) => ({
|
|
953
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
945
954
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
946
955
|
});
|
|
947
956
|
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : googleDefaultSignInResolver;
|
|
@@ -983,7 +992,7 @@ class MicrosoftAuthProvider {
|
|
|
983
992
|
tokenURL: options.tokenUrl,
|
|
984
993
|
passReqToCallback: false
|
|
985
994
|
}, (accessToken, refreshToken, params, fullProfile, done) => {
|
|
986
|
-
done(void 0, {fullProfile, accessToken, params}, {refreshToken});
|
|
995
|
+
done(void 0, { fullProfile, accessToken, params }, { refreshToken });
|
|
987
996
|
});
|
|
988
997
|
}
|
|
989
998
|
async start(req) {
|
|
@@ -993,14 +1002,14 @@ class MicrosoftAuthProvider {
|
|
|
993
1002
|
});
|
|
994
1003
|
}
|
|
995
1004
|
async handler(req) {
|
|
996
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1005
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
997
1006
|
return {
|
|
998
1007
|
response: await this.handleResult(result),
|
|
999
1008
|
refreshToken: privateInfo.refreshToken
|
|
1000
1009
|
};
|
|
1001
1010
|
}
|
|
1002
1011
|
async refresh(req) {
|
|
1003
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1012
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1004
1013
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
1005
1014
|
return this.handleResult({
|
|
1006
1015
|
fullProfile,
|
|
@@ -1011,8 +1020,8 @@ class MicrosoftAuthProvider {
|
|
|
1011
1020
|
}
|
|
1012
1021
|
async handleResult(result) {
|
|
1013
1022
|
const photo = await this.getUserPhoto(result.accessToken);
|
|
1014
|
-
result.fullProfile.photos = photo ? [{value: photo}] : void 0;
|
|
1015
|
-
const {profile} = await this.authHandler(result);
|
|
1023
|
+
result.fullProfile.photos = photo ? [{ value: photo }] : void 0;
|
|
1024
|
+
const { profile } = await this.authHandler(result);
|
|
1016
1025
|
const response = {
|
|
1017
1026
|
providerInfo: {
|
|
1018
1027
|
idToken: result.params.id_token,
|
|
@@ -1036,7 +1045,7 @@ class MicrosoftAuthProvider {
|
|
|
1036
1045
|
}
|
|
1037
1046
|
getUserPhoto(accessToken) {
|
|
1038
1047
|
return new Promise((resolve) => {
|
|
1039
|
-
got__default[
|
|
1048
|
+
got__default["default"].get("https://graph.microsoft.com/v1.0/me/photos/48x48/$value", {
|
|
1040
1049
|
encoding: "binary",
|
|
1041
1050
|
responseType: "buffer",
|
|
1042
1051
|
headers: {
|
|
@@ -1053,7 +1062,7 @@ class MicrosoftAuthProvider {
|
|
|
1053
1062
|
}
|
|
1054
1063
|
}
|
|
1055
1064
|
const microsoftEmailSignInResolver = async (info, ctx) => {
|
|
1056
|
-
const {profile} = info;
|
|
1065
|
+
const { profile } = info;
|
|
1057
1066
|
if (!profile.email) {
|
|
1058
1067
|
throw new Error("Microsoft profile contained no email");
|
|
1059
1068
|
}
|
|
@@ -1063,19 +1072,19 @@ const microsoftEmailSignInResolver = async (info, ctx) => {
|
|
|
1063
1072
|
}
|
|
1064
1073
|
});
|
|
1065
1074
|
const claims = getEntityClaims(entity);
|
|
1066
|
-
const token = await ctx.tokenIssuer.issueToken({claims});
|
|
1067
|
-
return {id: entity.metadata.name, entity, token};
|
|
1075
|
+
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1076
|
+
return { id: entity.metadata.name, entity, token };
|
|
1068
1077
|
};
|
|
1069
1078
|
const microsoftDefaultSignInResolver = async (info, ctx) => {
|
|
1070
|
-
const {profile} = info;
|
|
1079
|
+
const { profile } = info;
|
|
1071
1080
|
if (!profile.email) {
|
|
1072
1081
|
throw new Error("Profile contained no email");
|
|
1073
1082
|
}
|
|
1074
1083
|
const userId = profile.email.split("@")[0];
|
|
1075
1084
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1076
|
-
claims: {sub: userId, ent: [`user:default/${userId}`]}
|
|
1085
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
1077
1086
|
});
|
|
1078
|
-
return {id: userId, token};
|
|
1087
|
+
return { id: userId, token };
|
|
1079
1088
|
};
|
|
1080
1089
|
const createMicrosoftProvider = (options) => {
|
|
1081
1090
|
return ({
|
|
@@ -1097,7 +1106,7 @@ const createMicrosoftProvider = (options) => {
|
|
|
1097
1106
|
catalogApi,
|
|
1098
1107
|
tokenIssuer
|
|
1099
1108
|
});
|
|
1100
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile, params}) => ({
|
|
1109
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1101
1110
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1102
1111
|
});
|
|
1103
1112
|
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : microsoftDefaultSignInResolver;
|
|
@@ -1140,7 +1149,10 @@ class OAuth2AuthProvider {
|
|
|
1140
1149
|
authorizationURL: options.authorizationUrl,
|
|
1141
1150
|
tokenURL: options.tokenUrl,
|
|
1142
1151
|
passReqToCallback: false,
|
|
1143
|
-
scope: options.scope
|
|
1152
|
+
scope: options.scope,
|
|
1153
|
+
customHeaders: options.includeBasicAuth ? {
|
|
1154
|
+
Authorization: `Basic ${this.encodeClientCredentials(options.clientId, options.clientSecret)}`
|
|
1155
|
+
} : void 0
|
|
1144
1156
|
}, (accessToken, refreshToken, params, fullProfile, done) => {
|
|
1145
1157
|
done(void 0, {
|
|
1146
1158
|
fullProfile,
|
|
@@ -1161,7 +1173,7 @@ class OAuth2AuthProvider {
|
|
|
1161
1173
|
});
|
|
1162
1174
|
}
|
|
1163
1175
|
async handler(req) {
|
|
1164
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1176
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1165
1177
|
return {
|
|
1166
1178
|
response: await this.handleResult(result),
|
|
1167
1179
|
refreshToken: privateInfo.refreshToken
|
|
@@ -1183,7 +1195,7 @@ class OAuth2AuthProvider {
|
|
|
1183
1195
|
});
|
|
1184
1196
|
}
|
|
1185
1197
|
async handleResult(result) {
|
|
1186
|
-
const {profile} = await this.authHandler(result);
|
|
1198
|
+
const { profile } = await this.authHandler(result);
|
|
1187
1199
|
const response = {
|
|
1188
1200
|
providerInfo: {
|
|
1189
1201
|
idToken: result.params.id_token,
|
|
@@ -1206,17 +1218,20 @@ class OAuth2AuthProvider {
|
|
|
1206
1218
|
}
|
|
1207
1219
|
return response;
|
|
1208
1220
|
}
|
|
1221
|
+
encodeClientCredentials(clientID, clientSecret) {
|
|
1222
|
+
return Buffer.from(`${clientID}:${clientSecret}`).toString("base64");
|
|
1223
|
+
}
|
|
1209
1224
|
}
|
|
1210
|
-
const oAuth2DefaultSignInResolver = async (info, ctx) => {
|
|
1211
|
-
const {profile} = info;
|
|
1225
|
+
const oAuth2DefaultSignInResolver$1 = async (info, ctx) => {
|
|
1226
|
+
const { profile } = info;
|
|
1212
1227
|
if (!profile.email) {
|
|
1213
1228
|
throw new Error("Profile contained no email");
|
|
1214
1229
|
}
|
|
1215
1230
|
const userId = profile.email.split("@")[0];
|
|
1216
1231
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1217
|
-
claims: {sub: userId, ent: [`user:default/${userId}`]}
|
|
1232
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
1218
1233
|
});
|
|
1219
|
-
return {id: userId, token};
|
|
1234
|
+
return { id: userId, token };
|
|
1220
1235
|
};
|
|
1221
1236
|
const createOAuth2Provider = (options) => {
|
|
1222
1237
|
return ({
|
|
@@ -1234,15 +1249,16 @@ const createOAuth2Provider = (options) => {
|
|
|
1234
1249
|
const authorizationUrl = envConfig.getString("authorizationUrl");
|
|
1235
1250
|
const tokenUrl = envConfig.getString("tokenUrl");
|
|
1236
1251
|
const scope = envConfig.getOptionalString("scope");
|
|
1252
|
+
const includeBasicAuth = envConfig.getOptionalBoolean("includeBasicAuth");
|
|
1237
1253
|
const disableRefresh = (_a = envConfig.getOptionalBoolean("disableRefresh")) != null ? _a : false;
|
|
1238
1254
|
const catalogIdentityClient = new CatalogIdentityClient({
|
|
1239
1255
|
catalogApi,
|
|
1240
1256
|
tokenIssuer
|
|
1241
1257
|
});
|
|
1242
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile, params}) => ({
|
|
1258
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1243
1259
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1244
1260
|
});
|
|
1245
|
-
const signInResolverFn = (_c = (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver) != null ? _c : oAuth2DefaultSignInResolver;
|
|
1261
|
+
const signInResolverFn = (_c = (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver) != null ? _c : oAuth2DefaultSignInResolver$1;
|
|
1246
1262
|
const signInResolver = (info) => signInResolverFn(info, {
|
|
1247
1263
|
catalogIdentityClient,
|
|
1248
1264
|
tokenIssuer,
|
|
@@ -1259,7 +1275,8 @@ const createOAuth2Provider = (options) => {
|
|
|
1259
1275
|
authorizationUrl,
|
|
1260
1276
|
tokenUrl,
|
|
1261
1277
|
scope,
|
|
1262
|
-
logger
|
|
1278
|
+
logger,
|
|
1279
|
+
includeBasicAuth
|
|
1263
1280
|
});
|
|
1264
1281
|
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1265
1282
|
disableRefresh,
|
|
@@ -1269,6 +1286,168 @@ const createOAuth2Provider = (options) => {
|
|
|
1269
1286
|
});
|
|
1270
1287
|
};
|
|
1271
1288
|
|
|
1289
|
+
class OidcAuthProvider {
|
|
1290
|
+
constructor(options) {
|
|
1291
|
+
this.implementation = this.setupStrategy(options);
|
|
1292
|
+
this.scope = options.scope;
|
|
1293
|
+
this.prompt = options.prompt;
|
|
1294
|
+
this.signInResolver = options.signInResolver;
|
|
1295
|
+
this.authHandler = options.authHandler;
|
|
1296
|
+
this.tokenIssuer = options.tokenIssuer;
|
|
1297
|
+
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
1298
|
+
this.logger = options.logger;
|
|
1299
|
+
}
|
|
1300
|
+
async start(req) {
|
|
1301
|
+
const { strategy } = await this.implementation;
|
|
1302
|
+
const options = {
|
|
1303
|
+
scope: req.scope || this.scope || "openid profile email",
|
|
1304
|
+
state: encodeState(req.state)
|
|
1305
|
+
};
|
|
1306
|
+
const prompt = this.prompt || "none";
|
|
1307
|
+
if (prompt !== "auto") {
|
|
1308
|
+
options.prompt = prompt;
|
|
1309
|
+
}
|
|
1310
|
+
return await executeRedirectStrategy(req, strategy, options);
|
|
1311
|
+
}
|
|
1312
|
+
async handler(req) {
|
|
1313
|
+
const { strategy } = await this.implementation;
|
|
1314
|
+
const strategyResponse = await executeFrameHandlerStrategy(req, strategy);
|
|
1315
|
+
const {
|
|
1316
|
+
result: { userinfo, tokenset },
|
|
1317
|
+
privateInfo
|
|
1318
|
+
} = strategyResponse;
|
|
1319
|
+
const identityResponse = await this.handleResult({ tokenset, userinfo });
|
|
1320
|
+
return {
|
|
1321
|
+
response: identityResponse,
|
|
1322
|
+
refreshToken: privateInfo.refreshToken
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
async refresh(req) {
|
|
1326
|
+
const { client } = await this.implementation;
|
|
1327
|
+
const tokenset = await client.refresh(req.refreshToken);
|
|
1328
|
+
if (!tokenset.access_token) {
|
|
1329
|
+
throw new Error("Refresh failed");
|
|
1330
|
+
}
|
|
1331
|
+
const profile = await client.userinfo(tokenset.access_token);
|
|
1332
|
+
return this.handleResult({ tokenset, userinfo: profile });
|
|
1333
|
+
}
|
|
1334
|
+
async setupStrategy(options) {
|
|
1335
|
+
const issuer = await openidClient.Issuer.discover(options.metadataUrl);
|
|
1336
|
+
const client = new issuer.Client({
|
|
1337
|
+
access_type: "offline",
|
|
1338
|
+
client_id: options.clientId,
|
|
1339
|
+
client_secret: options.clientSecret,
|
|
1340
|
+
redirect_uris: [options.callbackUrl],
|
|
1341
|
+
response_types: ["code"],
|
|
1342
|
+
id_token_signed_response_alg: options.tokenSignedResponseAlg || "RS256",
|
|
1343
|
+
scope: options.scope || ""
|
|
1344
|
+
});
|
|
1345
|
+
const strategy = new openidClient.Strategy({
|
|
1346
|
+
client,
|
|
1347
|
+
passReqToCallback: false
|
|
1348
|
+
}, (tokenset, userinfo, done) => {
|
|
1349
|
+
if (typeof done !== "function") {
|
|
1350
|
+
throw new Error("OIDC IdP must provide a userinfo_endpoint in the metadata response");
|
|
1351
|
+
}
|
|
1352
|
+
done(void 0, { tokenset, userinfo }, {
|
|
1353
|
+
refreshToken: tokenset.refresh_token
|
|
1354
|
+
});
|
|
1355
|
+
});
|
|
1356
|
+
strategy.error = console.error;
|
|
1357
|
+
return { strategy, client };
|
|
1358
|
+
}
|
|
1359
|
+
async handleResult(result) {
|
|
1360
|
+
const { profile } = await this.authHandler(result);
|
|
1361
|
+
const response = {
|
|
1362
|
+
providerInfo: {
|
|
1363
|
+
idToken: result.tokenset.id_token,
|
|
1364
|
+
accessToken: result.tokenset.access_token,
|
|
1365
|
+
refreshToken: result.tokenset.refresh_token,
|
|
1366
|
+
scope: result.tokenset.scope,
|
|
1367
|
+
expiresInSeconds: result.tokenset.expires_in
|
|
1368
|
+
},
|
|
1369
|
+
profile
|
|
1370
|
+
};
|
|
1371
|
+
if (this.signInResolver) {
|
|
1372
|
+
response.backstageIdentity = await this.signInResolver({
|
|
1373
|
+
result,
|
|
1374
|
+
profile
|
|
1375
|
+
}, {
|
|
1376
|
+
tokenIssuer: this.tokenIssuer,
|
|
1377
|
+
catalogIdentityClient: this.catalogIdentityClient,
|
|
1378
|
+
logger: this.logger
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1381
|
+
return response;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
const oAuth2DefaultSignInResolver = async (info, ctx) => {
|
|
1385
|
+
const { profile } = info;
|
|
1386
|
+
if (!profile.email) {
|
|
1387
|
+
throw new Error("Profile contained no email");
|
|
1388
|
+
}
|
|
1389
|
+
const userId = profile.email.split("@")[0];
|
|
1390
|
+
const token = await ctx.tokenIssuer.issueToken({
|
|
1391
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
1392
|
+
});
|
|
1393
|
+
return { id: userId, token };
|
|
1394
|
+
};
|
|
1395
|
+
const createOidcProvider = (options) => {
|
|
1396
|
+
return ({
|
|
1397
|
+
providerId,
|
|
1398
|
+
globalConfig,
|
|
1399
|
+
config,
|
|
1400
|
+
tokenIssuer,
|
|
1401
|
+
catalogApi,
|
|
1402
|
+
logger
|
|
1403
|
+
}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1404
|
+
var _a, _b;
|
|
1405
|
+
const clientId = envConfig.getString("clientId");
|
|
1406
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
1407
|
+
const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1408
|
+
const metadataUrl = envConfig.getString("metadataUrl");
|
|
1409
|
+
const tokenSignedResponseAlg = envConfig.getOptionalString("tokenSignedResponseAlg");
|
|
1410
|
+
const scope = envConfig.getOptionalString("scope");
|
|
1411
|
+
const prompt = envConfig.getOptionalString("prompt");
|
|
1412
|
+
const catalogIdentityClient = new CatalogIdentityClient({
|
|
1413
|
+
catalogApi,
|
|
1414
|
+
tokenIssuer
|
|
1415
|
+
});
|
|
1416
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ userinfo }) => ({
|
|
1417
|
+
profile: {
|
|
1418
|
+
displayName: userinfo.name,
|
|
1419
|
+
email: userinfo.email,
|
|
1420
|
+
picture: userinfo.picture
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : oAuth2DefaultSignInResolver;
|
|
1424
|
+
const signInResolver = (info) => signInResolverFn(info, {
|
|
1425
|
+
catalogIdentityClient,
|
|
1426
|
+
tokenIssuer,
|
|
1427
|
+
logger
|
|
1428
|
+
});
|
|
1429
|
+
const provider = new OidcAuthProvider({
|
|
1430
|
+
clientId,
|
|
1431
|
+
clientSecret,
|
|
1432
|
+
callbackUrl,
|
|
1433
|
+
tokenSignedResponseAlg,
|
|
1434
|
+
metadataUrl,
|
|
1435
|
+
scope,
|
|
1436
|
+
prompt,
|
|
1437
|
+
signInResolver,
|
|
1438
|
+
authHandler,
|
|
1439
|
+
logger,
|
|
1440
|
+
tokenIssuer,
|
|
1441
|
+
catalogIdentityClient
|
|
1442
|
+
});
|
|
1443
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1444
|
+
disableRefresh: false,
|
|
1445
|
+
providerId,
|
|
1446
|
+
tokenIssuer
|
|
1447
|
+
});
|
|
1448
|
+
});
|
|
1449
|
+
};
|
|
1450
|
+
|
|
1272
1451
|
class OktaAuthProvider {
|
|
1273
1452
|
constructor(options) {
|
|
1274
1453
|
this._store = {
|
|
@@ -1312,14 +1491,14 @@ class OktaAuthProvider {
|
|
|
1312
1491
|
});
|
|
1313
1492
|
}
|
|
1314
1493
|
async handler(req) {
|
|
1315
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1494
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1316
1495
|
return {
|
|
1317
1496
|
response: await this.handleResult(result),
|
|
1318
1497
|
refreshToken: privateInfo.refreshToken
|
|
1319
1498
|
};
|
|
1320
1499
|
}
|
|
1321
1500
|
async refresh(req) {
|
|
1322
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1501
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1323
1502
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
1324
1503
|
return this.handleResult({
|
|
1325
1504
|
fullProfile,
|
|
@@ -1329,7 +1508,7 @@ class OktaAuthProvider {
|
|
|
1329
1508
|
});
|
|
1330
1509
|
}
|
|
1331
1510
|
async handleResult(result) {
|
|
1332
|
-
const {profile} = await this._authHandler(result);
|
|
1511
|
+
const { profile } = await this._authHandler(result);
|
|
1333
1512
|
const response = {
|
|
1334
1513
|
providerInfo: {
|
|
1335
1514
|
idToken: result.params.id_token,
|
|
@@ -1353,7 +1532,7 @@ class OktaAuthProvider {
|
|
|
1353
1532
|
}
|
|
1354
1533
|
}
|
|
1355
1534
|
const oktaEmailSignInResolver = async (info, ctx) => {
|
|
1356
|
-
const {profile} = info;
|
|
1535
|
+
const { profile } = info;
|
|
1357
1536
|
if (!profile.email) {
|
|
1358
1537
|
throw new Error("Okta profile contained no email");
|
|
1359
1538
|
}
|
|
@@ -1363,19 +1542,19 @@ const oktaEmailSignInResolver = async (info, ctx) => {
|
|
|
1363
1542
|
}
|
|
1364
1543
|
});
|
|
1365
1544
|
const claims = getEntityClaims(entity);
|
|
1366
|
-
const token = await ctx.tokenIssuer.issueToken({claims});
|
|
1367
|
-
return {id: entity.metadata.name, entity, token};
|
|
1545
|
+
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1546
|
+
return { id: entity.metadata.name, entity, token };
|
|
1368
1547
|
};
|
|
1369
1548
|
const oktaDefaultSignInResolver = async (info, ctx) => {
|
|
1370
|
-
const {profile} = info;
|
|
1549
|
+
const { profile } = info;
|
|
1371
1550
|
if (!profile.email) {
|
|
1372
1551
|
throw new Error("Okta profile contained no email");
|
|
1373
1552
|
}
|
|
1374
1553
|
const userId = profile.email.split("@")[0];
|
|
1375
1554
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1376
|
-
claims: {sub: userId, ent: [`user:default/${userId}`]}
|
|
1555
|
+
claims: { sub: userId, ent: [`user:default/${userId}`] }
|
|
1377
1556
|
});
|
|
1378
|
-
return {id: userId, token};
|
|
1557
|
+
return { id: userId, token };
|
|
1379
1558
|
};
|
|
1380
1559
|
const createOktaProvider = (_options) => {
|
|
1381
1560
|
return ({
|
|
@@ -1398,7 +1577,7 @@ const createOktaProvider = (_options) => {
|
|
|
1398
1577
|
catalogApi,
|
|
1399
1578
|
tokenIssuer
|
|
1400
1579
|
});
|
|
1401
|
-
const authHandler = (_options == null ? void 0 : _options.authHandler) ? _options.authHandler : async ({fullProfile, params}) => ({
|
|
1580
|
+
const authHandler = (_options == null ? void 0 : _options.authHandler) ? _options.authHandler : async ({ fullProfile, params }) => ({
|
|
1402
1581
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1403
1582
|
});
|
|
1404
1583
|
const signInResolverFn = (_b = (_a = _options == null ? void 0 : _options.signIn) == null ? void 0 : _a.resolver) != null ? _b : oktaDefaultSignInResolver;
|
|
@@ -1458,14 +1637,14 @@ class BitbucketAuthProvider {
|
|
|
1458
1637
|
});
|
|
1459
1638
|
}
|
|
1460
1639
|
async handler(req) {
|
|
1461
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1640
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1462
1641
|
return {
|
|
1463
1642
|
response: await this.handleResult(result),
|
|
1464
1643
|
refreshToken: privateInfo.refreshToken
|
|
1465
1644
|
};
|
|
1466
1645
|
}
|
|
1467
1646
|
async refresh(req) {
|
|
1468
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1647
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
1469
1648
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
1470
1649
|
return this.handleResult({
|
|
1471
1650
|
fullProfile,
|
|
@@ -1476,7 +1655,7 @@ class BitbucketAuthProvider {
|
|
|
1476
1655
|
}
|
|
1477
1656
|
async handleResult(result) {
|
|
1478
1657
|
result.fullProfile.avatarUrl = result.fullProfile._json.links.avatar.href;
|
|
1479
|
-
const {profile} = await this.authHandler(result);
|
|
1658
|
+
const { profile } = await this.authHandler(result);
|
|
1480
1659
|
const response = {
|
|
1481
1660
|
providerInfo: {
|
|
1482
1661
|
idToken: result.params.id_token,
|
|
@@ -1500,7 +1679,7 @@ class BitbucketAuthProvider {
|
|
|
1500
1679
|
}
|
|
1501
1680
|
}
|
|
1502
1681
|
const bitbucketUsernameSignInResolver = async (info, ctx) => {
|
|
1503
|
-
const {result} = info;
|
|
1682
|
+
const { result } = info;
|
|
1504
1683
|
if (!result.fullProfile.username) {
|
|
1505
1684
|
throw new Error("Bitbucket profile contained no Username");
|
|
1506
1685
|
}
|
|
@@ -1510,11 +1689,11 @@ const bitbucketUsernameSignInResolver = async (info, ctx) => {
|
|
|
1510
1689
|
}
|
|
1511
1690
|
});
|
|
1512
1691
|
const claims = getEntityClaims(entity);
|
|
1513
|
-
const token = await ctx.tokenIssuer.issueToken({claims});
|
|
1514
|
-
return {id: entity.metadata.name, entity, token};
|
|
1692
|
+
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1693
|
+
return { id: entity.metadata.name, entity, token };
|
|
1515
1694
|
};
|
|
1516
1695
|
const bitbucketUserIdSignInResolver = async (info, ctx) => {
|
|
1517
|
-
const {result} = info;
|
|
1696
|
+
const { result } = info;
|
|
1518
1697
|
if (!result.fullProfile.id) {
|
|
1519
1698
|
throw new Error("Bitbucket profile contained no User ID");
|
|
1520
1699
|
}
|
|
@@ -1524,8 +1703,8 @@ const bitbucketUserIdSignInResolver = async (info, ctx) => {
|
|
|
1524
1703
|
}
|
|
1525
1704
|
});
|
|
1526
1705
|
const claims = getEntityClaims(entity);
|
|
1527
|
-
const token = await ctx.tokenIssuer.issueToken({claims});
|
|
1528
|
-
return {id: entity.metadata.name, entity, token};
|
|
1706
|
+
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1707
|
+
return { id: entity.metadata.name, entity, token };
|
|
1529
1708
|
};
|
|
1530
1709
|
const createBitbucketProvider = (options) => {
|
|
1531
1710
|
return ({
|
|
@@ -1544,7 +1723,7 @@ const createBitbucketProvider = (options) => {
|
|
|
1544
1723
|
catalogApi,
|
|
1545
1724
|
tokenIssuer
|
|
1546
1725
|
});
|
|
1547
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile, params}) => ({
|
|
1726
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1548
1727
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1549
1728
|
});
|
|
1550
1729
|
const provider = new BitbucketAuthProvider({
|
|
@@ -1566,7 +1745,7 @@ const createBitbucketProvider = (options) => {
|
|
|
1566
1745
|
};
|
|
1567
1746
|
|
|
1568
1747
|
const defaultScopes = ["offline_access", "read:me"];
|
|
1569
|
-
class AtlassianStrategy extends OAuth2Strategy__default[
|
|
1748
|
+
class AtlassianStrategy extends OAuth2Strategy__default["default"] {
|
|
1570
1749
|
constructor(options, verify) {
|
|
1571
1750
|
if (!options.scope) {
|
|
1572
1751
|
throw new TypeError("Atlassian requires a scope option");
|
|
@@ -1576,7 +1755,7 @@ class AtlassianStrategy extends OAuth2Strategy__default['default'] {
|
|
|
1576
1755
|
...options,
|
|
1577
1756
|
authorizationURL: `https://auth.atlassian.com/authorize`,
|
|
1578
1757
|
tokenURL: `https://auth.atlassian.com/oauth/token`,
|
|
1579
|
-
scope: Array.from(new Set([...defaultScopes, ...scopes]))
|
|
1758
|
+
scope: Array.from(/* @__PURE__ */ new Set([...defaultScopes, ...scopes]))
|
|
1580
1759
|
};
|
|
1581
1760
|
super(optionsWithURLs, verify);
|
|
1582
1761
|
this.profileURL = "https://api.atlassian.com/me";
|
|
@@ -1613,8 +1792,8 @@ class AtlassianStrategy extends OAuth2Strategy__default['default'] {
|
|
|
1613
1792
|
provider: "atlassian",
|
|
1614
1793
|
username: resp.nickname,
|
|
1615
1794
|
displayName: resp.name,
|
|
1616
|
-
emails: [{value: resp.email}],
|
|
1617
|
-
photos: [{value: resp.picture}]
|
|
1795
|
+
emails: [{ value: resp.email }],
|
|
1796
|
+
photos: [{ value: resp.picture }]
|
|
1618
1797
|
};
|
|
1619
1798
|
}
|
|
1620
1799
|
}
|
|
@@ -1653,14 +1832,14 @@ class AtlassianAuthProvider {
|
|
|
1653
1832
|
}
|
|
1654
1833
|
async handler(req) {
|
|
1655
1834
|
var _a;
|
|
1656
|
-
const {result} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1835
|
+
const { result } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
1657
1836
|
return {
|
|
1658
1837
|
response: await this.handleResult(result),
|
|
1659
1838
|
refreshToken: (_a = result.refreshToken) != null ? _a : ""
|
|
1660
1839
|
};
|
|
1661
1840
|
}
|
|
1662
1841
|
async handleResult(result) {
|
|
1663
|
-
const {profile} = await this.authHandler(result);
|
|
1842
|
+
const { profile } = await this.authHandler(result);
|
|
1664
1843
|
const response = {
|
|
1665
1844
|
providerInfo: {
|
|
1666
1845
|
idToken: result.params.id_token,
|
|
@@ -1751,7 +1930,7 @@ class AwsAlbAuthProvider {
|
|
|
1751
1930
|
this.tokenIssuer = options.tokenIssuer;
|
|
1752
1931
|
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
1753
1932
|
this.logger = options.logger;
|
|
1754
|
-
this.keyCache = new NodeCache__default[
|
|
1933
|
+
this.keyCache = new NodeCache__default["default"]({ stdTTL: 3600 });
|
|
1755
1934
|
}
|
|
1756
1935
|
frameHandler() {
|
|
1757
1936
|
return Promise.resolve(void 0);
|
|
@@ -1795,8 +1974,8 @@ class AwsAlbAuthProvider {
|
|
|
1795
1974
|
familyName: claims.family_name,
|
|
1796
1975
|
givenName: claims.given_name
|
|
1797
1976
|
},
|
|
1798
|
-
emails: [{value: claims.email.toLowerCase()}],
|
|
1799
|
-
photos: [{value: claims.picture}]
|
|
1977
|
+
emails: [{ value: claims.email.toLowerCase() }],
|
|
1978
|
+
photos: [{ value: claims.picture }]
|
|
1800
1979
|
};
|
|
1801
1980
|
return {
|
|
1802
1981
|
fullProfile,
|
|
@@ -1808,7 +1987,7 @@ class AwsAlbAuthProvider {
|
|
|
1808
1987
|
}
|
|
1809
1988
|
}
|
|
1810
1989
|
async handleResult(result) {
|
|
1811
|
-
const {profile} = await this.authHandler(result);
|
|
1990
|
+
const { profile } = await this.authHandler(result);
|
|
1812
1991
|
const backstageIdentity = await this.signInResolver({
|
|
1813
1992
|
result,
|
|
1814
1993
|
profile
|
|
@@ -1822,7 +2001,7 @@ class AwsAlbAuthProvider {
|
|
|
1822
2001
|
accessToken: result.accessToken,
|
|
1823
2002
|
expiresInSeconds: result.expiresInSeconds
|
|
1824
2003
|
},
|
|
1825
|
-
backstageIdentity,
|
|
2004
|
+
backstageIdentity: prepareBackstageIdentityResponse(backstageIdentity),
|
|
1826
2005
|
profile
|
|
1827
2006
|
};
|
|
1828
2007
|
}
|
|
@@ -1831,14 +2010,14 @@ class AwsAlbAuthProvider {
|
|
|
1831
2010
|
if (optionalCacheKey) {
|
|
1832
2011
|
return crypto__namespace.createPublicKey(optionalCacheKey);
|
|
1833
2012
|
}
|
|
1834
|
-
const keyText = await fetch__default[
|
|
2013
|
+
const keyText = await fetch__default["default"](`https://public-keys.auth.elb.${this.region}.amazonaws.com/${keyId}`).then((response) => response.text());
|
|
1835
2014
|
const keyValue = crypto__namespace.createPublicKey(keyText);
|
|
1836
|
-
this.keyCache.set(keyId, keyValue.export({format: "pem", type: "spki"}));
|
|
2015
|
+
this.keyCache.set(keyId, keyValue.export({ format: "pem", type: "spki" }));
|
|
1837
2016
|
return keyValue;
|
|
1838
2017
|
}
|
|
1839
2018
|
}
|
|
1840
2019
|
const createAwsAlbProvider = (options) => {
|
|
1841
|
-
return ({config, tokenIssuer, catalogApi, logger}) => {
|
|
2020
|
+
return ({ config, tokenIssuer, catalogApi, logger }) => {
|
|
1842
2021
|
const region = config.getString("region");
|
|
1843
2022
|
const issuer = config.getOptionalString("iss");
|
|
1844
2023
|
if ((options == null ? void 0 : options.signIn.resolver) === void 0) {
|
|
@@ -1848,7 +2027,7 @@ const createAwsAlbProvider = (options) => {
|
|
|
1848
2027
|
catalogApi,
|
|
1849
2028
|
tokenIssuer
|
|
1850
2029
|
});
|
|
1851
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({fullProfile}) => ({
|
|
2030
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
1852
2031
|
profile: makeProfileInfo(fullProfile)
|
|
1853
2032
|
});
|
|
1854
2033
|
const signInResolver = options == null ? void 0 : options.signIn.resolver;
|
|
@@ -1864,182 +2043,98 @@ const createAwsAlbProvider = (options) => {
|
|
|
1864
2043
|
};
|
|
1865
2044
|
};
|
|
1866
2045
|
|
|
1867
|
-
class OidcAuthProvider {
|
|
1868
|
-
constructor(options) {
|
|
1869
|
-
this.implementation = this.setupStrategy(options);
|
|
1870
|
-
this.scope = options.scope;
|
|
1871
|
-
this.prompt = options.prompt;
|
|
1872
|
-
}
|
|
1873
|
-
async start(req) {
|
|
1874
|
-
const {strategy} = await this.implementation;
|
|
1875
|
-
const options = {
|
|
1876
|
-
accessType: "offline",
|
|
1877
|
-
scope: req.scope || this.scope || "openid profile email",
|
|
1878
|
-
state: encodeState(req.state)
|
|
1879
|
-
};
|
|
1880
|
-
const prompt = this.prompt || "none";
|
|
1881
|
-
if (prompt !== "auto") {
|
|
1882
|
-
options.prompt = prompt;
|
|
1883
|
-
}
|
|
1884
|
-
return await executeRedirectStrategy(req, strategy, options);
|
|
1885
|
-
}
|
|
1886
|
-
async handler(req) {
|
|
1887
|
-
const {strategy} = await this.implementation;
|
|
1888
|
-
const strategyResponse = await executeFrameHandlerStrategy(req, strategy);
|
|
1889
|
-
const {
|
|
1890
|
-
result: {userinfo, tokenset},
|
|
1891
|
-
privateInfo
|
|
1892
|
-
} = strategyResponse;
|
|
1893
|
-
const identityResponse = await this.populateIdentity({
|
|
1894
|
-
profile: {
|
|
1895
|
-
displayName: userinfo.name,
|
|
1896
|
-
email: userinfo.email,
|
|
1897
|
-
picture: userinfo.picture
|
|
1898
|
-
},
|
|
1899
|
-
providerInfo: {
|
|
1900
|
-
idToken: tokenset.id_token,
|
|
1901
|
-
accessToken: tokenset.access_token || "",
|
|
1902
|
-
scope: tokenset.scope || "",
|
|
1903
|
-
expiresInSeconds: tokenset.expires_in
|
|
1904
|
-
}
|
|
1905
|
-
});
|
|
1906
|
-
return {
|
|
1907
|
-
response: identityResponse,
|
|
1908
|
-
refreshToken: privateInfo.refreshToken
|
|
1909
|
-
};
|
|
1910
|
-
}
|
|
1911
|
-
async refresh(req) {
|
|
1912
|
-
const {client} = await this.implementation;
|
|
1913
|
-
const tokenset = await client.refresh(req.refreshToken);
|
|
1914
|
-
if (!tokenset.access_token) {
|
|
1915
|
-
throw new Error("Refresh failed");
|
|
1916
|
-
}
|
|
1917
|
-
const profile = await client.userinfo(tokenset.access_token);
|
|
1918
|
-
return this.populateIdentity({
|
|
1919
|
-
providerInfo: {
|
|
1920
|
-
accessToken: tokenset.access_token,
|
|
1921
|
-
refreshToken: tokenset.refresh_token,
|
|
1922
|
-
expiresInSeconds: tokenset.expires_in,
|
|
1923
|
-
idToken: tokenset.id_token,
|
|
1924
|
-
scope: tokenset.scope || ""
|
|
1925
|
-
},
|
|
1926
|
-
profile
|
|
1927
|
-
});
|
|
1928
|
-
}
|
|
1929
|
-
async setupStrategy(options) {
|
|
1930
|
-
const issuer = await openidClient.Issuer.discover(options.metadataUrl);
|
|
1931
|
-
const client = new issuer.Client({
|
|
1932
|
-
client_id: options.clientId,
|
|
1933
|
-
client_secret: options.clientSecret,
|
|
1934
|
-
redirect_uris: [options.callbackUrl],
|
|
1935
|
-
response_types: ["code"],
|
|
1936
|
-
id_token_signed_response_alg: options.tokenSignedResponseAlg || "RS256",
|
|
1937
|
-
scope: options.scope || ""
|
|
1938
|
-
});
|
|
1939
|
-
const strategy = new openidClient.Strategy({
|
|
1940
|
-
client,
|
|
1941
|
-
passReqToCallback: false
|
|
1942
|
-
}, (tokenset, userinfo, done) => {
|
|
1943
|
-
if (typeof done !== "function") {
|
|
1944
|
-
throw new Error("OIDC IdP must provide a userinfo_endpoint in the metadata response");
|
|
1945
|
-
}
|
|
1946
|
-
done(void 0, {tokenset, userinfo}, {
|
|
1947
|
-
refreshToken: tokenset.refresh_token
|
|
1948
|
-
});
|
|
1949
|
-
});
|
|
1950
|
-
strategy.error = console.error;
|
|
1951
|
-
return {strategy, client};
|
|
1952
|
-
}
|
|
1953
|
-
async populateIdentity(response) {
|
|
1954
|
-
const {profile} = response;
|
|
1955
|
-
if (!profile.email) {
|
|
1956
|
-
throw new Error("Profile does not contain an email");
|
|
1957
|
-
}
|
|
1958
|
-
const id = profile.email.split("@")[0];
|
|
1959
|
-
return {...response, backstageIdentity: {id}};
|
|
1960
|
-
}
|
|
1961
|
-
}
|
|
1962
|
-
const createOidcProvider = (_options) => {
|
|
1963
|
-
return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1964
|
-
const clientId = envConfig.getString("clientId");
|
|
1965
|
-
const clientSecret = envConfig.getString("clientSecret");
|
|
1966
|
-
const callbackUrl = `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1967
|
-
const metadataUrl = envConfig.getString("metadataUrl");
|
|
1968
|
-
const tokenSignedResponseAlg = envConfig.getOptionalString("tokenSignedResponseAlg");
|
|
1969
|
-
const scope = envConfig.getOptionalString("scope");
|
|
1970
|
-
const prompt = envConfig.getOptionalString("prompt");
|
|
1971
|
-
const provider = new OidcAuthProvider({
|
|
1972
|
-
clientId,
|
|
1973
|
-
clientSecret,
|
|
1974
|
-
callbackUrl,
|
|
1975
|
-
tokenSignedResponseAlg,
|
|
1976
|
-
metadataUrl,
|
|
1977
|
-
scope,
|
|
1978
|
-
prompt
|
|
1979
|
-
});
|
|
1980
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1981
|
-
disableRefresh: false,
|
|
1982
|
-
providerId,
|
|
1983
|
-
tokenIssuer
|
|
1984
|
-
});
|
|
1985
|
-
});
|
|
1986
|
-
};
|
|
1987
|
-
|
|
1988
2046
|
class SamlAuthProvider {
|
|
1989
2047
|
constructor(options) {
|
|
1990
2048
|
this.appUrl = options.appUrl;
|
|
2049
|
+
this.signInResolver = options.signInResolver;
|
|
2050
|
+
this.authHandler = options.authHandler;
|
|
1991
2051
|
this.tokenIssuer = options.tokenIssuer;
|
|
1992
|
-
this.
|
|
1993
|
-
|
|
2052
|
+
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
2053
|
+
this.logger = options.logger;
|
|
2054
|
+
this.strategy = new passportSaml.Strategy({ ...options }, (fullProfile, done) => {
|
|
2055
|
+
done(void 0, { fullProfile });
|
|
1994
2056
|
});
|
|
1995
2057
|
}
|
|
1996
2058
|
async start(req, res) {
|
|
1997
|
-
const {url} = await executeRedirectStrategy(req, this.strategy, {});
|
|
2059
|
+
const { url } = await executeRedirectStrategy(req, this.strategy, {});
|
|
1998
2060
|
res.redirect(url);
|
|
1999
2061
|
}
|
|
2000
2062
|
async frameHandler(req, res) {
|
|
2001
2063
|
try {
|
|
2002
|
-
const {result} = await executeFrameHandlerStrategy(req, this.strategy);
|
|
2003
|
-
const
|
|
2004
|
-
const
|
|
2005
|
-
|
|
2006
|
-
|
|
2064
|
+
const { result } = await executeFrameHandlerStrategy(req, this.strategy);
|
|
2065
|
+
const { profile } = await this.authHandler(result);
|
|
2066
|
+
const response = {
|
|
2067
|
+
profile,
|
|
2068
|
+
providerInfo: {}
|
|
2069
|
+
};
|
|
2070
|
+
if (this.signInResolver) {
|
|
2071
|
+
const signInResponse = await this.signInResolver({
|
|
2072
|
+
result,
|
|
2073
|
+
profile
|
|
2074
|
+
}, {
|
|
2075
|
+
tokenIssuer: this.tokenIssuer,
|
|
2076
|
+
catalogIdentityClient: this.catalogIdentityClient,
|
|
2077
|
+
logger: this.logger
|
|
2078
|
+
});
|
|
2079
|
+
response.backstageIdentity = prepareBackstageIdentityResponse(signInResponse);
|
|
2080
|
+
}
|
|
2007
2081
|
return postMessageResponse(res, this.appUrl, {
|
|
2008
2082
|
type: "authorization_response",
|
|
2009
|
-
response
|
|
2010
|
-
profile: {
|
|
2011
|
-
email: result.fullProfile.email,
|
|
2012
|
-
displayName: result.fullProfile.displayName
|
|
2013
|
-
},
|
|
2014
|
-
providerInfo: {},
|
|
2015
|
-
backstageIdentity: {id, idToken}
|
|
2016
|
-
}
|
|
2083
|
+
response
|
|
2017
2084
|
});
|
|
2018
2085
|
} catch (error) {
|
|
2019
|
-
const {name, message} = errors.isError(error) ? error : new Error("Encountered invalid error");
|
|
2086
|
+
const { name, message } = errors.isError(error) ? error : new Error("Encountered invalid error");
|
|
2020
2087
|
return postMessageResponse(res, this.appUrl, {
|
|
2021
2088
|
type: "authorization_response",
|
|
2022
|
-
error: {name, message}
|
|
2089
|
+
error: { name, message }
|
|
2023
2090
|
});
|
|
2024
2091
|
}
|
|
2025
2092
|
}
|
|
2026
2093
|
async logout(_req, res) {
|
|
2027
|
-
res.
|
|
2028
|
-
}
|
|
2029
|
-
identifyEnv() {
|
|
2030
|
-
return void 0;
|
|
2094
|
+
res.end();
|
|
2031
2095
|
}
|
|
2032
2096
|
}
|
|
2033
|
-
const
|
|
2034
|
-
|
|
2035
|
-
|
|
2097
|
+
const samlDefaultSignInResolver = async (info, ctx) => {
|
|
2098
|
+
const id = info.result.fullProfile.nameID;
|
|
2099
|
+
const token = await ctx.tokenIssuer.issueToken({
|
|
2100
|
+
claims: { sub: id }
|
|
2101
|
+
});
|
|
2102
|
+
return { id, token };
|
|
2103
|
+
};
|
|
2104
|
+
const createSamlProvider = (options) => {
|
|
2105
|
+
return ({
|
|
2106
|
+
providerId,
|
|
2107
|
+
globalConfig,
|
|
2108
|
+
config,
|
|
2109
|
+
tokenIssuer,
|
|
2110
|
+
catalogApi,
|
|
2111
|
+
logger
|
|
2112
|
+
}) => {
|
|
2113
|
+
var _a, _b;
|
|
2114
|
+
const catalogIdentityClient = new CatalogIdentityClient({
|
|
2115
|
+
catalogApi,
|
|
2116
|
+
tokenIssuer
|
|
2117
|
+
});
|
|
2118
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
2119
|
+
profile: {
|
|
2120
|
+
email: fullProfile.email,
|
|
2121
|
+
displayName: fullProfile.displayName
|
|
2122
|
+
}
|
|
2123
|
+
});
|
|
2124
|
+
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : samlDefaultSignInResolver;
|
|
2125
|
+
const signInResolver = (info) => signInResolverFn(info, {
|
|
2126
|
+
catalogIdentityClient,
|
|
2127
|
+
tokenIssuer,
|
|
2128
|
+
logger
|
|
2129
|
+
});
|
|
2130
|
+
return new SamlAuthProvider({
|
|
2036
2131
|
callbackUrl: `${globalConfig.baseUrl}/${providerId}/handler/frame`,
|
|
2037
2132
|
entryPoint: config.getString("entryPoint"),
|
|
2038
2133
|
logoutUrl: config.getOptionalString("logoutUrl"),
|
|
2039
2134
|
audience: config.getOptionalString("audience"),
|
|
2040
2135
|
issuer: config.getString("issuer"),
|
|
2041
2136
|
cert: config.getString("cert"),
|
|
2042
|
-
|
|
2137
|
+
privateKey: config.getOptionalString("privateKey"),
|
|
2043
2138
|
authnContext: config.getOptionalStringArray("authnContext"),
|
|
2044
2139
|
identifierFormat: config.getOptionalString("identifierFormat"),
|
|
2045
2140
|
decryptionPvk: config.getOptionalString("decryptionPvk"),
|
|
@@ -2047,13 +2142,16 @@ const createSamlProvider = (_options) => {
|
|
|
2047
2142
|
digestAlgorithm: config.getOptionalString("digestAlgorithm"),
|
|
2048
2143
|
acceptedClockSkewMs: config.getOptionalNumber("acceptedClockSkewMs"),
|
|
2049
2144
|
tokenIssuer,
|
|
2050
|
-
appUrl: globalConfig.appUrl
|
|
2051
|
-
|
|
2052
|
-
|
|
2145
|
+
appUrl: globalConfig.appUrl,
|
|
2146
|
+
authHandler,
|
|
2147
|
+
signInResolver,
|
|
2148
|
+
logger,
|
|
2149
|
+
catalogIdentityClient
|
|
2150
|
+
});
|
|
2053
2151
|
};
|
|
2054
2152
|
};
|
|
2055
2153
|
|
|
2056
|
-
class Auth0Strategy extends OAuth2Strategy__default[
|
|
2154
|
+
class Auth0Strategy extends OAuth2Strategy__default["default"] {
|
|
2057
2155
|
constructor(options, verify) {
|
|
2058
2156
|
const optionsWithURLs = {
|
|
2059
2157
|
...options,
|
|
@@ -2094,7 +2192,7 @@ class Auth0AuthProvider {
|
|
|
2094
2192
|
});
|
|
2095
2193
|
}
|
|
2096
2194
|
async handler(req) {
|
|
2097
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
2195
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
2098
2196
|
const profile = makeProfileInfo(result.fullProfile, result.params.id_token);
|
|
2099
2197
|
return {
|
|
2100
2198
|
response: await this.populateIdentity({
|
|
@@ -2110,7 +2208,7 @@ class Auth0AuthProvider {
|
|
|
2110
2208
|
};
|
|
2111
2209
|
}
|
|
2112
2210
|
async refresh(req) {
|
|
2113
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
2211
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
2114
2212
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
2115
2213
|
const profile = makeProfileInfo(fullProfile, params.id_token);
|
|
2116
2214
|
return this.populateIdentity({
|
|
@@ -2124,16 +2222,16 @@ class Auth0AuthProvider {
|
|
|
2124
2222
|
});
|
|
2125
2223
|
}
|
|
2126
2224
|
async populateIdentity(response) {
|
|
2127
|
-
const {profile} = response;
|
|
2225
|
+
const { profile } = response;
|
|
2128
2226
|
if (!profile.email) {
|
|
2129
2227
|
throw new Error("Profile does not contain an email");
|
|
2130
2228
|
}
|
|
2131
2229
|
const id = profile.email.split("@")[0];
|
|
2132
|
-
return {...response, backstageIdentity: {id}};
|
|
2230
|
+
return { ...response, backstageIdentity: { id, token: "" } };
|
|
2133
2231
|
}
|
|
2134
2232
|
}
|
|
2135
2233
|
const createAuth0Provider = (_options) => {
|
|
2136
|
-
return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
2234
|
+
return ({ providerId, globalConfig, config, tokenIssuer }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
2137
2235
|
const clientId = envConfig.getString("clientId");
|
|
2138
2236
|
const clientSecret = envConfig.getString("clientSecret");
|
|
2139
2237
|
const domain = envConfig.getString("domain");
|
|
@@ -2180,7 +2278,7 @@ class OneLoginProvider {
|
|
|
2180
2278
|
});
|
|
2181
2279
|
}
|
|
2182
2280
|
async handler(req) {
|
|
2183
|
-
const {result, privateInfo} = await executeFrameHandlerStrategy(req, this._strategy);
|
|
2281
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
2184
2282
|
const profile = makeProfileInfo(result.fullProfile, result.params.id_token);
|
|
2185
2283
|
return {
|
|
2186
2284
|
response: await this.populateIdentity({
|
|
@@ -2196,7 +2294,7 @@ class OneLoginProvider {
|
|
|
2196
2294
|
};
|
|
2197
2295
|
}
|
|
2198
2296
|
async refresh(req) {
|
|
2199
|
-
const {accessToken, params} = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
2297
|
+
const { accessToken, params } = await executeRefreshTokenStrategy(this._strategy, req.refreshToken, req.scope);
|
|
2200
2298
|
const fullProfile = await executeFetchUserProfileStrategy(this._strategy, accessToken);
|
|
2201
2299
|
const profile = makeProfileInfo(fullProfile, params.id_token);
|
|
2202
2300
|
return this.populateIdentity({
|
|
@@ -2210,16 +2308,16 @@ class OneLoginProvider {
|
|
|
2210
2308
|
});
|
|
2211
2309
|
}
|
|
2212
2310
|
async populateIdentity(response) {
|
|
2213
|
-
const {profile} = response;
|
|
2311
|
+
const { profile } = response;
|
|
2214
2312
|
if (!profile.email) {
|
|
2215
2313
|
throw new Error("OIDC profile contained no email");
|
|
2216
2314
|
}
|
|
2217
2315
|
const id = profile.email.split("@")[0];
|
|
2218
|
-
return {...response, backstageIdentity: {id}};
|
|
2316
|
+
return { ...response, backstageIdentity: { id, token: "" } };
|
|
2219
2317
|
}
|
|
2220
2318
|
}
|
|
2221
2319
|
const createOneLoginProvider = (_options) => {
|
|
2222
|
-
return ({providerId, globalConfig, config, tokenIssuer}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
2320
|
+
return ({ providerId, globalConfig, config, tokenIssuer }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
2223
2321
|
const clientId = envConfig.getString("clientId");
|
|
2224
2322
|
const clientSecret = envConfig.getString("clientSecret");
|
|
2225
2323
|
const issuer = envConfig.getString("issuer");
|
|
@@ -2255,8 +2353,8 @@ const factories = {
|
|
|
2255
2353
|
};
|
|
2256
2354
|
|
|
2257
2355
|
function createOidcRouter(options) {
|
|
2258
|
-
const {baseUrl, tokenIssuer} = options;
|
|
2259
|
-
const router = Router__default[
|
|
2356
|
+
const { baseUrl, tokenIssuer } = options;
|
|
2357
|
+
const router = Router__default["default"]();
|
|
2260
2358
|
const config = {
|
|
2261
2359
|
issuer: baseUrl,
|
|
2262
2360
|
token_endpoint: `${baseUrl}/v1/token`,
|
|
@@ -2274,8 +2372,8 @@ function createOidcRouter(options) {
|
|
|
2274
2372
|
res.json(config);
|
|
2275
2373
|
});
|
|
2276
2374
|
router.get("/.well-known/jwks.json", async (_req, res) => {
|
|
2277
|
-
const {keys} = await tokenIssuer.listPublicKeys();
|
|
2278
|
-
res.json({keys});
|
|
2375
|
+
const { keys } = await tokenIssuer.listPublicKeys();
|
|
2376
|
+
res.json({ keys });
|
|
2279
2377
|
});
|
|
2280
2378
|
router.get("/v1/token", (_req, res) => {
|
|
2281
2379
|
res.status(501).send("Not Implemented");
|
|
@@ -2295,21 +2393,30 @@ class IdentityClient {
|
|
|
2295
2393
|
this.keyStoreUpdated = 0;
|
|
2296
2394
|
}
|
|
2297
2395
|
async authenticate(token) {
|
|
2396
|
+
var _a;
|
|
2298
2397
|
if (!token) {
|
|
2299
|
-
throw new
|
|
2398
|
+
throw new errors.AuthenticationError("No token specified");
|
|
2300
2399
|
}
|
|
2301
2400
|
const key = await this.getKey(token);
|
|
2302
2401
|
if (!key) {
|
|
2303
|
-
throw new
|
|
2402
|
+
throw new errors.AuthenticationError("No signing key matching token found");
|
|
2304
2403
|
}
|
|
2305
2404
|
const decoded = jose.JWT.IdToken.verify(token, key, {
|
|
2306
2405
|
algorithms: ["ES256"],
|
|
2307
2406
|
audience: "backstage",
|
|
2308
2407
|
issuer: this.issuer
|
|
2309
2408
|
});
|
|
2409
|
+
if (!decoded.sub) {
|
|
2410
|
+
throw new errors.AuthenticationError("No user sub found in token");
|
|
2411
|
+
}
|
|
2310
2412
|
const user = {
|
|
2311
2413
|
id: decoded.sub,
|
|
2312
|
-
|
|
2414
|
+
token,
|
|
2415
|
+
identity: {
|
|
2416
|
+
type: "user",
|
|
2417
|
+
userEntityRef: decoded.sub,
|
|
2418
|
+
ownershipEntityRefs: (_a = decoded.ent) != null ? _a : []
|
|
2419
|
+
}
|
|
2313
2420
|
};
|
|
2314
2421
|
return user;
|
|
2315
2422
|
}
|
|
@@ -2321,19 +2428,19 @@ class IdentityClient {
|
|
|
2321
2428
|
return matches == null ? void 0 : matches[1];
|
|
2322
2429
|
}
|
|
2323
2430
|
async getKey(rawJwtToken) {
|
|
2324
|
-
const {header, payload} = jose.JWT.decode(rawJwtToken, {
|
|
2431
|
+
const { header, payload } = jose.JWT.decode(rawJwtToken, {
|
|
2325
2432
|
complete: true
|
|
2326
2433
|
});
|
|
2327
|
-
const keyStoreHasKey = !!this.keyStore.get({kid: header.kid});
|
|
2434
|
+
const keyStoreHasKey = !!this.keyStore.get({ kid: header.kid });
|
|
2328
2435
|
const issuedAfterLastRefresh = (payload == null ? void 0 : payload.iat) && payload.iat > this.keyStoreUpdated - CLOCK_MARGIN_S;
|
|
2329
2436
|
if (!keyStoreHasKey && issuedAfterLastRefresh) {
|
|
2330
2437
|
await this.refreshKeyStore();
|
|
2331
2438
|
}
|
|
2332
|
-
return this.keyStore.get({kid: header.kid});
|
|
2439
|
+
return this.keyStore.get({ kid: header.kid });
|
|
2333
2440
|
}
|
|
2334
2441
|
async listPublicKeys() {
|
|
2335
2442
|
const url = `${await this.discovery.getBaseUrl("auth")}/.well-known/jwks.json`;
|
|
2336
|
-
const response = await fetch__default[
|
|
2443
|
+
const response = await fetch__default["default"](url);
|
|
2337
2444
|
if (!response.ok) {
|
|
2338
2445
|
const payload = await response.text();
|
|
2339
2446
|
const message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
|
|
@@ -2369,13 +2476,13 @@ class TokenFactory {
|
|
|
2369
2476
|
const iat = Math.floor(Date.now() / MS_IN_S);
|
|
2370
2477
|
const exp = iat + this.keyDurationSeconds;
|
|
2371
2478
|
this.logger.info(`Issuing token for ${sub}, with entities ${ent != null ? ent : []}`);
|
|
2372
|
-
return jose.JWS.sign({iss, sub, aud, iat, exp, ent}, key, {
|
|
2479
|
+
return jose.JWS.sign({ iss, sub, aud, iat, exp, ent }, key, {
|
|
2373
2480
|
alg: key.alg,
|
|
2374
2481
|
kid: key.kid
|
|
2375
2482
|
});
|
|
2376
2483
|
}
|
|
2377
2484
|
async listPublicKeys() {
|
|
2378
|
-
const {items: keys} = await this.keyStore.listKeys();
|
|
2485
|
+
const { items: keys } = await this.keyStore.listKeys();
|
|
2379
2486
|
const validKeys = [];
|
|
2380
2487
|
const expiredKeys = [];
|
|
2381
2488
|
for (const key of keys) {
|
|
@@ -2389,13 +2496,13 @@ class TokenFactory {
|
|
|
2389
2496
|
}
|
|
2390
2497
|
}
|
|
2391
2498
|
if (expiredKeys.length > 0) {
|
|
2392
|
-
const kids = expiredKeys.map(({key}) => key.kid);
|
|
2499
|
+
const kids = expiredKeys.map(({ key }) => key.kid);
|
|
2393
2500
|
this.logger.info(`Removing expired signing keys, '${kids.join("', '")}'`);
|
|
2394
2501
|
this.keyStore.removeKeys(kids).catch((error) => {
|
|
2395
2502
|
this.logger.error(`Failed to remove expired keys, ${error}`);
|
|
2396
2503
|
});
|
|
2397
2504
|
}
|
|
2398
|
-
return {keys: validKeys.map(({key}) => key)};
|
|
2505
|
+
return { keys: validKeys.map(({ key }) => key) };
|
|
2399
2506
|
}
|
|
2400
2507
|
async getKey() {
|
|
2401
2508
|
if (this.privateKeyPromise) {
|
|
@@ -2433,7 +2540,7 @@ class TokenFactory {
|
|
|
2433
2540
|
const migrationsDir = backendCommon.resolvePackagePath("@backstage/plugin-auth-backend", "migrations");
|
|
2434
2541
|
const TABLE = "signing_keys";
|
|
2435
2542
|
const parseDate = (date) => {
|
|
2436
|
-
const parsedDate = typeof date === "string" ? luxon.DateTime.fromSQL(date, {zone: "UTC"}) : luxon.DateTime.fromJSDate(date);
|
|
2543
|
+
const parsedDate = typeof date === "string" ? luxon.DateTime.fromSQL(date, { zone: "UTC" }) : luxon.DateTime.fromJSDate(date);
|
|
2437
2544
|
if (!parsedDate.isValid) {
|
|
2438
2545
|
throw new Error(`Failed to parse date, reason: ${parsedDate.invalidReason}, explanation: ${parsedDate.invalidExplanation}`);
|
|
2439
2546
|
}
|
|
@@ -2441,7 +2548,7 @@ const parseDate = (date) => {
|
|
|
2441
2548
|
};
|
|
2442
2549
|
class DatabaseKeyStore {
|
|
2443
2550
|
static async create(options) {
|
|
2444
|
-
const {database} = options;
|
|
2551
|
+
const { database } = options;
|
|
2445
2552
|
await database.migrate.latest({
|
|
2446
2553
|
directory: migrationsDir
|
|
2447
2554
|
});
|
|
@@ -2472,7 +2579,7 @@ class DatabaseKeyStore {
|
|
|
2472
2579
|
|
|
2473
2580
|
class MemoryKeyStore {
|
|
2474
2581
|
constructor() {
|
|
2475
|
-
this.keys = new Map();
|
|
2582
|
+
this.keys = /* @__PURE__ */ new Map();
|
|
2476
2583
|
}
|
|
2477
2584
|
async addKey(key) {
|
|
2478
2585
|
this.keys.set(key.kid, {
|
|
@@ -2487,7 +2594,7 @@ class MemoryKeyStore {
|
|
|
2487
2594
|
}
|
|
2488
2595
|
async listKeys() {
|
|
2489
2596
|
return {
|
|
2490
|
-
items: Array.from(this.keys).map(([, {createdAt, key: keyStr}]) => ({
|
|
2597
|
+
items: Array.from(this.keys).map(([, { createdAt, key: keyStr }]) => ({
|
|
2491
2598
|
createdAt,
|
|
2492
2599
|
key: JSON.parse(keyStr)
|
|
2493
2600
|
}))
|
|
@@ -2504,7 +2611,7 @@ class FirestoreKeyStore {
|
|
|
2504
2611
|
this.timeout = timeout;
|
|
2505
2612
|
}
|
|
2506
2613
|
static async create(settings) {
|
|
2507
|
-
const {path, timeout, ...firestoreSettings} = settings != null ? settings : {};
|
|
2614
|
+
const { path, timeout, ...firestoreSettings } = settings != null ? settings : {};
|
|
2508
2615
|
const database = new firestore.Firestore(firestoreSettings);
|
|
2509
2616
|
return new FirestoreKeyStore(database, path != null ? path : DEFAULT_DOCUMENT_PATH, timeout != null ? timeout : DEFAULT_TIMEOUT_MS);
|
|
2510
2617
|
}
|
|
@@ -2552,7 +2659,7 @@ class FirestoreKeyStore {
|
|
|
2552
2659
|
class KeyStores {
|
|
2553
2660
|
static async fromConfig(config, options) {
|
|
2554
2661
|
var _a;
|
|
2555
|
-
const {logger, database} = options != null ? options : {};
|
|
2662
|
+
const { logger, database } = options != null ? options : {};
|
|
2556
2663
|
const ks = config.getOptionalConfig("auth.keyStore");
|
|
2557
2664
|
const provider = (_a = ks == null ? void 0 : ks.getOptionalString("provider")) != null ? _a : "database";
|
|
2558
2665
|
logger == null ? void 0 : logger.info(`Configuring "${provider}" as KeyStore provider`);
|
|
@@ -2585,36 +2692,31 @@ class KeyStores {
|
|
|
2585
2692
|
}
|
|
2586
2693
|
}
|
|
2587
2694
|
|
|
2588
|
-
async function createRouter({
|
|
2589
|
-
logger,
|
|
2590
|
-
|
|
2591
|
-
discovery,
|
|
2592
|
-
database,
|
|
2593
|
-
providerFactories
|
|
2594
|
-
}) {
|
|
2595
|
-
const router = Router__default['default']();
|
|
2695
|
+
async function createRouter(options) {
|
|
2696
|
+
const { logger, config, discovery, database, providerFactories } = options;
|
|
2697
|
+
const router = Router__default["default"]();
|
|
2596
2698
|
const appUrl = config.getString("app.baseUrl");
|
|
2597
2699
|
const authUrl = await discovery.getExternalBaseUrl("auth");
|
|
2598
|
-
const keyStore = await KeyStores.fromConfig(config, {logger, database});
|
|
2700
|
+
const keyStore = await KeyStores.fromConfig(config, { logger, database });
|
|
2599
2701
|
const keyDurationSeconds = 3600;
|
|
2600
2702
|
const tokenIssuer = new TokenFactory({
|
|
2601
2703
|
issuer: authUrl,
|
|
2602
2704
|
keyStore,
|
|
2603
2705
|
keyDurationSeconds,
|
|
2604
|
-
logger: logger.child({component: "token-factory"})
|
|
2706
|
+
logger: logger.child({ component: "token-factory" })
|
|
2605
2707
|
});
|
|
2606
|
-
const catalogApi = new catalogClient.CatalogClient({discoveryApi: discovery});
|
|
2708
|
+
const catalogApi = new catalogClient.CatalogClient({ discoveryApi: discovery });
|
|
2607
2709
|
const secret = config.getOptionalString("auth.session.secret");
|
|
2608
2710
|
if (secret) {
|
|
2609
|
-
router.use(cookieParser__default[
|
|
2610
|
-
router.use(session__default[
|
|
2611
|
-
router.use(passport__default[
|
|
2612
|
-
router.use(passport__default[
|
|
2711
|
+
router.use(cookieParser__default["default"](secret));
|
|
2712
|
+
router.use(session__default["default"]({ secret, saveUninitialized: false, resave: false }));
|
|
2713
|
+
router.use(passport__default["default"].initialize());
|
|
2714
|
+
router.use(passport__default["default"].session());
|
|
2613
2715
|
} else {
|
|
2614
|
-
router.use(cookieParser__default[
|
|
2716
|
+
router.use(cookieParser__default["default"]());
|
|
2615
2717
|
}
|
|
2616
|
-
router.use(express__default[
|
|
2617
|
-
router.use(express__default[
|
|
2718
|
+
router.use(express__default["default"].urlencoded({ extended: false }));
|
|
2719
|
+
router.use(express__default["default"].json());
|
|
2618
2720
|
const allProviderFactories = {
|
|
2619
2721
|
...factories,
|
|
2620
2722
|
...providerFactories
|
|
@@ -2628,14 +2730,14 @@ async function createRouter({
|
|
|
2628
2730
|
try {
|
|
2629
2731
|
const provider = providerFactory({
|
|
2630
2732
|
providerId,
|
|
2631
|
-
globalConfig: {baseUrl: authUrl, appUrl, isOriginAllowed},
|
|
2733
|
+
globalConfig: { baseUrl: authUrl, appUrl, isOriginAllowed },
|
|
2632
2734
|
config: providersConfig.getConfig(providerId),
|
|
2633
2735
|
logger,
|
|
2634
2736
|
tokenIssuer,
|
|
2635
2737
|
discovery,
|
|
2636
2738
|
catalogApi
|
|
2637
2739
|
});
|
|
2638
|
-
const r = Router__default[
|
|
2740
|
+
const r = Router__default["default"]();
|
|
2639
2741
|
r.get("/start", provider.start.bind(provider));
|
|
2640
2742
|
r.get("/handler/frame", provider.frameHandler.bind(provider));
|
|
2641
2743
|
r.post("/handler/frame", provider.frameHandler.bind(provider));
|
|
@@ -2667,7 +2769,7 @@ async function createRouter({
|
|
|
2667
2769
|
baseUrl: authUrl
|
|
2668
2770
|
}));
|
|
2669
2771
|
router.use("/:provider/", (req) => {
|
|
2670
|
-
const {provider} = req.params;
|
|
2772
|
+
const { provider } = req.params;
|
|
2671
2773
|
throw new errors.NotFoundError(`Unknown auth provider '${provider}'`);
|
|
2672
2774
|
});
|
|
2673
2775
|
return router;
|
|
@@ -2675,9 +2777,9 @@ async function createRouter({
|
|
|
2675
2777
|
function createOriginFilter(config) {
|
|
2676
2778
|
var _a;
|
|
2677
2779
|
const appUrl = config.getString("app.baseUrl");
|
|
2678
|
-
const {origin: appOrigin} = new URL(appUrl);
|
|
2780
|
+
const { origin: appOrigin } = new URL(appUrl);
|
|
2679
2781
|
const allowedOrigins = config.getOptionalStringArray("auth.experimentalExtraAllowedOrigins");
|
|
2680
|
-
const allowedOriginPatterns = (_a = allowedOrigins == null ? void 0 : allowedOrigins.map((pattern) => new minimatch.Minimatch(pattern, {nocase: true, noglobstar: true}))) != null ? _a : [];
|
|
2782
|
+
const allowedOriginPatterns = (_a = allowedOrigins == null ? void 0 : allowedOrigins.map((pattern) => new minimatch.Minimatch(pattern, { nocase: true, noglobstar: true }))) != null ? _a : [];
|
|
2681
2783
|
return (origin) => {
|
|
2682
2784
|
if (origin === appOrigin) {
|
|
2683
2785
|
return true;
|
|
@@ -2686,6 +2788,7 @@ function createOriginFilter(config) {
|
|
|
2686
2788
|
};
|
|
2687
2789
|
}
|
|
2688
2790
|
|
|
2791
|
+
exports.CatalogIdentityClient = CatalogIdentityClient;
|
|
2689
2792
|
exports.IdentityClient = IdentityClient;
|
|
2690
2793
|
exports.OAuthAdapter = OAuthAdapter;
|
|
2691
2794
|
exports.OAuthEnvironmentHandler = OAuthEnvironmentHandler;
|
|
@@ -2699,16 +2802,20 @@ exports.createGitlabProvider = createGitlabProvider;
|
|
|
2699
2802
|
exports.createGoogleProvider = createGoogleProvider;
|
|
2700
2803
|
exports.createMicrosoftProvider = createMicrosoftProvider;
|
|
2701
2804
|
exports.createOAuth2Provider = createOAuth2Provider;
|
|
2805
|
+
exports.createOidcProvider = createOidcProvider;
|
|
2702
2806
|
exports.createOktaProvider = createOktaProvider;
|
|
2703
2807
|
exports.createOriginFilter = createOriginFilter;
|
|
2704
2808
|
exports.createRouter = createRouter;
|
|
2809
|
+
exports.createSamlProvider = createSamlProvider;
|
|
2705
2810
|
exports.defaultAuthProviderFactories = factories;
|
|
2706
2811
|
exports.encodeState = encodeState;
|
|
2707
2812
|
exports.ensuresXRequestedWith = ensuresXRequestedWith;
|
|
2813
|
+
exports.getEntityClaims = getEntityClaims;
|
|
2708
2814
|
exports.googleEmailSignInResolver = googleEmailSignInResolver;
|
|
2709
2815
|
exports.microsoftEmailSignInResolver = microsoftEmailSignInResolver;
|
|
2710
2816
|
exports.oktaEmailSignInResolver = oktaEmailSignInResolver;
|
|
2711
2817
|
exports.postMessageResponse = postMessageResponse;
|
|
2818
|
+
exports.prepareBackstageIdentityResponse = prepareBackstageIdentityResponse;
|
|
2712
2819
|
exports.readState = readState;
|
|
2713
2820
|
exports.verifyNonce = verifyNonce;
|
|
2714
2821
|
//# sourceMappingURL=index.cjs.js.map
|