@backstage/plugin-auth-backend 0.10.2 → 0.11.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 +30 -0
- package/dist/index.cjs.js +73 -18
- package/dist/index.cjs.js.map +1 -1
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @backstage/plugin-auth-backend
|
|
2
2
|
|
|
3
|
+
## 0.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3884bf0348: **BREAKING**: The default sign-in resolvers for all providers, if you choose to
|
|
8
|
+
use them, now emit the token `sub` and `ent` claims on the standard,
|
|
9
|
+
all-lowercase form, instead of the mixed-case form. The mixed-case form causes
|
|
10
|
+
problems for implementations that naively do string comparisons on refs. The end
|
|
11
|
+
result is that you may for example see your Backstage token `sub` claim now
|
|
12
|
+
become `'user:default/my-id'` instead of `'user:default/My-ID'`.
|
|
13
|
+
|
|
14
|
+
On a related note, specifically the SAML provider now correctly issues both
|
|
15
|
+
`sub` and `ent` claims, and on the full entity ref form instead of the short
|
|
16
|
+
form with only the ID.
|
|
17
|
+
|
|
18
|
+
**NOTE**: For a long time, it has been strongly recommended that you provide
|
|
19
|
+
your own sign-in resolver instead of using the builtin ones, and that will
|
|
20
|
+
become mandatory in the future.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- d64b8d3678: chore(deps): bump `minimatch` from 3.0.4 to 5.0.0
|
|
25
|
+
- 6e1cbc12a6: Updated according to the new `getEntityFacets` catalog API method
|
|
26
|
+
- 919cf2f836: Minor updates to match the new `targetRef` field of relations, and to stop consuming the `target` field
|
|
27
|
+
- Updated dependencies
|
|
28
|
+
- @backstage/backend-common@0.11.0
|
|
29
|
+
- @backstage/catalog-model@0.11.0
|
|
30
|
+
- @backstage/catalog-client@0.7.2
|
|
31
|
+
- @backstage/plugin-auth-node@0.1.3
|
|
32
|
+
|
|
3
33
|
## 0.10.2
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -607,10 +607,10 @@ class CatalogIdentityClient {
|
|
|
607
607
|
}
|
|
608
608
|
const memberOf = entities.flatMap((e) => {
|
|
609
609
|
var _a, _b;
|
|
610
|
-
return (_b = (_a = e.relations) == null ? void 0 : _a.filter((r) => r.type === catalogModel.RELATION_MEMBER_OF).map((r) => r.
|
|
610
|
+
return (_b = (_a = e.relations) == null ? void 0 : _a.filter((r) => r.type === catalogModel.RELATION_MEMBER_OF).map((r) => r.targetRef)) != null ? _b : [];
|
|
611
611
|
});
|
|
612
612
|
const newEntityRefs = [
|
|
613
|
-
...new Set(resolvedEntityRefs.
|
|
613
|
+
...new Set(resolvedEntityRefs.map(catalogModel.stringifyEntityRef).concat(memberOf))
|
|
614
614
|
];
|
|
615
615
|
logger == null ? void 0 : logger.debug(`Found catalog membership: ${newEntityRefs.join()}`);
|
|
616
616
|
return newEntityRefs;
|
|
@@ -620,7 +620,7 @@ class CatalogIdentityClient {
|
|
|
620
620
|
function getEntityClaims(entity) {
|
|
621
621
|
var _a, _b;
|
|
622
622
|
const userRef = catalogModel.stringifyEntityRef(entity);
|
|
623
|
-
const membershipRefs = (_b = (_a = entity.relations) == null ? void 0 : _a.filter((r) => r.type === catalogModel.RELATION_MEMBER_OF && r.
|
|
623
|
+
const membershipRefs = (_b = (_a = entity.relations) == null ? void 0 : _a.filter((r) => r.type === catalogModel.RELATION_MEMBER_OF && r.targetRef.startsWith("group:")).map((r) => r.targetRef)) != null ? _b : [];
|
|
624
624
|
return {
|
|
625
625
|
sub: userRef,
|
|
626
626
|
ent: [userRef, ...membershipRefs]
|
|
@@ -1261,10 +1261,15 @@ class GithubAuthProvider {
|
|
|
1261
1261
|
const githubDefaultSignInResolver = async (info, ctx) => {
|
|
1262
1262
|
const { fullProfile } = info.result;
|
|
1263
1263
|
const userId = fullProfile.username || fullProfile.id;
|
|
1264
|
+
const entityRef = catalogModel.stringifyEntityRef({
|
|
1265
|
+
kind: "User",
|
|
1266
|
+
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
1267
|
+
name: userId
|
|
1268
|
+
});
|
|
1264
1269
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1265
1270
|
claims: {
|
|
1266
|
-
sub:
|
|
1267
|
-
ent: [
|
|
1271
|
+
sub: entityRef,
|
|
1272
|
+
ent: [entityRef]
|
|
1268
1273
|
}
|
|
1269
1274
|
});
|
|
1270
1275
|
return { id: userId, token };
|
|
@@ -1333,8 +1338,16 @@ const gitlabDefaultSignInResolver = async (info, ctx) => {
|
|
|
1333
1338
|
if (profile.email) {
|
|
1334
1339
|
id = profile.email.split("@")[0];
|
|
1335
1340
|
}
|
|
1341
|
+
const entityRef = catalogModel.stringifyEntityRef({
|
|
1342
|
+
kind: "User",
|
|
1343
|
+
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
1344
|
+
name: id
|
|
1345
|
+
});
|
|
1336
1346
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1337
|
-
claims: {
|
|
1347
|
+
claims: {
|
|
1348
|
+
sub: entityRef,
|
|
1349
|
+
ent: [entityRef]
|
|
1350
|
+
}
|
|
1338
1351
|
});
|
|
1339
1352
|
return { id, token };
|
|
1340
1353
|
};
|
|
@@ -1566,8 +1579,16 @@ const googleDefaultSignInResolver = async (info, ctx) => {
|
|
|
1566
1579
|
ctx.logger.warn(`Failed to look up user, ${error}, falling back to allowing login based on email pattern, this will probably break in the future`);
|
|
1567
1580
|
userId = profile.email.split("@")[0];
|
|
1568
1581
|
}
|
|
1582
|
+
const entityRef = catalogModel.stringifyEntityRef({
|
|
1583
|
+
kind: "User",
|
|
1584
|
+
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
1585
|
+
name: userId
|
|
1586
|
+
});
|
|
1569
1587
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1570
|
-
claims: {
|
|
1588
|
+
claims: {
|
|
1589
|
+
sub: entityRef,
|
|
1590
|
+
ent: [entityRef]
|
|
1591
|
+
}
|
|
1571
1592
|
});
|
|
1572
1593
|
return { id: userId, token };
|
|
1573
1594
|
};
|
|
@@ -1723,10 +1744,15 @@ const microsoftDefaultSignInResolver = async (info, ctx) => {
|
|
|
1723
1744
|
throw new Error("Profile contained no email");
|
|
1724
1745
|
}
|
|
1725
1746
|
const userId = profile.email.split("@")[0];
|
|
1747
|
+
const entityRef = catalogModel.stringifyEntityRef({
|
|
1748
|
+
kind: "User",
|
|
1749
|
+
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
1750
|
+
name: userId
|
|
1751
|
+
});
|
|
1726
1752
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1727
1753
|
claims: {
|
|
1728
|
-
sub:
|
|
1729
|
-
ent: [
|
|
1754
|
+
sub: entityRef,
|
|
1755
|
+
ent: [entityRef]
|
|
1730
1756
|
}
|
|
1731
1757
|
});
|
|
1732
1758
|
return { id: userId, token };
|
|
@@ -1868,14 +1894,22 @@ class OAuth2AuthProvider {
|
|
|
1868
1894
|
return Buffer.from(`${clientID}:${clientSecret}`).toString("base64");
|
|
1869
1895
|
}
|
|
1870
1896
|
}
|
|
1871
|
-
const oAuth2DefaultSignInResolver
|
|
1897
|
+
const oAuth2DefaultSignInResolver = async (info, ctx) => {
|
|
1872
1898
|
const { profile } = info;
|
|
1873
1899
|
if (!profile.email) {
|
|
1874
1900
|
throw new Error("Profile contained no email");
|
|
1875
1901
|
}
|
|
1876
1902
|
const userId = profile.email.split("@")[0];
|
|
1903
|
+
const entityRef = catalogModel.stringifyEntityRef({
|
|
1904
|
+
kind: "User",
|
|
1905
|
+
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
1906
|
+
name: userId
|
|
1907
|
+
});
|
|
1877
1908
|
const token = await ctx.tokenIssuer.issueToken({
|
|
1878
|
-
claims: {
|
|
1909
|
+
claims: {
|
|
1910
|
+
sub: entityRef,
|
|
1911
|
+
ent: [entityRef]
|
|
1912
|
+
}
|
|
1879
1913
|
});
|
|
1880
1914
|
return { id: userId, token };
|
|
1881
1915
|
};
|
|
@@ -1906,7 +1940,7 @@ const createOAuth2Provider = (options) => {
|
|
|
1906
1940
|
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1907
1941
|
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1908
1942
|
});
|
|
1909
|
-
const signInResolverFn = (_c = (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver) != null ? _c : oAuth2DefaultSignInResolver
|
|
1943
|
+
const signInResolverFn = (_c = (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver) != null ? _c : oAuth2DefaultSignInResolver;
|
|
1910
1944
|
const signInResolver = (info) => signInResolverFn(info, {
|
|
1911
1945
|
catalogIdentityClient,
|
|
1912
1946
|
tokenIssuer,
|
|
@@ -2102,16 +2136,21 @@ class OidcAuthProvider {
|
|
|
2102
2136
|
return response;
|
|
2103
2137
|
}
|
|
2104
2138
|
}
|
|
2105
|
-
const
|
|
2139
|
+
const oidcDefaultSignInResolver = async (info, ctx) => {
|
|
2106
2140
|
const { profile } = info;
|
|
2107
2141
|
if (!profile.email) {
|
|
2108
2142
|
throw new Error("Profile contained no email");
|
|
2109
2143
|
}
|
|
2110
2144
|
const userId = profile.email.split("@")[0];
|
|
2145
|
+
const entityRef = catalogModel.stringifyEntityRef({
|
|
2146
|
+
kind: "User",
|
|
2147
|
+
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
2148
|
+
name: userId
|
|
2149
|
+
});
|
|
2111
2150
|
const token = await ctx.tokenIssuer.issueToken({
|
|
2112
2151
|
claims: {
|
|
2113
|
-
sub:
|
|
2114
|
-
ent: [
|
|
2152
|
+
sub: entityRef,
|
|
2153
|
+
ent: [entityRef]
|
|
2115
2154
|
}
|
|
2116
2155
|
});
|
|
2117
2156
|
return { id: userId, token };
|
|
@@ -2146,7 +2185,7 @@ const createOidcProvider = (options) => {
|
|
|
2146
2185
|
picture: userinfo.picture
|
|
2147
2186
|
}
|
|
2148
2187
|
});
|
|
2149
|
-
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b :
|
|
2188
|
+
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : oidcDefaultSignInResolver;
|
|
2150
2189
|
const signInResolver = (info) => signInResolverFn(info, {
|
|
2151
2190
|
catalogIdentityClient,
|
|
2152
2191
|
tokenIssuer,
|
|
@@ -2281,8 +2320,16 @@ const oktaDefaultSignInResolver = async (info, ctx) => {
|
|
|
2281
2320
|
throw new Error("Okta profile contained no email");
|
|
2282
2321
|
}
|
|
2283
2322
|
const userId = profile.email.split("@")[0];
|
|
2323
|
+
const entityRef = catalogModel.stringifyEntityRef({
|
|
2324
|
+
kind: "User",
|
|
2325
|
+
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
2326
|
+
name: userId
|
|
2327
|
+
});
|
|
2284
2328
|
const token = await ctx.tokenIssuer.issueToken({
|
|
2285
|
-
claims: {
|
|
2329
|
+
claims: {
|
|
2330
|
+
sub: entityRef,
|
|
2331
|
+
ent: [entityRef]
|
|
2332
|
+
}
|
|
2286
2333
|
});
|
|
2287
2334
|
return { id: userId, token };
|
|
2288
2335
|
};
|
|
@@ -2520,8 +2567,16 @@ class SamlAuthProvider {
|
|
|
2520
2567
|
}
|
|
2521
2568
|
const samlDefaultSignInResolver = async (info, ctx) => {
|
|
2522
2569
|
const id = info.result.fullProfile.nameID;
|
|
2570
|
+
const entityRef = catalogModel.stringifyEntityRef({
|
|
2571
|
+
kind: "User",
|
|
2572
|
+
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
2573
|
+
name: id
|
|
2574
|
+
});
|
|
2523
2575
|
const token = await ctx.tokenIssuer.issueToken({
|
|
2524
|
-
claims: {
|
|
2576
|
+
claims: {
|
|
2577
|
+
sub: entityRef,
|
|
2578
|
+
ent: [entityRef]
|
|
2579
|
+
}
|
|
2525
2580
|
});
|
|
2526
2581
|
return { id, token };
|
|
2527
2582
|
};
|