Merge pull request #26141 from backstage/rugvip/no-service

backend-plugin-api: remove identity and token manager services
This commit is contained in:
Patrik Oldsberg
2024-08-22 10:05:23 +02:00
committed by GitHub
54 changed files with 182 additions and 508 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-plugin-api': minor
---
**BREAKING**: The deprecated identity and token manager services have been removed. This means that `coreServices.identity` and `coreServices.tokenManager` are gone, along with related types and utilities in other packages.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-app-api': minor
---
**BREAKING**: The deprecated `identityServiceFactory` and `tokenManagerServiceFactory` have been removed.
+1 -1
View File
@@ -2,4 +2,4 @@
'@backstage/backend-defaults': minor
---
**BREAKING**: The backwards compatibility with plugins using legacy auth through the token manage service has been removed. This means that instead of falling back to using the old token manager, requests towards plugins that don't support the new auth system will simply fail. Please make sure that all plugins in your deployment are hosted within a backend instance from the new backend system.
**BREAKING**: The backwards compatibility with plugins using legacy auth through the token manager service has been removed. This means that instead of falling back to using the old token manager, requests towards plugins that don't support the new auth system will simply fail. Please make sure that all plugins in your deployment are hosted within a backend instance from the new backend system.
+11
View File
@@ -0,0 +1,11 @@
---
'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch
'@backstage/plugin-search-backend-module-techdocs': patch
'@backstage/plugin-search-backend-module-catalog': patch
'@backstage/plugin-search-backend-module-explore': patch
'@backstage/plugin-permission-node': patch
'@backstage/plugin-signals-backend': patch
'@backstage/plugin-auth-backend': patch
---
Internal refactor to remove dependencies on the identity and token manager services, which have been removed. Public APIs no longer require the identity service or token manager to be provided.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-test-utils': minor
---
**BREAKING**: Removed service mocks for the identity and token manager services, which have been removed from `@backstage/backend-plugin-api`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
Internal refactor to re-declare the token manager service which was removed from `@backstage/backend-plugin-api`, but is still supported in this package for backwards compatibility.
+64
View File
@@ -0,0 +1,64 @@
---
'@backstage/backend-defaults': minor
---
**BREAKING**: The default backend instance no longer provides implementations for the identity and token manager services, which have been removed from `@backstage/backend-plugin-api`.
If you rely on plugins that still require these services, you can add them to your own backend by re-creating the service reference and factory.
The following can be used to implement the identity service:
```ts
import {
coreServices,
createServiceFactory,
createServiceRef,
} from '@backstage/backend-plugin-api';
import {
DefaultIdentityClient,
IdentityApi,
} from '@backstage/plugin-auth-node';
backend.add(
createServiceFactory({
service: createServiceRef<IdentityApi>({ id: 'core.identity' }),
deps: {
discovery: coreServices.discovery,
},
async factory({ discovery }) {
return DefaultIdentityClient.create({ discovery });
},
}),
);
```
The following can be used to implement the token manager service:
```ts
import { ServerTokenManager, TokenManager } from '@backstage/backend-common';
import { createBackend } from '@backstage/backend-defaults';
import {
coreServices,
createServiceFactory,
createServiceRef,
} from '@backstage/backend-plugin-api';
backend.add(
createServiceFactory({
service: createServiceRef<TokenManager>({ id: 'core.tokenManager' }),
deps: {
config: coreServices.rootConfig,
logger: coreServices.rootLogger,
},
createRootContext({ config, logger }) {
return ServerTokenManager.fromConfig(config, {
logger,
allowDisabledTokenManager: true,
});
},
async factory(_deps, tokenManager) {
return tokenManager;
},
}),
);
```
-16
View File
@@ -4,9 +4,7 @@
```ts
import { BackendFeature } from '@backstage/backend-plugin-api';
import { IdentityService } from '@backstage/backend-plugin-api';
import { ServiceFactory } from '@backstage/backend-plugin-api';
import { TokenManagerService } from '@backstage/backend-plugin-api';
// @public (undocumented)
export interface Backend {
@@ -34,18 +32,4 @@ export interface CreateSpecializedBackendOptions {
// (undocumented)
defaultServiceFactories: ServiceFactory[];
}
// @public @deprecated (undocumented)
export const identityServiceFactory: ServiceFactory<
IdentityService,
'plugin',
'singleton'
>;
// @public @deprecated (undocumented)
export const tokenManagerServiceFactory: ServiceFactory<
TokenManagerService,
'plugin',
'singleton'
>;
```
-1
View File
@@ -21,4 +21,3 @@
*/
export * from './wiring';
export * from './services/implementations';
@@ -1,35 +0,0 @@
/*
* Copyright 2022 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,
createServiceFactory,
} from '@backstage/backend-plugin-api';
import { DefaultIdentityClient } from '@backstage/plugin-auth-node';
/**
* @public
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
*/
export const identityServiceFactory = createServiceFactory({
service: coreServices.identity,
deps: {
discovery: coreServices.discovery,
},
async factory({ discovery }) {
return DefaultIdentityClient.create({ discovery });
},
});
@@ -1,17 +0,0 @@
/*
* 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.
*/
export { identityServiceFactory } from './identityServiceFactory';
@@ -1,18 +0,0 @@
/*
* Copyright 2022 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.
*/
export * from './identity';
export * from './tokenManager';
@@ -1,17 +0,0 @@
/*
* 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.
*/
export { tokenManagerServiceFactory } from './tokenManagerServiceFactory';
@@ -1,33 +0,0 @@
/*
* Copyright 2022 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 { tokenManagerServiceFactory } from './tokenManagerServiceFactory';
import { ServiceFactoryTester } from '@backstage/backend-test-utils';
describe('tokenManagerFactory', () => {
it('should create a disabled manager without configuration', async () => {
const tokenManager = await ServiceFactoryTester.from(
tokenManagerServiceFactory,
).getSubject();
await expect(tokenManager.authenticate('abc')).rejects.toThrow(
'no legacy keys are configured',
);
await expect(tokenManager.getToken()).rejects.toThrow(
'no legacy keys are configured',
);
});
});
@@ -1,42 +0,0 @@
/*
* Copyright 2022 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,
createServiceFactory,
} from '@backstage/backend-plugin-api';
import { ServerTokenManager } from '@backstage/backend-common';
/**
* @public
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
*/
export const tokenManagerServiceFactory = createServiceFactory({
service: coreServices.tokenManager,
deps: {
config: coreServices.rootConfig,
logger: coreServices.rootLogger,
},
createRootContext({ config, logger }) {
return ServerTokenManager.fromConfig(config, {
logger,
allowDisabledTokenManager: true,
});
},
async factory(_deps, tokenManager) {
return tokenManager;
},
});
+7 -4
View File
@@ -22,7 +22,6 @@ import Docker from 'dockerode';
import { ErrorRequestHandler } from 'express';
import express from 'express';
import { HttpAuthService } from '@backstage/backend-plugin-api';
import { IdentityService } from '@backstage/backend-plugin-api';
import { isChildPath as isChildPath_2 } from '@backstage/backend-plugin-api';
import { isDatabaseConflictError as isDatabaseConflictError_2 } from '@backstage/backend-plugin-api';
import { KubeConfig } from '@kubernetes/client-node';
@@ -44,7 +43,6 @@ import { Router } from 'express';
import { SchedulerService } from '@backstage/backend-plugin-api';
import { Server } from 'http';
import { ServiceRef } from '@backstage/backend-plugin-api';
import { TokenManagerService } from '@backstage/backend-plugin-api';
import { TransportStreamOptions } from 'winston-transport';
import { UrlReaderService } from '@backstage/backend-plugin-api';
import { UserInfoService } from '@backstage/backend-plugin-api';
@@ -101,7 +99,7 @@ export function createLegacyAuthAdapters<
auth?: AuthService;
httpAuth?: HttpAuthService;
userInfo?: UserInfoService;
identity?: IdentityService;
identity?: LegacyIdentityService;
tokenManager?: TokenManager;
discovery: PluginEndpointDiscovery;
},
@@ -547,7 +545,12 @@ export interface StatusCheckHandlerOptions {
}
// @public @deprecated (undocumented)
export type TokenManager = TokenManagerService;
export interface TokenManager {
authenticate(token: string): Promise<void>;
getToken(): Promise<{
token: string;
}>;
}
// @public @deprecated
export function useHotCleanup(
@@ -14,18 +14,28 @@
* limitations under the License.
*/
import { mockServices } from '@backstage/backend-test-utils';
import { createLegacyAuthAdapters } from './createLegacyAuthAdapters';
import { Request } from 'express';
import { TokenManager } from '../../deprecated';
const mockTokenManager: TokenManager = {
async getToken(): Promise<{ token: string }> {
return { token: 'mock-token' };
},
async authenticate(token: string): Promise<void> {
if (token !== 'mock-token') {
throw new Error('Invalid token');
}
},
};
describe('createLegacyAuthAdapters', () => {
it('should pass through auth if only auth is provided', () => {
const auth = {};
const ret = createLegacyAuthAdapters({
auth: auth as any,
tokenManager: mockServices.tokenManager(),
tokenManager: mockTokenManager,
discovery: {} as any,
identity: mockServices.identity(),
});
expect(ret.auth).toBe(auth);
@@ -35,9 +45,8 @@ describe('createLegacyAuthAdapters', () => {
const httpAuth = {};
const ret = createLegacyAuthAdapters({
httpAuth: httpAuth as any,
tokenManager: mockServices.tokenManager(),
tokenManager: mockTokenManager,
discovery: {} as any,
identity: mockServices.identity(),
});
expect(ret.httpAuth).toBe(httpAuth);
@@ -49,9 +58,8 @@ describe('createLegacyAuthAdapters', () => {
const ret = createLegacyAuthAdapters({
auth: auth as any,
httpAuth: httpAuth as any,
tokenManager: mockServices.tokenManager(),
tokenManager: mockTokenManager,
discovery: {} as any,
identity: mockServices.identity(),
});
expect(ret.auth).toBe(auth);
@@ -64,9 +72,8 @@ describe('createLegacyAuthAdapters', () => {
const ret = createLegacyAuthAdapters({
auth: auth as any,
userInfo: userInfo as any,
tokenManager: mockServices.tokenManager(),
tokenManager: mockTokenManager,
discovery: {} as any,
identity: mockServices.identity(),
});
expect(ret.auth).toBe(auth);
@@ -77,9 +84,8 @@ describe('createLegacyAuthAdapters', () => {
const ret = createLegacyAuthAdapters({
auth: undefined,
httpAuth: undefined,
tokenManager: mockServices.tokenManager(),
tokenManager: mockTokenManager,
discovery: {} as any,
identity: mockServices.identity(),
});
expect(ret).toEqual({
@@ -94,7 +100,6 @@ describe('createLegacyAuthAdapters', () => {
auth: undefined,
httpAuth: undefined,
discovery: {} as any,
identity: mockServices.identity(),
});
const credentials = await httpAuth.credentials({
@@ -116,13 +121,12 @@ describe('createLegacyAuthAdapters', () => {
auth: undefined,
httpAuth: undefined,
tokenManager: {
...mockServices.tokenManager(),
...mockTokenManager,
async getToken() {
return { token: 'new-token' };
},
},
discovery: {} as any,
identity: mockServices.identity(),
});
const credentials = await httpAuth.credentials({
@@ -23,8 +23,6 @@ import {
BackstageUserInfo,
BackstageUserPrincipal,
HttpAuthService,
IdentityService,
TokenManagerService,
UserInfoService,
} from '@backstage/backend-plugin-api';
import { AuthenticationError, NotAllowedError } from '@backstage/errors';
@@ -44,11 +42,12 @@ import {
import { decodeJwt } from 'jose';
import { TokenManager, PluginEndpointDiscovery } from '../../deprecated';
import { JsonObject } from '@backstage/types';
import { LegacyIdentityService } from '../legacy';
class AuthCompat implements AuthService {
constructor(
private readonly identity: IdentityService,
private readonly tokenManager?: TokenManagerService,
private readonly identity: LegacyIdentityService,
private readonly tokenManager?: TokenManager,
) {}
isPrincipal<TType extends keyof BackstagePrincipalTypes>(
@@ -299,7 +298,7 @@ export function createLegacyAuthAdapters<
auth?: AuthService;
httpAuth?: HttpAuthService;
userInfo?: UserInfoService;
identity?: IdentityService;
identity?: LegacyIdentityService;
tokenManager?: TokenManager;
discovery: PluginEndpointDiscovery;
},
@@ -14,10 +14,25 @@
* limitations under the License.
*/
import { TokenManagerService } from '@backstage/backend-plugin-api';
/**
* @public
* @deprecated Please {@link https://backstage.io/docs/tutorials/auth-service-migration | migrate} to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead.
*/
export type TokenManager = TokenManagerService;
export interface TokenManager {
/**
* Fetches a valid token.
*
* @remarks
*
* Tokens are valid for roughly one hour; the actual deadline is set in the
* payload `exp` claim. Never hold on to tokens for reuse; always ask for a
* new one for each outgoing request. This ensures that you always get a
* valid, fresh one.
*/
getToken(): Promise<{ token: string }>;
/**
* Validates a given token.
*/
authenticate(token: string): Promise<void>;
}
@@ -14,12 +14,7 @@
* limitations under the License.
*/
import {
Backend,
createSpecializedBackend,
identityServiceFactory,
tokenManagerServiceFactory,
} from '@backstage/backend-app-api';
import { Backend, createSpecializedBackend } from '@backstage/backend-app-api';
import { authServiceFactory } from '@backstage/backend-defaults/auth';
import { cacheServiceFactory } from '@backstage/backend-defaults/cache';
import { databaseServiceFactory } from '@backstage/backend-defaults/database';
@@ -47,7 +42,6 @@ export const defaultServiceFactories = [
discoveryServiceFactory,
httpAuthServiceFactory,
httpRouterServiceFactory,
identityServiceFactory,
lifecycleServiceFactory,
loggerServiceFactory,
permissionsServiceFactory,
@@ -56,7 +50,6 @@ export const defaultServiceFactories = [
rootLifecycleServiceFactory,
rootLoggerServiceFactory,
schedulerServiceFactory,
tokenManagerServiceFactory,
userInfoServiceFactory,
urlReaderServiceFactory,
eventsServiceFactory,
@@ -19,7 +19,6 @@ import {
mockServices,
registerMswTestHooks,
} from '@backstage/backend-test-utils';
import { tokenManagerServiceFactory } from '@backstage/backend-app-api';
import { authServiceFactory } from './authServiceFactory';
import { base64url, decodeJwt } from 'jose';
import { discoveryServiceFactory } from '../discovery';
@@ -32,7 +31,6 @@ const server = setupServer();
// TODO: Ship discovery mock service in the service factory tester
const mockDeps = [
discoveryServiceFactory,
tokenManagerServiceFactory,
mockServices.rootConfig.factory({
data: {
backend: {
@@ -35,13 +35,11 @@ export const permissionsServiceFactory = createServiceFactory({
auth: coreServices.auth,
config: coreServices.rootConfig,
discovery: coreServices.discovery,
tokenManager: coreServices.tokenManager,
},
async factory({ auth, config, discovery, tokenManager }) {
async factory({ auth, config, discovery }) {
return ServerPermissionClient.fromConfig(config, {
auth,
discovery,
tokenManager,
});
},
});
-16
View File
@@ -12,7 +12,6 @@ import { Duration } from 'luxon';
import { EvaluatorRequestOptions } from '@backstage/plugin-permission-common';
import { Handler } from 'express';
import { HumanDuration } from '@backstage/types';
import { IdentityApi } from '@backstage/plugin-auth-node';
import { isChildPath } from '@backstage/cli-common';
import { JsonObject } from '@backstage/types';
import { JsonValue } from '@backstage/types';
@@ -194,11 +193,7 @@ export namespace coreServices {
const rootLifecycle: ServiceRef<RootLifecycleService, 'root', 'singleton'>;
const rootLogger: ServiceRef<RootLoggerService, 'root', 'singleton'>;
const scheduler: ServiceRef<SchedulerService, 'plugin', 'singleton'>;
const // @deprecated
tokenManager: ServiceRef<TokenManagerService, 'plugin', 'singleton'>;
const urlReader: ServiceRef<UrlReaderService, 'plugin', 'singleton'>;
const // @deprecated
identity: ServiceRef<IdentityService, 'plugin', 'singleton'>;
}
// @public
@@ -383,9 +378,6 @@ export interface HttpRouterServiceAuthPolicy {
path: string;
}
// @public @deprecated
export interface IdentityService extends IdentityApi {}
export { isChildPath };
// @public
@@ -654,14 +646,6 @@ export interface ServiceRefOptions<
scope?: TScope;
}
// @public @deprecated
export interface TokenManagerService {
authenticate(token: string): Promise<void>;
getToken(): Promise<{
token: string;
}>;
}
// @public
export interface UrlReaderService {
readTree(
@@ -1,27 +0,0 @@
/*
* Copyright 2020 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 { IdentityApi } from '@backstage/plugin-auth-node';
/**
* This is the legacy service for identity handling in Backstage. Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead.
*
* See the {@link https://backstage.io/docs/backend-system/core-services/identity | service documentation} for more details.
*
* @public
* @deprecated Please {@link https://backstage.io/docs/tutorials/auth-service-migration | migrate} to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead.
*/
export interface IdentityService extends IdentityApi {}
@@ -1,42 +0,0 @@
/*
* Copyright 2022 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.
*/
/**
* This is the legacy service for creating and validating tokens. Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead.
*
* See the {@link https://backstage.io/docs/backend-system/core-services/token-manager | service documentation} for more details.
*
* @public
* @deprecated Please {@link https://backstage.io/docs/tutorials/auth-service-migration | migrate} to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead.
*/
export interface TokenManagerService {
/**
* Fetches a valid token.
*
* @remarks
*
* Tokens are valid for roughly one hour; the actual deadline is set in the
* payload `exp` claim. Never hold on to tokens for reuse; always ask for a
* new one for each outgoing request. This ensures that you always get a
* valid, fresh one.
*/
getToken(): Promise<{ token: string }>;
/**
* Validates a given token.
*/
authenticate(token: string): Promise<void>;
}
@@ -239,20 +239,6 @@ export namespace coreServices {
import('./SchedulerService').SchedulerService
>({ id: 'core.scheduler' });
/**
* Deprecated service authentication service, use the `auth` service instead.
*
* See {@link TokenManagerService}
* and {@link https://backstage.io/docs/backend-system/core-services/token-manager | the service docs}
* for more information.
*
* @public
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
*/
export const tokenManager = createServiceRef<
import('./TokenManagerService').TokenManagerService
>({ id: 'core.tokenManager' });
/**
* Reading content from external systems.
*
@@ -265,18 +251,4 @@ export namespace coreServices {
export const urlReader = createServiceRef<
import('./UrlReaderService').UrlReaderService
>({ id: 'core.urlReader' });
/**
* Deprecated user authentication service, use the `auth` service instead.
*
* See {@link IdentityService}
* and {@link https://backstage.io/docs/backend-system/core-services/identity | the service docs}
* for more information.
*
* @public
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
*/
export const identity = createServiceRef<
import('./IdentityService').IdentityService
>({ id: 'core.identity' });
}
@@ -64,7 +64,6 @@ export type {
SchedulerServiceTaskScheduleDefinition,
SchedulerServiceTaskScheduleDefinitionConfig,
} from './SchedulerService';
export type { TokenManagerService } from './TokenManagerService';
export type {
UrlReaderServiceReadTreeOptions,
UrlReaderServiceReadTreeResponse,
@@ -78,4 +77,3 @@ export type {
UrlReaderService,
} from './UrlReaderService';
export type { BackstageUserInfo, UserInfoService } from './UserInfoService';
export type { IdentityService } from './IdentityService';
-24
View File
@@ -23,7 +23,6 @@ import { ExtendedHttpServer } from '@backstage/backend-defaults/rootHttpRouter';
import { ExtensionPoint } from '@backstage/backend-plugin-api';
import { HttpAuthService } from '@backstage/backend-plugin-api';
import { HttpRouterService } from '@backstage/backend-plugin-api';
import { IdentityService } from '@backstage/backend-plugin-api';
import { JsonObject } from '@backstage/types';
import Keyv from 'keyv';
import { Knex } from 'knex';
@@ -39,7 +38,6 @@ import { RootLoggerService } from '@backstage/backend-plugin-api';
import { SchedulerService } from '@backstage/backend-plugin-api';
import { ServiceFactory } from '@backstage/backend-plugin-api';
import { ServiceRef } from '@backstage/backend-plugin-api';
import { TokenManagerService } from '@backstage/backend-plugin-api';
import { UrlReaderService } from '@backstage/backend-plugin-api';
import { UserInfoService } from '@backstage/backend-plugin-api';
@@ -217,17 +215,6 @@ export namespace mockServices {
) => ServiceMock<HttpRouterService>;
}
// (undocumented)
export function identity(): IdentityService;
// (undocumented)
export namespace identity {
const // (undocumented)
factory: () => ServiceFactory<IdentityService, 'plugin', 'singleton'>;
const // (undocumented)
mock: (
partialImpl?: Partial<IdentityService> | undefined,
) => ServiceMock<IdentityService>;
}
// (undocumented)
export namespace lifecycle {
const // (undocumented)
factory: () => ServiceFactory<LifecycleService, 'plugin', 'singleton'>;
@@ -324,17 +311,6 @@ export namespace mockServices {
) => ServiceMock<SchedulerService>;
}
// (undocumented)
export function tokenManager(): TokenManagerService;
// (undocumented)
export namespace tokenManager {
const // (undocumented)
factory: () => ServiceFactory<TokenManagerService, 'plugin', 'singleton'>;
const // (undocumented)
mock: (
partialImpl?: Partial<TokenManagerService> | undefined,
) => ServiceMock<TokenManagerService>;
}
// (undocumented)
export namespace urlReader {
const // (undocumented)
factory: () => ServiceFactory<UrlReaderService, 'plugin', 'singleton'>;
@@ -1,35 +0,0 @@
/*
* 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 { IdentityService } from '@backstage/backend-plugin-api';
import {
IdentityApiGetIdentityRequest,
BackstageIdentityResponse,
} from '@backstage/plugin-auth-node';
export class MockIdentityService implements IdentityService {
getIdentity(
_options: IdentityApiGetIdentityRequest,
): Promise<BackstageIdentityResponse | undefined> {
return Promise.resolve({
token: 'mock-token',
identity: {
type: 'user',
userEntityRef: 'user:default/mock-user',
ownershipEntityRefs: [],
},
});
}
}
@@ -35,12 +35,10 @@ import {
BackstageUserInfo,
DiscoveryService,
HttpAuthService,
IdentityService,
LoggerService,
RootConfigService,
ServiceFactory,
ServiceRef,
TokenManagerService,
UserInfoService,
coreServices,
createServiceFactory,
@@ -53,7 +51,6 @@ import {
import { JsonObject } from '@backstage/types';
import { MockAuthService } from './MockAuthService';
import { MockHttpAuthService } from './MockHttpAuthService';
import { MockIdentityService } from './MockIdentityService';
import { MockRootLoggerService } from './MockRootLoggerService';
import { MockUserInfoService } from './MockUserInfoService';
import { mockCredentials } from './mockCredentials';
@@ -167,46 +164,6 @@ export namespace mockServices {
}));
}
export function tokenManager(): TokenManagerService {
return {
async getToken(): Promise<{ token: string }> {
return { token: 'mock-token' };
},
async authenticate(token: string): Promise<void> {
if (token !== 'mock-token') {
throw new Error('Invalid token');
}
},
};
}
export namespace tokenManager {
export const factory = () =>
createServiceFactory({
service: coreServices.tokenManager,
deps: {},
factory: () => tokenManager(),
});
export const mock = simpleMock(coreServices.tokenManager, () => ({
authenticate: jest.fn(),
getToken: jest.fn(),
}));
}
export function identity(): IdentityService {
return new MockIdentityService();
}
export namespace identity {
export const factory = () =>
createServiceFactory({
service: coreServices.identity,
deps: {},
factory: () => identity(),
});
export const mock = simpleMock(coreServices.identity, () => ({
getIdentity: jest.fn(),
}));
}
export function auth(options?: {
pluginId?: string;
disableDefaultAuthPolicy?: boolean;
@@ -198,13 +198,12 @@ describe('TestBackend', () => {
rootLifecycle: coreServices.rootLifecycle,
rootLogger: coreServices.rootLogger,
scheduler: coreServices.scheduler,
tokenManager: coreServices.tokenManager,
urlReader: coreServices.urlReader,
auth: coreServices.auth,
httpAuth: coreServices.httpAuth,
},
async init(deps) {
expect(Object.keys(deps)).toHaveLength(17);
expect(Object.keys(deps)).toHaveLength(16);
expect(Object.values(deps)).not.toContain(undefined);
},
});
@@ -72,7 +72,6 @@ export const defaultServiceFactories = [
mockServices.database.factory(),
mockServices.httpAuth.factory(),
mockServices.httpRouter.factory(),
mockServices.identity.factory(),
mockServices.lifecycle.factory(),
mockServices.logger.factory(),
mockServices.permissions.factory(),
@@ -80,7 +79,6 @@ export const defaultServiceFactories = [
mockServices.rootLifecycle.factory(),
mockServices.rootLogger.factory(),
mockServices.scheduler.factory(),
mockServices.tokenManager.factory(),
mockServices.userInfo.factory(),
mockServices.urlReader.factory(),
mockServices.events.factory(),
+2 -3
View File
@@ -41,7 +41,6 @@ import { RootConfigService } from '@backstage/backend-plugin-api';
import { SignInInfo as SignInInfo_2 } from '@backstage/plugin-auth-node';
import { SignInResolver as SignInResolver_2 } from '@backstage/plugin-auth-node';
import { TokenManager } from '@backstage/backend-common';
import { TokenManagerService } from '@backstage/backend-plugin-api';
import { TokenParams as TokenParams_2 } from '@backstage/plugin-auth-node';
import { UserEntity } from '@backstage/catalog-model';
import { WebMessageResponse as WebMessageResponse_2 } from '@backstage/plugin-auth-node';
@@ -126,7 +125,7 @@ export type BitbucketServerOAuthResult = {
export class CatalogIdentityClient {
constructor(options: {
catalogApi: CatalogApi;
tokenManager: TokenManager;
tokenManager?: TokenManager;
discovery: DiscoveryService;
auth?: AuthService;
httpAuth?: HttpAuthService;
@@ -673,7 +672,7 @@ export interface RouterOptions {
// (undocumented)
tokenFactoryAlgorithm?: string;
// (undocumented)
tokenManager: TokenManagerService;
tokenManager?: TokenManager;
}
// @public (undocumented)
-3
View File
@@ -65,7 +65,6 @@ export const authPlugin = createBackendPlugin({
config: coreServices.rootConfig,
database: coreServices.database,
discovery: coreServices.discovery,
tokenManager: coreServices.tokenManager,
auth: coreServices.auth,
httpAuth: coreServices.httpAuth,
catalogApi: catalogServiceRef,
@@ -76,7 +75,6 @@ export const authPlugin = createBackendPlugin({
config,
database,
discovery,
tokenManager,
auth,
httpAuth,
catalogApi,
@@ -86,7 +84,6 @@ export const authPlugin = createBackendPlugin({
config,
database,
discovery,
tokenManager,
auth,
httpAuth,
catalogApi,
@@ -45,7 +45,7 @@ export class CatalogIdentityClient {
constructor(options: {
catalogApi: CatalogApi;
tokenManager: TokenManager;
tokenManager?: TokenManager;
discovery: DiscoveryService;
auth?: AuthService;
httpAuth?: HttpAuthService;
@@ -34,7 +34,6 @@ describe('CatalogAuthResolverContext', () => {
logger: mockServices.logger.mock(),
catalogApi: mockCatalogApi as CatalogApi,
tokenIssuer: {} as TokenIssuer,
tokenManager: mockServices.tokenManager(),
discovery: {} as DiscoveryService,
auth: mockServices.auth(),
httpAuth: mockServices.httpAuth(),
@@ -66,7 +66,7 @@ export class CatalogAuthResolverContext implements AuthResolverContext {
logger: LoggerService;
catalogApi: CatalogApi;
tokenIssuer: TokenIssuer;
tokenManager: TokenManager;
tokenManager?: TokenManager;
discovery: DiscoveryService;
auth: AuthService;
httpAuth: HttpAuthService;
+1 -1
View File
@@ -50,7 +50,7 @@ export function bindProviderRouters(
discovery: PluginEndpointDiscovery;
auth: AuthService;
httpAuth: HttpAuthService;
tokenManager: TokenManager;
tokenManager?: TokenManager;
tokenIssuer: TokenIssuer;
ownershipResolver?: AuthOwnershipResolver;
catalogApi?: CatalogApi;
+5 -3
View File
@@ -24,11 +24,13 @@ import {
HttpAuthService,
LoggerService,
RootConfigService,
TokenManagerService,
} from '@backstage/backend-plugin-api';
import { defaultAuthProviderFactories } from '../providers';
import { AuthOwnershipResolver } from '@backstage/plugin-auth-node';
import { createLegacyAuthAdapters } from '@backstage/backend-common';
import {
TokenManager,
createLegacyAuthAdapters,
} from '@backstage/backend-common';
import { NotFoundError } from '@backstage/errors';
import { CatalogApi } from '@backstage/catalog-client';
import {
@@ -56,7 +58,7 @@ export interface RouterOptions {
database: DatabaseService;
config: RootConfigService;
discovery: DiscoveryService;
tokenManager: TokenManagerService;
tokenManager?: TokenManager;
auth?: AuthService;
httpAuth?: HttpAuthService;
tokenFactoryAlgorithm?: string;
@@ -40,23 +40,13 @@ export const catalogModuleBitbucketCloudEntityProvider = createBackendModule({
events: eventsServiceRef,
logger: coreServices.logger,
scheduler: coreServices.scheduler,
tokenManager: coreServices.tokenManager,
},
async init({
catalog,
catalogApi,
config,
events,
logger,
scheduler,
tokenManager,
}) {
async init({ catalog, catalogApi, config, events, logger, scheduler }) {
const providers = BitbucketCloudEntityProvider.fromConfig(config, {
catalogApi,
events,
logger,
scheduler,
tokenManager,
});
catalog.addEntityProvider(providers);
@@ -5,7 +5,7 @@
```ts
import { BackendFeature } from '@backstage/backend-plugin-api';
import express from 'express';
import { IdentityApi } from '@backstage/plugin-auth-node';
import { HttpAuthService } from '@backstage/backend-plugin-api';
import { LoggerService } from '@backstage/backend-plugin-api';
// @public
@@ -18,7 +18,7 @@ export default exampleTodoListPlugin;
// @public
export interface RouterOptions {
// (undocumented)
identity: IdentityApi;
httpAuth: HttpAuthService;
// (undocumented)
logger: LoggerService;
}
@@ -30,14 +30,14 @@ export const exampleTodoListPlugin = createBackendPlugin({
register(env) {
env.registerInit({
deps: {
identity: coreServices.identity,
httpAuth: coreServices.httpAuth,
logger: coreServices.logger,
httpRouter: coreServices.httpRouter,
},
async init({ identity, logger, httpRouter }) {
async init({ httpAuth, logger, httpRouter }) {
httpRouter.use(
await createRouter({
identity,
httpAuth,
logger,
}),
);
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import { DefaultIdentityClient } from '@backstage/plugin-auth-node';
import express from 'express';
import request from 'supertest';
@@ -27,7 +26,7 @@ describe('createRouter', () => {
beforeAll(async () => {
const router = await createRouter({
logger: mockServices.logger.mock(),
identity: {} as DefaultIdentityClient,
httpAuth: mockServices.httpAuth.mock(),
});
app = express().use(router);
});
@@ -19,8 +19,7 @@ import express from 'express';
import Router from 'express-promise-router';
import { add, getAll, update } from './todos';
import { InputError } from '@backstage/errors';
import { IdentityApi } from '@backstage/plugin-auth-node';
import { LoggerService } from '@backstage/backend-plugin-api';
import { HttpAuthService, LoggerService } from '@backstage/backend-plugin-api';
/**
* Dependencies of the todo-list router
@@ -29,7 +28,7 @@ import { LoggerService } from '@backstage/backend-plugin-api';
*/
export interface RouterOptions {
logger: LoggerService;
identity: IdentityApi;
httpAuth: HttpAuthService;
}
/**
@@ -44,7 +43,7 @@ export interface RouterOptions {
export async function createRouter(
options: RouterOptions,
): Promise<express.Router> {
const { logger, identity } = options;
const { logger, httpAuth } = options;
const router = Router();
router.use(express.json());
@@ -59,16 +58,16 @@ export async function createRouter(
});
router.post('/todos', async (req, res) => {
let author: string | undefined = undefined;
const user = await identity.getIdentity({ request: req });
author = user?.identity.userEntityRef;
const credentials = await httpAuth.credentials(req, { allow: ['user'] });
if (!isTodoCreateRequest(req.body)) {
throw new InputError('Invalid payload');
}
const todo = add({ title: req.body.title, author });
const todo = add({
title: req.body.title,
author: credentials.principal.userEntityRef,
});
res.json(todo);
});
+2 -2
View File
@@ -29,7 +29,7 @@ import { PermissionsServiceRequestOptions } from '@backstage/backend-plugin-api'
import { PolicyDecision } from '@backstage/plugin-permission-common';
import { QueryPermissionRequest } from '@backstage/plugin-permission-common';
import { ResourcePermission } from '@backstage/plugin-permission-common';
import { TokenManagerService } from '@backstage/backend-plugin-api';
import { TokenManager } from '@backstage/backend-common';
import { z } from 'zod';
// @public
@@ -290,7 +290,7 @@ export class ServerPermissionClient implements PermissionsService {
config: Config,
options: {
discovery: DiscoveryService;
tokenManager: TokenManagerService;
tokenManager?: TokenManager;
auth?: AuthService;
},
): ServerPermissionClient;
@@ -82,7 +82,6 @@ describe('ServerPermissionClient', () => {
it('should bypass the permission backend if permissions are disabled', async () => {
const client = ServerPermissionClient.fromConfig(new ConfigReader({}), {
discovery,
tokenManager: mockServices.tokenManager.mock(),
auth: mockServices.auth(),
});
@@ -101,7 +100,6 @@ describe('ServerPermissionClient', () => {
it('should bypass the permission backend if permissions are enabled and request has valid server credentials', async () => {
const client = ServerPermissionClient.fromConfig(config, {
discovery,
tokenManager: mockServices.tokenManager.mock(),
auth: mockServices.auth(),
});
@@ -115,7 +113,6 @@ describe('ServerPermissionClient', () => {
it('should call the permission backend if permissions are enabled and request does not have valid server credentials', async () => {
const client = ServerPermissionClient.fromConfig(config, {
discovery,
tokenManager: mockServices.tokenManager.mock(),
auth: mockServices.auth(),
});
@@ -156,7 +153,6 @@ describe('ServerPermissionClient', () => {
it('should bypass the permission backend if permissions are disabled', async () => {
const client = ServerPermissionClient.fromConfig(new ConfigReader({}), {
discovery,
tokenManager: mockServices.tokenManager.mock(),
auth: mockServices.auth(),
});
@@ -173,7 +169,6 @@ describe('ServerPermissionClient', () => {
it('should bypass the permission backend if permissions are enabled and request has valid server credentials', async () => {
const client = ServerPermissionClient.fromConfig(config, {
discovery,
tokenManager: mockServices.tokenManager.mock(),
auth: mockServices.auth(),
});
@@ -190,7 +185,6 @@ describe('ServerPermissionClient', () => {
it('should call the permission backend if permissions are enabled and request does not have valid server credentials', async () => {
const client = ServerPermissionClient.fromConfig(config, {
discovery,
tokenManager: mockServices.tokenManager.mock(),
auth: mockServices.auth(),
});
@@ -223,7 +217,6 @@ describe('ServerPermissionClient', () => {
}),
{
discovery,
tokenManager: mockServices.tokenManager(),
auth: mockServices.auth(),
},
);
@@ -14,7 +14,10 @@
* limitations under the License.
*/
import { createLegacyAuthAdapters } from '@backstage/backend-common';
import {
TokenManager,
createLegacyAuthAdapters,
} from '@backstage/backend-common';
import {
AuthService,
BackstageCredentials,
@@ -22,7 +25,6 @@ import {
DiscoveryService,
PermissionsService,
PermissionsServiceRequestOptions,
TokenManagerService,
} from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import {
@@ -51,7 +53,8 @@ export class ServerPermissionClient implements PermissionsService {
config: Config,
options: {
discovery: DiscoveryService;
tokenManager: TokenManagerService;
/** @deprecated This option will be removed in the future, provide a the auth option instead */
tokenManager?: TokenManager;
auth?: AuthService;
},
) {
@@ -62,6 +65,7 @@ export class ServerPermissionClient implements PermissionsService {
if (
permissionEnabled &&
tokenManager &&
(tokenManager as any).isInsecureServerTokenManager
) {
throw new Error(
@@ -80,7 +80,6 @@ export default createBackendModule({
auth: coreServices.auth,
config: coreServices.rootConfig,
discovery: coreServices.discovery,
tokenManager: coreServices.tokenManager,
scheduler: coreServices.scheduler,
indexRegistry: searchIndexRegistryExtensionPoint,
catalog: catalogServiceRef,
@@ -89,7 +88,6 @@ export default createBackendModule({
auth,
config,
discovery,
tokenManager,
scheduler,
indexRegistry,
catalog,
@@ -102,7 +100,6 @@ export default createBackendModule({
auth,
entityTransformer,
discovery,
tokenManager,
catalogClient: catalog,
}),
});
@@ -43,7 +43,6 @@ export default createBackendModule({
logger: coreServices.logger,
discovery: coreServices.discovery,
scheduler: coreServices.scheduler,
tokenManager: coreServices.tokenManager,
auth: coreServices.auth,
indexRegistry: searchIndexRegistryExtensionPoint,
},
@@ -52,7 +51,6 @@ export default createBackendModule({
logger,
discovery,
scheduler,
tokenManager,
auth,
indexRegistry,
}) {
@@ -74,7 +72,6 @@ export default createBackendModule({
discovery,
logger,
auth,
tokenManager,
}),
});
},
@@ -78,7 +78,6 @@ export default createBackendModule({
auth: coreServices.auth,
httpAuth: coreServices.httpAuth,
discovery: coreServices.discovery,
tokenManager: coreServices.tokenManager,
scheduler: coreServices.scheduler,
catalog: catalogServiceRef,
indexRegistry: searchIndexRegistryExtensionPoint,
@@ -89,7 +88,6 @@ export default createBackendModule({
auth,
httpAuth,
discovery,
tokenManager,
scheduler,
catalog,
indexRegistry,
@@ -110,7 +108,6 @@ export default createBackendModule({
schedule: scheduler.createScheduledTaskRunner(schedule),
factory: DefaultTechDocsCollatorFactory.fromConfig(config, {
discovery,
tokenManager,
auth,
httpAuth,
logger,
+1 -1
View File
@@ -28,7 +28,7 @@ export interface RouterOptions {
// (undocumented)
events: EventsService;
// (undocumented)
identity: IdentityApi;
identity?: IdentityApi;
// (undocumented)
lifecycle?: LifecycleService;
// (undocumented)
-3
View File
@@ -34,7 +34,6 @@ export const signalsPlugin = createBackendPlugin({
logger: coreServices.logger,
config: coreServices.rootConfig,
lifecycle: coreServices.rootLifecycle,
identity: coreServices.identity,
discovery: coreServices.discovery,
userInfo: coreServices.userInfo,
auth: coreServices.auth,
@@ -45,7 +44,6 @@ export const signalsPlugin = createBackendPlugin({
logger,
config,
lifecycle,
identity,
discovery,
userInfo,
auth,
@@ -55,7 +53,6 @@ export const signalsPlugin = createBackendPlugin({
await createRouter({
logger,
config,
identity,
lifecycle,
discovery,
userInfo,
@@ -40,7 +40,7 @@ import { Config } from '@backstage/config';
export interface RouterOptions {
logger: LoggerService;
events: EventsService;
identity: IdentityApi;
identity?: IdentityApi;
discovery: PluginEndpointDiscovery;
config: Config;
lifecycle?: LifecycleService;
@@ -15,9 +15,7 @@
*/
import { createBackend } from '@backstage/backend-defaults';
import { mockServices } from '@backstage/backend-test-utils';
const backend = createBackend();
backend.add(mockServices.identity.factory());
backend.add(import('../src/alpha'));
backend.start();