@backstage/plugin-auth-backend 0.13.0 → 0.13.1-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @backstage/plugin-auth-backend
2
2
 
3
+ ## 0.13.1-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - cfc0f19699: Updated dependency `fs-extra` to `10.1.0`.
8
+ - 787ae0d541: Add more common predefined sign-in resolvers to auth providers.
9
+
10
+ Add the existing resolver to more providers (already available at `google`):
11
+
12
+ - `providers.microsoft.resolvers.emailLocalPartMatchingUserEntityName()`
13
+ - `providers.okta.resolvers.emailLocalPartMatchingUserEntityName()`
14
+
15
+ Add a new resolver for simple email-to-email matching:
16
+
17
+ - `providers.google.resolvers.emailMatchingUserEntityProfileEmail()`
18
+ - `providers.microsoft.resolvers.emailMatchingUserEntityProfileEmail()`
19
+ - `providers.okta.resolvers.emailMatchingUserEntityProfileEmail()`
20
+
21
+ - 9ec4e0613e: Update to `jose` 4.6.0
22
+ - Updated dependencies
23
+ - @backstage/backend-common@0.13.3-next.0
24
+ - @backstage/plugin-auth-node@0.2.1-next.0
25
+
3
26
  ## 0.13.0
4
27
 
5
28
  ### Minor Changes
package/dist/index.cjs.js CHANGED
@@ -763,10 +763,6 @@ const createAuth0Provider = auth0.create;
763
763
 
764
764
  const ALB_JWT_HEADER = "x-amzn-oidc-data";
765
765
  const ALB_ACCESS_TOKEN_HEADER = "x-amzn-oidc-accesstoken";
766
- const getJWTHeaders = (input) => {
767
- const encoded = input.split(".")[0];
768
- return JSON.parse(Buffer.from(encoded, "base64").toString("utf8"));
769
- };
770
766
  class AwsAlbAuthProvider {
771
767
  constructor(options) {
772
768
  this.region = options.region;
@@ -801,9 +797,8 @@ class AwsAlbAuthProvider {
801
797
  throw new errors.AuthenticationError(`Missing ALB OIDC header: ${ALB_ACCESS_TOKEN_HEADER}`);
802
798
  }
803
799
  try {
804
- const headers = getJWTHeaders(jwt);
805
- const key = await this.getKey(headers.kid);
806
- const claims = jose.JWT.verify(jwt, key);
800
+ const verifyResult = await jose.jwtVerify(jwt, this.getKey);
801
+ const claims = verifyResult.payload;
807
802
  if (this.issuer && claims.iss !== this.issuer) {
808
803
  throw new errors.AuthenticationError("Issuer mismatch on JWT token");
809
804
  }
@@ -843,14 +838,17 @@ class AwsAlbAuthProvider {
843
838
  profile
844
839
  };
845
840
  }
846
- async getKey(keyId) {
847
- const optionalCacheKey = this.keyCache.get(keyId);
841
+ async getKey(header) {
842
+ if (!header.kid) {
843
+ throw new errors.AuthenticationError("No key id was specified in header");
844
+ }
845
+ const optionalCacheKey = this.keyCache.get(header.kid);
848
846
  if (optionalCacheKey) {
849
847
  return crypto__namespace.createPublicKey(optionalCacheKey);
850
848
  }
851
- const keyText = await fetch__default["default"](`https://public-keys.auth.elb.${encodeURIComponent(this.region)}.amazonaws.com/${encodeURIComponent(keyId)}`).then((response) => response.text());
849
+ const keyText = await fetch__default["default"](`https://public-keys.auth.elb.${encodeURIComponent(this.region)}.amazonaws.com/${encodeURIComponent(header.kid)}`).then((response) => response.text());
852
850
  const keyValue = crypto__namespace.createPublicKey(keyText);
853
- this.keyCache.set(keyId, keyValue.export({ format: "pem", type: "spki" }));
851
+ this.keyCache.set(header.kid, keyValue.export({ format: "pem", type: "spki" }));
854
852
  return keyValue;
855
853
  }
856
854
  }
@@ -1257,6 +1255,17 @@ const commonByEmailLocalPartResolver = async (info, ctx) => {
1257
1255
  entityRef: { name: localPart }
1258
1256
  });
1259
1257
  };
