diff --git a/.changeset/giant-nails-grow.md b/.changeset/giant-nails-grow.md index f96efce2ba..7ea36968b9 100644 --- a/.changeset/giant-nails-grow.md +++ b/.changeset/giant-nails-grow.md @@ -2,15 +2,50 @@ '@backstage/plugin-auth-backend': minor --- -- Moved `IdentityClient`, `BackstageSignInResult`, `BackstageIdentityResponse`, - and `BackstageUserIdentity` to `@backstage/plugin-auth-node`. +The following breaking changes were made, which may imply specifically needing +to make small adjustments in your custom auth providers. + +- **BREAKING**: Moved `IdentityClient`, `BackstageSignInResult`, + `BackstageIdentityResponse`, and `BackstageUserIdentity` to + `@backstage/plugin-auth-node`. +- **BREAKING**: Removed deprecated type `BackstageIdentity`, please use + `BackstageSignInResult` from `@backstage/plugin-auth-node` instead. While moving over, `IdentityClient` was also changed in the following ways: -- Made `IdentityClient.listPublicKeys` private. It was only used in tests, and - should not be part of the API surface of that class. -- Removed the static `IdentityClient.getBearerToken`. It is now replaced by - `getBearerTokenFromAuthorizationHeader` from `@backstage/plugin-auth-node`. +- **BREAKING**: Made `IdentityClient.listPublicKeys` private. It was only used + in tests, and should not be part of the API surface of that class. +- **BREAKING**: Removed the static `IdentityClient.getBearerToken`. It is now + replaced by `getBearerTokenFromAuthorizationHeader` from + `@backstage/plugin-auth-node`. +- **BREAKING**: Removed the constructor. Please use the `IdentityClient.create` + static method instead. Since the `IdentityClient` interface is marked as experimental, this is a breaking change without a deprecation period. + +In your auth providers, you may need to update your imports and usages as +follows (example code; yours may be slightly different): + +````diff +-import { IdentityClient } from '@backstage/plugin-auth-backend'; ++import { ++ IdentityClient, ++ getBearerTokenFromAuthorizationHeader ++} from '@backstage/plugin-auth-node'; + + // ... + +- const identity = new IdentityClient({ ++ const identity = IdentityClient.create({ + discovery, + issuer: await discovery.getExternalBaseUrl('auth'), + });``` + + // ... + + const token = +- IdentityClient.getBearerToken(req.headers.authorization) || ++ getBearerTokenFromAuthorizationHeader(req.headers.authorization) || + req.cookies['token']; +```` diff --git a/contrib/docs/tutorials/authenticate-api-requests.md b/contrib/docs/tutorials/authenticate-api-requests.md index 25dd08e054..45ae38b8b7 100644 --- a/contrib/docs/tutorials/authenticate-api-requests.md +++ b/contrib/docs/tutorials/authenticate-api-requests.md @@ -15,7 +15,10 @@ import cookieParser from 'cookie-parser'; import { Request, Response, NextFunction } from 'express'; import { JWT } from 'jose'; import { URL } from 'url'; -import { IdentityClient } from '@backstage/plugin-auth-backend'; +import { + IdentityClient, + getBearerTokenFromAuthorizationHeader, +} from '@backstage/plugin-auth-node'; // ... @@ -44,7 +47,7 @@ async function main() { // ... const discovery = SingleHostDiscovery.fromConfig(config); - const identity = new IdentityClient({ + const identity = IdentityClient.create({ discovery, issuer: await discovery.getExternalBaseUrl('auth'), }); @@ -58,7 +61,7 @@ async function main() { ) => { try { const token = - IdentityClient.getBearerToken(req.headers.authorization) || + getBearerTokenFromAuthorizationHeader(req.headers.authorization) || req.cookies['token']; req.user = await identity.authenticate(token); if (!req.headers.authorization) { @@ -80,7 +83,7 @@ async function main() { const apiRouter = Router(); apiRouter.use(cookieParser()); - // The auth route must be publically available as it is used during login + // The auth route must be publicly available as it is used during login apiRouter.use('/auth', await auth(authEnv)); // Add a simple endpoint to be used when setting a token cookie apiRouter.use('/cookie', authMiddleware, (_req, res) => { diff --git a/packages/backend/src/plugins/permission.ts b/packages/backend/src/plugins/permission.ts index 6ba24ba1f7..276d16ff97 100644 --- a/packages/backend/src/plugins/permission.ts +++ b/packages/backend/src/plugins/permission.ts @@ -40,7 +40,7 @@ export default async function createPlugin( logger, discovery, policy: new AllowAllPermissionPolicy(), - identity: new IdentityClient({ + identity: IdentityClient.create({ discovery, issuer: await discovery.getExternalBaseUrl('auth'), }), diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 66153fd0af..416da59b46 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -128,9 +128,6 @@ export type AwsAlbProviderOptions = { }; }; -// @public @deprecated -export type BackstageIdentity = BackstageSignInResult; - // Warning: (ae-missing-release-tag) "BitbucketOAuthResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index 37ce09978c..78814ae7e6 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -48,6 +48,6 @@ export type { // These types are needed for a postMessage from the login pop-up // to the frontend -export type { AuthResponse, BackstageIdentity, ProfileInfo } from './types'; +export type { AuthResponse, ProfileInfo } from './types'; export { prepareBackstageIdentityResponse } from './prepareBackstageIdentityResponse'; diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index 6bef80fd4c..5bd52f0c94 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -164,14 +164,6 @@ export type AuthResponse = { backstageIdentity?: BackstageIdentityResponse; }; -/** - * The old exported symbol for {@link @backstage/plugin-auth-node#BackstageSignInResult}. - * - * @public - * @deprecated Use the {@link @backstage/plugin-auth-node#BackstageSignInResult} instead. - */ -export type BackstageIdentity = BackstageSignInResult; - /** * Used to display login information to user, i.e. sidebar popup. * diff --git a/plugins/auth-node/api-report.md b/plugins/auth-node/api-report.md index 7a04ba8181..7840fc7d74 100644 --- a/plugins/auth-node/api-report.md +++ b/plugins/auth-node/api-report.md @@ -34,7 +34,10 @@ export function getBearerTokenFromAuthorizationHeader( // @public export class IdentityClient { - constructor(options: { discovery: PluginEndpointDiscovery; issuer: string }); authenticate(token: string | undefined): Promise; + static create(options: { + discovery: PluginEndpointDiscovery; + issuer: string; + }): IdentityClient; } ``` diff --git a/plugins/auth-node/src/IdentityClient.test.ts b/plugins/auth-node/src/IdentityClient.test.ts index cddc5f33a2..72ef7f2a57 100644 --- a/plugins/auth-node/src/IdentityClient.test.ts +++ b/plugins/auth-node/src/IdentityClient.test.ts @@ -98,7 +98,7 @@ describe('IdentityClient', () => { afterEach(() => server.resetHandlers()); beforeEach(() => { - client = new IdentityClient({ discovery, issuer: mockBaseUrl }); + client = IdentityClient.create({ discovery, issuer: mockBaseUrl }); factory = new FakeTokenFactory({ issuer: mockBaseUrl, keyDurationSeconds, diff --git a/plugins/auth-node/src/IdentityClient.ts b/plugins/auth-node/src/IdentityClient.ts index ddbccff027..d8e841bf75 100644 --- a/plugins/auth-node/src/IdentityClient.ts +++ b/plugins/auth-node/src/IdentityClient.ts @@ -35,7 +35,20 @@ export class IdentityClient { private keyStore: JWKS.KeyStore; private keyStoreUpdated: number; - constructor(options: { discovery: PluginEndpointDiscovery; issuer: string }) { + /** + * Create a new {@link IdentityClient} instance. + */ + static create(options: { + discovery: PluginEndpointDiscovery; + issuer: string; + }): IdentityClient { + return new IdentityClient(options); + } + + private constructor(options: { + discovery: PluginEndpointDiscovery; + issuer: string; + }) { this.discovery = options.discovery; this.issuer = options.issuer; this.keyStore = new JWKS.KeyStore();