@backstage/plugin-auth-backend 0.22.6-next.3 → 0.22.7

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.22.7
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/backend-common@0.23.1
9
+ - @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.12
10
+ - @backstage/plugin-auth-backend-module-oidc-provider@0.2.1
11
+ - @backstage/plugin-auth-node@0.4.15
12
+ - @backstage/plugin-auth-backend-module-atlassian-provider@0.2.1
13
+ - @backstage/plugin-auth-backend-module-bitbucket-provider@0.1.3
14
+ - @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.1.3
15
+ - @backstage/plugin-auth-backend-module-github-provider@0.1.17
16
+ - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.17
17
+ - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.15
18
+ - @backstage/plugin-auth-backend-module-oauth2-provider@0.2.1
19
+ - @backstage/plugin-auth-backend-module-okta-provider@0.0.13
20
+ - @backstage/plugin-auth-backend-module-onelogin-provider@0.1.1
21
+ - @backstage/backend-plugin-api@0.6.20
22
+ - @backstage/catalog-client@1.6.5
23
+ - @backstage/catalog-model@1.5.0
24
+ - @backstage/config@1.2.0
25
+ - @backstage/errors@1.2.4
26
+ - @backstage/types@1.1.1
27
+ - @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.1.3
28
+ - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.15
29
+ - @backstage/plugin-auth-backend-module-google-provider@0.1.17
30
+ - @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.13
31
+ - @backstage/plugin-catalog-node@1.12.2
32
+
33
+ ## 0.22.6
34
+
35
+ ### Patch Changes
36
+
37
+ - 3e823d3: Limited user tokens will no longer include the `ent` field in its payload. Ownership claims will now be fetched from the user info service.
38
+
39
+ NOTE: Limited tokens issued prior to this change will no longer be valid. Users may have to clear their browser cookies in order to refresh their auth tokens.
40
+
41
+ - 8869b8e: Updated local development setup.
42
+ - 78a0b08: Internal refactor to handle `BackendFeature` contract change.
43
+ - d44a20a: Added additional plugin metadata to `package.json`.
44
+ - 3e1bb15: Updated to use the new `@backstage/plugin-auth-backend-module-onelogin-provider` implementation
45
+ - Updated dependencies
46
+ - @backstage/backend-common@0.23.0
47
+ - @backstage/plugin-auth-backend-module-onelogin-provider@0.1.0
48
+ - @backstage/backend-plugin-api@0.6.19
49
+ - @backstage/plugin-auth-node@0.4.14
50
+ - @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.1.2
51
+ - @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.1.2
52
+ - @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.12
53
+ - @backstage/plugin-auth-backend-module-atlassian-provider@0.2.0
54
+ - @backstage/plugin-auth-backend-module-bitbucket-provider@0.1.2
55
+ - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.14
56
+ - @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.11
57
+ - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.14
58
+ - @backstage/plugin-auth-backend-module-github-provider@0.1.16
59
+ - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.16
60
+ - @backstage/plugin-auth-backend-module-google-provider@0.1.16
61
+ - @backstage/plugin-auth-backend-module-oauth2-provider@0.2.0
62
+ - @backstage/plugin-auth-backend-module-oidc-provider@0.2.0
63
+ - @backstage/plugin-auth-backend-module-okta-provider@0.0.12
64
+ - @backstage/plugin-catalog-node@1.12.1
65
+ - @backstage/catalog-client@1.6.5
66
+ - @backstage/catalog-model@1.5.0
67
+ - @backstage/config@1.2.0
68
+ - @backstage/errors@1.2.4
69
+ - @backstage/types@1.1.1
70
+
3
71
  ## 0.22.6-next.3
4
72
 
5
73
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -35,10 +35,10 @@ var catalogClient = require('@backstage/catalog-client');
35
35
  var minimatch = require('minimatch');
36
36
  var catalogModel = require('@backstage/catalog-model');
37
37
  var backendCommon = require('@backstage/backend-common');
38
+ var lodash = require('lodash');
38
39
  var luxon = require('luxon');
39
40
  var uuid = require('uuid');
40
41
  var firestore = require('@google-cloud/firestore');
41
- var lodash = require('lodash');
42
42
  var fs = require('fs');