1258
+ const commonByEmailResolver = async (info, ctx) => {
1259
+ const { profile } = info;
1260
+ if (!profile.email) {
1261
+ throw new Error("Login failed, user profile does not contain an email");
1262
+ }
1263
+ return ctx.signInWithCatalogUser({
1264
+ filter: {
1265
+ "spec.profile.email": profile.email
1266
+ }
1267
+ });
1268
+ };
1260
1269
 
1261
1270
  class GoogleAuthProvider {
1262
1271
  constructor(options) {
@@ -1354,6 +1363,7 @@ const google = createAuthProviderIntegration({
1354
1363
  },
1355
1364
  resolvers: {
1356
1365
  emailLocalPartMatchingUserEntityName: () => commonByEmailLocalPartResolver,
1366
+ emailMatchingUserEntityProfileEmail: () => commonByEmailResolver,
1357
1367
  emailMatchingUserEntityAnnotation() {
1358
1368
  return async (info, ctx) => {
1359
1369
  const { profile } = info;
@@ -1483,6 +1493,8 @@ const microsoft = createAuthProviderIntegration({
1483
1493
  });
1484
1494
  },
1485
1495
  resolvers: {
1496
+ emailLocalPartMatchingUserEntityName: () => commonByEmailLocalPartResolver,
1497
+ emailMatchingUserEntityProfileEmail: () => commonByEmailResolver,
1486
1498
  emailMatchingUserEntityAnnotation() {
1487
1499
  return async (info, ctx) => {
1488
1500
  const { profile } = info;
@@ -1659,7 +1671,7 @@ class Oauth2ProxyAuthProvider {
1659
1671
  if (!jwt) {
1660
1672
  throw new errors.AuthenticationError(`Missing or in incorrect format - Oauth2Proxy OIDC header: ${OAUTH2_PROXY_JWT_HEADER}`);
1661
1673
  }
1662
- const decodedJWT = jose.JWT.decode(jwt);
1674
+ const decodedJWT = jose.decodeJwt(jwt);
1663
1675
  return {
1664
1676
  fullProfile: decodedJWT,
1665
1677
  accessToken: jwt
@@ -1919,6 +1931,8 @@ const okta = createAuthProviderIntegration({
1919
1931
  });
1920
1932
  },
1921
1933
  resolvers: {
1934
+ emailLocalPartMatchingUserEntityName: () => commonByEmailLocalPartResolver,
1935
+ emailMatchingUserEntityProfileEmail: () => commonByEmailResolver,
1922
1936
  emailMatchingUserEntityAnnotation() {
1923
1937
  return async (info, ctx) => {
1924
1938
  const { profile } = info;
@@ -2299,10 +2313,10 @@ class TokenFactory {
2299
2313
  throw new Error('"sub" claim provided by the auth resolver is not a valid EntityRef.');
2300
2314
  }
2301
2315
  this.logger.info(`Issuing token for ${sub}, with entities ${ent != null ? ent : []}`);
2302
- return jose.JWS.sign({ iss, sub, aud, iat, exp, ent }, key, {
2303
- alg: key.alg,
2304
- kid: key.kid
2305
- });
2316
+ if (!key.alg) {
2317
+ throw new errors.AuthenticationError("No algorithm was provided in the key");
2318
+ }
2319
+ return new jose.SignJWT({ iss, sub, 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));
2306
2320
  }
2307
2321
  async listPublicKeys() {
2308
2322
  const { items: keys } = await this.keyStore.listKeys();
@@ -2339,14 +2353,14 @@ class TokenFactory {
2339
2353
  seconds: this.keyDurationSeconds
2340
2354
  }).toJSDate();
2341
2355
  const promise = (async () => {
2342
- const key = await jose.JWK.generate("EC", "P-256", {
2343
- use: "sig",
2344
- kid: uuid.v4(),
2345
- alg: "ES256"
2346
- });
2347
- this.logger.info(`Created new signing key ${key.kid}`);
2348
- await this.keyStore.addKey(key.toJWK(false));
2349
- return key;
2356
+ const key = await jose.generateKeyPair("ES256");
2357
+ const publicKey = await jose.exportJWK(key.publicKey);
2358
+ const privateKey = await jose.exportJWK(key.privateKey);
2359
+ publicKey.kid = privateKey.kid = uuid.v4();
2360
+ publicKey.alg = privateKey.alg = "ES256";
2361
+ this.logger.info(`Created new signing key ${publicKey.kid}`);
2362
+ await this.keyStore.addKey(publicKey);
2363
+ return privateKey;
2350
2364
  })();
2351
2365
  this.privateKeyPromise = promise;
2352
2366
  try {