@backstage/plugin-auth-backend 0.20.4-next.1 → 0.21.0-next.3

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 CHANGED
@@ -1,5 +1,73 @@
1
1
  # @backstage/plugin-auth-backend
2
2
 
3
+ ## 0.21.0-next.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 8321c97: Added `experimentalExtraAllowedOrigins` to config
8
+ - Updated dependencies
9
+ - @backstage/backend-common@0.21.0-next.3
10
+ - @backstage/plugin-auth-backend-module-oidc-provider@0.1.0-next.3
11
+ - @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.2-next.3
12
+ - @backstage/plugin-auth-backend-module-atlassian-provider@0.1.2-next.3
13
+ - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.5-next.3
14
+ - @backstage/plugin-auth-backend-module-github-provider@0.1.7-next.3
15
+ - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.7-next.3
16
+ - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.7-next.3
17
+ - @backstage/plugin-auth-backend-module-okta-provider@0.0.3-next.3
18
+ - @backstage/plugin-catalog-node@1.6.2-next.3
19
+ - @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.0-next.2
20
+ - @backstage/plugin-auth-node@0.4.4-next.3
21
+ - @backstage/backend-plugin-api@0.6.10-next.3
22
+ - @backstage/catalog-client@1.6.0-next.1
23
+ - @backstage/catalog-model@1.4.4-next.0
24
+ - @backstage/config@1.1.1
25
+ - @backstage/errors@1.2.3
26
+ - @backstage/types@1.1.1
27
+ - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.4-next.3
28
+ - @backstage/plugin-auth-backend-module-google-provider@0.1.7-next.3
29
+
30
+ ## 0.21.0-next.2
31
+
32
+ ### Minor Changes
33
+
34
+ - 7dd8463: **BREAKING**: The `saml` provider has been migrated from `passport-saml` to `@node-saml/passport-saml`.
35
+
36
+ This comes with breaking changes to config options:
37
+
38
+ - `audience` is now mandatory
39
+ - `wantAuthnResponseSigned` is now exposed and defaults to `true`
40
+ - `wantAssertionsSigned` is now exposed and defaults to `true`
41
+
42
+ ### Patch Changes
43
+
44
+ - 97f8724: Support additional algorithms in the `/.well-known/openid-configuration` endpoint.
45
+ - a9e0107: The auth backend will now refuse to issue user tokens are excessively large.
46
+ - d4cc552: The helper function `makeProfileInfo` and `PassportHelpers.transformProfile`
47
+ were refactored to use the `jose` library.
48
+ - 8e8a25d: Ability for user to configure backstage token expiration
49
+ - Updated dependencies
50
+ - @backstage/backend-common@0.21.0-next.2
51
+ - @backstage/backend-plugin-api@0.6.10-next.2
52
+ - @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.0-next.1
53
+ - @backstage/plugin-auth-node@0.4.4-next.2
54
+ - @backstage/plugin-auth-backend-module-atlassian-provider@0.1.2-next.2
55
+ - @backstage/plugin-auth-backend-module-github-provider@0.1.7-next.2
56
+ - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.7-next.2
57
+ - @backstage/plugin-auth-backend-module-google-provider@0.1.7-next.2
58
+ - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.5-next.2
59
+ - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.7-next.2
60
+ - @backstage/plugin-auth-backend-module-oidc-provider@0.1.0-next.2
61
+ - @backstage/plugin-auth-backend-module-okta-provider@0.0.3-next.2
62
+ - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.4-next.2
63
+ - @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.2-next.2
64
+ - @backstage/plugin-catalog-node@1.6.2-next.2
65
+ - @backstage/config@1.1.1
66
+ - @backstage/catalog-client@1.6.0-next.1
67
+ - @backstage/catalog-model@1.4.4-next.0
68
+ - @backstage/errors@1.2.3
69
+ - @backstage/types@1.1.1
70
+
3
71
  ## 0.20.4-next.1
4
72
 
5
73
  ### 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,14 @@ export interface Config {
