auth-backend

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2022-08-19 13:54:05 +02:00
parent fa07cc8ff2
commit 2fc41ebf07
20 changed files with 89 additions and 101 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-auth-backend': minor
---
Removed the previously deprecated class `AtlassianAuthProvider`. Please use `providers.atlassian.create(...)` instead.
+33 -78
View File
@@ -24,26 +24,6 @@ import { TokenSet } from 'openid-client';
import { UserEntity } from '@backstage/catalog-model';
import { UserinfoResponse } from 'openid-client';
// @public @deprecated (undocumented)
export class AtlassianAuthProvider implements OAuthHandlers {
// Warning: (ae-forgotten-export) The symbol "AtlassianAuthProviderOptions" needs to be exported by the entry point index.d.ts
constructor(options: AtlassianAuthProviderOptions);
// (undocumented)
handler(req: express.Request): Promise<{
response: OAuthResponse;
refreshToken: string | undefined;
}>;
// (undocumented)
refresh(req: OAuthRefreshRequest): Promise<{
response: OAuthResponse;
refreshToken: string | undefined;
}>;
// Warning: (ae-forgotten-export) The symbol "RedirectInfo" needs to be exported by the entry point index.d.ts
//
// (undocumented)
start(req: OAuthStartRequest): Promise<RedirectInfo>;
}
// @public
export type AuthHandler<TAuthResult> = (
input: TAuthResult,
@@ -63,8 +43,6 @@ export type AuthProviderConfig = {
cookieConfigurer?: CookieConfigurer;
};
// Warning: (ae-missing-release-tag) "AuthProviderFactory" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type AuthProviderFactory = (options: {
providerId: string;
@@ -74,8 +52,6 @@ export type AuthProviderFactory = (options: {
resolverContext: AuthResolverContext;
}) => AuthProviderRouteHandlers;
// Warning: (ae-missing-release-tag) "AuthProviderRouteHandlers" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export interface AuthProviderRouteHandlers {
frameHandler(req: express.Request, res: express.Response): Promise<void>;
@@ -129,8 +105,6 @@ export type AwsAlbResult = {
accessToken: string;
};
// Warning: (ae-missing-release-tag) "BitbucketOAuthResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type BitbucketOAuthResult = {
fullProfile: BitbucketPassportProfile;
@@ -143,8 +117,6 @@ export type BitbucketOAuthResult = {
refreshToken?: string;
};
// Warning: (ae-missing-release-tag) "BitbucketPassportProfile" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type BitbucketPassportProfile = Profile & {
id?: string;
@@ -160,15 +132,14 @@ export type BitbucketPassportProfile = Profile & {
};
};
// Warning: (ae-missing-release-tag) "CatalogIdentityClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export class CatalogIdentityClient {
constructor(options: { catalogApi: CatalogApi; tokenManager: TokenManager });
// Warning: (ae-forgotten-export) The symbol "UserQuery" needs to be exported by the entry point index.d.ts
findUser(query: UserQuery): Promise<UserEntity>;
// Warning: (ae-forgotten-export) The symbol "MemberClaimQuery" needs to be exported by the entry point index.d.ts
resolveCatalogMembership(query: MemberClaimQuery): Promise<string[]>;
findUser(query: { annotations: Record<string, string> }): Promise<UserEntity>;
resolveCatalogMembership(query: {
entityRefs: string[];
logger?: Logger;
}): Promise<string[]>;
}
// @public
@@ -217,8 +188,6 @@ export type CookieConfigurer = (ctx: {
secure: boolean;
};
// Warning: (ae-missing-release-tag) "createAuthProviderIntegration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function createAuthProviderIntegration<
TCreateOptions extends unknown[],
@@ -233,13 +202,9 @@ export function createAuthProviderIntegration<
resolvers: Readonly<string extends keyof TResolvers ? never : TResolvers>;
}>;
// Warning: (ae-missing-release-tag) "createOriginFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function createOriginFilter(config: Config): (origin: string) => boolean;
// Warning: (ae-missing-release-tag) "createRouter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function createRouter(options: RouterOptions): Promise<express.Router>;
@@ -248,13 +213,9 @@ export const defaultAuthProviderFactories: {
[providerId: string]: AuthProviderFactory;
};
// Warning: (ae-missing-release-tag) "encodeState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const encodeState: (state: OAuthState) => string;
// Warning: (ae-missing-release-tag) "ensuresXRequestedWith" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const ensuresXRequestedWith: (req: express.Request) => boolean;
@@ -273,8 +234,6 @@ export type GcpIapTokenInfo = {
// @public
export function getDefaultOwnershipEntityRefs(entity: Entity): string[];
// Warning: (ae-missing-release-tag) "GithubOAuthResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type GithubOAuthResult = {
fullProfile: Profile;
@@ -295,20 +254,19 @@ export type OAuth2ProxyResult<JWTPayload = {}> = {
getHeader(name: string): string | undefined;
};
// Warning: (ae-missing-release-tag) "OAuthAdapter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export class OAuthAdapter implements AuthProviderRouteHandlers {
constructor(handlers: OAuthHandlers, options: Options);
constructor(handlers: OAuthHandlers, options: OAuthAdapterOptions);
// (undocumented)
frameHandler(req: express.Request, res: express.Response): Promise<void>;
// Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts
//
// (undocumented)
static fromConfig(
config: AuthProviderConfig,
handlers: OAuthHandlers,
options: Pick<Options, 'providerId' | 'persistScopes' | 'callbackUrl'>,
options: Pick<
OAuthAdapterOptions,
'providerId' | 'persistScopes' | 'callbackUrl'
>,
): OAuthAdapter;
// (undocumented)
logout(req: express.Request, res: express.Response): Promise<void>;
@@ -318,8 +276,18 @@ export class OAuthAdapter implements AuthProviderRouteHandlers {
start(req: express.Request, res: express.Response): Promise<void>;
}
// Warning: (ae-missing-release-tag) "OAuthEnvironmentHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OAuthAdapterOptions = {
providerId: string;
secure: boolean;
persistScopes?: boolean;
cookieDomain: string;
cookiePath: string;
appOrigin: string;
isOriginAllowed: (origin: string) => boolean;
callbackUrl: string;
};
// @public (undocumented)
export class OAuthEnvironmentHandler implements AuthProviderRouteHandlers {
constructor(handlers: Map<string, AuthProviderRouteHandlers>);
@@ -352,8 +320,6 @@ export interface OAuthHandlers {
start(req: OAuthStartRequest): Promise<RedirectInfo>;
}
// Warning: (ae-missing-release-tag) "OAuthProviderInfo" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OAuthProviderInfo = {
accessToken: string;
@@ -362,8 +328,6 @@ export type OAuthProviderInfo = {
scope: string;
};
// Warning: (ae-missing-release-tag) "OAuthProviderOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export type OAuthProviderOptions = {
clientId: string;
@@ -371,8 +335,6 @@ export type OAuthProviderOptions = {
callbackUrl: string;
};
// Warning: (ae-missing-release-tag) "OAuthRefreshRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OAuthRefreshRequest = express.Request<{}> & {
scope: string;
@@ -386,8 +348,6 @@ export type OAuthResponse = {
backstageIdentity?: BackstageSignInResult;
};
// Warning: (ae-missing-release-tag) "OAuthResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OAuthResult = {
fullProfile: Profile;
@@ -400,16 +360,12 @@ export type OAuthResult = {
refreshToken?: string;
};
// Warning: (ae-missing-release-tag) "OAuthStartRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OAuthStartRequest = express.Request<{}> & {
scope: string;
state: OAuthState;
};
// Warning: (ae-missing-release-tag) "OAuthState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OAuthState = {
nonce: string;
@@ -424,8 +380,6 @@ export type OidcAuthResult = {
userinfo: UserinfoResponse;
};
// Warning: (ae-missing-release-tag) "postMessageResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const postMessageResponse: (
res: express.Response,
@@ -445,6 +399,11 @@ export type ProfileInfo = {
picture?: string;
};
// @public (undocumented)
export type ProviderFactories = {
[s: string]: AuthProviderFactory;
};
// @public
export const providers: Readonly<{
atlassian: Readonly<{
@@ -692,13 +651,15 @@ export const providers: Readonly<{
}>;
}>;
// Warning: (ae-missing-release-tag) "readState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const readState: (stateString: string) => OAuthState;
// Warning: (ae-missing-release-tag) "RouterOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type RedirectInfo = {
url: string;
status?: number;
};
// @public (undocumented)
export interface RouterOptions {
// (undocumented)
@@ -709,8 +670,6 @@ export interface RouterOptions {
discovery: PluginEndpointDiscovery;
// (undocumented)
logger: Logger;
// Warning: (ae-forgotten-export) The symbol "ProviderFactories" needs to be exported by the entry point index.d.ts
//
// (undocumented)
providerFactories?: ProviderFactories;
// (undocumented)
@@ -749,13 +708,9 @@ export type TokenParams = {
};
};
// Warning: (ae-missing-release-tag) "verifyNonce" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const verifyNonce: (req: express.Request, providerId: string) => void;
// Warning: (ae-missing-release-tag) "WebMessageResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export type WebMessageResponse =
| {
@@ -26,17 +26,10 @@ import {
} from '@backstage/catalog-model';
import { TokenManager } from '@backstage/backend-common';
type UserQuery = {
annotations: Record<string, string>;
};
type MemberClaimQuery = {
entityRefs: string[];
logger?: Logger;
};
/**
* A catalog client tailored for reading out identity data from the catalog.
*
* @public
*/
export class CatalogIdentityClient {
private readonly catalogApi: CatalogApi;
@@ -52,7 +45,9 @@ export class CatalogIdentityClient {
*
* Throws a NotFoundError or ConflictError if 0 or multiple users are found.
*/
async findUser(query: UserQuery): Promise<UserEntity> {
async findUser(query: {
annotations: Record<string, string>;
}): Promise<UserEntity> {
const filter: Record<string, string> = {
kind: 'user',
};
@@ -81,7 +76,10 @@ export class CatalogIdentityClient {
*
* Returns a superset of the entity names that can be passed directly to `issueToken` as `ent`.
*/
async resolveCatalogMembership(query: MemberClaimQuery): Promise<string[]> {
async resolveCatalogMembership(query: {
entityRefs: string[];
logger?: Logger;
}): Promise<string[]> {
const { entityRefs, logger } = query;
const resolvedEntityRefs = entityRefs
.map((ref: string) => {
@@ -24,6 +24,7 @@ export const safelyEncodeURIComponent = (value: string) => {
return encodeURIComponent(value).replace(/'/g, '%27');
};
/** @public */
export const postMessageResponse = (
res: express.Response,
appOrigin: string,
@@ -68,6 +69,7 @@ export const postMessageResponse = (
res.end(`<html><body><script>${script}</script></body></html>`);
};
/** @public */
export const ensuresXRequestedWith = (req: express.Request) => {
const requiredHeader = req.header('X-Requested-With');
if (!requiredHeader || requiredHeader !== 'XMLHttpRequest') {
@@ -19,6 +19,8 @@ import { AuthResponse } from '../../providers/types';
/**
* Payload sent as a post message after the auth request is complete.
* If successful then has a valid payload with Auth information else contains an error.
*
* @public
*/
export type WebMessageResponse =
| {
@@ -44,7 +44,8 @@ import { prepareBackstageIdentityResponse } from '../../providers/prepareBacksta
export const THOUSAND_DAYS_MS = 1000 * 24 * 60 * 60 * 1000;
export const TEN_MINUTES_MS = 600 * 1000;
export type Options = {
/** @public */
export type OAuthAdapterOptions = {
providerId: string;
secure: boolean;
persistScopes?: boolean;
@@ -54,11 +55,16 @@ export type Options = {
isOriginAllowed: (origin: string) => boolean;
callbackUrl: string;
};
/** @public */
export class OAuthAdapter implements AuthProviderRouteHandlers {
static fromConfig(
config: AuthProviderConfig,
handlers: OAuthHandlers,
options: Pick<Options, 'providerId' | 'persistScopes' | 'callbackUrl'>,
options: Pick<
OAuthAdapterOptions,
'providerId' | 'persistScopes' | 'callbackUrl'
>,
): OAuthAdapter {
const { origin: appOrigin } = new URL(config.appUrl);
@@ -83,7 +89,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers {
constructor(
private readonly handlers: OAuthHandlers,
private readonly options: Options,
private readonly options: OAuthAdapterOptions,
) {
this.baseCookieOptions = {
httpOnly: true,
@@ -20,6 +20,7 @@ import { InputError, NotFoundError } from '@backstage/errors';
import { readState } from './helpers';
import { AuthProviderRouteHandlers } from '../../providers/types';
/** @public */
export class OAuthEnvironmentHandler implements AuthProviderRouteHandlers {
static mapConfig(
config: Config,
@@ -19,6 +19,7 @@ import { OAuthState } from './types';
import pickBy from 'lodash/pickBy';
import { CookieConfigurer } from '../../providers/types';
/** @public */
export const readState = (stateString: string): OAuthState => {
const state = Object.fromEntries(
new URLSearchParams(Buffer.from(stateString, 'hex').toString('utf-8')),
@@ -35,6 +36,7 @@ export const readState = (stateString: string): OAuthState => {
return state as OAuthState;
};
/** @public */
export const encodeState = (state: OAuthState): string => {
const stateString = new URLSearchParams(
pickBy<string>(state, value => value !== undefined),
@@ -43,6 +45,7 @@ export const encodeState = (state: OAuthState): string => {
return Buffer.from(stateString, 'utf-8').toString('hex');
};
/** @public */
export const verifyNonce = (req: express.Request, providerId: string) => {
const cookieNonce = req.cookies[`${providerId}-nonce`];
const state: OAuthState = readState(req.query.state?.toString() ?? '');
@@ -15,6 +15,7 @@
*/
export { OAuthEnvironmentHandler } from './OAuthEnvironmentHandler';
export type { OAuthAdapterOptions } from './OAuthAdapter';
export { OAuthAdapter } from './OAuthAdapter';
export { encodeState, verifyNonce, readState } from './helpers';
export type {
@@ -21,6 +21,8 @@ import { RedirectInfo, ProfileInfo } from '../../providers/types';
/**
* Common options for passport.js-based OAuth providers
*
* @public
*/
export type OAuthProviderOptions = {
/**
@@ -37,6 +39,7 @@ export type OAuthProviderOptions = {
callbackUrl: string;
};
/** @public */
export type OAuthResult = {
fullProfile: PassportProfile;
params: {
@@ -59,6 +62,7 @@ export type OAuthResponse = {
backstageIdentity?: BackstageSignInResult;
};
/** @public */
export type OAuthProviderInfo = {
/**
* An access token issued for the signed in user.
@@ -78,6 +82,7 @@ export type OAuthProviderInfo = {
scope: string;
};
/** @public */
export type OAuthState = {
/* A type for the serialized value in the `state` parameter of the OAuth authorization flow
*/
@@ -87,11 +92,13 @@ export type OAuthState = {
scope?: string;
};
/** @public */
export type OAuthStartRequest = express.Request<{}> & {
scope: string;
state: OAuthState;
};
/** @public */
export type OAuthRefreshRequest = express.Request<{}> & {
scope: string;
refreshToken: string;
@@ -14,4 +14,4 @@
* limitations under the License.
*/
export { atlassian, AtlassianAuthProvider } from './provider';
export { atlassian } from './provider';
@@ -44,6 +44,7 @@ import {
import express from 'express';
import { createAuthProviderIntegration } from '../createAuthProviderIntegration';
/** @public */
export type AtlassianAuthProviderOptions = OAuthProviderOptions & {
scopes: string;
signInResolver?: SignInResolver<OAuthResult>;
@@ -58,10 +59,6 @@ export const atlassianDefaultAuthHandler: AuthHandler<OAuthResult> = async ({
profile: makeProfileInfo(fullProfile, params.id_token),
});
/**
* @public
* @deprecated This export is deprecated and will be removed in the future.
*/
export class AtlassianAuthProvider implements OAuthHandlers {
private readonly _strategy: AtlassianStrategy;
private readonly signInResolver?: SignInResolver<OAuthResult>;
@@ -54,6 +54,7 @@ type Options = OAuthProviderOptions & {
resolverContext: AuthResolverContext;
};
/** @public */
export type BitbucketOAuthResult = {
fullProfile: BitbucketPassportProfile;
params: {
@@ -65,6 +66,7 @@ export type BitbucketOAuthResult = {
refreshToken?: string;
};
/** @public */
export type BitbucketPassportProfile = PassportProfile & {
id?: string;
displayName?: string;
@@ -146,7 +146,6 @@ export type CloudflareAccessIdentityProfile = {
};
/**
*
* @public
*/
export type CloudflareAccessResult = {
@@ -22,6 +22,8 @@ import { AuthProviderFactory, SignInResolver } from './types';
*
* The returned object facilitates the creation of provider instances, and
* supplies built-in sign-in resolvers for the specific provider.
*
* @public
*/
export function createAuthProviderIntegration<
TCreateOptions extends unknown[],
@@ -52,6 +52,7 @@ type PrivateInfo = {
refreshToken?: string;
};
/** @public */
export type GithubOAuthResult = {
fullProfile: PassportProfile;
params: {
+1 -1
View File
@@ -14,7 +14,6 @@
* limitations under the License.
*/
export { AtlassianAuthProvider } from './atlassian';
export type { AwsAlbResult } from './aws-alb';
export type {
BitbucketOAuthResult,
@@ -50,6 +49,7 @@ export type {
StateEncoder,
AuthResponse,
ProfileInfo,
RedirectInfo,
} from './types';
export { prepareBackstageIdentityResponse } from './prepareBackstageIdentityResponse';
@@ -126,6 +126,7 @@ export type AuthProviderConfig = {
cookieConfigurer?: CookieConfigurer;
};
/** @public */
export type RedirectInfo = {
/**
* URL to redirect to
@@ -147,6 +148,8 @@ export type RedirectInfo = {
* `/auth/[provider]/handler/frame -> frameHandler`
* `/auth/[provider]/refresh -> refresh`
* `/auth/[provider]/logout -> logout`
*
* @public
*/
export interface AuthProviderRouteHandlers {
/**
@@ -192,6 +195,7 @@ export interface AuthProviderRouteHandlers {
logout?(req: express.Request, res: express.Response): Promise<void>;
}
/** @public */
export type AuthProviderFactory = (options: {
providerId: string;
globalConfig: AuthProviderConfig;
+5 -1
View File
@@ -36,8 +36,10 @@ import passport from 'passport';
import { Minimatch } from 'minimatch';
import { CatalogAuthResolverContext } from '../lib/resolvers';
type ProviderFactories = { [s: string]: AuthProviderFactory };
/** @public */
export type ProviderFactories = { [s: string]: AuthProviderFactory };
/** @public */
export interface RouterOptions {
logger: Logger;
database: PluginDatabaseManager;
@@ -48,6 +50,7 @@ export interface RouterOptions {
providerFactories?: ProviderFactories;
}
/** @public */
export async function createRouter(
options: RouterOptions,
): Promise<express.Router> {
@@ -187,6 +190,7 @@ export async function createRouter(
return router;
}
/** @public */
export function createOriginFilter(
config: Config,
): (origin: string) => boolean {
-1
View File
@@ -199,7 +199,6 @@ const PACKAGE_ROOTS = ['packages', 'plugins'];
const ALLOW_WARNINGS = [
'packages/core-components',
'plugins/auth-backend',
'plugins/catalog',
'plugins/catalog-graphql',
'plugins/catalog-import',