@backstage/plugin-auth-backend 0.26.1-next.0 → 0.27.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 +58 -0
- package/config.d.ts +59 -4
- package/dist/authPlugin.cjs.js +14 -1
- package/dist/authPlugin.cjs.js.map +1 -1
- package/dist/database/OfflineSessionDatabase.cjs.js +136 -0
- package/dist/database/OfflineSessionDatabase.cjs.js.map +1 -0
- package/dist/lib/refreshToken.cjs.js +60 -0
- package/dist/lib/refreshToken.cjs.js.map +1 -0
- package/dist/service/CimdClient.cjs.js +133 -0
- package/dist/service/CimdClient.cjs.js.map +1 -0
- package/dist/service/OfflineAccessService.cjs.js +177 -0
- package/dist/service/OfflineAccessService.cjs.js.map +1 -0
- package/dist/service/OidcError.cjs.js +57 -0
- package/dist/service/OidcError.cjs.js.map +1 -0
- package/dist/service/OidcRouter.cjs.js +219 -148
- package/dist/service/OidcRouter.cjs.js.map +1 -1
- package/dist/service/OidcService.cjs.js +174 -60
- package/dist/service/OidcService.cjs.js.map +1 -1
- package/dist/service/readTokenExpiration.cjs.js +9 -26
- package/dist/service/readTokenExpiration.cjs.js.map +1 -1
- package/dist/service/router.cjs.js +19 -27
- package/dist/service/router.cjs.js.map +1 -1
- package/migrations/20251020000000_offline_sessions.js +78 -0
- package/migrations/20251217120000_drop_oidc_clients_fk.js +44 -0
- package/package.json +18 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport cookieParser from 'cookie-parser';\nimport {\n AuthService,\n DatabaseService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { AuthOwnershipResolver } from '@backstage/plugin-auth-node';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\nimport { NotFoundError } from '@backstage/errors';\nimport { KeyStores } from '../identity/KeyStores';\nimport { TokenFactory } from '../identity/TokenFactory';\nimport { UserInfoDatabase } from '../database/UserInfoDatabase';\nimport session from 'express-session';\nimport connectSessionKnex from 'connect-session-knex';\nimport passport from 'passport';\nimport { AuthDatabase } from '../database/AuthDatabase';\nimport {
|
|
1
|
+
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport cookieParser from 'cookie-parser';\nimport {\n AuthService,\n DatabaseService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { AuthOwnershipResolver } from '@backstage/plugin-auth-node';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\nimport { NotFoundError } from '@backstage/errors';\nimport { KeyStores } from '../identity/KeyStores';\nimport { TokenFactory } from '../identity/TokenFactory';\nimport { UserInfoDatabase } from '../database/UserInfoDatabase';\nimport session from 'express-session';\nimport connectSessionKnex from 'connect-session-knex';\nimport passport from 'passport';\nimport { AuthDatabase } from '../database/AuthDatabase';\nimport { readBackstageTokenExpiration } from './readTokenExpiration';\nimport { TokenIssuer } from '../identity/types';\nimport { StaticTokenIssuer } from '../identity/StaticTokenIssuer';\nimport { StaticKeyStore } from '../identity/StaticKeyStore';\nimport { bindProviderRouters, ProviderFactories } from '../providers/router';\nimport { OidcRouter } from './OidcRouter';\nimport { OidcDatabase } from '../database/OidcDatabase';\nimport { OfflineAccessService } from './OfflineAccessService';\n\ninterface RouterOptions {\n logger: LoggerService;\n database: DatabaseService;\n config: RootConfigService;\n discovery: DiscoveryService;\n auth: AuthService;\n tokenFactoryAlgorithm?: string;\n providerFactories?: ProviderFactories;\n catalog: CatalogService;\n ownershipResolver?: AuthOwnershipResolver;\n httpAuth: HttpAuthService;\n offlineAccess?: OfflineAccessService;\n}\n\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const {\n logger,\n config,\n discovery,\n database: db,\n tokenFactoryAlgorithm,\n providerFactories = {},\n httpAuth,\n } = options;\n\n const router = Router();\n\n const appUrl = config.getString('app.baseUrl');\n const authUrl = await discovery.getExternalBaseUrl('auth');\n const backstageTokenExpiration = readBackstageTokenExpiration(config);\n const database = AuthDatabase.create(db);\n\n const keyStore = await KeyStores.fromConfig(config, {\n logger,\n database,\n });\n\n const userInfo = await UserInfoDatabase.create({\n database,\n });\n\n const omitClaimsFromToken = config.getOptionalBoolean(\n 'auth.omitIdentityTokenOwnershipClaim',\n )\n ? ['ent']\n : [];\n\n let tokenIssuer: TokenIssuer;\n if (keyStore instanceof StaticKeyStore) {\n tokenIssuer = new StaticTokenIssuer(\n {\n logger: logger.child({ component: 'token-factory' }),\n issuer: authUrl,\n sessionExpirationSeconds: backstageTokenExpiration,\n omitClaimsFromToken,\n },\n keyStore as StaticKeyStore,\n );\n } else {\n tokenIssuer = new TokenFactory({\n issuer: authUrl,\n keyStore,\n keyDurationSeconds: backstageTokenExpiration,\n logger: logger.child({ component: 'token-factory' }),\n algorithm:\n tokenFactoryAlgorithm ??\n config.getOptionalString('auth.identityTokenAlgorithm'),\n omitClaimsFromToken,\n });\n }\n\n const secret = config.getOptionalString('auth.session.secret');\n if (secret) {\n router.use(cookieParser(secret));\n const enforceCookieSSL = authUrl.startsWith('https');\n const KnexSessionStore = connectSessionKnex(session);\n router.use(\n session({\n secret,\n saveUninitialized: false,\n resave: false,\n cookie: { secure: enforceCookieSSL ? 'auto' : false },\n store: new KnexSessionStore({\n createtable: false,\n knex: await database.get(),\n }),\n }),\n );\n router.use(passport.initialize());\n router.use(passport.session());\n } else {\n router.use(cookieParser());\n }\n\n router.use(express.urlencoded({ extended: false }));\n router.use(express.json());\n\n bindProviderRouters(router, {\n providers: providerFactories,\n appUrl,\n baseUrl: authUrl,\n tokenIssuer,\n ...options,\n auth: options.auth,\n userInfo,\n });\n\n const oidc = await OidcDatabase.create({ database });\n\n const oidcRouter = OidcRouter.create({\n auth: options.auth,\n tokenIssuer,\n baseUrl: authUrl,\n appUrl,\n userInfo,\n oidc,\n logger,\n httpAuth,\n config,\n offlineAccess: options.offlineAccess,\n });\n\n router.use(oidcRouter.getRouter());\n\n // Gives a more helpful error message than a plain 404\n router.use('/:provider/', req => {\n const { provider } = req.params;\n throw new NotFoundError(`Unknown auth provider '${provider}'`);\n });\n\n return router;\n}\n"],"names":["router","Router","readBackstageTokenExpiration","AuthDatabase","KeyStores","UserInfoDatabase","StaticKeyStore","StaticTokenIssuer","TokenFactory","cookieParser","connectSessionKnex","session","passport","express","bindProviderRouters","OidcDatabase","OidcRouter","NotFoundError"],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 The Backstage Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// @ts-check
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {import('knex').Knex} knex
|
|
21
|
+
*/
|
|
22
|
+
exports.up = async function up(knex) {
|
|
23
|
+
await knex.schema.createTable('offline_sessions', table => {
|
|
24
|
+
table.comment(
|
|
25
|
+
'Offline sessions for refresh tokens in dynamic client registration and device auth flows',
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
table
|
|
29
|
+
.string('id')
|
|
30
|
+
.primary()
|
|
31
|
+
.notNullable()
|
|
32
|
+
.comment('Persistent session ID that remains across token rotations');
|
|
33
|
+
|
|
34
|
+
table
|
|
35
|
+
.string('user_entity_ref')
|
|
36
|
+
.notNullable()
|
|
37
|
+
.comment('Backstage user entity reference');
|
|
38
|
+
|
|
39
|
+
table
|
|
40
|
+
.string('oidc_client_id')
|
|
41
|
+
.nullable()
|
|
42
|
+
.comment('OIDC client identifier (optional, for OIDC flows)');
|
|
43
|
+
|
|
44
|
+
table
|
|
45
|
+
.text('token_hash')
|
|
46
|
+
.notNullable()
|
|
47
|
+
.comment('Current refresh token hash (scrypt)');
|
|
48
|
+
|
|
49
|
+
table
|
|
50
|
+
.timestamp('created_at', { useTz: true, precision: 0 })
|
|
51
|
+
.notNullable()
|
|
52
|
+
.defaultTo(knex.fn.now())
|
|
53
|
+
.comment('Session creation timestamp');
|
|
54
|
+
|
|
55
|
+
table
|
|
56
|
+
.timestamp('last_used_at', { useTz: true, precision: 0 })
|
|
57
|
+
.notNullable()
|
|
58
|
+
.defaultTo(knex.fn.now())
|
|
59
|
+
.comment('Last token refresh timestamp');
|
|
60
|
+
|
|
61
|
+
table
|
|
62
|
+
.foreign('oidc_client_id')
|
|
63
|
+
.references('client_id')
|
|
64
|
+
.inTable('oidc_clients')
|
|
65
|
+
.onDelete('CASCADE');
|
|
66
|
+
table.index('user_entity_ref', 'offline_sessions_user_idx');
|
|
67
|
+
table.index('oidc_client_id', 'offline_sessions_oidc_client_idx');
|
|
68
|
+
table.index('created_at', 'offline_sessions_created_idx');
|
|
69
|
+
table.index('last_used_at', 'offline_sessions_last_used_idx');
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {import('knex').Knex} knex
|
|
75
|
+
*/
|
|
76
|
+
exports.down = async function down(knex) {
|
|
77
|
+
await knex.schema.dropTable('offline_sessions');
|
|
78
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 The Backstage Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// @ts-check
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Drop the foreign key constraint on oauth_authorization_sessions.client_id
|
|
21
|
+
* to allow CIMD (Client ID Metadata Document) clients which are not stored
|
|
22
|
+
* in the oidc_clients table.
|
|
23
|
+
*
|
|
24
|
+
* @param {import('knex').Knex} knex
|
|
25
|
+
*/
|
|
26
|
+
exports.up = async function up(knex) {
|
|
27
|
+
await knex.schema.alterTable('oauth_authorization_sessions', table => {
|
|
28
|
+
table.dropForeign(['client_id']);
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {import('knex').Knex} knex
|
|
34
|
+
*/
|
|
35
|
+
exports.down = async function down(knex) {
|
|
36
|
+
// Delete sessions with CIMD client_ids (not in oidc_clients) before re-adding FK
|
|
37
|
+
await knex('oauth_authorization_sessions')
|
|
38
|
+
.whereNotIn('client_id', knex('oidc_clients').select('client_id'))
|
|
39
|
+
.delete();
|
|
40
|
+
|
|
41
|
+
await knex.schema.alterTable('oauth_authorization_sessions', table => {
|
|
42
|
+
table.foreign('client_id').references('client_id').inTable('oidc_clients');
|
|
43
|
+
});
|
|
44
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-auth-backend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "A Backstage backend plugin that handles authentication",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "backend-plugin",
|
|
@@ -47,19 +47,20 @@
|
|
|
47
47
|
"test": "backstage-cli package test"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@backstage/backend-plugin-api": "1.7.0
|
|
51
|
-
"@backstage/catalog-model": "1.7.6",
|
|
52
|
-
"@backstage/config": "1.3.6",
|
|
53
|
-
"@backstage/errors": "1.2.7",
|
|
54
|
-
"@backstage/plugin-auth-node": "0.6.
|
|
55
|
-
"@backstage/plugin-catalog-node": "
|
|
56
|
-
"@backstage/types": "1.2.2",
|
|
50
|
+
"@backstage/backend-plugin-api": "^1.7.0",
|
|
51
|
+
"@backstage/catalog-model": "^1.7.6",
|
|
52
|
+
"@backstage/config": "^1.3.6",
|
|
53
|
+
"@backstage/errors": "^1.2.7",
|
|
54
|
+
"@backstage/plugin-auth-node": "^0.6.13",
|
|
55
|
+
"@backstage/plugin-catalog-node": "^2.0.0",
|
|
56
|
+
"@backstage/types": "^1.2.2",
|
|
57
57
|
"@google-cloud/firestore": "^7.0.0",
|
|
58
58
|
"connect-session-knex": "^4.0.0",
|
|
59
59
|
"cookie-parser": "^1.4.5",
|
|
60
60
|
"express": "^4.22.0",
|
|
61
61
|
"express-promise-router": "^4.1.0",
|
|
62
62
|
"express-session": "^1.17.1",
|
|
63
|
+
"ipaddr.js": "^2.3.0",
|
|
63
64
|
"jose": "^5.0.0",
|
|
64
65
|
"knex": "^3.0.0",
|
|
65
66
|
"lodash": "^4.17.21",
|
|
@@ -67,18 +68,21 @@
|
|
|
67
68
|
"matcher": "^4.0.0",
|
|
68
69
|
"minimatch": "^9.0.0",
|
|
69
70
|
"passport": "^0.7.0",
|
|
70
|
-
"uuid": "^11.0.0"
|
|
71
|
+
"uuid": "^11.0.0",
|
|
72
|
+
"zod": "^4.3.5",
|
|
73
|
+
"zod-validation-error": "^5.0.0"
|
|
71
74
|
},
|
|
72
75
|
"devDependencies": {
|
|
73
|
-
"@backstage/backend-defaults": "0.15.
|
|
74
|
-
"@backstage/backend-test-utils": "1.
|
|
75
|
-
"@backstage/cli": "0.35.
|
|
76
|
-
"@backstage/plugin-auth-backend-module-google-provider": "0.3.
|
|
77
|
-
"@backstage/plugin-auth-backend-module-guest-provider": "0.2.16
|
|
76
|
+
"@backstage/backend-defaults": "^0.15.2",
|
|
77
|
+
"@backstage/backend-test-utils": "^1.11.0",
|
|
78
|
+
"@backstage/cli": "^0.35.4",
|
|
79
|
+
"@backstage/plugin-auth-backend-module-google-provider": "^0.3.12",
|
|
80
|
+
"@backstage/plugin-auth-backend-module-guest-provider": "^0.2.16",
|
|
78
81
|
"@types/cookie-parser": "^1.4.2",
|
|
79
82
|
"@types/express": "^4.17.6",
|
|
80
83
|
"@types/express-session": "^1.17.2",
|
|
81
84
|
"@types/passport": "^1.0.3",
|
|
85
|
+
"msw": "^1.0.0",
|
|
82
86
|
"supertest": "^7.0.0"
|
|
83
87
|
},
|
|
84
88
|
"configSchema": "config.d.ts",
|