184
186
  cfaccess?: {
185
187
  teamName: string;
186
188
  };
189
+ /**
190
+ * The backstage token expiration.
191
+ */
192
+ backstageTokenExpiration?: HumanDuration;
187
193
  };
194
+ /**
195
+ * Additional app origins to allow for authenticating
196
+ */
197
+ experimentalExtraAllowedOrigins?: string[];
188
198
  };
189
199
  }
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');
16
+ var jose = require('jose');
17
17
  var pluginAuthBackendModuleAwsAlbProvider = require('@backstage/plugin-auth-backend-module-aws-alb-provider');
18
18
  var passportBitbucketOauth2 = require('passport-bitbucket-oauth2');
19
19
  var fetch = require('node-fetch');
20
- var jose = require('jose');
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,6 +42,7 @@ 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
 
@@ -51,7 +51,6 @@ var Router__default = /*#__PURE__*/_interopDefaultLegacy(Router);
51
51
  var cookieParser__default = /*#__PURE__*/_interopDefaultLegacy(cookieParser);
52
52
  var Auth0InternalStrategy__default = /*#__PURE__*/_interopDefaultLegacy(Auth0InternalStrategy);
53
53
  var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
54
- var jwtDecoder__default = /*#__PURE__*/_interopDefaultLegacy(jwtDecoder);
55
54
  var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
56
55
  var session__default = /*#__PURE__*/_interopDefaultLegacy(session);
57
56
  var connectSessionKnex__default = /*#__PURE__*/_interopDefaultLegacy(connectSessionKnex);
