Authentication services, permissions management, and user information handling for secure backend operations in Backstage applications.
Token validation and authentication for plugin-to-plugin communication.
/**
* Interface for handling plugin tokens
*/
interface PluginTokenHandler {
/**
* Verify a plugin token and return associated credentials
* @param token - Plugin token to verify
* @returns Backstage credentials if token is valid
*/
verifyToken(token: string): Promise<BackstageCredentials>;
}
/**
* Service reference for plugin token handler decorators
*/
const pluginTokenHandlerDecoratorServiceRef: ServiceRef<PluginTokenHandler>;HTTP request authentication and credential extraction.
/**
* Default implementation of HTTP authentication service
*/
class DefaultHttpAuthService implements HttpAuthService {
constructor(options: DefaultHttpAuthServiceOptions);
/**
* Extract credentials from HTTP request
* @param req - Express request object
* @returns Backstage credentials or undefined if not authenticated
*/
credentials(req: Request): Promise<BackstageCredentials | undefined>;
/**
* Extract credentials from HTTP request with cookie support
* @param req - Express request object
* @param res - Express response object
* @returns Backstage credentials or undefined if not authenticated
*/
credentials(req: Request, res: Response): Promise<BackstageCredentials | undefined>;
}
interface DefaultHttpAuthServiceOptions {
/**
* Default credentials to use when no authentication is provided
*/
defaultCredentials?: BackstageCredentials;
}Audit logging and event tracking for security and compliance.
/**
* Default implementation of the auditor service
*/
class DefaultAuditorService implements AuditorService {
/**
* Log an audit event
* @param request - Audit event request details
* @returns Promise that resolves when event is logged
*/
log(request: AuditorEventRequest): Promise<void>;
}
/**
* Winston-based root auditor service implementation
*/
class WinstonRootAuditorService implements RootAuditorService {
constructor(options: WinstonRootAuditorServiceOptions);
/**
* Log an audit event at the root level
* @param event - Audit event details
* @returns Promise that resolves when event is logged
*/
log(event: AuditorEvent): Promise<void>;
}
interface WinstonRootAuditorServiceOptions {
logger: Logger;
auditLogger?: Logger;
}Type definitions for audit events and logging.
/**
* Audit event structure
*/
type AuditorEvent = {
eventName: string;
stage: string;
status: AuditorEventStatus;
level: 'info' | 'warn' | 'error' | 'debug';
actorId?: string;
actorDetails?: AuditorEventActorDetails;
issuedAt: Date;
request?: AuditorEventRequest;
response?: {
status: number;
body?: unknown;
};
errors?: Error[];
meta?: Record<string, unknown>;
};
/**
* Status enumeration for audit events
*/
type AuditorEventStatus = 'succeeded' | 'failed';
/**
* Actor details for audit events
*/
type AuditorEventActorDetails = {
ip?: string;
userAgent?: string;
hostname?: string;
userEntityRef?: string;
};
/**
* Request structure for audit events
*/
type AuditorEventRequest = {
url: string;
method: string;
body?: unknown;
params?: Record<string, string>;
query?: Record<string, string | string[]>;
};
/**
* Options for audit events
*/
type AuditorEventOptions = {
actorId?: string;
actorDetails?: AuditorEventActorDetails;
request?: AuditorEventRequest;
response?: {
status: number;
body?: unknown;
};
errors?: Error[];
meta?: Record<string, unknown>;
};
/**
* Function signature for audit logging
*/
type AuditorLogFunction = (
eventName: string,
stage: string,
options?: AuditorEventOptions
) => Promise<void>;HTTP Authentication Service:
import { DefaultHttpAuthService } from "@backstage/backend-defaults/httpAuth";
import express from "express";
const httpAuthService = new DefaultHttpAuthService({
defaultCredentials: {
type: 'user',
userEntityRef: 'user:default/guest'
}
});
const app = express();
app.use(async (req, res, next) => {
try {
const credentials = await httpAuthService.credentials(req, res);
if (credentials) {
req.credentials = credentials;
}
next();
} catch (error) {
res.status(401).json({ error: 'Authentication failed' });
}
});Plugin Token Handler:
import { pluginTokenHandlerDecoratorServiceRef } from "@backstage/backend-defaults/auth";
// In a plugin factory
export default createBackendPlugin({
pluginId: 'example',
register(env) {
env.registerInit({
deps: {
tokenHandler: pluginTokenHandlerDecoratorServiceRef,
},
async init({ tokenHandler }) {
// Verify plugin tokens
const credentials = await tokenHandler.verifyToken('plugin-token-here');
console.log('Plugin authenticated:', credentials);
},
});
},
});Audit Logging:
import { DefaultAuditorService, WinstonRootAuditorService } from "@backstage/backend-defaults/auditor";
// Root-level audit service
const rootAuditor = new WinstonRootAuditorService({
logger: backstageLogger,
auditLogger: auditSpecificLogger
});
// Plugin-level audit service
const pluginAuditor = new DefaultAuditorService();
// Log audit events
await rootAuditor.log({
eventName: 'user_login',
stage: 'authentication',
status: 'succeeded',
level: 'info',
actorId: 'user:default/john.doe',
actorDetails: {
ip: '192.168.1.100',
userAgent: 'Mozilla/5.0...',
userEntityRef: 'user:default/john.doe'
},
issuedAt: new Date(),
request: {
url: '/api/auth/login',
method: 'POST',
body: { username: 'john.doe' }
},
response: {
status: 200,
body: { success: true }
}
});
// Log plugin-specific audit event
await pluginAuditor.log({
url: '/api/catalog/entities',
method: 'GET',
params: { kind: 'Component' },
query: { filter: 'metadata.name=my-service' }
});Service Factory Integration:
import {
authServiceFactory,
httpAuthServiceFactory,
permissionsServiceFactory,
auditorServiceFactory
} from "@backstage/backend-defaults";
// These service factories are automatically included in createBackend()
// but can be used individually if needed
const backend = createBackend();
// Add authentication services
backend.add(authServiceFactory);
backend.add(httpAuthServiceFactory);
backend.add(permissionsServiceFactory);
backend.add(auditorServiceFactory);
await backend.start();interface BackstageCredentials {
type: 'user' | 'service' | 'none';
userEntityRef?: string;
ownershipEntityRefs?: string[];
expiresAt?: Date;
}
interface HttpAuthService {
credentials(req: Request, res?: Response): Promise<BackstageCredentials | undefined>;
}
interface AuditorService {
log(request: AuditorEventRequest): Promise<void>;
}
interface RootAuditorService {
log(event: AuditorEvent): Promise<void>;
}
interface PermissionsService {
authorize(
requests: PermissionRequest[],
options?: { credentials: BackstageCredentials }
): Promise<PermissionResponse[]>;
}
interface PermissionRequest {
permission: Permission;
resourceRef?: string;
}
interface PermissionResponse {
result: 'ALLOW' | 'DENY' | 'CONDITIONAL';
conditions?: PermissionCondition;
}