removed logacy, oauth, and some more provider code

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2025-04-15 21:56:28 +02:00
parent d72da5ec19
commit 5205cc9c4e
15 changed files with 0 additions and 1035 deletions
@@ -1,61 +0,0 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AuthResolverContext } from '@backstage/plugin-auth-node';
import { AuthHandler } from '../../providers';
import { OAuthResult } from '../oauth';
import { PassportProfile } from '../passport/types';
import { adaptLegacyOAuthHandler } from './adaptLegacyOAuthHandler';
describe('adaptLegacyOAuthHandler', () => {
it('should pass through undefined', () => {
expect(adaptLegacyOAuthHandler(undefined)).toBeUndefined();
});
it('should convert an old auth handler to a new profile transform', () => {
const authHandler: AuthHandler<OAuthResult> = jest.fn();
const profileTransform = adaptLegacyOAuthHandler(authHandler);
profileTransform?.(
{
fullProfile: { id: 'id' } as PassportProfile,
session: {
accessToken: 'token',
expiresInSeconds: 3,
scope: 'sco pe',
tokenType: 'bear',
idToken: 'id-token',
refreshToken: 'refresh-token',
},
},
{ ctx: 'ctx' } as unknown as AuthResolverContext,
);
expect(authHandler).toHaveBeenCalledWith(
{
fullProfile: { id: 'id' },
accessToken: 'token',
params: {
scope: 'sco pe',
id_token: 'id-token',
expires_in: 3,
token_type: 'bear',
},
},
{ ctx: 'ctx' },
);
});
});
@@ -1,46 +0,0 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
OAuthAuthenticatorResult,
ProfileTransform,
} from '@backstage/plugin-auth-node';
import { AuthHandler } from '../../providers';
import { OAuthResult } from '../oauth';
import { PassportProfile } from '../passport/types';
/** @internal */
export function adaptLegacyOAuthHandler(
authHandler?: AuthHandler<OAuthResult>,
): ProfileTransform<OAuthAuthenticatorResult<PassportProfile>> | undefined {
return (
authHandler &&
(async (result, ctx) =>
authHandler(
{
fullProfile: result.fullProfile,
accessToken: result.session.accessToken,
params: {
scope: result.session.scope,
id_token: result.session.idToken,
token_type: result.session.tokenType,
expires_in: result.session.expiresInSeconds!,
},
},
ctx,
))
);
}
@@ -1,69 +0,0 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
AuthResolverContext,
PassportProfile,
} from '@backstage/plugin-auth-node';
import { adaptLegacyOAuthSignInResolver } from './adaptLegacyOAuthSignInResolver';
describe('adaptLegacyOAuthSignInResolver', () => {
it('should pass through undefined', () => {
expect(adaptLegacyOAuthSignInResolver(undefined)).toBeUndefined();
});
it('should convert a legacy resolver to a new one', () => {
const legacyResolver = jest.fn();
const newResolver = adaptLegacyOAuthSignInResolver(legacyResolver);
newResolver?.(
{
profile: { email: 'em@i.l' },
result: {
fullProfile: { id: 'id' } as PassportProfile,
session: {
accessToken: 'token',
expiresInSeconds: 3,
scope: 'sco pe',
tokenType: 'bear',
idToken: 'id-token',
refreshToken: 'refresh-token',
},
},
},
{ ctx: 'ctx' } as unknown as AuthResolverContext,
);
expect(legacyResolver).toHaveBeenCalledWith(
{
profile: { email: 'em@i.l' },
result: {
fullProfile: { id: 'id' },
accessToken: 'token',
refreshToken: 'refresh-token',
params: {
scope: 'sco pe',
id_token: 'id-token',
expires_in: 3,
token_type: 'bear',
},
},
},
{ ctx: 'ctx' },
);
});
});
@@ -1,49 +0,0 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
OAuthAuthenticatorResult,
PassportProfile,
SignInResolver,
} from '@backstage/plugin-auth-node';
import { OAuthResult } from '../oauth';
/** @internal */
export function adaptLegacyOAuthSignInResolver(
signInResolver?: SignInResolver<OAuthResult>,
): SignInResolver<OAuthAuthenticatorResult<PassportProfile>> | undefined {
return (
signInResolver &&
(async (input, ctx) =>
signInResolver(
{
profile: input.profile,
result: {
fullProfile: input.result.fullProfile,
accessToken: input.result.session.accessToken,
refreshToken: input.result.session.refreshToken,
params: {
scope: input.result.session.scope,
id_token: input.result.session.idToken,
token_type: input.result.session.tokenType,
expires_in: input.result.session.expiresInSeconds!,
},
},
},
ctx,
))
);
}
@@ -1,85 +0,0 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
AuthResolverContext,
PassportProfile,
} from '@backstage/plugin-auth-node';
import { adaptOAuthSignInResolverToLegacy } from './adaptOAuthSignInResolverToLegacy';
describe('adaptOAuthSignInResolverToLegacy', () => {
it('should pass through an empty object', () => {
const legacyResolvers = adaptOAuthSignInResolverToLegacy({});
expect(legacyResolvers).toEqual({});
// @ts-expect-error
legacyResolvers.missing?.();
});
it('should adapt a collection of sign-in resolvers', () => {
const resolverA = jest.fn();
const resolverB = jest.fn();
const legacyResolvers = adaptOAuthSignInResolverToLegacy({
resolverA,
resolverB,
});
const legacyResolverA = legacyResolvers.resolverA();
legacyResolverA(
{
profile: { email: 'em@i.l' },
result: {
fullProfile: { id: 'id' } as PassportProfile,
accessToken: 'token',
refreshToken: 'refresh-token',
params: {
scope: 'sco pe',
id_token: 'id-token',
expires_in: 3,
token_type: 'bear',
},
},
},
{ ctx: 'ctx' } as unknown as AuthResolverContext,
);
expect(resolverA).toHaveBeenCalledWith(
{
profile: { email: 'em@i.l' },
result: {
fullProfile: { id: 'id' } as PassportProfile,
session: {
accessToken: 'token',
expiresInSeconds: 3,
scope: 'sco pe',
tokenType: 'bear',
idToken: 'id-token',
refreshToken: 'refresh-token',
},
},
},
{ ctx: 'ctx' },
);
expect(resolverB).not.toHaveBeenCalled();
legacyResolvers.resolverB()(
{ profile: {}, result: { params: {} } } as any,
{} as any,
);
expect(resolverB).toHaveBeenCalled();
});
});
@@ -1,55 +0,0 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
OAuthAuthenticatorResult,
PassportProfile,
SignInResolver,
} from '@backstage/plugin-auth-node';
import { OAuthResult } from '../oauth';
/** @internal */
export function adaptOAuthSignInResolverToLegacy<
TKeys extends string,
>(resolvers: {
[key in TKeys]: SignInResolver<OAuthAuthenticatorResult<PassportProfile>>;
}): { [key in TKeys]: () => SignInResolver<OAuthResult> } {
const legacyResolvers = {} as {
[key in TKeys]: () => SignInResolver<OAuthResult>;
};
for (const name of Object.keys(resolvers) as TKeys[]) {
const resolver = resolvers[name];
legacyResolvers[name] = () => async (input, ctx) =>
resolver(
{
profile: input.profile,
result: {
fullProfile: input.result.fullProfile,
session: {
accessToken: input.result.accessToken,
expiresInSeconds: input.result.params.expires_in,
scope: input.result.params.scope,
idToken: input.result.params.id_token,
tokenType: input.result.params.token_type ?? 'bearer',
refreshToken: input.result.refreshToken,
},
},
},
ctx,
);
}
return legacyResolvers;
}
@@ -1,19 +0,0 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { adaptLegacyOAuthHandler } from './adaptLegacyOAuthHandler';
export { adaptLegacyOAuthSignInResolver } from './adaptLegacyOAuthSignInResolver';
export { adaptOAuthSignInResolverToLegacy } from './adaptOAuthSignInResolverToLegacy';
@@ -1,23 +0,0 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { OAuthEnvironmentHandler as _OAuthEnvironmentHandler } from '@backstage/plugin-auth-node';
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export const OAuthEnvironmentHandler = _OAuthEnvironmentHandler;
@@ -1,213 +0,0 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import express from 'express';
import {
verifyNonce,
encodeState,
readState,
defaultCookieConfigurer,
} from './helpers';
describe('OAuthProvider Utils', () => {
describe('encodeState', () => {
it('should serialized values', () => {
const state = {
nonce: '123',
env: 'development',
origin: 'https://example.com',
};
const encoded = encodeState(state);
expect(encoded).toBe(
Buffer.from(
'nonce=123&env=development&origin=https%3A%2F%2Fexample.com',
).toString('hex'),
);
expect(readState(encoded)).toEqual(state);
});
it('should not include undefined values', () => {
const state = { nonce: '123', env: 'development', origin: undefined };
const encoded = encodeState(state);
expect(encoded).toBe(
Buffer.from('nonce=123&env=development').toString('hex'),
);
expect(readState(encoded)).toEqual(state);
});
});
describe('verifyNonce', () => {
it('should throw error if cookie nonce missing', () => {
const state = { nonce: 'NONCE', env: 'development' };
const mockRequest = {
cookies: {},
query: {
state: encodeState(state),
},
} as unknown as express.Request;
expect(() => {
verifyNonce(mockRequest, 'providera');
}).toThrow('Auth response is missing cookie nonce');
});
it('should throw error if state nonce missing', () => {
const mockRequest = {
cookies: {
'providera-nonce': 'NONCE',
},
query: {},
} as unknown as express.Request;
expect(() => {
verifyNonce(mockRequest, 'providera');
}).toThrow('OAuth state is invalid, missing env');
});
it('should throw error if nonce mismatch', () => {
const state = { nonce: 'NONCEB', env: 'development' };
const mockRequest = {
cookies: {
'providera-nonce': 'NONCEA',
},
query: {
state: encodeState(state),
},
} as unknown as express.Request;
expect(() => {
verifyNonce(mockRequest, 'providera');
}).toThrow('Invalid nonce');
});
it('should not throw any error if nonce matches', () => {
const state = { nonce: 'NONCE', env: 'development' };
const mockRequest = {
cookies: {
'providera-nonce': 'NONCE',
},
query: {
state: encodeState(state),
},
} as unknown as express.Request;
expect(() => {
verifyNonce(mockRequest, 'providera');
}).not.toThrow();
});
});
describe('defaultCookieConfigurer', () => {
it('should set the correct domain and path for a base url', () => {
expect(
defaultCookieConfigurer({
baseUrl: '',
providerId: 'test-provider',
callbackUrl: 'http://domain.org/auth',
appOrigin: 'http://domain.org',
}),
).toMatchObject({
domain: 'domain.org',
path: '/auth/test-provider',
secure: false,
});
});
it('should set the correct domain and path for a url containing a frame handler', () => {
expect(
defaultCookieConfigurer({
baseUrl: '',
providerId: 'test-provider',
callbackUrl: 'http://domain.org/auth/test-provider/handler/frame',
appOrigin: 'http://domain.org',
}),
).toMatchObject({
domain: 'domain.org',
path: '/auth/test-provider',
secure: false,
});
});
it('should set the secure flag if url is using https', () => {
expect(
defaultCookieConfigurer({
baseUrl: '',
providerId: 'test-provider',
callbackUrl: 'https://domain.org/auth',
appOrigin: 'http://domain.org',
}),
).toMatchObject({
secure: true,
});
});
it('should set sameSite to lax for https on the same domain', () => {
expect(
defaultCookieConfigurer({
baseUrl: '',
providerId: 'test-provider',
callbackUrl: 'https://domain.org/auth',
appOrigin: 'http://domain.org',
}),
).toMatchObject({
sameSite: 'lax',
secure: true,
});
});
it('should set sameSite to lax for http on the same domain', () => {
expect(
defaultCookieConfigurer({
baseUrl: '',
providerId: 'test-provider',
callbackUrl: 'http://domain.org/auth',
appOrigin: 'http://domain.org',
}),
).toMatchObject({
sameSite: 'lax',
secure: false,
});
});
it('should set sameSite to lax if not secure and on different domains', () => {
expect(
defaultCookieConfigurer({
baseUrl: '',
providerId: 'test-provider',
callbackUrl: 'http://authdomain.org/auth',
appOrigin: 'http://domain.org',
}),
).toMatchObject({
sameSite: 'lax',
secure: false,
});
});
it('should set sameSite to none if secure and on different domains', () => {
expect(
defaultCookieConfigurer({
baseUrl: '',
providerId: 'test-provider',
callbackUrl: 'https://authdomain.org/auth',
appOrigin: 'http://domain.org',
}),
).toMatchObject({
sameSite: 'none',
secure: true,
});
});
});
});
@@ -1,82 +0,0 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import express from 'express';
import {
CookieConfigurer,
OAuthState,
decodeOAuthState,
encodeOAuthState,
} from '@backstage/plugin-auth-node';
/**
* @public
* @deprecated Use `decodeOAuthState` from `@backstage/plugin-auth-node` instead
*/
export const readState = decodeOAuthState;
/**
* @public
* @deprecated Use `encodeOAuthState` from `@backstage/plugin-auth-node` instead
*/
export const encodeState = encodeOAuthState;
/**
* @public
* @deprecated Use inline logic to make sure the session and state nonce matches instead.
*/
export const verifyNonce = (req: express.Request, providerId: string) => {
const cookieNonce = req.cookies[`${providerId}-nonce`];
const state: OAuthState = readState(req.query.state?.toString() ?? '');
const stateNonce = state.nonce;
if (!cookieNonce) {
throw new Error('Auth response is missing cookie nonce');
}
if (stateNonce.length === 0) {
throw new Error('Auth response is missing state nonce');
}
if (cookieNonce !== stateNonce) {
throw new Error('Invalid nonce');
}
};
export const defaultCookieConfigurer: CookieConfigurer = ({
callbackUrl,
providerId,
appOrigin,
}) => {
const { hostname: domain, pathname, protocol } = new URL(callbackUrl);
const secure = protocol === 'https:';
// For situations where the auth-backend is running on a
// different domain than the app, we set the SameSite attribute
// to 'none' to allow third-party access to the cookie, but
// only if it's in a secure context (https).
let sameSite: ReturnType<CookieConfigurer>['sameSite'] = 'lax';
if (new URL(appOrigin).hostname !== domain && secure) {
sameSite = 'none';
}
// If the provider supports callbackUrls, the pathname will
// contain the complete path to the frame handler so we need
// to slice off the trailing part of the path.
const path = pathname.endsWith(`${providerId}/handler/frame`)
? pathname.slice(0, -'/handler/frame'.length)
: `${pathname}/${providerId}`;
return { domain, path, secure, sameSite };
};
@@ -1,29 +0,0 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { OAuthEnvironmentHandler } from './OAuthEnvironmentHandler';
export { encodeState, verifyNonce, readState } from './helpers';
export type {
OAuthHandlers,
OAuthProviderInfo,
OAuthProviderOptions,
OAuthResponse,
OAuthState,
OAuthStartRequest,
OAuthRefreshRequest,
OAuthLogoutRequest,
OAuthResult,
} from './types';
-158
View File
@@ -1,158 +0,0 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import express from 'express';
import { Profile as PassportProfile } from 'passport';
import {
BackstageSignInResult,
ProfileInfo,
OAuthState as _OAuthState,
} from '@backstage/plugin-auth-node';
import { OAuthStartResponse } from '../../providers/types';
/**
* Common options for passport.js-based OAuth providers
*
* @public
* @deprecated No longer in use
*/
export type OAuthProviderOptions = {
/**
* Client ID of the auth provider.
*/
clientId: string;
/**
* Client Secret of the auth provider.
*/
clientSecret: string;
/**
* Callback URL to be passed to the auth provider to redirect to after the user signs in.
*/
callbackUrl: string;
};
/**
* @public
* @deprecated Use `OAuthAuthenticatorResult<PassportProfile>` from `@backstage/plugin-auth-node` instead
*/
export type OAuthResult = {
fullProfile: PassportProfile;
params: {
id_token?: string;
scope: string;
token_type?: string;
expires_in: number;
};
accessToken: string;
refreshToken?: string;
};
/**
* @public
* @deprecated Use `ClientAuthResponse` from `@backstage/plugin-auth-node` instead
*/
export type OAuthResponse = {
profile: ProfileInfo;
providerInfo: OAuthProviderInfo;
backstageIdentity?: BackstageSignInResult;
};
/**
* @public
* @deprecated Use `createOAuthRouteHandlers` from `@backstage/plugin-auth-node` instead
*/
export type OAuthProviderInfo = {
/**
* An access token issued for the signed in user.
*/
accessToken: string;
/**
* (Optional) Id token issued for the signed in user.
*/
idToken?: string;
/**
* Expiry of the access token in seconds.
*/
expiresInSeconds?: number;
/**
* Scopes granted for the access token.
*/
scope: string;
};
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export type OAuthState = _OAuthState;
/**
* @public
* @deprecated Use `createOAuthRouteHandlers` from `@backstage/plugin-auth-node` instead
*/
export type OAuthStartRequest = express.Request<{}> & {
scope: string;
state: OAuthState;
};
/**
* @public
* @deprecated Use `createOAuthRouteHandlers` from `@backstage/plugin-auth-node` instead
*/
export type OAuthRefreshRequest = express.Request<{}> & {
scope: string;
refreshToken: string;
};
/**
* @public
* @deprecated Use `createOAuthRouteHandlers` from `@backstage/plugin-auth-node` instead
*/
export type OAuthLogoutRequest = express.Request<{}> & {
refreshToken: string;
};
/**
* @public
* @deprecated Use `createOAuthRouteHandlers` from `@backstage/plugin-auth-node` instead
*/
export interface OAuthHandlers {
/**
* Initiate a sign in request with an auth provider.
*/
start(req: OAuthStartRequest): Promise<OAuthStartResponse>;
/**
* Handle the redirect from the auth provider when the user has signed in.
*/
handler(req: express.Request): Promise<{
response: OAuthResponse;
refreshToken?: string;
}>;
/**
* (Optional) Given a refresh token and scope fetches a new access token from the auth provider.
*/
refresh?(req: OAuthRefreshRequest): Promise<{
response: OAuthResponse;
refreshToken?: string;
}>;
/**
* (Optional) Sign out of the auth provider.
*/
logout?(req: OAuthLogoutRequest): Promise<void>;
}
@@ -17,18 +17,7 @@
export { createOriginFilter, type ProviderFactories } from './router';
export type {
AuthProviderConfig,
AuthProviderRouteHandlers,
AuthProviderFactory,
AuthHandler,
AuthResolverCatalogUserQuery,
AuthResolverContext,
AuthHandlerResult,
SignInResolver,
SignInInfo,
CookieConfigurer,
StateEncoder,
AuthResponse,
ProfileInfo,
OAuthStartResponse,
} from './types';
@@ -1,58 +0,0 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SignInResolver } from '@backstage/plugin-auth-node';
/**
* A common sign-in resolver that looks up the user using the local part of
* their email address as the entity name.
*/
export const commonByEmailLocalPartResolver: SignInResolver<unknown> = async (
info,
ctx,
) => {
const { profile } = info;
if (!profile.email) {
throw new Error('Login failed, user profile does not contain an email');
}
const [localPart] = profile.email.split('@');
return ctx.signInWithCatalogUser({
entityRef: { name: localPart },
});
};
/**
* A common sign-in resolver that looks up the user using their email address
* as email of the entity.
*/
export const commonByEmailResolver: SignInResolver<unknown> = async (
info,
ctx,
) => {
const { profile } = info;
if (!profile.email) {
throw new Error('Login failed, user profile does not contain an email');
}
return ctx.signInWithCatalogUser({
filter: {
'spec.profile.email': profile.email,
},
});
};
@@ -15,36 +15,9 @@
*/
import {
AuthProviderConfig as _AuthProviderConfig,
AuthProviderRouteHandlers as _AuthProviderRouteHandlers,
AuthProviderFactory as _AuthProviderFactory,
AuthResolverCatalogUserQuery as _AuthResolverCatalogUserQuery,
AuthResolverContext as _AuthResolverContext,
ClientAuthResponse as _ClientAuthResponse,
CookieConfigurer as _CookieConfigurer,
ProfileInfo as _ProfileInfo,
SignInInfo as _SignInInfo,
SignInResolver as _SignInResolver,
} from '@backstage/plugin-auth-node';
import { OAuthStartRequest } from '../lib/oauth/types';
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export type AuthResolverCatalogUserQuery = _AuthResolverCatalogUserQuery;
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export type AuthResolverContext = _AuthResolverContext;
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export type CookieConfigurer = _CookieConfigurer;
/**
* @public
@@ -61,48 +34,6 @@ export type OAuthStartResponse = {
status?: number;
};
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export type AuthProviderConfig = _AuthProviderConfig;
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export type AuthProviderRouteHandlers = _AuthProviderRouteHandlers;
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export type AuthProviderFactory = _AuthProviderFactory;
/**
* @public
* @deprecated import `ClientAuthResponse` from `@backstage/plugin-auth-node` instead
*/
export type AuthResponse<TProviderInfo> = _ClientAuthResponse<TProviderInfo>;
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export type ProfileInfo = _ProfileInfo;
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export type SignInInfo<TAuthResult> = _SignInInfo<TAuthResult>;
/**
* @public
* @deprecated import from `@backstage/plugin-auth-node` instead
*/
export type SignInResolver<TAuthResult> = _SignInResolver<TAuthResult>;
/**
* The return type of an authentication handler. Must contain valid profile
* information.
@@ -130,11 +61,3 @@ export type AuthHandler<TAuthResult> = (
input: TAuthResult,
context: _AuthResolverContext,
) => Promise<AuthHandlerResult>;
/**
* @public
* @deprecated Use `createOAuthRouteHandlers` from `@backstage/plugin-auth-node` instead
*/
export type StateEncoder = (
req: OAuthStartRequest,
) => Promise<{ encodedState: string }>;