@@ -450,7 +449,7 @@ const makeProfileInfo = (profile, idToken) => {
450
449
  let displayName = (_b = (_a = profile.displayName) != null ? _a : profile.username) != null ? _b : profile.id;
451
450
  if ((!email || !picture || !displayName) && idToken) {
452
451
  try {
453
- const decoded = jwtDecoder__default["default"](idToken);
452
+ const decoded = jose.decodeJwt(idToken);
454
453
  if (!email && decoded.email) {
455
454
  email = decoded.email;
456
455
  }
@@ -1412,9 +1411,10 @@ class SamlAuthProvider {
1412
1411
  this.signInResolver = options.signInResolver;
1413
1412
  this.authHandler = options.authHandler;
1414
1413
  this.resolverContext = options.resolverContext;
1415
- this.strategy = new passportSaml.Strategy({ ...options }, (fullProfile, done) => {
1416
- done(void 0, { fullProfile });
1417
- });
1414
+ const verifier = (profile, done) => {
1415
+ done(null, { fullProfile: profile });
1416
+ };
1417
+ this.strategy = new passportSaml.Strategy(options, verifier, verifier);
1418
1418
  }
1419
1419
  async start(req, res) {
1420
1420
  const { url } = await executeRedirectStrategy(req, this.strategy, {});
@@ -1471,7 +1471,7 @@ const saml = createAuthProviderIntegration({
1471
1471
  callbackUrl: `${globalConfig.baseUrl}/${providerId}/handler/frame`,
1472
1472
  entryPoint: config.getString("entryPoint"),
1473
1473
  logoutUrl: config.getOptionalString("logoutUrl"),
1474
- audience: config.getOptionalString("audience"),
1474
+ audience: config.getString("audience"),
1475
1475
  issuer: config.getString("issuer"),
1476
1476
  cert: config.getString("cert"),
1477
1477
  privateKey: config.getOptionalString("privateKey"),
@@ -1481,6 +1481,10 @@ const saml = createAuthProviderIntegration({
1481
1481
  signatureAlgorithm: config.getOptionalString("signatureAlgorithm"),
1482
1482
  digestAlgorithm: config.getOptionalString("digestAlgorithm"),
1483
1483
  acceptedClockSkewMs: config.getOptionalNumber("acceptedClockSkewMs"),
1484
+ wantAuthnResponseSigned: config.getOptionalBoolean(
1485
+ "wantAuthnResponseSigned"
1486
+ ),
1487
+ wantAssertionsSigned: config.getOptionalBoolean("wantAssertionsSigned"),
1484
1488
  appUrl: globalConfig.appUrl,
1485
1489
  authHandler,
1486
1490
  signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
@@ -1838,7 +1842,18 @@ function createOidcRouter(options) {
1838
1842
  jwks_uri: `${baseUrl}/.well-known/jwks.json`,
1839
1843
  response_types_supported: ["id_token"],
1840
1844
  subject_types_supported: ["public"],
1841
- id_token_signing_alg_values_supported: ["RS256"],
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
+ ],
1842
1857
  scopes_supported: ["openid"],
1843
1858
  token_endpoint_auth_methods_supported: [],
1844
1859
  claims_supported: ["sub"],
@@ -1867,6 +1882,7 @@ var __publicField$4 = (obj, key, value) => {
1867
1882
  return value;
1868
1883
  };
1869
1884
  const MS_IN_S$1 = 1e3;
1885
+ const MAX_TOKEN_LENGTH = 32768;
1870
1886
  class TokenFactory {
1871
1887
  constructor(options) {
1872
1888
  __publicField$4(this, "issuer");
@@ -1901,7 +1917,16 @@ class TokenFactory {
1901
1917
  if (!key.alg) {
1902
1918
  throw new errors.AuthenticationError("No algorithm was provided in the key");
1903
1919
  }
1904
- return new jose.SignJWT({ ...additionalClaims, iss, sub, ent, aud, iat, exp }).setProtectedHeader({ alg: key.alg, kid: key.kid }).setIssuer(iss).setAudience(aud).setSubject(sub).setIssuedAt(iat).setExpirationTime(exp).sign(await jose.importJWK(key));
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;
1905
1930
  }
1906
1931
  // This will be called by other services that want to verify ID tokens.
1907
1932
  // It is important that it returns a list of all public keys that could
@@ -2478,7 +2503,25 @@ _database = new WeakMap();
2478
2503
  _promise = new WeakMap();
2479
2504
  let AuthDatabase = _AuthDatabase;
2480
2505
 
2481
- const BACKSTAGE_SESSION_EXPIRATION = 3600;
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
+ }
2482
2525
 
2483
2526
  var __defProp = Object.defineProperty;
2484
2527
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -2545,8 +2588,8 @@ async function createRouter(options) {
2545
2588
  const router = Router__default["default"]();
2546
2589
  const appUrl = config.getString("app.baseUrl");
2547
2590
  const authUrl = await discovery.getExternalBaseUrl("auth");
2591
+ const backstageTokenExpiration = readBackstageTokenExpiration(config);
2548
2592
  const authDb = AuthDatabase.create(database);
2549
- const sessionExpirationSeconds = BACKSTAGE_SESSION_EXPIRATION;
2550
2593
  const keyStore = await KeyStores.fromConfig(config, {
2551
2594
  logger,
2552
2595
  database: authDb
@@ -2557,7 +2600,7 @@ async function createRouter(options) {
2557
2600
  {
2558
2601
  logger: logger.child({ component: "token-factory" }),
2559
2602
  issuer: authUrl,
2560
- sessionExpirationSeconds
2603
+ sessionExpirationSeconds: backstageTokenExpiration
2561
2604
  },
2562
2605
  keyStore
2563
2606
  );
@@ -2565,7 +2608,7 @@ async function createRouter(options) {
2565
2608
  tokenIssuer = new TokenFactory({
2566
2609
  issuer: authUrl,
2567
2610
  keyStore,
2568
- keyDurationSeconds: sessionExpirationSeconds,
2611
+ keyDurationSeconds: backstageTokenExpiration,
2569
2612
  logger: logger.child({ component: "token-factory" }),
2570
2613
  algorithm: tokenFactoryAlgorithm != null ? tokenFactoryAlgorithm : config.getOptionalString("auth.identityTokenAlgorithm")
2571
2614
  });