auth-backend: decorateWithIdentity -> prepareBackstageIdentityResponse + API report fixes

Co-authored-by: blam <ben@blam.sh>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-12-06 17:13:26 +01:00
parent a036b65c2f
commit 1154ec0017
8 changed files with 40 additions and 26 deletions
+7 -11
View File
@@ -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, 'identity'>,
): 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;
@@ -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) => {
@@ -51,6 +51,11 @@ export type OAuthResult = {
refreshToken?: string;
};
/**
* The expected response from an OAuth flow.
*
* @public
*/
export type OAuthResponse = {
profile: ProfileInfo;
providerInfo: OAuthProviderInfo;
@@ -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,
};
}
+1 -1
View File
@@ -47,4 +47,4 @@ export type {
ProfileInfo,
} from './types';
export { decorateWithIdentity } from './decorateWithIdentity';
export { prepareBackstageIdentityResponse } from './prepareBackstageIdentityResponse';
@@ -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<BackstageIdentityResponse, 'identity'>,
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,
@@ -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, {
@@ -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.