auth-backend: migrate to support new auth services
Co-authored-by: Fredrik Adelöw <freben@gmail.com> Co-authored-by: Carl-Erik Bergström <cbergstrom@spotify.com> Co-authored-by: blam <ben@blam.sh> Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend': minor
|
||||
---
|
||||
|
||||
**BREAKING**: The `CatalogIdentityClient` constructor now also requires the `discovery` service to be forwarded from the plugin environment. This is part of the migration to support the new auth services, which has also been done for the `createRouter` function.
|
||||
@@ -8,6 +8,7 @@ import { AuthProviderFactory as AuthProviderFactory_2 } from '@backstage/plugin-
|
||||
import { AuthProviderRouteHandlers as AuthProviderRouteHandlers_2 } from '@backstage/plugin-auth-node';
|
||||
import { AuthResolverCatalogUserQuery as AuthResolverCatalogUserQuery_2 } from '@backstage/plugin-auth-node';
|
||||
import { AuthResolverContext as AuthResolverContext_2 } from '@backstage/plugin-auth-node';
|
||||
import { AuthService } from '@backstage/backend-plugin-api';
|
||||
import { AwsAlbResult as AwsAlbResult_2 } from '@backstage/plugin-auth-backend-module-aws-alb-provider';
|
||||
import { BackendFeature } from '@backstage/backend-plugin-api';
|
||||
import { BackstageSignInResult } from '@backstage/plugin-auth-node';
|
||||
@@ -17,11 +18,13 @@ import { ClientAuthResponse } from '@backstage/plugin-auth-node';
|
||||
import { Config } from '@backstage/config';
|
||||
import { CookieConfigurer as CookieConfigurer_2 } from '@backstage/plugin-auth-node';
|
||||
import { decodeOAuthState } from '@backstage/plugin-auth-node';
|
||||
import { DiscoveryService } from '@backstage/backend-plugin-api';
|
||||
import { encodeOAuthState } from '@backstage/plugin-auth-node';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import express from 'express';
|
||||
import { GcpIapResult as GcpIapResult_2 } from '@backstage/plugin-auth-backend-module-gcp-iap-provider';
|
||||
import { GcpIapTokenInfo as GcpIapTokenInfo_2 } from '@backstage/plugin-auth-backend-module-gcp-iap-provider';
|
||||
import { HttpAuthService } from '@backstage/backend-plugin-api';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
import { OAuth2ProxyResult as OAuth2ProxyResult_2 } from '@backstage/plugin-auth-backend-module-oauth2-proxy-provider';
|
||||
import { OAuthEnvironmentHandler as OAuthEnvironmentHandler_2 } from '@backstage/plugin-auth-node';
|
||||
@@ -117,7 +120,13 @@ export type BitbucketServerOAuthResult = {
|
||||
|
||||
// @public
|
||||
export class CatalogIdentityClient {
|
||||
constructor(options: { catalogApi: CatalogApi; tokenManager: TokenManager });
|
||||
constructor(options: {
|
||||
catalogApi: CatalogApi;
|
||||
tokenManager: TokenManager;
|
||||
discovery: DiscoveryService;
|
||||
auth?: AuthService;
|
||||
httpAuth?: HttpAuthService;
|
||||
});
|
||||
findUser(query: { annotations: Record<string, string> }): Promise<UserEntity>;
|
||||
resolveCatalogMembership(query: {
|
||||
entityRefs: string[];
|
||||
@@ -642,6 +651,8 @@ export const readState: typeof decodeOAuthState;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface RouterOptions {
|
||||
// (undocumented)
|
||||
auth?: AuthService;
|
||||
// (undocumented)
|
||||
catalogApi?: CatalogApi;
|
||||
// (undocumented)
|
||||
@@ -653,6 +664,8 @@ export interface RouterOptions {
|
||||
// (undocumented)
|
||||
discovery: PluginEndpointDiscovery;
|
||||
// (undocumented)
|
||||
httpAuth?: HttpAuthService;
|
||||
// (undocumented)
|
||||
logger: LoggerService;
|
||||
// (undocumented)
|
||||
providerFactories?: ProviderFactories;
|
||||
|
||||
@@ -75,6 +75,10 @@ export const authPlugin = createBackendPlugin({
|
||||
providerFactories: Object.fromEntries(providers),
|
||||
disableDefaultProviderFactories: true,
|
||||
});
|
||||
httpRouter.addAuthPolicy({
|
||||
path: '/',
|
||||
allow: 'unauthenticated',
|
||||
});
|
||||
httpRouter.use(router);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -48,6 +48,7 @@ describe('CatalogIdentityClient', () => {
|
||||
catalogApi.getEntities.mockResolvedValueOnce({ items: [{} as UserEntity] });
|
||||
tokenManager.getToken.mockResolvedValue({ token: 'my-token' });
|
||||
const client = new CatalogIdentityClient({
|
||||
discovery: {} as any,
|
||||
catalogApi: catalogApi as Partial<CatalogApi> as CatalogApi,
|
||||
tokenManager,
|
||||
});
|
||||
@@ -106,6 +107,7 @@ describe('CatalogIdentityClient', () => {
|
||||
tokenManager.getToken.mockResolvedValue({ token: 'my-token' });
|
||||
|
||||
const client = new CatalogIdentityClient({
|
||||
discovery: {} as any,
|
||||
catalogApi: catalogApi as Partial<CatalogApi> as CatalogApi,
|
||||
tokenManager,
|
||||
});
|
||||
|
||||
@@ -14,7 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
AuthService,
|
||||
DiscoveryService,
|
||||
HttpAuthService,
|
||||
LoggerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { ConflictError, NotFoundError } from '@backstage/errors';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import {
|
||||
@@ -24,7 +29,10 @@ import {
|
||||
stringifyEntityRef,
|
||||
UserEntity,
|
||||
} from '@backstage/catalog-model';
|
||||
import { TokenManager } from '@backstage/backend-common';
|
||||
import {
|
||||
TokenManager,
|
||||
createLegacyAuthAdapters,
|
||||
} from '@backstage/backend-common';
|
||||
|
||||
/**
|
||||
* A catalog client tailored for reading out identity data from the catalog.
|
||||
@@ -33,11 +41,25 @@ import { TokenManager } from '@backstage/backend-common';
|
||||
*/
|
||||
export class CatalogIdentityClient {
|
||||
private readonly catalogApi: CatalogApi;
|
||||
private readonly tokenManager: TokenManager;
|
||||
private readonly auth: AuthService;
|
||||
|
||||
constructor(options: { catalogApi: CatalogApi; tokenManager: TokenManager }) {
|
||||
constructor(options: {
|
||||
catalogApi: CatalogApi;
|
||||
tokenManager: TokenManager;
|
||||
discovery: DiscoveryService;
|
||||
auth?: AuthService;
|
||||
httpAuth?: HttpAuthService;
|
||||
}) {
|
||||
this.catalogApi = options.catalogApi;
|
||||
this.tokenManager = options.tokenManager;
|
||||
|
||||
const { auth } = createLegacyAuthAdapters({
|
||||
auth: options.auth,
|
||||
httpAuth: options.httpAuth,
|
||||
discovery: options.discovery,
|
||||
tokenManager: options.tokenManager,
|
||||
});
|
||||
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +77,11 @@ export class CatalogIdentityClient {
|
||||
filter[`metadata.annotations.${key}`] = value;
|
||||
}
|
||||
|
||||
const { token } = await this.tokenManager.getToken();
|
||||
const { token } = await this.auth.getPluginRequestToken({
|
||||
onBehalfOf: await this.auth.getOwnServiceCredentials(),
|
||||
targetPluginId: 'catalog',
|
||||
});
|
||||
|
||||
const { items } = await this.catalogApi.getEntities({ filter }, { token });
|
||||
|
||||
if (items.length !== 1) {
|
||||
@@ -101,7 +127,12 @@ export class CatalogIdentityClient {
|
||||
'metadata.namespace': ref.namespace,
|
||||
'metadata.name': ref.name,
|
||||
}));
|
||||
const { token } = await this.tokenManager.getToken();
|
||||
|
||||
const { token } = await this.auth.getPluginRequestToken({
|
||||
onBehalfOf: await this.auth.getOwnServiceCredentials(),
|
||||
targetPluginId: 'catalog',
|
||||
});
|
||||
|
||||
const entities = await this.catalogApi
|
||||
.getEntities({ filter }, { token })
|
||||
.then(r => r.items);
|
||||
|
||||
@@ -24,7 +24,12 @@ import {
|
||||
stringifyEntityRef,
|
||||
} from '@backstage/catalog-model';
|
||||
import { ConflictError, InputError, NotFoundError } from '@backstage/errors';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
AuthService,
|
||||
DiscoveryService,
|
||||
HttpAuthService,
|
||||
LoggerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { TokenIssuer } from '../../identity/types';
|
||||
import { CatalogIdentityClient } from '../catalog';
|
||||
import {
|
||||
@@ -61,17 +66,24 @@ export class CatalogAuthResolverContext implements AuthResolverContext {
|
||||
catalogApi: CatalogApi;
|
||||
tokenIssuer: TokenIssuer;
|
||||
tokenManager: TokenManager;
|
||||
discovery: DiscoveryService;
|
||||
auth: AuthService;
|
||||
httpAuth: HttpAuthService;
|
||||
}): CatalogAuthResolverContext {
|
||||
const catalogIdentityClient = new CatalogIdentityClient({
|
||||
catalogApi: options.catalogApi,
|
||||
tokenManager: options.tokenManager,
|
||||
discovery: options.discovery,
|
||||
auth: options.auth,
|
||||
httpAuth: options.httpAuth,
|
||||
});
|
||||
|
||||
return new CatalogAuthResolverContext(
|
||||
options.logger,
|
||||
options.tokenIssuer,
|
||||
catalogIdentityClient,
|
||||
options.catalogApi,
|
||||
options.tokenManager,
|
||||
options.auth,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -80,7 +92,7 @@ export class CatalogAuthResolverContext implements AuthResolverContext {
|
||||
public readonly tokenIssuer: TokenIssuer,
|
||||
public readonly catalogIdentityClient: CatalogIdentityClient,
|
||||
private readonly catalogApi: CatalogApi,
|
||||
private readonly tokenManager: TokenManager,
|
||||
private readonly auth: AuthService,
|
||||
) {}
|
||||
|
||||
async issueToken(params: TokenParams) {
|
||||
@@ -90,7 +102,10 @@ export class CatalogAuthResolverContext implements AuthResolverContext {
|
||||
|
||||
async findCatalogUser(query: AuthResolverCatalogUserQuery) {
|
||||
let result: Entity[] | Entity | undefined = undefined;
|
||||
const { token } = await this.tokenManager.getToken();
|
||||
const { token } = await this.auth.getPluginRequestToken({
|
||||
onBehalfOf: await this.auth.getOwnServiceCredentials(),
|
||||
targetPluginId: 'catalog',
|
||||
});
|
||||
|
||||
if ('entityRef' in query) {
|
||||
const entityRef = parseEntityRef(query.entityRef, {
|
||||
|
||||
@@ -18,7 +18,11 @@ import {
|
||||
PluginEndpointDiscovery,
|
||||
TokenManager,
|
||||
} from '@backstage/backend-common';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
AuthService,
|
||||
HttpAuthService,
|
||||
LoggerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { CatalogApi, CatalogClient } from '@backstage/catalog-client';
|
||||
import { Config } from '@backstage/config';
|
||||
import { NotFoundError, assertError } from '@backstage/errors';
|
||||
@@ -41,6 +45,8 @@ export function bindProviderRouters(
|
||||
config: Config;
|
||||
logger: LoggerService;
|
||||
discovery: PluginEndpointDiscovery;
|
||||
auth: AuthService;
|
||||
httpAuth: HttpAuthService;
|
||||
tokenManager: TokenManager;
|
||||
tokenIssuer: TokenIssuer;
|
||||
catalogApi?: CatalogApi;
|
||||
@@ -53,6 +59,8 @@ export function bindProviderRouters(
|
||||
config,
|
||||
logger,
|
||||
discovery,
|
||||
auth,
|
||||
httpAuth,
|
||||
tokenManager,
|
||||
tokenIssuer,
|
||||
catalogApi,
|
||||
@@ -69,10 +77,10 @@ export function bindProviderRouters(
|
||||
const provider = providerFactory({
|
||||
providerId,
|
||||
appUrl,
|
||||
baseUrl: baseUrl,
|
||||
baseUrl,
|
||||
isOriginAllowed,
|
||||
globalConfig: {
|
||||
baseUrl: baseUrl,
|
||||
baseUrl,
|
||||
appUrl,
|
||||
isOriginAllowed,
|
||||
},
|
||||
@@ -84,6 +92,9 @@ export function bindProviderRouters(
|
||||
catalogApi ?? new CatalogClient({ discoveryApi: discovery }),
|
||||
tokenIssuer,
|
||||
tokenManager,
|
||||
discovery,
|
||||
auth,
|
||||
httpAuth,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -17,12 +17,17 @@
|
||||
import express from 'express';
|
||||
import Router from 'express-promise-router';
|
||||
import cookieParser from 'cookie-parser';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
AuthService,
|
||||
HttpAuthService,
|
||||
LoggerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { defaultAuthProviderFactories } from '../providers';
|
||||
import {
|
||||
PluginDatabaseManager,
|
||||
PluginEndpointDiscovery,
|
||||
TokenManager,
|
||||
createLegacyAuthAdapters,
|
||||
} from '@backstage/backend-common';
|
||||
import { NotFoundError } from '@backstage/errors';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
@@ -45,6 +50,8 @@ export interface RouterOptions {
|
||||
config: Config;
|
||||
discovery: PluginEndpointDiscovery;
|
||||
tokenManager: TokenManager;
|
||||
auth?: AuthService;
|
||||
httpAuth?: HttpAuthService;
|
||||
tokenFactoryAlgorithm?: string;
|
||||
providerFactories?: ProviderFactories;
|
||||
disableDefaultProviderFactories?: boolean;
|
||||
@@ -63,6 +70,9 @@ export async function createRouter(
|
||||
tokenFactoryAlgorithm,
|
||||
providerFactories = {},
|
||||
} = options;
|
||||
|
||||
const { auth, httpAuth } = createLegacyAuthAdapters(options);
|
||||
|
||||
const router = Router();
|
||||
|
||||
const appUrl = config.getString('app.baseUrl');
|
||||
@@ -136,6 +146,8 @@ export async function createRouter(
|
||||
baseUrl: authUrl,
|
||||
tokenIssuer,
|
||||
...options,
|
||||
auth,
|
||||
httpAuth,
|
||||
});
|
||||
|
||||
bindOidcRouter(router, {
|
||||
|
||||
Reference in New Issue
Block a user