@backstage/plugin-auth-backend 0.22.6-next.2 → 0.22.6
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 +70 -0
- package/dist/index.cjs.js +54 -129
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/migrations/20240510120825_user_info.js +49 -0
- package/package.json +30 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# @backstage/plugin-auth-backend
|
|
2
2
|
|
|
3
|
+
## 0.22.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 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.
|
|
8
|
+
|
|
9
|
+
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.
|
|
10
|
+
|
|
11
|
+
- 8869b8e: Updated local development setup.
|
|
12
|
+
- 78a0b08: Internal refactor to handle `BackendFeature` contract change.
|
|
13
|
+
- d44a20a: Added additional plugin metadata to `package.json`.
|
|
14
|
+
- 3e1bb15: Updated to use the new `@backstage/plugin-auth-backend-module-onelogin-provider` implementation
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
- @backstage/backend-common@0.23.0
|
|
17
|
+
- @backstage/plugin-auth-backend-module-onelogin-provider@0.1.0
|
|
18
|
+
- @backstage/backend-plugin-api@0.6.19
|
|
19
|
+
- @backstage/plugin-auth-node@0.4.14
|
|
20
|
+
- @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.1.2
|
|
21
|
+
- @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.1.2
|
|
22
|
+
- @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.12
|
|
23
|
+
- @backstage/plugin-auth-backend-module-atlassian-provider@0.2.0
|
|
24
|
+
- @backstage/plugin-auth-backend-module-bitbucket-provider@0.1.2
|
|
25
|
+
- @backstage/plugin-auth-backend-module-microsoft-provider@0.1.14
|
|
26
|
+
- @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.11
|
|
27
|
+
- @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.14
|
|
28
|
+
- @backstage/plugin-auth-backend-module-github-provider@0.1.16
|
|
29
|
+
- @backstage/plugin-auth-backend-module-gitlab-provider@0.1.16
|
|
30
|
+
- @backstage/plugin-auth-backend-module-google-provider@0.1.16
|
|
31
|
+
- @backstage/plugin-auth-backend-module-oauth2-provider@0.2.0
|
|
32
|
+
- @backstage/plugin-auth-backend-module-oidc-provider@0.2.0
|
|
33
|
+
- @backstage/plugin-auth-backend-module-okta-provider@0.0.12
|
|
34
|
+
- @backstage/plugin-catalog-node@1.12.1
|
|
35
|
+
- @backstage/catalog-client@1.6.5
|
|
36
|
+
- @backstage/catalog-model@1.5.0
|
|
37
|
+
- @backstage/config@1.2.0
|
|
38
|
+
- @backstage/errors@1.2.4
|
|
39
|
+
- @backstage/types@1.1.1
|
|
40
|
+
|
|
41
|
+
## 0.22.6-next.3
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- d44a20a: Added additional plugin metadata to `package.json`.
|
|
46
|
+
- 3e1bb15: Updated to use the new `@backstage/plugin-auth-backend-module-onelogin-provider` implementation
|
|
47
|
+
- Updated dependencies
|
|
48
|
+
- @backstage/plugin-auth-backend-module-onelogin-provider@0.1.0-next.0
|
|
49
|
+
- @backstage/backend-plugin-api@0.6.19-next.3
|
|
50
|
+
- @backstage/plugin-auth-node@0.4.14-next.3
|
|
51
|
+
- @backstage/plugin-auth-backend-module-atlassian-provider@0.2.0-next.2
|
|
52
|
+
- @backstage/plugin-auth-backend-module-bitbucket-provider@0.1.2-next.2
|
|
53
|
+
- @backstage/plugin-auth-backend-module-github-provider@0.1.16-next.2
|
|
54
|
+
- @backstage/plugin-auth-backend-module-gitlab-provider@0.1.16-next.2
|
|
55
|
+
- @backstage/plugin-auth-backend-module-google-provider@0.1.16-next.2
|
|
56
|
+
- @backstage/plugin-auth-backend-module-microsoft-provider@0.1.14-next.2
|
|
57
|
+
- @backstage/plugin-auth-backend-module-oauth2-provider@0.2.0-next.2
|
|
58
|
+
- @backstage/plugin-auth-backend-module-oidc-provider@0.2.0-next.3
|
|
59
|
+
- @backstage/plugin-auth-backend-module-okta-provider@0.0.12-next.2
|
|
60
|
+
- @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.1.2-next.3
|
|
61
|
+
- @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.1.2-next.2
|
|
62
|
+
- @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.12-next.2
|
|
63
|
+
- @backstage/plugin-auth-backend-module-aws-alb-provider@0.1.11-next.3
|
|
64
|
+
- @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.14-next.2
|
|
65
|
+
- @backstage/plugin-catalog-node@1.12.1-next.2
|
|
66
|
+
- @backstage/backend-common@0.23.0-next.3
|
|
67
|
+
- @backstage/catalog-client@1.6.5
|
|
68
|
+
- @backstage/catalog-model@1.5.0
|
|
69
|
+
- @backstage/config@1.2.0
|
|
70
|
+
- @backstage/errors@1.2.4
|
|
71
|
+
- @backstage/types@1.1.1
|
|
72
|
+
|
|
3
73
|
## 0.22.6-next.2
|
|
4
74
|
|
|
5
75
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -26,7 +26,7 @@ var pluginAuthBackendModuleOauth2Provider = require('@backstage/plugin-auth-back
|
|
|
26
26
|
var pluginAuthBackendModuleOauth2ProxyProvider = require('@backstage/plugin-auth-backend-module-oauth2-proxy-provider');
|
|
27
27
|
var pluginAuthBackendModuleOidcProvider = require('@backstage/plugin-auth-backend-module-oidc-provider');
|
|
28
28
|
var pluginAuthBackendModuleOktaProvider = require('@backstage/plugin-auth-backend-module-okta-provider');
|
|
29
|
-
var
|
|
29
|
+
var pluginAuthBackendModuleOneloginProvider = require('@backstage/plugin-auth-backend-module-onelogin-provider');
|
|
30
30
|
var passportSaml = require('@node-saml/passport-saml');
|
|
31
31
|
var passportOauth2 = require('passport-oauth2');
|
|
32
32
|
var fetch = require('node-fetch');
|
|
@@ -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');
|
|
@@ -952,120 +952,12 @@ const okta = createAuthProviderIntegration({
|
|
|
952
952
|
}
|
|
953
953
|
});
|
|
954
954
|
|
|
955
|
-
class OneLoginProvider {
|
|
956
|
-
_strategy;
|
|
957
|
-
signInResolver;
|
|
958
|
-
authHandler;
|
|
959
|
-
resolverContext;
|
|
960
|
-
constructor(options) {
|
|
961
|
-
this.signInResolver = options.signInResolver;
|
|
962
|
-
this.authHandler = options.authHandler;
|
|
963
|
-
this.resolverContext = options.resolverContext;
|
|
964
|
-
this._strategy = new passportOneloginOauth.Strategy(
|
|
965
|
-
{
|
|
966
|
-
issuer: options.issuer,
|
|
967
|
-
clientID: options.clientId,
|
|
968
|
-
clientSecret: options.clientSecret,
|
|
969
|
-
callbackURL: options.callbackUrl,
|
|
970
|
-
passReqToCallback: false
|
|
971
|
-
},
|
|
972
|
-
(accessToken, refreshToken, params, fullProfile, done) => {
|
|
973
|
-
done(
|
|
974
|
-
void 0,
|
|
975
|
-
{
|
|
976
|
-
accessToken,
|
|
977
|
-
refreshToken,
|
|
978
|
-
params,
|
|
979
|
-
fullProfile
|
|
980
|
-
},
|
|
981
|
-
{
|
|
982
|
-
refreshToken
|
|
983
|
-
}
|
|
984
|
-
);
|
|
985
|
-
}
|
|
986
|
-
);
|
|
987
|
-
}
|
|
988
|
-
async start(req) {
|
|
989
|
-
return await executeRedirectStrategy(req, this._strategy, {
|
|
990
|
-
accessType: "offline",
|
|
991
|
-
prompt: "consent",
|
|
992
|
-
scope: "openid",
|
|
993
|
-
state: encodeState(req.state)
|
|
994
|
-
});
|
|
995
|
-
}
|
|
996
|
-
async handler(req) {
|
|
997
|
-
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this._strategy);
|
|
998
|
-
return {
|
|
999
|
-
response: await this.handleResult(result),
|
|
1000
|
-
refreshToken: privateInfo.refreshToken
|
|
1001
|
-
};
|
|
1002
|
-
}
|
|
1003
|
-
async refresh(req) {
|
|
1004
|
-
const { accessToken, refreshToken, params } = await executeRefreshTokenStrategy(
|
|
1005
|
-
this._strategy,
|
|
1006
|
-
req.refreshToken,
|
|
1007
|
-
"openid"
|
|
1008
|
-
);
|
|
1009
|
-
const fullProfile = await executeFetchUserProfileStrategy(
|
|
1010
|
-
this._strategy,
|
|
1011
|
-
accessToken
|
|
1012
|
-
);
|
|
1013
|
-
return {
|
|
1014
|
-
response: await this.handleResult({
|
|
1015
|
-
fullProfile,
|
|
1016
|
-
params,
|
|
1017
|
-
accessToken
|
|
1018
|
-
}),
|
|
1019
|
-
refreshToken
|
|
1020
|
-
};
|
|
1021
|
-
}
|
|
1022
|
-
async handleResult(result) {
|
|
1023
|
-
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
1024
|
-
const response = {
|
|
1025
|
-
providerInfo: {
|
|
1026
|
-
idToken: result.params.id_token,
|
|
1027
|
-
accessToken: result.accessToken,
|
|
1028
|
-
scope: result.params.scope,
|
|
1029
|
-
expiresInSeconds: result.params.expires_in
|
|
1030
|
-
},
|
|
1031
|
-
profile
|
|
1032
|
-
};
|
|
1033
|
-
if (this.signInResolver) {
|
|
1034
|
-
response.backstageIdentity = await this.signInResolver(
|
|
1035
|
-
{
|
|
1036
|
-
result,
|
|
1037
|
-
profile
|
|
1038
|
-
},
|
|
1039
|
-
this.resolverContext
|
|
1040
|
-
);
|
|
1041
|
-
}
|
|
1042
|
-
return response;
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
955
|
const onelogin = createAuthProviderIntegration({
|
|
1046
956
|
create(options) {
|
|
1047
|
-
return
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1052
|
-
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1053
|
-
const authHandler = options?.authHandler ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1054
|
-
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1055
|
-
});
|
|
1056
|
-
const provider = new OneLoginProvider({
|
|
1057
|
-
clientId,
|
|
1058
|
-
clientSecret,
|
|
1059
|
-
callbackUrl,
|
|
1060
|
-
issuer,
|
|
1061
|
-
authHandler,
|
|
1062
|
-
signInResolver: options?.signIn?.resolver,
|
|
1063
|
-
resolverContext
|
|
1064
|
-
});
|
|
1065
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1066
|
-
providerId,
|
|
1067
|
-
callbackUrl
|
|
1068
|
-
});
|
|
957
|
+
return pluginAuthNode.createOAuthProviderFactory({
|
|
958
|
+
authenticator: pluginAuthBackendModuleOneloginProvider.oneLoginAuthenticator,
|
|
959
|
+
profileTransform: adaptLegacyOAuthHandler(options?.authHandler),
|
|
960
|
+
signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver)
|
|
1069
961
|
});
|
|
1070
962
|
}
|
|
1071
963
|
});
|
|
@@ -1687,7 +1579,7 @@ function createOriginFilter(config) {
|
|
|
1687
1579
|
}
|
|
1688
1580
|
|
|
1689
1581
|
function bindOidcRouter(targetRouter, options) {
|
|
1690
|
-
const { baseUrl, auth, tokenIssuer } = options;
|
|
1582
|
+
const { baseUrl, auth, tokenIssuer, userInfoDatabaseHandler } = options;
|
|
1691
1583
|
const router = Router__default.default();
|
|
1692
1584
|
targetRouter.use(router);
|
|
1693
1585
|
const config = {
|
|
@@ -1738,16 +1630,16 @@ function bindOidcRouter(targetRouter, options) {
|
|
|
1738
1630
|
"Userinfo endpoint must be called with a token that represents a user principal"
|
|
1739
1631
|
);
|
|
1740
1632
|
}
|
|
1741
|
-
const { sub: userEntityRef
|
|
1633
|
+
const { sub: userEntityRef } = jose.decodeJwt(token);
|
|
1742
1634
|
if (typeof userEntityRef !== "string") {
|
|
1743
1635
|
throw new Error("Invalid user token, user entity ref must be a string");
|
|
1744
1636
|
}
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1637
|
+
const userInfo = await userInfoDatabaseHandler.getUserInfo(userEntityRef);
|
|
1638
|
+
if (!userInfo) {
|
|
1639
|
+
res.status(404).send("User info not found");
|
|
1640
|
+
return;
|
|
1749
1641
|
}
|
|
1750
|
-
res.json(
|
|
1642
|
+
res.json(userInfo);
|
|
1751
1643
|
});
|
|
1752
1644
|
}
|
|
1753
1645
|
|
|
@@ -1759,6 +1651,7 @@ class TokenFactory {
|
|
|
1759
1651
|
keyStore;
|
|
1760
1652
|
keyDurationSeconds;
|
|
1761
1653
|
algorithm;
|
|
1654
|
+
userInfoDatabaseHandler;
|
|
1762
1655
|
keyExpiry;
|
|
1763
1656
|
privateKeyPromise;
|
|
1764
1657
|
constructor(options) {
|
|
@@ -1767,6 +1660,7 @@ class TokenFactory {
|
|
|
1767
1660
|
this.keyStore = options.keyStore;
|
|
1768
1661
|
this.keyDurationSeconds = options.keyDurationSeconds;
|
|
1769
1662
|
this.algorithm = options.algorithm ?? "ES256";
|
|
1663
|
+
this.userInfoDatabaseHandler = options.userInfoDatabaseHandler;
|
|
1770
1664
|
}
|
|
1771
1665
|
async issueToken(params) {
|
|
1772
1666
|
const key = await this.getKey();
|
|
@@ -1793,7 +1687,7 @@ class TokenFactory {
|
|
|
1793
1687
|
alg: key.alg,
|
|
1794
1688
|
kid: key.kid
|
|
1795
1689
|
},
|
|
1796
|
-
payload: { sub,
|
|
1690
|
+
payload: { sub, iat, exp },
|
|
1797
1691
|
key: signingKey
|
|
1798
1692
|
});
|
|
1799
1693
|
const claims = {
|
|
@@ -1818,6 +1712,9 @@ class TokenFactory {
|
|
|
1818
1712
|
)}'`
|
|
1819
1713
|
);
|
|
1820
1714
|
}
|
|
1715
|
+
await this.userInfoDatabaseHandler.addUserInfo({
|
|
1716
|
+
claims: lodash.omit(claims, ["aud", "iat", "iss", "uip"])
|
|
1717
|
+
});
|
|
1821
1718
|
return token;
|
|
1822
1719
|
}
|
|
1823
1720
|
// This will be called by other services that want to verify ID tokens.
|
|
@@ -1888,7 +1785,6 @@ class TokenFactory {
|
|
|
1888
1785
|
};
|
|
1889
1786
|
const payload = {
|
|
1890
1787
|
sub: options.payload.sub,
|
|
1891
|
-
ent: options.payload.ent,
|
|
1892
1788
|
iat: options.payload.iat,
|
|
1893
1789
|
exp: options.payload.exp
|
|
1894
1790
|
};
|
|
@@ -1899,7 +1795,7 @@ class TokenFactory {
|
|
|
1899
1795
|
}
|
|
1900
1796
|
}
|
|
1901
1797
|
|
|
1902
|
-
const TABLE = "signing_keys";
|
|
1798
|
+
const TABLE$1 = "signing_keys";
|
|
1903
1799
|
const parseDate = (date) => {
|
|
1904
1800
|
const parsedDate = typeof date === "string" ? luxon.DateTime.fromSQL(date, { zone: "UTC" }) : luxon.DateTime.fromJSDate(date);
|
|
1905
1801
|
if (!parsedDate.isValid) {
|
|
@@ -1914,13 +1810,13 @@ class DatabaseKeyStore {
|
|
|
1914
1810
|
this.client = client;
|
|
1915
1811
|
}
|
|
1916
1812
|
async addKey(key) {
|
|
1917
|
-
await this.client(TABLE).insert({
|
|
1813
|
+
await this.client(TABLE$1).insert({
|
|
1918
1814
|
kid: key.kid,
|
|
1919
1815
|
key: JSON.stringify(key)
|
|
1920
1816
|
});
|
|
1921
1817
|
}
|
|
1922
1818
|
async listKeys() {
|
|
1923
|
-
const rows = await this.client(TABLE).select();
|
|
1819
|
+
const rows = await this.client(TABLE$1).select();
|
|
1924
1820
|
return {
|
|
1925
1821
|
items: rows.map((row) => ({
|
|
1926
1822
|
key: JSON.parse(row.key),
|
|
@@ -1929,7 +1825,7 @@ class DatabaseKeyStore {
|
|
|
1929
1825
|
};
|
|
1930
1826
|
}
|
|
1931
1827
|
async removeKeys(kids) {
|
|
1932
|
-
await this.client(TABLE).delete().whereIn("kid", kids);
|
|
1828
|
+
await this.client(TABLE$1).delete().whereIn("kid", kids);
|
|
1933
1829
|
}
|
|
1934
1830
|
}
|
|
1935
1831
|
|
|
@@ -2166,6 +2062,30 @@ class KeyStores {
|
|
|
2166
2062
|
}
|
|
2167
2063
|
}
|
|
2168
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
|
+
|
|
2169
2089
|
const migrationsDir = backendPluginApi.resolvePackagePath(
|
|
2170
2090
|
"@backstage/plugin-auth-backend",
|
|
2171
2091
|
"migrations"
|
|
@@ -2293,6 +2213,9 @@ async function createRouter(options) {
|
|
|
2293
2213
|
logger,
|
|
2294
2214
|
database: authDb
|
|
2295
2215
|
});
|
|
2216
|
+
const userInfoDatabaseHandler = new UserInfoDatabaseHandler(
|
|
2217
|
+
await authDb.get()
|
|
2218
|
+
);
|
|
2296
2219
|
let tokenIssuer;
|
|
2297
2220
|
if (keyStore instanceof StaticKeyStore) {
|
|
2298
2221
|
tokenIssuer = new StaticTokenIssuer(
|
|
@@ -2309,7 +2232,8 @@ async function createRouter(options) {
|
|
|
2309
2232
|
keyStore,
|
|
2310
2233
|
keyDurationSeconds: backstageTokenExpiration,
|
|
2311
2234
|
logger: logger.child({ component: "token-factory" }),
|
|
2312
|
-
algorithm: tokenFactoryAlgorithm ?? config.getOptionalString("auth.identityTokenAlgorithm")
|
|
2235
|
+
algorithm: tokenFactoryAlgorithm ?? config.getOptionalString("auth.identityTokenAlgorithm"),
|
|
2236
|
+
userInfoDatabaseHandler
|
|
2313
2237
|
});
|
|
2314
2238
|
}
|
|
2315
2239
|
const secret = config.getOptionalString("auth.session.secret");
|
|
@@ -2352,7 +2276,8 @@ async function createRouter(options) {
|
|
|
2352
2276
|
bindOidcRouter(router, {
|
|
2353
2277
|
auth,
|
|
2354
2278
|
tokenIssuer,
|
|
2355
|
-
baseUrl: authUrl
|
|
2279
|
+
baseUrl: authUrl,
|
|
2280
|
+
userInfoDatabaseHandler
|
|
2356
2281
|
});
|
|
2357
2282
|
router.use("/:provider/", (req) => {
|
|
2358
2283
|
const { provider } = req.params;
|