add comments

Signed-off-by: Aramis <sennyeyaramis@gmail.com>
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>
This commit is contained in:
Aramis
2024-01-27 16:31:08 -05:00
committed by aramissennyeydd
parent 1aedf6c524
commit 085ddf4084
8 changed files with 60 additions and 65 deletions
+6 -6
View File
@@ -27,6 +27,12 @@ import {
} from '@backstage/core-plugin-api';
export const providers = [
{
id: 'guest-auth-provider',
title: 'Guest',
message: 'Sign in as a guest',
apiRef: guestAuthApiRef,
},
{
id: 'google-auth-provider',
title: 'Google',
@@ -75,10 +81,4 @@ export const providers = [
message: 'Sign In using Bitbucket Server',
apiRef: bitbucketServerAuthApiRef,
},
{
id: 'guest-auth-provider',
title: 'Guest',
message: 'Sign in as a guest',
apiRef: guestAuthApiRef,
},
];
@@ -41,7 +41,7 @@ const DEFAULT_PROVIDER = {
};
/**
* Implements a guest auth flow.
* Implements a guest auth flow. Heavily based on SAML flow with added support for refreshing the token.
*
* @public
*/
@@ -16,9 +16,15 @@
import { DirectAuthConnector } from './DirectAuthConnector';
/**
* Add support for refreshing direct tokens. Used for guest authentication.
*/
export class RefreshingDirectAuthConnector<
DirectAuthResponse,
> extends DirectAuthConnector<DirectAuthResponse> {
/**
* Pulled from DefaultAuthConnector and adapted for use with DirectAuthConnector.
*/
async refreshSession(): Promise<any> {
const res = await fetch(
`${await this.buildUrl('/refresh')}&optional=true`,
@@ -21,17 +21,21 @@ import type {
SignInResolver,
} from '@backstage/plugin-auth-node';
import { createGuestAuthRouteHandlers } from './createGuestAuthRouteHandlers';
import { GuestInfo } from './types';
import { guestResolver } from './resolvers';
const defaultTransform: ProfileTransform<{}> = async () => {
return {
profile: {
displayName: 'Guest',
},
};
};
/** @public */
export function createGuestAuthProviderFactory(options?: {
profileTransform?: ProfileTransform<GuestInfo>;
signInResolver?: SignInResolver<GuestInfo>;
signInResolverFactories?: Record<
string,
SignInResolverFactory<GuestInfo, unknown>
>;
profileTransform?: ProfileTransform<{}>;
signInResolver?: SignInResolver<{}>;
signInResolverFactories?: Record<string, SignInResolverFactory<{}, unknown>>;
}): AuthProviderFactory {
return ctx => {
const signInResolver = options?.signInResolver ?? guestResolver();
@@ -41,6 +45,7 @@ export function createGuestAuthProviderFactory(options?: {
`No sign-in resolver configured for guest auth provider '${ctx.providerId}'`,
);
}
const profileTransform = options?.profileTransform ?? defaultTransform;
return createGuestAuthRouteHandlers({
signInResolver,
@@ -48,7 +53,7 @@ export function createGuestAuthProviderFactory(options?: {
appUrl: ctx.appUrl,
config: ctx.config,
resolverContext: ctx.resolverContext,
profileTransform: options?.profileTransform,
profileTransform,
});
};
}
@@ -25,7 +25,6 @@ import {
prepareBackstageIdentityResponse,
sendWebMessageResponse,
} from '@backstage/plugin-auth-node';
import { GuestInfo } from './types';
/** @public */
export interface GuestAuthRouteHandlersOptions {
@@ -33,77 +32,61 @@ export interface GuestAuthRouteHandlersOptions {
baseUrl: string;
appUrl: string;
resolverContext: AuthResolverContext;
signInResolver: SignInResolver<GuestInfo>;
profileTransform?: ProfileTransform<GuestInfo>;
signInResolver: SignInResolver<{}>;
profileTransform: ProfileTransform<{}>;
}
const DEFAULT_RESULT: GuestInfo = { name: 'Guest' };
/** @public */
export function createGuestAuthRouteHandlers(
options: GuestAuthRouteHandlersOptions,
): AuthProviderRouteHandlers {
const { resolverContext, signInResolver, appUrl } = options;
const { resolverContext, signInResolver, appUrl, profileTransform } = options;
const createGuestSession = async (): Promise<ClientAuthResponse<{}>> => {
const { profile } = await profileTransform({}, resolverContext);
const identity = await signInResolver(
{ profile, result: {} },
resolverContext,
);
const defaultTransform: ProfileTransform<GuestInfo> = async result => {
return {
profile: {
displayName: result.name,
},
profile,
providerInfo: {},
backstageIdentity: prepareBackstageIdentityResponse(identity),
};
};
const profileTransform = options.profileTransform ?? defaultTransform;
return {
async start(_, res): Promise<void> {
// We are the auth provider for guests, skip this step.
res.redirect('handler/frame');
},
/**
* This is where we create the token for the guest user. You can override the
* entityRef for the guest user with `signInResolver`.
*/
async frameHandler(_, res): Promise<void> {
const { profile } = await profileTransform(
DEFAULT_RESULT,
resolverContext,
);
const response: ClientAuthResponse<GuestInfo> = {
profile,
providerInfo: DEFAULT_RESULT,
};
if (signInResolver) {
const identity = await signInResolver(
{ profile, result: DEFAULT_RESULT },
resolverContext,
);
response.backstageIdentity = prepareBackstageIdentityResponse(identity);
}
const session = await createGuestSession();
// post message back to popup if successful
sendWebMessageResponse(res, appUrl, {
type: 'authorization_response',
response,
response: session,
});
},
/**
* Support refreshing the guest user's token. This should just improve the experience of
* browsing while in guest mode.
*/
async refresh(this: never, _: Request, res: Response): Promise<void> {
const { profile } = await profileTransform(
DEFAULT_RESULT,
resolverContext,
);
const identity = await signInResolver(
{ profile, result: DEFAULT_RESULT },
resolverContext,
);
const response: ClientAuthResponse<{}> = {
profile,
providerInfo: DEFAULT_RESULT,
backstageIdentity: prepareBackstageIdentityResponse(identity),
};
res.status(200).json(response);
const session = await createGuestSession();
res.status(200).json(session);
},
async logout(_, res) {
// If we don't send a response or it gets cached into a 204, the page will hang.
res.end();
},
};
@@ -21,5 +21,4 @@
*/
export { createGuestAuthProviderFactory } from './createGuestAuthFactory';
export type { GuestInfo } from './types';
export { authModuleGuestProvider as default } from './module';
@@ -17,6 +17,12 @@
import { stringifyEntityRef } from '@backstage/catalog-model';
import { createSignInResolverFactory } from '@backstage/plugin-auth-node';
/**
* Provide a default implementation of the user to resolve to. By default, this
* is `user:default/guest`. We will attempt to get that user if they're in the
* catalog. If that user doesn't exist in the catalog, we will still create a
* token for them so they can keep viewing.
*/
export const guestResolver = createSignInResolverFactory({
create() {
return async (_, ctx) => {
@@ -16,10 +16,6 @@
import { ProfileTransform } from '@backstage/plugin-auth-node';
export type GuestInfo = {
name: string;
};
export interface GuestAuthenticator {
defaultProfileTransform: ProfileTransform<GuestInfo>;
defaultProfileTransform: ProfileTransform<{}>;
}