Merge pull request #23127 from backstage/blam/make-provider-info-available

auth: Treat `providerInfo` as a separate property from `authenticate`
This commit is contained in:
Ben Lambert
2024-02-21 13:52:06 +01:00
committed by GitHub
13 changed files with 75 additions and 28 deletions
+8
View File
@@ -0,0 +1,8 @@
---
'@backstage/plugin-auth-backend-module-oauth2-proxy-provider': patch
'@backstage/plugin-auth-backend-module-aws-alb-provider': patch
'@backstage/plugin-auth-backend-module-gcp-iap-provider': patch
'@backstage/plugin-auth-node': patch
---
Fix issue with `providerInfo` not being set properly for some proxy providers, by making `providerInfo` an explicit optional return from `authenticate`
@@ -21,7 +21,11 @@ export const awsAlbAuthenticator: ProxyAuthenticator<
issuer: string;
getKey: (header: JWTHeaderParameters) => Promise<KeyObject>;
},
AwsAlbResult
AwsAlbResult,
{
accessToken: string;
expiresInSeconds: number;
}
>;
// @public
@@ -107,6 +107,10 @@ describe('AwsAlbProvider', () => {
expiresInSeconds: mockClaims.exp,
accessToken: mockAccessToken,
},
providerInfo: {
accessToken: mockAccessToken,
expiresInSeconds: mockClaims.exp,
},
});
});
});
@@ -81,8 +81,12 @@ export const awsAlbAuthenticator = createProxyAuthenticator({
return {
result: {
fullProfile,
accessToken: accessToken,
expiresInSeconds: claims.exp,
},
providerInfo: {
accessToken: accessToken,
expiresInSeconds: claims.exp,
accessToken,
},
};
} catch (e) {
@@ -18,6 +18,9 @@ export const gcpIapAuthenticator: ProxyAuthenticator<
jwtHeader: string;
tokenValidator: (token: string) => Promise<GcpIapTokenInfo>;
},
{
iapToken: GcpIapTokenInfo;
},
{
iapToken: GcpIapTokenInfo;
}
@@ -45,7 +45,10 @@ describe('GcpIapProvider', () => {
},
ctx,
),
).resolves.toEqual({ result: { iapToken: { sub: 's', email: 'e' } } });
).resolves.toEqual({
result: { iapToken: { sub: 's', email: 'e' } },
providerInfo: { iapToken: { sub: 's', email: 'e' } },
});
});
it('should find custom JWT header', async () => {
@@ -66,7 +69,10 @@ describe('GcpIapProvider', () => {
},
ctx,
),
).resolves.toEqual({ result: { iapToken: { sub: 's', email: 'e' } } });
).resolves.toEqual({
result: { iapToken: { sub: 's', email: 'e' } },
providerInfo: { iapToken: { sub: 's', email: 'e' } },
});
});
it('should throw if header is missing', async () => {
@@ -47,6 +47,9 @@ export const gcpIapAuthenticator = createProxyAuthenticator({
const iapToken = await tokenValidator(token);
return { result: { iapToken } };
return {
result: { iapToken },
providerInfo: { iapToken },
};
},
});
@@ -18,8 +18,11 @@ export const OAUTH2_PROXY_JWT_HEADER = 'X-OAUTH2-PROXY-ID-TOKEN';
// @public (undocumented)
export const oauth2ProxyAuthenticator: ProxyAuthenticator<
unknown,
OAuth2ProxyResult
Promise<void>,
OAuth2ProxyResult,
{
accessToken: string;
}
>;
// @public
@@ -31,10 +31,7 @@ import { OAuth2ProxyResult } from './types';
export const OAUTH2_PROXY_JWT_HEADER = 'X-OAUTH2-PROXY-ID-TOKEN';
/** @public */
export const oauth2ProxyAuthenticator = createProxyAuthenticator<
unknown,
OAuth2ProxyResult
>({
export const oauth2ProxyAuthenticator = createProxyAuthenticator({
defaultProfileTransform: async (result: OAuth2ProxyResult) => {
return {
profile: {
@@ -63,7 +60,13 @@ export const oauth2ProxyAuthenticator = createProxyAuthenticator<
return req.get(name);
},
};
return { result };
return {
result,
providerInfo: {
accessToken: result.accessToken,
},
};
} catch (e) {
throw new AuthenticationError('Authentication failed', e);
}
+11 -6
View File
@@ -173,13 +173,13 @@ export function createOAuthRouteHandlers<TProfile>(
): AuthProviderRouteHandlers;
// @public (undocumented)
export function createProxyAuthenticator<TContext, TResult>(
authenticator: ProxyAuthenticator<TContext, TResult>,
): ProxyAuthenticator<TContext, TResult>;
export function createProxyAuthenticator<TContext, TResult, TProviderInfo>(
authenticator: ProxyAuthenticator<TContext, TResult, TProviderInfo>,
): ProxyAuthenticator<TContext, TResult, TProviderInfo>;
// @public (undocumented)
export function createProxyAuthProviderFactory<TResult>(options: {
authenticator: ProxyAuthenticator<unknown, TResult>;
authenticator: ProxyAuthenticator<unknown, TResult, unknown>;
profileTransform?: ProfileTransform<TResult>;
signInResolver?: SignInResolver<TResult>;
signInResolverFactories?: Record<
@@ -538,7 +538,11 @@ export type ProfileTransform<TResult> = (
}>;
// @public (undocumented)
export interface ProxyAuthenticator<TContext, TResult> {
export interface ProxyAuthenticator<
TContext,
TResult,
TProviderInfo = undefined,
> {
// (undocumented)
authenticate(
options: {
@@ -547,6 +551,7 @@ export interface ProxyAuthenticator<TContext, TResult> {
ctx: TContext,
): Promise<{
result: TResult;
providerInfo?: TProviderInfo;
}>;
// (undocumented)
defaultProfileTransform: ProfileTransform<TResult>;
@@ -557,7 +562,7 @@ export interface ProxyAuthenticator<TContext, TResult> {
// @public (undocumented)
export interface ProxyAuthRouteHandlersOptions<TResult> {
// (undocumented)
authenticator: ProxyAuthenticator<any, TResult>;
authenticator: ProxyAuthenticator<any, TResult, unknown>;
// (undocumented)
config: Config;
// (undocumented)
@@ -28,7 +28,7 @@ import { ProxyAuthenticator } from './types';
/** @public */
export function createProxyAuthProviderFactory<TResult>(options: {
authenticator: ProxyAuthenticator<unknown, TResult>;
authenticator: ProxyAuthenticator<unknown, TResult, unknown>;
profileTransform?: ProfileTransform<TResult>;
signInResolver?: SignInResolver<TResult>;
signInResolverFactories?: Record<
@@ -29,7 +29,7 @@ import { NotImplementedError } from '@backstage/errors';
/** @public */
export interface ProxyAuthRouteHandlersOptions<TResult> {
authenticator: ProxyAuthenticator<any, TResult>;
authenticator: ProxyAuthenticator<any, TResult, unknown>;
config: Config;
resolverContext: AuthResolverContext;
signInResolver: SignInResolver<TResult>;
@@ -56,7 +56,7 @@ export function createProxyAuthRouteHandlers<TResult>(
},
async refresh(this: never, req: Request, res: Response): Promise<void> {
const { result } = await authenticator.authenticate(
const { result, providerInfo } = await authenticator.authenticate(
{ req },
authenticatorCtx,
);
@@ -68,9 +68,9 @@ export function createProxyAuthRouteHandlers<TResult>(
resolverContext,
);
const response: ClientAuthResponse<{}> = {
const response: ClientAuthResponse<unknown> = {
profile,
providerInfo: {},
providerInfo,
backstageIdentity: prepareBackstageIdentityResponse(identity),
};
+9 -5
View File
@@ -19,18 +19,22 @@ import { Request } from 'express';
import { ProfileTransform } from '../types';
/** @public */
export interface ProxyAuthenticator<TContext, TResult> {
export interface ProxyAuthenticator<
TContext,
TResult,
TProviderInfo = undefined,
> {
defaultProfileTransform: ProfileTransform<TResult>;
initialize(ctx: { config: Config }): TContext;
authenticate(
options: { req: Request },
ctx: TContext,
): Promise<{ result: TResult }>;
): Promise<{ result: TResult; providerInfo?: TProviderInfo }>;
}
/** @public */
export function createProxyAuthenticator<TContext, TResult>(
authenticator: ProxyAuthenticator<TContext, TResult>,
): ProxyAuthenticator<TContext, TResult> {
export function createProxyAuthenticator<TContext, TResult, TProviderInfo>(
authenticator: ProxyAuthenticator<TContext, TResult, TProviderInfo>,
): ProxyAuthenticator<TContext, TResult, TProviderInfo> {
return authenticator;
}