diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 41c017ef6b..a4076208ae 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -124,9 +124,7 @@ export interface BackstageIdentityResponse extends BackstageSignInResult { identity: BackstageUserIdentity; } -// Warning: (ae-missing-release-tag) "BackstageSignInResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export interface BackstageSignInResult { // @deprecated entity?: Entity; @@ -299,11 +297,6 @@ export const createSamlProvider: ( options?: SamlProviderOptions | undefined, ) => AuthProviderFactory; -// @public -export function decorateWithIdentity( - signInResolverResponse: Omit, -): BackstageIdentityResponse; - // Warning: (ae-missing-release-tag) "factories" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -512,9 +505,7 @@ export type OAuthRefreshRequest = express.Request<{}> & { refreshToken: string; }; -// Warning: (ae-missing-release-tag) "OAuthResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export type OAuthResponse = { profile: ProfileInfo; providerInfo: OAuthProviderInfo; @@ -576,6 +567,11 @@ export const postMessageResponse: ( response: WebMessageResponse, ) => void; +// @public +export function prepareBackstageIdentityResponse( + result: BackstageSignInResult, +): BackstageIdentityResponse; + // @public export type ProfileInfo = { email?: string; diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts index bb0bbf9dbd..eb3f7efa42 100644 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts +++ b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts @@ -38,7 +38,7 @@ import { OAuthRefreshRequest, OAuthState, } from './types'; -import { decorateWithIdentity } from '../../providers/decorateWithIdentity'; +import { prepareBackstageIdentityResponse } from '../../providers/prepareBackstageIdentityResponse'; export const THOUSAND_DAYS_MS = 1000 * 24 * 60 * 60 * 1000; export const TEN_MINUTES_MS = 600 * 1000; @@ -240,14 +240,14 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { } if (identity.token) { - return decorateWithIdentity(identity); + return prepareBackstageIdentityResponse(identity); } const token = await this.options.tokenIssuer.issueToken({ claims: { sub: identity.id }, }); - return decorateWithIdentity({ ...identity, token }); + return prepareBackstageIdentityResponse({ ...identity, token }); } private setNonceCookie = (res: express.Response, nonce: string) => { diff --git a/plugins/auth-backend/src/lib/oauth/types.ts b/plugins/auth-backend/src/lib/oauth/types.ts index 48e3ffe6ea..cd1439b399 100644 --- a/plugins/auth-backend/src/lib/oauth/types.ts +++ b/plugins/auth-backend/src/lib/oauth/types.ts @@ -51,6 +51,11 @@ export type OAuthResult = { refreshToken?: string; }; +/** + * The expected response from an OAuth flow. + * + * @public + */ export type OAuthResponse = { profile: ProfileInfo; providerInfo: OAuthProviderInfo; diff --git a/plugins/auth-backend/src/providers/aws-alb/provider.ts b/plugins/auth-backend/src/providers/aws-alb/provider.ts index 027d5190de..114bc9a204 100644 --- a/plugins/auth-backend/src/providers/aws-alb/provider.ts +++ b/plugins/auth-backend/src/providers/aws-alb/provider.ts @@ -32,7 +32,7 @@ import { CatalogIdentityClient } from '../../lib/catalog'; import { Profile as PassportProfile } from 'passport'; import { makeProfileInfo } from '../../lib/passport'; import { AuthenticationError } from '@backstage/errors'; -import { decorateWithIdentity } from '../decorateWithIdentity'; +import { prepareBackstageIdentityResponse } from '../prepareBackstageIdentityResponse'; export const ALB_JWT_HEADER = 'x-amzn-oidc-data'; export const ALB_ACCESSTOKEN_HEADER = 'x-amzn-oidc-accesstoken'; @@ -199,7 +199,7 @@ export class AwsAlbAuthProvider implements AuthProviderRouteHandlers { accessToken: result.accessToken, expiresInSeconds: result.expiresInSeconds, }, - backstageIdentity: decorateWithIdentity(backstageIdentity), + backstageIdentity: prepareBackstageIdentityResponse(backstageIdentity), profile, }; } diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index 9fe77fe593..4ecbb98fd2 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -47,4 +47,4 @@ export type { ProfileInfo, } from './types'; -export { decorateWithIdentity } from './decorateWithIdentity'; +export { prepareBackstageIdentityResponse } from './prepareBackstageIdentityResponse'; diff --git a/plugins/auth-backend/src/providers/decorateWithIdentity.ts b/plugins/auth-backend/src/providers/prepareBackstageIdentityResponse.ts similarity index 74% rename from plugins/auth-backend/src/providers/decorateWithIdentity.ts rename to plugins/auth-backend/src/providers/prepareBackstageIdentityResponse.ts index 0e0756f8a8..31df7a4cef 100644 --- a/plugins/auth-backend/src/providers/decorateWithIdentity.ts +++ b/plugins/auth-backend/src/providers/prepareBackstageIdentityResponse.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { BackstageIdentityResponse } from './types'; +import { BackstageIdentityResponse, BackstageSignInResult } from './types'; function parseJwtPayload(token: string) { const [_header, payload, _signature] = token.split('.'); @@ -22,16 +22,20 @@ function parseJwtPayload(token: string) { } /** - * @public - * * Parses token and decorates the BackstageIdentityResponse with identity information sourced from the token + * + * @public */ -export function decorateWithIdentity( - signInResolverResponse: Omit, +export function prepareBackstageIdentityResponse( + result: BackstageSignInResult, ): BackstageIdentityResponse { - const { sub, ent } = parseJwtPayload(signInResolverResponse.token); + const { sub, ent } = parseJwtPayload(result.token); return { - ...signInResolverResponse, + ...{ + // TODO: idToken is for backwards compatibility and can be removed in the future + idToken: result.token, + ...result, + }, identity: { type: 'user', userEntityRef: sub, diff --git a/plugins/auth-backend/src/providers/saml/provider.ts b/plugins/auth-backend/src/providers/saml/provider.ts index d0f7791aaa..8a4afd1fa6 100644 --- a/plugins/auth-backend/src/providers/saml/provider.ts +++ b/plugins/auth-backend/src/providers/saml/provider.ts @@ -38,7 +38,7 @@ import { TokenIssuer } from '../../identity/types'; import { isError } from '@backstage/errors'; import { CatalogIdentityClient } from '../../lib/catalog'; import { Logger } from 'winston'; -import { decorateWithIdentity } from '../decorateWithIdentity'; +import { prepareBackstageIdentityResponse } from '../prepareBackstageIdentityResponse'; /** @public */ export type SamlAuthResult = { @@ -118,7 +118,8 @@ export class SamlAuthProvider implements AuthProviderRouteHandlers { }, ); - response.backstageIdentity = decorateWithIdentity(signInResponse); + response.backstageIdentity = + prepareBackstageIdentityResponse(signInResponse); } return postMessageResponse(res, this.appUrl, { diff --git a/plugins/auth-backend/src/providers/types.ts b/plugins/auth-backend/src/providers/types.ts index 9f93e6fa21..dafa52163c 100644 --- a/plugins/auth-backend/src/providers/types.ts +++ b/plugins/auth-backend/src/providers/types.ts @@ -164,6 +164,14 @@ export type BackstageUserIdentity = { ownershipEntityRefs: string[]; }; +/** + * A representation of a successful Backstage sign-in. + * + * Compared to the {@link BackstageIdentityResponse} this type omits + * the decoded identity information embedded in the token. + * + * @public + */ export interface BackstageSignInResult { /** * An opaque ID that uniquely identifies the user within Backstage.