auth-backend: add plugin export for new backend system

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-08-18 13:10:27 +02:00
parent c80013badd
commit 7944d43f47
12 changed files with 203 additions and 9 deletions
@@ -0,0 +1,45 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
import request from 'supertest';
import { authPlugin } from './authPlugin';
describe('authPlugin', () => {
it('should provide an OpenID configuration', async () => {
const { server } = await startTestBackend({
features: [
authPlugin,
mockServices.rootConfig.factory({
data: {
app: {
baseUrl: 'http://localhost:3000',
},
},
}),
],
});
const res = await request(server).get(
'/api/auth/.well-known/openid-configuration',
);
expect(res.status).toBe(200);
expect(res.body).toMatchObject({
claims_supported: ['sub'],
issuer: `http://localhost:${server.port()}/api/auth`,
});
});
});
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
coreServices,
createBackendPlugin,
} from '@backstage/backend-plugin-api';
import {
AuthProviderFactory,
authProvidersExtensionPoint,
} from '@backstage/plugin-auth-node';
import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';
import { createRouter } from './service/router';
/**
* Auth plugin
*
* @public
*/
export const authPlugin = createBackendPlugin({
pluginId: 'auth',
register(reg) {
const providers = new Map<string, AuthProviderFactory>();
reg.registerExtensionPoint(authProvidersExtensionPoint, {
registerProvider({ providerId, factory }) {
if (providers.has(providerId)) {
throw new Error(
`Auth provider '${providerId}' was already registered`,
);
}
providers.set(providerId, factory);
},
});
reg.registerInit({
deps: {
httpRouter: coreServices.httpRouter,
logger: coreServices.logger,
config: coreServices.rootConfig,
database: coreServices.database,
discovery: coreServices.discovery,
tokenManager: coreServices.tokenManager,
catalogApi: catalogServiceRef,
},
async init({
httpRouter,
logger,
config,
database,
discovery,
tokenManager,
catalogApi,
}) {
const router = await createRouter({
logger,
config,
database,
discovery,
tokenManager,
catalogApi,
providerFactories: Object.fromEntries(providers),
disableDefaultProviderFactories: true,
});
httpRouter.use(router);
},
});
},
});
+1
View File
@@ -20,6 +20,7 @@
* @packageDocumentation
*/
export { authPlugin } from './authPlugin';
export * from './service/router';
export type { TokenParams } from './identity';
export * from './providers';
+14 -9
View File
@@ -51,6 +51,7 @@ export interface RouterOptions {
tokenManager: TokenManager;
tokenFactoryAlgorithm?: string;
providerFactories?: ProviderFactories;
disableDefaultProviderFactories?: boolean;
catalogApi?: CatalogApi;
}
@@ -65,7 +66,7 @@ export async function createRouter(
database,
tokenManager,
tokenFactoryAlgorithm,
providerFactories,
providerFactories = {},
catalogApi,
} = options;
const router = Router();
@@ -85,7 +86,9 @@ export async function createRouter(
keyStore,
keyDurationSeconds,
logger: logger.child({ component: 'token-factory' }),
algorithm: tokenFactoryAlgorithm,
algorithm:
tokenFactoryAlgorithm ??
config.getOptionalString('auth.identityTokenAlgorithm'),
});
const secret = config.getOptionalString('auth.session.secret');
@@ -113,19 +116,21 @@ export async function createRouter(
router.use(express.urlencoded({ extended: false }));
router.use(express.json());
const allProviderFactories = {
...defaultAuthProviderFactories,
...providerFactories,
};
const providersConfig = config.getConfig('auth.providers');
const configuredProviders = providersConfig.keys();
const allProviderFactories = options.disableDefaultProviderFactories
? providerFactories
: {
...defaultAuthProviderFactories,
...providerFactories,
};
const providersConfig = config.getOptionalConfig('auth.providers');
const isOriginAllowed = createOriginFilter(config);
for (const [providerId, providerFactory] of Object.entries(
allProviderFactories,
)) {
if (configuredProviders.includes(providerId)) {
if (providersConfig?.has(providerId)) {
logger.info(`Configuring auth provider: ${providerId}`);
try {
const provider = providerFactory({