@backstage/plugin-auth-backend 0.20.4-next.0 → 0.21.0-next.2
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 +67 -0
- package/README.md +11 -0
- package/config.d.ts +6 -0
- package/dist/index.cjs.js +89 -199
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +12 -8
- package/package.json +23 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# @backstage/plugin-auth-backend
|
|
2
2
|
|
|
3
|
+
## 0.21.0-next.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 7dd8463: **BREAKING**: The `saml` provider has been migrated from `passport-saml` to `@node-saml/passport-saml`.
|
|
8
|
+
|
|
9
|
+
This comes with breaking changes to config options:
|
|
10
|
+
|
|
11
|
+
- `audience` is now mandatory
|
|
12
|
+
- `wantAuthnResponseSigned` is now exposed and defaults to `true`
|
|
13
|
+
- `wantAssertionsSigned` is now exposed and defaults to `true`
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 97f8724: Support additional algorithms in the `/.well-known/openid-configuration` endpoint.
|
|
18
|
+
- a9e0107: The auth backend will now refuse to issue user tokens are excessively large.
|
|
19
|
+
- d4cc552: The helper function `makeProfileInfo` and `PassportHelpers.transformProfile`
|
|
20
|
+
were refactored to use the `jose` library.
|
|
21
|
+
- 8e8a25d: Ability for user to configure backstage token expiration
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
- @backstage/backend-common@0.21.0-next.2
|
|
24
|
+
- @backstage/backend-plugin-api@0.6.10-next.2
|
|
25
|
+
- @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.0-next.1
|
|
26
|
+
- @backstage/plugin-auth-node@0.4.4-next.2
|
|
27
|
+
- @backstage/plugin-auth-backend-module-atlassian-provider@0.1.2-next.2
|
|
28
|
+
- @backstage/plugin-auth-backend-module-github-provider@0.1.7-next.2
|
|
29
|
+
- @backstage/plugin-auth-backend-module-gitlab-provider@0.1.7-next.2
|
|
30
|
+
- @backstage/plugin-auth-backend-module-google-provider@0.1.7-next.2
|
|
31
|
+
- @backstage/plugin-auth-backend-module-microsoft-provider@0.1.5-next.2
|
|
32
|
+
- @backstage/plugin-auth-backend-module-oauth2-provider@0.1.7-next.2
|
|
33
|
+
- @backstage/plugin-auth-backend-module-oidc-provider@0.1.0-next.2
|
|
34
|
+
- @backstage/plugin-auth-backend-module-okta-provider@0.0.3-next.2
|
|
35
|
+
- @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.4-next.2
|
|
36
|
+
- @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.2-next.2
|
|
37
|
+
- @backstage/plugin-catalog-node@1.6.2-next.2
|
|
38
|
+
- @backstage/config@1.1.1
|
|
39
|
+
- @backstage/catalog-client@1.6.0-next.1
|
|
40
|
+
- @backstage/catalog-model@1.4.4-next.0
|
|
41
|
+
- @backstage/errors@1.2.3
|
|
42
|
+
- @backstage/types@1.1.1
|
|
43
|
+
|
|
44
|
+
## 0.20.4-next.1
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- 23a98f8: Migrated the AWS ALB auth provider to new `@backstage/plugin-auth-backend-module-aws-alb-provider` module package.
|
|
49
|
+
- Updated dependencies
|
|
50
|
+
- @backstage/catalog-model@1.4.4-next.0
|
|
51
|
+
- @backstage/catalog-client@1.6.0-next.1
|
|
52
|
+
- @backstage/backend-plugin-api@0.6.10-next.1
|
|
53
|
+
- @backstage/backend-common@0.21.0-next.1
|
|
54
|
+
- @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.0-next.0
|
|
55
|
+
- @backstage/config@1.1.1
|
|
56
|
+
- @backstage/errors@1.2.3
|
|
57
|
+
- @backstage/plugin-auth-backend-module-atlassian-provider@0.1.2-next.1
|
|
58
|
+
- @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.4-next.1
|
|
59
|
+
- @backstage/plugin-auth-backend-module-github-provider@0.1.7-next.1
|
|
60
|
+
- @backstage/plugin-auth-backend-module-gitlab-provider@0.1.7-next.1
|
|
61
|
+
- @backstage/plugin-auth-backend-module-google-provider@0.1.7-next.1
|
|
62
|
+
- @backstage/plugin-auth-backend-module-microsoft-provider@0.1.5-next.1
|
|
63
|
+
- @backstage/plugin-auth-backend-module-oauth2-provider@0.1.7-next.1
|
|
64
|
+
- @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.2-next.1
|
|
65
|
+
- @backstage/plugin-auth-backend-module-oidc-provider@0.1.0-next.1
|
|
66
|
+
- @backstage/plugin-auth-backend-module-okta-provider@0.0.3-next.1
|
|
67
|
+
- @backstage/plugin-auth-node@0.4.4-next.1
|
|
68
|
+
- @backstage/plugin-catalog-node@1.6.2-next.1
|
|
69
|
+
|
|
3
70
|
## 0.20.4-next.0
|
|
4
71
|
|
|
5
72
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -165,3 +165,14 @@ To try out SAML, you can use the mock identity provider:
|
|
|
165
165
|
## Links
|
|
166
166
|
|
|
167
167
|
- [The Backstage homepage](https://backstage.io)
|
|
168
|
+
|
|
169
|
+
## Configuring Token Expiration in App Config
|
|
170
|
+
|
|
171
|
+
If you need to change Backstage token expiration from the default value of one hour you can do so through configuration. Note that this is **not** the session duration, but rather the duration that the short-term cryptographic tokens are valid for. The expiration can not be set lower than 10 minutes or above 24 hours.
|
|
172
|
+
|
|
173
|
+
This is what the configuration looks like:
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
auth:
|
|
177
|
+
backstageTokenExpiration: { minutes: <user_defined_value> }
|
|
178
|
+
```
|
package/config.d.ts
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { HumanDuration } from '@backstage/types';
|
|
18
|
+
|
|
17
19
|
export interface Config {
|
|
18
20
|
/** Configuration options for the auth plugin */
|
|
19
21
|
auth?: {
|
|
@@ -184,6 +186,10 @@ export interface Config {
|
|
|
184
186
|
cfaccess?: {
|
|
185
187
|
teamName: string;
|
|
186
188
|
};
|
|
189
|
+
/**
|
|
190
|
+
* The backstage token expiration.
|
|
191
|
+
*/
|
|
192
|
+
backstageTokenExpiration?: HumanDuration;
|
|
187
193
|
};
|
|
188
194
|
};
|
|
189
195
|
}
|
package/dist/index.cjs.js
CHANGED
|
@@ -13,11 +13,10 @@ var Auth0InternalStrategy = require('passport-auth0');
|
|
|
13
13
|
var crypto = require('crypto');
|
|
14
14
|
var url = require('url');
|
|
15
15
|
var errors = require('@backstage/errors');
|
|
16
|
-
var jwtDecoder = require('jwt-decode');
|
|
17
|
-
var fetch = require('node-fetch');
|
|
18
|
-
var NodeCache = require('node-cache');
|
|
19
16
|
var jose = require('jose');
|
|
17
|
+
var pluginAuthBackendModuleAwsAlbProvider = require('@backstage/plugin-auth-backend-module-aws-alb-provider');
|
|
20
18
|
var passportBitbucketOauth2 = require('passport-bitbucket-oauth2');
|
|
19
|
+
var fetch = require('node-fetch');
|
|
21
20
|
var pluginAuthBackendModuleGcpIapProvider = require('@backstage/plugin-auth-backend-module-gcp-iap-provider');
|
|
22
21
|
var pluginAuthBackendModuleGithubProvider = require('@backstage/plugin-auth-backend-module-github-provider');
|
|
23
22
|
var pluginAuthBackendModuleGitlabProvider = require('@backstage/plugin-auth-backend-module-gitlab-provider');
|
|
@@ -28,7 +27,7 @@ var pluginAuthBackendModuleOauth2ProxyProvider = require('@backstage/plugin-auth
|
|
|
28
27
|
var pluginAuthBackendModuleOidcProvider = require('@backstage/plugin-auth-backend-module-oidc-provider');
|
|
29
28
|
var pluginAuthBackendModuleOktaProvider = require('@backstage/plugin-auth-backend-module-okta-provider');
|
|
30
29
|
var passportOneloginOauth = require('passport-onelogin-oauth');
|
|
31
|
-
var passportSaml = require('passport-saml');
|
|
30
|
+
var passportSaml = require('@node-saml/passport-saml');
|
|
32
31
|
var passportOauth2 = require('passport-oauth2');
|
|
33
32
|
var catalogClient = require('@backstage/catalog-client');
|
|
34
33
|
var catalogModel = require('@backstage/catalog-model');
|
|
@@ -43,36 +42,16 @@ var passport = require('passport');
|
|
|
43
42
|
var minimatch = require('minimatch');
|
|
44
43
|
var backendCommon = require('@backstage/backend-common');
|
|
45
44
|
var config = require('@backstage/config');
|
|
45
|
+
var types = require('@backstage/types');
|
|
46
46
|
|
|
47
47
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
48
48
|
|
|
49
|
-
function _interopNamespace(e) {
|
|
50
|
-
if (e && e.__esModule) return e;
|
|
51
|
-
var n = Object.create(null);
|
|
52
|
-
if (e) {
|
|
53
|
-
Object.keys(e).forEach(function (k) {
|
|
54
|
-
if (k !== 'default') {
|
|
55
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
56
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
57
|
-
enumerable: true,
|
|
58
|
-
get: function () { return e[k]; }
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
n["default"] = e;
|
|
64
|
-
return Object.freeze(n);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
49
|
var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
|
|
68
50
|
var Router__default = /*#__PURE__*/_interopDefaultLegacy(Router);
|
|
69
51
|
var cookieParser__default = /*#__PURE__*/_interopDefaultLegacy(cookieParser);
|
|
70
52
|
var Auth0InternalStrategy__default = /*#__PURE__*/_interopDefaultLegacy(Auth0InternalStrategy);
|
|
71
53
|
var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
|
|
72
|
-
var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
|
|
73
|
-
var jwtDecoder__default = /*#__PURE__*/_interopDefaultLegacy(jwtDecoder);
|
|
74
54
|
var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
|
|
75
|
-
var NodeCache__default = /*#__PURE__*/_interopDefaultLegacy(NodeCache);
|
|
76
55
|
var session__default = /*#__PURE__*/_interopDefaultLegacy(session);
|
|
77
56
|
var connectSessionKnex__default = /*#__PURE__*/_interopDefaultLegacy(connectSessionKnex);
|
|
78
57
|
var passport__default = /*#__PURE__*/_interopDefaultLegacy(passport);
|
|
@@ -240,10 +219,10 @@ const ensuresXRequestedWith = (req) => {
|
|
|
240
219
|
|
|
241
220
|
const prepareBackstageIdentityResponse = pluginAuthNode.prepareBackstageIdentityResponse;
|
|
242
221
|
|
|
243
|
-
var __defProp$
|
|
244
|
-
var __defNormalProp$
|
|
245
|
-
var __publicField$
|
|
246
|
-
__defNormalProp$
|
|
222
|
+
var __defProp$c = Object.defineProperty;
|
|
223
|
+
var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
224
|
+
var __publicField$c = (obj, key, value) => {
|
|
225
|
+
__defNormalProp$c(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
247
226
|
return value;
|
|
248
227
|
};
|
|
249
228
|
const THOUSAND_DAYS_MS = 1e3 * 24 * 60 * 60 * 1e3;
|
|
@@ -252,8 +231,8 @@ class OAuthAdapter {
|
|
|
252
231
|
constructor(handlers, options) {
|
|
253
232
|
this.handlers = handlers;
|
|
254
233
|
this.options = options;
|
|
255
|
-
__publicField$
|
|
256
|
-
__publicField$
|
|
234
|
+
__publicField$c(this, "baseCookieOptions");
|
|
235
|
+
__publicField$c(this, "setNonceCookie", (res, nonce, cookieConfig) => {
|
|
257
236
|
res.cookie(`${this.options.providerId}-nonce`, nonce, {
|
|
258
237
|
maxAge: TEN_MINUTES_MS,
|
|
259
238
|
...this.baseCookieOptions,
|
|
@@ -261,34 +240,34 @@ class OAuthAdapter {
|
|
|
261
240
|
path: `${cookieConfig.path}/handler`
|
|
262
241
|
});
|
|
263
242
|
});
|
|
264
|
-
__publicField$
|
|
243
|
+
__publicField$c(this, "setGrantedScopeCookie", (res, scope, cookieConfig) => {
|
|
265
244
|
res.cookie(`${this.options.providerId}-granted-scope`, scope, {
|
|
266
245
|
maxAge: THOUSAND_DAYS_MS,
|
|
267
246
|
...this.baseCookieOptions,
|
|
268
247
|
...cookieConfig
|
|
269
248
|
});
|
|
270
249
|
});
|
|
271
|
-
__publicField$
|
|
250
|
+
__publicField$c(this, "getRefreshTokenFromCookie", (req) => {
|
|
272
251
|
return req.cookies[`${this.options.providerId}-refresh-token`];
|
|
273
252
|
});
|
|
274
|
-
__publicField$
|
|
253
|
+
__publicField$c(this, "getGrantedScopeFromCookie", (req) => {
|
|
275
254
|
return req.cookies[`${this.options.providerId}-granted-scope`];
|
|
276
255
|
});
|
|
277
|
-
__publicField$
|
|
256
|
+
__publicField$c(this, "setRefreshTokenCookie", (res, refreshToken, cookieConfig) => {
|
|
278
257
|
res.cookie(`${this.options.providerId}-refresh-token`, refreshToken, {
|
|
279
258
|
maxAge: THOUSAND_DAYS_MS,
|
|
280
259
|
...this.baseCookieOptions,
|
|
281
260
|
...cookieConfig
|
|
282
261
|
});
|
|
283
262
|
});
|
|
284
|
-
__publicField$
|
|
263
|
+
__publicField$c(this, "removeRefreshTokenCookie", (res, cookieConfig) => {
|
|
285
264
|
res.cookie(`${this.options.providerId}-refresh-token`, "", {
|
|
286
265
|
maxAge: 0,
|
|
287
266
|
...this.baseCookieOptions,
|
|
288
267
|
...cookieConfig
|
|
289
268
|
});
|
|
290
269
|
});
|
|
291
|
-
__publicField$
|
|
270
|
+
__publicField$c(this, "getCookieConfig", (origin) => {
|
|
292
271
|
return this.options.cookieConfigurer({
|
|
293
272
|
providerId: this.options.providerId,
|
|
294
273
|
baseUrl: this.options.baseUrl,
|
|
@@ -470,7 +449,7 @@ const makeProfileInfo = (profile, idToken) => {
|
|
|
470
449
|
let displayName = (_b = (_a = profile.displayName) != null ? _a : profile.username) != null ? _b : profile.id;
|
|
471
450
|
if ((!email || !picture || !displayName) && idToken) {
|
|
472
451
|
try {
|
|
473
|
-
const decoded =
|
|
452
|
+
const decoded = jose.decodeJwt(idToken);
|
|
474
453
|
if (!email && decoded.email) {
|
|
475
454
|
email = decoded.email;
|
|
476
455
|
}
|
|
@@ -586,21 +565,21 @@ const executeFetchUserProfileStrategy = async (providerStrategy, accessToken) =>
|
|
|
586
565
|
});
|
|
587
566
|
};
|
|
588
567
|
|
|
589
|
-
var __defProp$
|
|
590
|
-
var __defNormalProp$
|
|
591
|
-
var __publicField$
|
|
592
|
-
__defNormalProp$
|
|
568
|
+
var __defProp$b = Object.defineProperty;
|
|
569
|
+
var __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
570
|
+
var __publicField$b = (obj, key, value) => {
|
|
571
|
+
__defNormalProp$b(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
593
572
|
return value;
|
|
594
573
|
};
|
|
595
574
|
class Auth0AuthProvider {
|
|
596
575
|
constructor(options) {
|
|
597
|
-
__publicField$
|
|
598
|
-
__publicField$
|
|
599
|
-
__publicField$
|
|
600
|
-
__publicField$
|
|
601
|
-
__publicField$
|
|
602
|
-
__publicField$
|
|
603
|
-
__publicField$
|
|
576
|
+
__publicField$b(this, "_strategy");
|
|
577
|
+
__publicField$b(this, "signInResolver");
|
|
578
|
+
__publicField$b(this, "authHandler");
|
|
579
|
+
__publicField$b(this, "resolverContext");
|
|
580
|
+
__publicField$b(this, "audience");
|
|
581
|
+
__publicField$b(this, "connection");
|
|
582
|
+
__publicField$b(this, "connectionScope");
|
|
604
583
|
/**
|
|
605
584
|
* Due to passport-auth0 forcing options.state = true,
|
|
606
585
|
* passport-oauth2 requires express-session to be installed
|
|
@@ -609,7 +588,7 @@ class Auth0AuthProvider {
|
|
|
609
588
|
* passport-oauth2, which is the StateStore implementation used when options.state = false,
|
|
610
589
|
* allowing us to avoid using express-session in order to integrate with auth0.
|
|
611
590
|
*/
|
|
612
|
-
__publicField$
|
|
591
|
+
__publicField$b(this, "store", {
|
|
613
592
|
store(_req, cb) {
|
|
614
593
|
cb(null, null);
|
|
615
594
|
},
|
|
@@ -750,147 +729,14 @@ const auth0 = createAuthProviderIntegration({
|
|
|
750
729
|
}
|
|
751
730
|
});
|
|
752
731
|
|
|
753
|
-
var __defProp$b = Object.defineProperty;
|
|
754
|
-
var __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
755
|
-
var __publicField$b = (obj, key, value) => {
|
|
756
|
-
__defNormalProp$b(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
757
|
-
return value;
|
|
758
|
-
};
|
|
759
|
-
const ALB_JWT_HEADER = "x-amzn-oidc-data";
|
|
760
|
-
const ALB_ACCESS_TOKEN_HEADER = "x-amzn-oidc-accesstoken";
|
|
761
|
-
class AwsAlbAuthProvider {
|
|
762
|
-
constructor(options) {
|
|
763
|
-
__publicField$b(this, "region");
|
|
764
|
-
__publicField$b(this, "issuer");
|
|
765
|
-
__publicField$b(this, "resolverContext");
|
|
766
|
-
__publicField$b(this, "keyCache");
|
|
767
|
-
__publicField$b(this, "authHandler");
|
|
768
|
-
__publicField$b(this, "signInResolver");
|
|
769
|
-
__publicField$b(this, "getKey", async (header) => {
|
|
770
|
-
if (!header.kid) {
|
|
771
|
-
throw new errors.AuthenticationError("No key id was specified in header");
|
|
772
|
-
}
|
|
773
|
-
const optionalCacheKey = this.keyCache.get(header.kid);
|
|
774
|
-
if (optionalCacheKey) {
|
|
775
|
-
return crypto__namespace.createPublicKey(optionalCacheKey);
|
|
776
|
-
}
|
|
777
|
-
const keyText = await fetch__default["default"](
|
|
778
|
-
`https://public-keys.auth.elb.${encodeURIComponent(
|
|
779
|
-
this.region
|
|
780
|
-
)}.amazonaws.com/${encodeURIComponent(header.kid)}`
|
|
781
|
-
).then((response) => response.text());
|
|
782
|
-
const keyValue = crypto__namespace.createPublicKey(keyText);
|
|
783
|
-
this.keyCache.set(
|
|
784
|
-
header.kid,
|
|
785
|
-
keyValue.export({ format: "pem", type: "spki" })
|
|
786
|
-
);
|
|
787
|
-
return keyValue;
|
|
788
|
-
});
|
|
789
|
-
this.region = options.region;
|
|
790
|
-
this.issuer = options.issuer;
|
|
791
|
-
this.authHandler = options.authHandler;
|
|
792
|
-
this.signInResolver = options.signInResolver;
|
|
793
|
-
this.resolverContext = options.resolverContext;
|
|
794
|
-
this.keyCache = new NodeCache__default["default"]({ stdTTL: 3600 });
|
|
795
|
-
}
|
|
796
|
-
frameHandler() {
|
|
797
|
-
return Promise.resolve(void 0);
|
|
798
|
-
}
|
|
799
|
-
async refresh(req, res) {
|
|
800
|
-
try {
|
|
801
|
-
const result = await this.getResult(req);
|
|
802
|
-
const response = await this.handleResult(result);
|
|
803
|
-
res.json(response);
|
|
804
|
-
} catch (e) {
|
|
805
|
-
throw new errors.AuthenticationError(
|
|
806
|
-
"Exception occurred during AWS ALB token refresh",
|
|
807
|
-
e
|
|
808
|
-
);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
start() {
|
|
812
|
-
return Promise.resolve(void 0);
|
|
813
|
-
}
|
|
814
|
-
async getResult(req) {
|
|
815
|
-
const jwt = req.header(ALB_JWT_HEADER);
|
|
816
|
-
const accessToken = req.header(ALB_ACCESS_TOKEN_HEADER);
|
|
817
|
-
if (jwt === void 0) {
|
|
818
|
-
throw new errors.AuthenticationError(
|
|
819
|
-
`Missing ALB OIDC header: ${ALB_JWT_HEADER}`
|
|
820
|
-
);
|
|
821
|
-
}
|
|
822
|
-
if (accessToken === void 0) {
|
|
823
|
-
throw new errors.AuthenticationError(
|
|
824
|
-
`Missing ALB OIDC header: ${ALB_ACCESS_TOKEN_HEADER}`
|
|
825
|
-
);
|
|
826
|
-
}
|
|
827
|
-
try {
|
|
828
|
-
const verifyResult = await jose.jwtVerify(jwt, this.getKey);
|
|
829
|
-
const claims = verifyResult.payload;
|
|
830
|
-
if (this.issuer && claims.iss !== this.issuer) {
|
|
831
|
-
throw new errors.AuthenticationError("Issuer mismatch on JWT token");
|
|
832
|
-
}
|
|
833
|
-
const fullProfile = {
|
|
834
|
-
provider: "unknown",
|
|
835
|
-
id: claims.sub,
|
|
836
|
-
displayName: claims.name,
|
|
837
|
-
username: claims.email.split("@")[0].toLowerCase(),
|
|
838
|
-
name: {
|
|
839
|
-
familyName: claims.family_name,
|
|
840
|
-
givenName: claims.given_name
|
|
841
|
-
},
|
|
842
|
-
emails: [{ value: claims.email.toLowerCase() }],
|
|
843
|
-
photos: [{ value: claims.picture }]
|
|
844
|
-
};
|
|
845
|
-
return {
|
|
846
|
-
fullProfile,
|
|
847
|
-
expiresInSeconds: claims.exp,
|
|
848
|
-
accessToken
|
|
849
|
-
};
|
|
850
|
-
} catch (e) {
|
|
851
|
-
throw new Error(`Exception occurred during JWT processing: ${e}`);
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
async handleResult(result) {
|
|
855
|
-
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
856
|
-
const backstageIdentity = await this.signInResolver(
|
|
857
|
-
{
|
|
858
|
-
result,
|
|
859
|
-
profile
|
|
860
|
-
},
|
|
861
|
-
this.resolverContext
|
|
862
|
-
);
|
|
863
|
-
return {
|
|
864
|
-
providerInfo: {
|
|
865
|
-
accessToken: result.accessToken,
|
|
866
|
-
expiresInSeconds: result.expiresInSeconds
|
|
867
|
-
},
|
|
868
|
-
backstageIdentity: prepareBackstageIdentityResponse(backstageIdentity),
|
|
869
|
-
profile
|
|
870
|
-
};
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
732
|
const awsAlb = createAuthProviderIntegration({
|
|
874
733
|
create(options) {
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
);
|
|
882
|
-
}
|
|
883
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
884
|
-
profile: makeProfileInfo(fullProfile)
|
|
885
|
-
});
|
|
886
|
-
return new AwsAlbAuthProvider({
|
|
887
|
-
region,
|
|
888
|
-
issuer,
|
|
889
|
-
signInResolver: options == null ? void 0 : options.signIn.resolver,
|
|
890
|
-
authHandler,
|
|
891
|
-
resolverContext
|
|
892
|
-
});
|
|
893
|
-
};
|
|
734
|
+
var _a;
|
|
735
|
+
return pluginAuthNode.createProxyAuthProviderFactory({
|
|
736
|
+
authenticator: pluginAuthBackendModuleAwsAlbProvider.awsAlbAuthenticator,
|
|
737
|
+
profileTransform: options == null ? void 0 : options.authHandler,
|
|
738
|
+
signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver
|
|
739
|
+
});
|
|
894
740
|
}
|
|
895
741
|
});
|
|
896
742
|
|
|
@@ -1565,9 +1411,10 @@ class SamlAuthProvider {
|
|
|
1565
1411
|
this.signInResolver = options.signInResolver;
|
|
1566
1412
|
this.authHandler = options.authHandler;
|
|
1567
1413
|
this.resolverContext = options.resolverContext;
|
|
1568
|
-
|
|
1569
|
-
done(
|
|
1570
|
-
}
|
|
1414
|
+
const verifier = (profile, done) => {
|
|
1415
|
+
done(null, { fullProfile: profile });
|
|
1416
|
+
};
|
|
1417
|
+
this.strategy = new passportSaml.Strategy(options, verifier, verifier);
|
|
1571
1418
|
}
|
|
1572
1419
|
async start(req, res) {
|
|
1573
1420
|
const { url } = await executeRedirectStrategy(req, this.strategy, {});
|
|
@@ -1624,7 +1471,7 @@ const saml = createAuthProviderIntegration({
|
|
|
1624
1471
|
callbackUrl: `${globalConfig.baseUrl}/${providerId}/handler/frame`,
|
|
1625
1472
|
entryPoint: config.getString("entryPoint"),
|
|
1626
1473
|
logoutUrl: config.getOptionalString("logoutUrl"),
|
|
1627
|
-
audience: config.
|
|
1474
|
+
audience: config.getString("audience"),
|
|
1628
1475
|
issuer: config.getString("issuer"),
|
|
1629
1476
|
cert: config.getString("cert"),
|
|
1630
1477
|
privateKey: config.getOptionalString("privateKey"),
|
|
@@ -1634,6 +1481,10 @@ const saml = createAuthProviderIntegration({
|
|
|
1634
1481
|
signatureAlgorithm: config.getOptionalString("signatureAlgorithm"),
|
|
1635
1482
|
digestAlgorithm: config.getOptionalString("digestAlgorithm"),
|
|
1636
1483
|
acceptedClockSkewMs: config.getOptionalNumber("acceptedClockSkewMs"),
|
|
1484
|
+
wantAuthnResponseSigned: config.getOptionalBoolean(
|
|
1485
|
+
"wantAuthnResponseSigned"
|
|
1486
|
+
),
|
|
1487
|
+
wantAssertionsSigned: config.getOptionalBoolean("wantAssertionsSigned"),
|
|
1637
1488
|
appUrl: globalConfig.appUrl,
|
|
1638
1489
|
authHandler,
|
|
1639
1490
|
signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
|
|
@@ -1991,7 +1842,18 @@ function createOidcRouter(options) {
|
|
|
1991
1842
|
jwks_uri: `${baseUrl}/.well-known/jwks.json`,
|
|
1992
1843
|
response_types_supported: ["id_token"],
|
|
1993
1844
|
subject_types_supported: ["public"],
|
|
1994
|
-
id_token_signing_alg_values_supported: [
|
|
1845
|
+
id_token_signing_alg_values_supported: [
|
|
1846
|
+
"RS256",
|
|
1847
|
+
"RS384",
|
|
1848
|
+
"RS512",
|
|
1849
|
+
"ES256",
|
|
1850
|
+
"ES384",
|
|
1851
|
+
"ES512",
|
|
1852
|
+
"PS256",
|
|
1853
|
+
"PS384",
|
|
1854
|
+
"PS512",
|
|
1855
|
+
"EdDSA"
|
|
1856
|
+
],
|
|
1995
1857
|
scopes_supported: ["openid"],
|
|
1996
1858
|
token_endpoint_auth_methods_supported: [],
|
|
1997
1859
|
claims_supported: ["sub"],
|
|
@@ -2020,6 +1882,7 @@ var __publicField$4 = (obj, key, value) => {
|
|
|
2020
1882
|
return value;
|
|
2021
1883
|
};
|
|
2022
1884
|
const MS_IN_S$1 = 1e3;
|
|
1885
|
+
const MAX_TOKEN_LENGTH = 32768;
|
|
2023
1886
|
class TokenFactory {
|
|
2024
1887
|
constructor(options) {
|
|
2025
1888
|
__publicField$4(this, "issuer");
|
|
@@ -2054,7 +1917,16 @@ class TokenFactory {
|
|
|
2054
1917
|
if (!key.alg) {
|
|
2055
1918
|
throw new errors.AuthenticationError("No algorithm was provided in the key");
|
|
2056
1919
|
}
|
|
2057
|
-
|
|
1920
|
+
const claims = { ...additionalClaims, iss, sub, ent, aud, iat, exp };
|
|
1921
|
+
const token = await new jose.SignJWT(claims).setProtectedHeader({ alg: key.alg, kid: key.kid }).setIssuer(iss).setAudience(aud).setSubject(sub).setIssuedAt(iat).setExpirationTime(exp).sign(await jose.importJWK(key));
|
|
1922
|
+
if (token.length > MAX_TOKEN_LENGTH) {
|
|
1923
|
+
throw new Error(
|
|
1924
|
+
`Failed to issue a new user token. The resulting token is excessively large, with either too many ownership claims or too large custom claims. You likely have a bug either in the sign-in resolver or catalog data. The following claims were requested: '${JSON.stringify(
|
|
1925
|
+
claims
|
|
1926
|
+
)}'`
|
|
1927
|
+
);
|
|
1928
|
+
}
|
|
1929
|
+
return token;
|
|
2058
1930
|
}
|
|
2059
1931
|
// This will be called by other services that want to verify ID tokens.
|
|
2060
1932
|
// It is important that it returns a list of all public keys that could
|
|
@@ -2631,7 +2503,25 @@ _database = new WeakMap();
|
|
|
2631
2503
|
_promise = new WeakMap();
|
|
2632
2504
|
let AuthDatabase = _AuthDatabase;
|
|
2633
2505
|
|
|
2634
|
-
const
|
|
2506
|
+
const TOKEN_EXP_DEFAULT_S = 3600;
|
|
2507
|
+
const TOKEN_EXP_MIN_S = 600;
|
|
2508
|
+
const TOKEN_EXP_MAX_S = 86400;
|
|
2509
|
+
function readBackstageTokenExpiration(config$1) {
|
|
2510
|
+
const processingIntervalKey = "auth.backstageTokenExpiration";
|
|
2511
|
+
if (!config$1.has(processingIntervalKey)) {
|
|
2512
|
+
return TOKEN_EXP_DEFAULT_S;
|
|
2513
|
+
}
|
|
2514
|
+
const duration = config.readDurationFromConfig(config$1, {
|
|
2515
|
+
key: processingIntervalKey
|
|
2516
|
+
});
|
|
2517
|
+
const durationS = Math.round(types.durationToMilliseconds(duration) / 1e3);
|
|
2518
|
+
if (durationS < TOKEN_EXP_MIN_S) {
|
|
2519
|
+
return TOKEN_EXP_MIN_S;
|
|
2520
|
+
} else if (durationS > TOKEN_EXP_MAX_S) {
|
|
2521
|
+
return TOKEN_EXP_MAX_S;
|
|
2522
|
+
}
|
|
2523
|
+
return durationS;
|
|
2524
|
+
}
|
|
2635
2525
|
|
|
2636
2526
|
var __defProp = Object.defineProperty;
|
|
2637
2527
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -2698,8 +2588,8 @@ async function createRouter(options) {
|
|
|
2698
2588
|
const router = Router__default["default"]();
|
|
2699
2589
|
const appUrl = config.getString("app.baseUrl");
|
|
2700
2590
|
const authUrl = await discovery.getExternalBaseUrl("auth");
|
|
2591
|
+
const backstageTokenExpiration = readBackstageTokenExpiration(config);
|
|
2701
2592
|
const authDb = AuthDatabase.create(database);
|
|
2702
|
-
const sessionExpirationSeconds = BACKSTAGE_SESSION_EXPIRATION;
|
|
2703
2593
|
const keyStore = await KeyStores.fromConfig(config, {
|
|
2704
2594
|
logger,
|
|
2705
2595
|
database: authDb
|
|
@@ -2710,7 +2600,7 @@ async function createRouter(options) {
|
|
|
2710
2600
|
{
|
|
2711
2601
|
logger: logger.child({ component: "token-factory" }),
|
|
2712
2602
|
issuer: authUrl,
|
|
2713
|
-
sessionExpirationSeconds
|
|
2603
|
+
sessionExpirationSeconds: backstageTokenExpiration
|
|
2714
2604
|
},
|
|
2715
2605
|
keyStore
|
|
2716
2606
|
);
|
|
@@ -2718,7 +2608,7 @@ async function createRouter(options) {
|
|
|
2718
2608
|
tokenIssuer = new TokenFactory({
|
|
2719
2609
|
issuer: authUrl,
|
|
2720
2610
|
keyStore,
|
|
2721
|
-
keyDurationSeconds:
|
|
2611
|
+
keyDurationSeconds: backstageTokenExpiration,
|
|
2722
2612
|
logger: logger.child({ component: "token-factory" }),
|
|
2723
2613
|
algorithm: tokenFactoryAlgorithm != null ? tokenFactoryAlgorithm : config.getOptionalString("auth.identityTokenAlgorithm")
|
|
2724
2614
|
});
|