43
43
  var session = require('express-session');
44
44
  var connectSessionKnex = require('connect-session-knex');
@@ -1579,7 +1579,7 @@ function createOriginFilter(config) {
1579
1579
  }
1580
1580
 
1581
1581
  function bindOidcRouter(targetRouter, options) {
1582
- const { baseUrl, auth, tokenIssuer } = options;
1582
+ const { baseUrl, auth, tokenIssuer, userInfoDatabaseHandler } = options;
1583
1583
  const router = Router__default.default();
1584
1584
  targetRouter.use(router);
1585
1585
  const config = {
@@ -1630,16 +1630,16 @@ function bindOidcRouter(targetRouter, options) {
1630
1630
  "Userinfo endpoint must be called with a token that represents a user principal"
1631
1631
  );
1632
1632
  }
1633
- const { sub: userEntityRef, ent: ownershipEntityRefs = [] } = jose.decodeJwt(token);
1633
+ const { sub: userEntityRef } = jose.decodeJwt(token);
1634
1634
  if (typeof userEntityRef !== "string") {
1635
1635
  throw new Error("Invalid user token, user entity ref must be a string");
1636
1636
  }
1637
- if (!Array.isArray(ownershipEntityRefs) || ownershipEntityRefs.some((ref) => typeof ref !== "string")) {
1638
- throw new Error(
1639
- "Invalid user token, ownership entity refs must be an array of strings"
1640
- );
1637
+ const userInfo = await userInfoDatabaseHandler.getUserInfo(userEntityRef);
1638
+ if (!userInfo) {
1639
+ res.status(404).send("User info not found");
1640
+ return;
1641
1641
  }
1642
- res.json({ sub: userEntityRef, ent: ownershipEntityRefs });
1642
+ res.json(userInfo);
1643
1643
  });
1644
1644
  }
1645
1645
 
@@ -1651,6 +1651,7 @@ class TokenFactory {
1651
1651
  keyStore;
1652
1652
  keyDurationSeconds;
1653
1653
  algorithm;
1654
+ userInfoDatabaseHandler;
1654
1655
  keyExpiry;
1655
1656
  privateKeyPromise;
1656
1657
  constructor(options) {
@@ -1659,6 +1660,7 @@ class TokenFactory {
1659
1660
  this.keyStore = options.keyStore;
1660
1661
  this.keyDurationSeconds = options.keyDurationSeconds;
1661
1662
  this.algorithm = options.algorithm ?? "ES256";
1663
+ this.userInfoDatabaseHandler = options.userInfoDatabaseHandler;
1662
1664
  }
1663
1665
  async issueToken(params) {
1664
1666
  const key = await this.getKey();
@@ -1685,7 +1687,7 @@ class TokenFactory {
1685
1687
  alg: key.alg,
1686
1688
  kid: key.kid
1687
1689
  },
1688
- payload: { sub, ent, iat, exp },
1690
+ payload: { sub, iat, exp },
1689
1691
  key: signingKey
1690
1692
  });
1691
1693
  const claims = {
@@ -1710,6 +1712,9 @@ class TokenFactory {
1710
1712
  )}'`
1711
1713
  );
1712
1714
  }
1715
+ await this.userInfoDatabaseHandler.addUserInfo({
1716
+ claims: lodash.omit(claims, ["aud", "iat", "iss", "uip"])
1717
+ });
1713
1718
  return token;
1714
1719
  }
1715
1720
  // This will be called by other services that want to verify ID tokens.
@@ -1780,7 +1785,6 @@ class TokenFactory {
1780
1785
  };
1781
1786
  const payload = {
1782
1787
  sub: options.payload.sub,
1783
- ent: options.payload.ent,
1784
1788
  iat: options.payload.iat,
1785
1789
  exp: options.payload.exp
1786
1790
  };
@@ -1791,7 +1795,7 @@ class TokenFactory {
1791
1795
  }
1792
1796
  }
1793
1797
 
1794
- const TABLE = "signing_keys";
1798
+ const TABLE$1 = "signing_keys";
1795
1799
  const parseDate = (date) => {
1796
1800
  const parsedDate = typeof date === "string" ? luxon.DateTime.fromSQL(date, { zone: "UTC" }) : luxon.DateTime.fromJSDate(date);
1797
1801
  if (!parsedDate.isValid) {
@@ -1806,13 +1810,13 @@ class DatabaseKeyStore {
1806
1810
  this.client = client;
1807
1811
  }
1808
1812
  async addKey(key) {
1809
- await this.client(TABLE).insert({
1813
+ await this.client(TABLE$1).insert({
1810
1814
  kid: key.kid,
1811
1815
  key: JSON.stringify(key)
1812
1816
  });
1813
1817
  }
1814
1818
  async listKeys() {
1815
- const rows = await this.client(TABLE).select();
1819
+ const rows = await this.client(TABLE$1).select();
1816
1820
  return {
1817
1821
  items: rows.map((row) => ({
1818
1822
  key: JSON.parse(row.key),
@@ -1821,7 +1825,7 @@ class DatabaseKeyStore {
1821
1825
  };
1822
1826
  }
1823
1827
  async removeKeys(kids) {
1824
- await this.client(TABLE).delete().whereIn("kid", kids);
1828
+ await this.client(TABLE$1).delete().whereIn("kid", kids);
1825
1829
  }
1826
1830
  }
1827
1831
 
@@ -2058,6 +2062,30 @@ class KeyStores {
2058
2062
  }
2059
2063
  }
2060
2064
 
2065
+ const TABLE = "user_info";
2066
+ class UserInfoDatabaseHandler {
2067
+ constructor(client) {
2068
+ this.client = client;
2069
+ }
2070
+ async addUserInfo(userInfo) {
2071
+ await this.client(TABLE).insert({
2072
+ user_entity_ref: userInfo.claims.sub,
2073
+ user_info: JSON.stringify(userInfo),
2074
+ exp: luxon.DateTime.fromSeconds(userInfo.claims.exp, {
2075
+ zone: "utc"
2076
+ }).toSQL({ includeOffset: false })
2077
+ }).onConflict("user_entity_ref").merge();
2078
+ }
2079
+ async getUserInfo(userEntityRef) {
2080
+ const info = await this.client(TABLE).where({ user_entity_ref: userEntityRef }).first();
2081
+ if (!info) {
2082
+ return void 0;
2083
+ }
2084
+ const userInfo = JSON.parse(info.user_info);
2085
+ return userInfo;
2086
+ }
2087
+ }
2088
+
2061
2089
  const migrationsDir = backendPluginApi.resolvePackagePath(
2062
2090
  "@backstage/plugin-auth-backend",
2063
2091
  "migrations"
@@ -2185,6 +2213,9 @@ async function createRouter(options) {
2185
2213
  logger,
2186
2214
  database: authDb
2187
2215
  });
2216
+ const userInfoDatabaseHandler = new UserInfoDatabaseHandler(
2217
+ await authDb.get()
2218
+ );
2188
2219
  let tokenIssuer;
2189
2220
  if (keyStore instanceof StaticKeyStore) {
2190
2221
  tokenIssuer = new StaticTokenIssuer(
@@ -2201,7 +2232,8 @@ async function createRouter(options) {
2201
2232
  keyStore,
2202
2233
  keyDurationSeconds: backstageTokenExpiration,
2203
2234
  logger: logger.child({ component: "token-factory" }),
2204
- algorithm: tokenFactoryAlgorithm ?? config.getOptionalString("auth.identityTokenAlgorithm")
2235
+ algorithm: tokenFactoryAlgorithm ?? config.getOptionalString("auth.identityTokenAlgorithm"),
2236
+ userInfoDatabaseHandler
2205
2237
  });
2206
2238
  }
2207
2239
  const secret = config.getOptionalString("auth.session.secret");
@@ -2244,7 +2276,8 @@ async function createRouter(options) {
2244
2276
  bindOidcRouter(router, {
2245
2277
  auth,
2246
2278
  tokenIssuer,
2247
- baseUrl: authUrl
2279
+ baseUrl: authUrl,
2280
+ userInfoDatabaseHandler
2248
2281
  });
2249
2282
  router.use("/:provider/", (req) => {
2250
2283
  const { provider } = req.params;