@backstage/plugin-auth-node 0.5.3-next.0 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/extensions/AuthOwnershipResolutionExtensionPoint.cjs.js +10 -0
- package/dist/extensions/AuthOwnershipResolutionExtensionPoint.cjs.js.map +1 -0
- package/dist/extensions/AuthProvidersExtensionPoint.cjs.js +10 -0
- package/dist/extensions/AuthProvidersExtensionPoint.cjs.js.map +1 -0
- package/dist/flow/sendWebMessageResponse.cjs.js +41 -0
- package/dist/flow/sendWebMessageResponse.cjs.js.map +1 -0
- package/dist/identity/DefaultIdentityClient.cjs.js +103 -0
- package/dist/identity/DefaultIdentityClient.cjs.js.map +1 -0
- package/dist/identity/IdentityClient.cjs.js +27 -0
- package/dist/identity/IdentityClient.cjs.js.map +1 -0
- package/dist/identity/getBearerTokenFromAuthorizationHeader.cjs.js +12 -0
- package/dist/identity/getBearerTokenFromAuthorizationHeader.cjs.js.map +1 -0
- package/dist/identity/prepareBackstageIdentityResponse.cjs.js +36 -0
- package/dist/identity/prepareBackstageIdentityResponse.cjs.js.map +1 -0
- package/dist/index.cjs.js +48 -1063
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/oauth/CookieScopeManager.cjs.js +90 -0
- package/dist/oauth/CookieScopeManager.cjs.js.map +1 -0
- package/dist/oauth/OAuthCookieManager.cjs.js +87 -0
- package/dist/oauth/OAuthCookieManager.cjs.js.map +1 -0
- package/dist/oauth/OAuthEnvironmentHandler.cjs.js +64 -0
- package/dist/oauth/OAuthEnvironmentHandler.cjs.js.map +1 -0
- package/dist/oauth/PassportOAuthAuthenticatorHelper.cjs.js +69 -0
- package/dist/oauth/PassportOAuthAuthenticatorHelper.cjs.js.map +1 -0
- package/dist/oauth/createOAuthProviderFactory.cjs.js +37 -0
- package/dist/oauth/createOAuthProviderFactory.cjs.js.map +1 -0
- package/dist/oauth/createOAuthRouteHandlers.cjs.js +215 -0
- package/dist/oauth/createOAuthRouteHandlers.cjs.js.map +1 -0
- package/dist/oauth/state.cjs.js +31 -0
- package/dist/oauth/state.cjs.js.map +1 -0
- package/dist/oauth/types.cjs.js +8 -0
- package/dist/oauth/types.cjs.js.map +1 -0
- package/dist/passport/PassportHelpers.cjs.js +144 -0
- package/dist/passport/PassportHelpers.cjs.js.map +1 -0
- package/dist/proxy/createProxyAuthProviderFactory.cjs.js +32 -0
- package/dist/proxy/createProxyAuthProviderFactory.cjs.js.map +1 -0
- package/dist/proxy/createProxyRouteHandlers.cjs.js +39 -0
- package/dist/proxy/createProxyRouteHandlers.cjs.js.map +1 -0
- package/dist/proxy/types.cjs.js +8 -0
- package/dist/proxy/types.cjs.js.map +1 -0
- package/dist/sign-in/commonSignInResolvers.cjs.js +70 -0
- package/dist/sign-in/commonSignInResolvers.cjs.js.map +1 -0
- package/dist/sign-in/createSignInResolverFactory.cjs.js +37 -0
- package/dist/sign-in/createSignInResolverFactory.cjs.js.map +1 -0
- package/dist/sign-in/readDeclarativeSignInResolver.cjs.js +38 -0
- package/dist/sign-in/readDeclarativeSignInResolver.cjs.js.map +1 -0
- package/dist/types.cjs.js +17 -0
- package/dist/types.cjs.js.map +1 -0
- package/package.json +7 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createProxyAuthProviderFactory.cjs.js","sources":["../../src/proxy/createProxyAuthProviderFactory.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n readDeclarativeSignInResolver,\n SignInResolverFactory,\n} from '../sign-in';\nimport {\n AuthProviderFactory,\n ProfileTransform,\n SignInResolver,\n} from '../types';\nimport { createProxyAuthRouteHandlers } from './createProxyRouteHandlers';\nimport { ProxyAuthenticator } from './types';\n\n/** @public */\nexport function createProxyAuthProviderFactory<TResult>(options: {\n authenticator: ProxyAuthenticator<unknown, TResult, unknown>;\n profileTransform?: ProfileTransform<TResult>;\n signInResolver?: SignInResolver<TResult>;\n signInResolverFactories?: Record<string, SignInResolverFactory>;\n}): AuthProviderFactory {\n return ctx => {\n const signInResolver =\n options.signInResolver ??\n readDeclarativeSignInResolver({\n config: ctx.config,\n signInResolverFactories: options.signInResolverFactories ?? {},\n });\n\n if (!signInResolver) {\n throw new Error(\n `No sign-in resolver configured for proxy auth provider '${ctx.providerId}'`,\n );\n }\n\n return createProxyAuthRouteHandlers<TResult>({\n signInResolver,\n config: ctx.config,\n authenticator: options.authenticator,\n resolverContext: ctx.resolverContext,\n profileTransform: options.profileTransform,\n });\n };\n}\n"],"names":["readDeclarativeSignInResolver","createProxyAuthRouteHandlers"],"mappings":";;;;;;;;;AA6BO,SAAS,+BAAwC,OAKhC,EAAA;AACtB,EAAA,OAAO,CAAO,GAAA,KAAA;AACZ,IAAM,MAAA,cAAA,GACJ,OAAQ,CAAA,cAAA,IACRA,2DAA8B,CAAA;AAAA,MAC5B,QAAQ,GAAI,CAAA,MAAA;AAAA,MACZ,uBAAA,EAAyB,OAAQ,CAAA,uBAAA,IAA2B,EAAC;AAAA,KAC9D,CAAA,CAAA;AAEH,IAAA,IAAI,CAAC,cAAgB,EAAA;AACnB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,wDAAA,EAA2D,IAAI,UAAU,CAAA,CAAA,CAAA;AAAA,OAC3E,CAAA;AAAA,KACF;AAEA,IAAA,OAAOC,qDAAsC,CAAA;AAAA,MAC3C,cAAA;AAAA,MACA,QAAQ,GAAI,CAAA,MAAA;AAAA,MACZ,eAAe,OAAQ,CAAA,aAAA;AAAA,MACvB,iBAAiB,GAAI,CAAA,eAAA;AAAA,MACrB,kBAAkB,OAAQ,CAAA,gBAAA;AAAA,KAC3B,CAAA,CAAA;AAAA,GACH,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var prepareBackstageIdentityResponse = require('../identity/prepareBackstageIdentityResponse.cjs.js');
|
|
4
|
+
var errors = require('@backstage/errors');
|
|
5
|
+
require('jose');
|
|
6
|
+
|
|
7
|
+
function createProxyAuthRouteHandlers(options) {
|
|
8
|
+
const { authenticator, config, resolverContext, signInResolver } = options;
|
|
9
|
+
const profileTransform = options.profileTransform ?? authenticator.defaultProfileTransform;
|
|
10
|
+
const authenticatorCtx = authenticator.initialize({ config });
|
|
11
|
+
return {
|
|
12
|
+
async start() {
|
|
13
|
+
throw new errors.NotImplementedError("Not implemented");
|
|
14
|
+
},
|
|
15
|
+
async frameHandler() {
|
|
16
|
+
throw new errors.NotImplementedError("Not implemented");
|
|
17
|
+
},
|
|
18
|
+
async refresh(req, res) {
|
|
19
|
+
const { result, providerInfo } = await authenticator.authenticate(
|
|
20
|
+
{ req },
|
|
21
|
+
authenticatorCtx
|
|
22
|
+
);
|
|
23
|
+
const { profile } = await profileTransform(result, resolverContext);
|
|
24
|
+
const identity = await signInResolver(
|
|
25
|
+
{ profile, result },
|
|
26
|
+
resolverContext
|
|
27
|
+
);
|
|
28
|
+
const response = {
|
|
29
|
+
profile,
|
|
30
|
+
providerInfo,
|
|
31
|
+
backstageIdentity: prepareBackstageIdentityResponse.prepareBackstageIdentityResponse(identity)
|
|
32
|
+
};
|
|
33
|
+
res.status(200).json(response);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
exports.createProxyAuthRouteHandlers = createProxyAuthRouteHandlers;
|
|
39
|
+
//# sourceMappingURL=createProxyRouteHandlers.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createProxyRouteHandlers.cjs.js","sources":["../../src/proxy/createProxyRouteHandlers.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Request, Response } from 'express';\nimport { Config } from '@backstage/config';\nimport {\n AuthProviderRouteHandlers,\n AuthResolverContext,\n ClientAuthResponse,\n ProfileTransform,\n SignInResolver,\n} from '../types';\nimport { ProxyAuthenticator } from './types';\nimport { prepareBackstageIdentityResponse } from '../identity';\nimport { NotImplementedError } from '@backstage/errors';\n\n/** @public */\nexport interface ProxyAuthRouteHandlersOptions<TResult> {\n authenticator: ProxyAuthenticator<any, TResult, unknown>;\n config: Config;\n resolverContext: AuthResolverContext;\n signInResolver: SignInResolver<TResult>;\n profileTransform?: ProfileTransform<TResult>;\n}\n\n/** @public */\nexport function createProxyAuthRouteHandlers<TResult>(\n options: ProxyAuthRouteHandlersOptions<TResult>,\n): AuthProviderRouteHandlers {\n const { authenticator, config, resolverContext, signInResolver } = options;\n\n const profileTransform =\n options.profileTransform ?? authenticator.defaultProfileTransform;\n const authenticatorCtx = authenticator.initialize({ config });\n\n return {\n async start(): Promise<void> {\n throw new NotImplementedError('Not implemented');\n },\n\n async frameHandler(): Promise<void> {\n throw new NotImplementedError('Not implemented');\n },\n\n async refresh(this: never, req: Request, res: Response): Promise<void> {\n const { result, providerInfo } = await authenticator.authenticate(\n { req },\n authenticatorCtx,\n );\n\n const { profile } = await profileTransform(result, resolverContext);\n\n const identity = await signInResolver(\n { profile, result },\n resolverContext,\n );\n\n const response: ClientAuthResponse<unknown> = {\n profile,\n providerInfo,\n backstageIdentity: prepareBackstageIdentityResponse(identity),\n };\n\n res.status(200).json(response);\n },\n };\n}\n"],"names":["NotImplementedError","prepareBackstageIdentityResponse"],"mappings":";;;;;;AAuCO,SAAS,6BACd,OAC2B,EAAA;AAC3B,EAAA,MAAM,EAAE,aAAA,EAAe,MAAQ,EAAA,eAAA,EAAiB,gBAAmB,GAAA,OAAA,CAAA;AAEnE,EAAM,MAAA,gBAAA,GACJ,OAAQ,CAAA,gBAAA,IAAoB,aAAc,CAAA,uBAAA,CAAA;AAC5C,EAAA,MAAM,gBAAmB,GAAA,aAAA,CAAc,UAAW,CAAA,EAAE,QAAQ,CAAA,CAAA;AAE5D,EAAO,OAAA;AAAA,IACL,MAAM,KAAuB,GAAA;AAC3B,MAAM,MAAA,IAAIA,2BAAoB,iBAAiB,CAAA,CAAA;AAAA,KACjD;AAAA,IAEA,MAAM,YAA8B,GAAA;AAClC,MAAM,MAAA,IAAIA,2BAAoB,iBAAiB,CAAA,CAAA;AAAA,KACjD;AAAA,IAEA,MAAM,OAAqB,CAAA,GAAA,EAAc,GAA8B,EAAA;AACrE,MAAA,MAAM,EAAE,MAAA,EAAQ,YAAa,EAAA,GAAI,MAAM,aAAc,CAAA,YAAA;AAAA,QACnD,EAAE,GAAI,EAAA;AAAA,QACN,gBAAA;AAAA,OACF,CAAA;AAEA,MAAA,MAAM,EAAE,OAAQ,EAAA,GAAI,MAAM,gBAAA,CAAiB,QAAQ,eAAe,CAAA,CAAA;AAElE,MAAA,MAAM,WAAW,MAAM,cAAA;AAAA,QACrB,EAAE,SAAS,MAAO,EAAA;AAAA,QAClB,eAAA;AAAA,OACF,CAAA;AAEA,MAAA,MAAM,QAAwC,GAAA;AAAA,QAC5C,OAAA;AAAA,QACA,YAAA;AAAA,QACA,iBAAA,EAAmBC,kEAAiC,QAAQ,CAAA;AAAA,OAC9D,CAAA;AAEA,MAAA,GAAA,CAAI,MAAO,CAAA,GAAG,CAAE,CAAA,IAAA,CAAK,QAAQ,CAAA,CAAA;AAAA,KAC/B;AAAA,GACF,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.cjs.js","sources":["../../src/proxy/types.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Request } from 'express';\nimport { ProfileTransform } from '../types';\n\n/** @public */\nexport interface ProxyAuthenticator<\n TContext,\n TResult,\n TProviderInfo = undefined,\n> {\n defaultProfileTransform: ProfileTransform<TResult>;\n initialize(ctx: { config: Config }): TContext;\n authenticate(\n options: { req: Request },\n ctx: TContext,\n ): Promise<{ result: TResult; providerInfo?: TProviderInfo }>;\n}\n\n/** @public */\nexport function createProxyAuthenticator<TContext, TResult, TProviderInfo>(\n authenticator: ProxyAuthenticator<TContext, TResult, TProviderInfo>,\n): ProxyAuthenticator<TContext, TResult, TProviderInfo> {\n return authenticator;\n}\n"],"names":[],"mappings":";;AAmCO,SAAS,yBACd,aACsD,EAAA;AACtD,EAAO,OAAA,aAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var zod = require('zod');
|
|
4
|
+
var createSignInResolverFactory = require('./createSignInResolverFactory.cjs.js');
|
|
5
|
+
var errors = require('@backstage/errors');
|
|
6
|
+
|
|
7
|
+
const reEmail = /^([^@+]+)(\+[^@]+)?(@.*)$/;
|
|
8
|
+
exports.commonSignInResolvers = void 0;
|
|
9
|
+
((commonSignInResolvers2) => {
|
|
10
|
+
commonSignInResolvers2.emailMatchingUserEntityProfileEmail = createSignInResolverFactory.createSignInResolverFactory({
|
|
11
|
+
create() {
|
|
12
|
+
return async (info, ctx) => {
|
|
13
|
+
const { profile } = info;
|
|
14
|
+
if (!profile.email) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
"Login failed, user profile does not contain an email"
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
return await ctx.signInWithCatalogUser({
|
|
21
|
+
filter: {
|
|
22
|
+
"spec.profile.email": profile.email
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
} catch (err) {
|
|
26
|
+
if (err?.name === "NotFoundError") {
|
|
27
|
+
const m = profile.email.match(reEmail);
|
|
28
|
+
if (m?.length === 4) {
|
|
29
|
+
const [_, name, _plus, domain] = m;
|
|
30
|
+
const noPlusEmail = `${name}${domain}`;
|
|
31
|
+
return ctx.signInWithCatalogUser({
|
|
32
|
+
filter: {
|
|
33
|
+
"spec.profile.email": noPlusEmail
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
throw err;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
commonSignInResolvers2.emailLocalPartMatchingUserEntityName = createSignInResolverFactory.createSignInResolverFactory({
|
|
44
|
+
optionsSchema: zod.z.object({
|
|
45
|
+
allowedDomains: zod.z.array(zod.z.string()).optional()
|
|
46
|
+
}).optional(),
|
|
47
|
+
create(options = {}) {
|
|
48
|
+
const { allowedDomains } = options;
|
|
49
|
+
return async (info, ctx) => {
|
|
50
|
+
const { profile } = info;
|
|
51
|
+
if (!profile.email) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
"Login failed, user profile does not contain an email"
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
const [localPart] = profile.email.split("@");
|
|
57
|
+
const domain = profile.email.slice(localPart.length + 1);
|
|
58
|
+
if (allowedDomains && !allowedDomains.includes(domain)) {
|
|
59
|
+
throw new errors.NotAllowedError(
|
|
60
|
+
"Sign-in user email is not from an allowed domain"
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
return ctx.signInWithCatalogUser({
|
|
64
|
+
entityRef: { name: localPart }
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
})(exports.commonSignInResolvers || (exports.commonSignInResolvers = {}));
|
|
70
|
+
//# sourceMappingURL=commonSignInResolvers.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commonSignInResolvers.cjs.js","sources":["../../src/sign-in/commonSignInResolvers.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { z } from 'zod';\nimport { createSignInResolverFactory } from './createSignInResolverFactory';\nimport { NotAllowedError } from '@backstage/errors';\n\n// This splits an email \"joe+work@acme.com\" into [\"joe\", \"+work\", \"@acme.com\"]\n// so that we can remove the plus addressing. May output a shorter array:\n// [\"joe\", \"@acme.com\"], if no plus addressing was found.\nconst reEmail = /^([^@+]+)(\\+[^@]+)?(@.*)$/;\n\n/**\n * A collection of common sign-in resolvers that work with any auth provider.\n *\n * @public\n */\nexport namespace commonSignInResolvers {\n /**\n * A common sign-in resolver that looks up the user using their email address\n * as email of the entity.\n */\n export const emailMatchingUserEntityProfileEmail =\n createSignInResolverFactory({\n create() {\n return async (info, ctx) => {\n const { profile } = info;\n\n if (!profile.email) {\n throw new Error(\n 'Login failed, user profile does not contain an email',\n );\n }\n\n try {\n return await ctx.signInWithCatalogUser({\n filter: {\n 'spec.profile.email': profile.email,\n },\n });\n } catch (err) {\n if (err?.name === 'NotFoundError') {\n // Try removing the plus addressing from the email address\n const m = profile.email.match(reEmail);\n if (m?.length === 4) {\n const [_, name, _plus, domain] = m;\n const noPlusEmail = `${name}${domain}`;\n\n return ctx.signInWithCatalogUser({\n filter: {\n 'spec.profile.email': noPlusEmail,\n },\n });\n }\n }\n // Email had no plus addressing or is missing in the catalog, forward failure\n throw err;\n }\n };\n },\n });\n\n /**\n * A common sign-in resolver that looks up the user using the local part of\n * their email address as the entity name.\n */\n export const emailLocalPartMatchingUserEntityName =\n createSignInResolverFactory({\n optionsSchema: z\n .object({\n allowedDomains: z.array(z.string()).optional(),\n })\n .optional(),\n create(options = {}) {\n const { allowedDomains } = options;\n return async (info, ctx) => {\n const { profile } = info;\n\n if (!profile.email) {\n throw new Error(\n 'Login failed, user profile does not contain an email',\n );\n }\n const [localPart] = profile.email.split('@');\n const domain = profile.email.slice(localPart.length + 1);\n\n if (allowedDomains && !allowedDomains.includes(domain)) {\n throw new NotAllowedError(\n 'Sign-in user email is not from an allowed domain',\n );\n }\n\n return ctx.signInWithCatalogUser({\n entityRef: { name: localPart },\n });\n };\n },\n });\n}\n"],"names":["commonSignInResolvers","createSignInResolverFactory","z","NotAllowedError"],"mappings":";;;;;;AAuBA,MAAM,OAAU,GAAA,2BAAA,CAAA;AAOCA,uCAAA;AAAA,CAAV,CAAUA,sBAAV,KAAA;AAKE,EAAMA,sBAAAA,CAAA,sCACXC,uDAA4B,CAAA;AAAA,IAC1B,MAAS,GAAA;AACP,MAAO,OAAA,OAAO,MAAM,GAAQ,KAAA;AAC1B,QAAM,MAAA,EAAE,SAAY,GAAA,IAAA,CAAA;AAEpB,QAAI,IAAA,CAAC,QAAQ,KAAO,EAAA;AAClB,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,sDAAA;AAAA,WACF,CAAA;AAAA,SACF;AAEA,QAAI,IAAA;AACF,UAAO,OAAA,MAAM,IAAI,qBAAsB,CAAA;AAAA,YACrC,MAAQ,EAAA;AAAA,cACN,sBAAsB,OAAQ,CAAA,KAAA;AAAA,aAChC;AAAA,WACD,CAAA,CAAA;AAAA,iBACM,GAAK,EAAA;AACZ,UAAI,IAAA,GAAA,EAAK,SAAS,eAAiB,EAAA;AAEjC,YAAA,MAAM,CAAI,GAAA,OAAA,CAAQ,KAAM,CAAA,KAAA,CAAM,OAAO,CAAA,CAAA;AACrC,YAAI,IAAA,CAAA,EAAG,WAAW,CAAG,EAAA;AACnB,cAAA,MAAM,CAAC,CAAA,EAAG,IAAM,EAAA,KAAA,EAAO,MAAM,CAAI,GAAA,CAAA,CAAA;AACjC,cAAA,MAAM,WAAc,GAAA,CAAA,EAAG,IAAI,CAAA,EAAG,MAAM,CAAA,CAAA,CAAA;AAEpC,cAAA,OAAO,IAAI,qBAAsB,CAAA;AAAA,gBAC/B,MAAQ,EAAA;AAAA,kBACN,oBAAsB,EAAA,WAAA;AAAA,iBACxB;AAAA,eACD,CAAA,CAAA;AAAA,aACH;AAAA,WACF;AAEA,UAAM,MAAA,GAAA,CAAA;AAAA,SACR;AAAA,OACF,CAAA;AAAA,KACF;AAAA,GACD,CAAA,CAAA;AAMI,EAAMD,sBAAAA,CAAA,uCACXC,uDAA4B,CAAA;AAAA,IAC1B,aAAA,EAAeC,MACZ,MAAO,CAAA;AAAA,MACN,gBAAgBA,KAAE,CAAA,KAAA,CAAMA,MAAE,MAAO,EAAC,EAAE,QAAS,EAAA;AAAA,KAC9C,EACA,QAAS,EAAA;AAAA,IACZ,MAAA,CAAO,OAAU,GAAA,EAAI,EAAA;AACnB,MAAM,MAAA,EAAE,gBAAmB,GAAA,OAAA,CAAA;AAC3B,MAAO,OAAA,OAAO,MAAM,GAAQ,KAAA;AAC1B,QAAM,MAAA,EAAE,SAAY,GAAA,IAAA,CAAA;AAEpB,QAAI,IAAA,CAAC,QAAQ,KAAO,EAAA;AAClB,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,sDAAA;AAAA,WACF,CAAA;AAAA,SACF;AACA,QAAA,MAAM,CAAC,SAAS,CAAA,GAAI,OAAQ,CAAA,KAAA,CAAM,MAAM,GAAG,CAAA,CAAA;AAC3C,QAAA,MAAM,SAAS,OAAQ,CAAA,KAAA,CAAM,KAAM,CAAA,SAAA,CAAU,SAAS,CAAC,CAAA,CAAA;AAEvD,QAAA,IAAI,cAAkB,IAAA,CAAC,cAAe,CAAA,QAAA,CAAS,MAAM,CAAG,EAAA;AACtD,UAAA,MAAM,IAAIC,sBAAA;AAAA,YACR,kDAAA;AAAA,WACF,CAAA;AAAA,SACF;AAEA,QAAA,OAAO,IAAI,qBAAsB,CAAA;AAAA,UAC/B,SAAA,EAAW,EAAE,IAAA,EAAM,SAAU,EAAA;AAAA,SAC9B,CAAA,CAAA;AAAA,OACH,CAAA;AAAA,KACF;AAAA,GACD,CAAA,CAAA;AAAA,CAhFY,EAAAH,6BAAA,KAAAA,6BAAA,GAAA,EAAA,CAAA,CAAA;;"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var zodToJsonSchema = require('zod-to-json-schema');
|
|
4
|
+
var zodValidationError = require('zod-validation-error');
|
|
5
|
+
var errors = require('@backstage/errors');
|
|
6
|
+
|
|
7
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var zodToJsonSchema__default = /*#__PURE__*/_interopDefaultCompat(zodToJsonSchema);
|
|
10
|
+
|
|
11
|
+
function createSignInResolverFactory(options) {
|
|
12
|
+
const { optionsSchema } = options;
|
|
13
|
+
if (!optionsSchema) {
|
|
14
|
+
return (resolverOptions) => {
|
|
15
|
+
if (resolverOptions) {
|
|
16
|
+
throw new errors.InputError("sign-in resolver does not accept options");
|
|
17
|
+
}
|
|
18
|
+
return options.create(void 0);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const factory = (...[resolverOptions]) => {
|
|
22
|
+
let parsedOptions;
|
|
23
|
+
try {
|
|
24
|
+
parsedOptions = optionsSchema.parse(resolverOptions);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
throw new errors.InputError(
|
|
27
|
+
`Invalid sign-in resolver options, ${zodValidationError.fromError(error)}`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return options.create(parsedOptions);
|
|
31
|
+
};
|
|
32
|
+
factory.optionsJsonSchema = zodToJsonSchema__default.default(optionsSchema);
|
|
33
|
+
return factory;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exports.createSignInResolverFactory = createSignInResolverFactory;
|
|
37
|
+
//# sourceMappingURL=createSignInResolverFactory.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSignInResolverFactory.cjs.js","sources":["../../src/sign-in/createSignInResolverFactory.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ZodSchema, ZodTypeDef } from 'zod';\nimport { SignInResolver } from '../types';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport { JsonObject } from '@backstage/types';\nimport { fromError } from 'zod-validation-error';\nimport { InputError } from '@backstage/errors';\n\n/** @public */\nexport interface SignInResolverFactory<TAuthResult = any, TOptions = any> {\n (\n ...options: undefined extends TOptions\n ? [options?: TOptions]\n : [options: TOptions]\n ): SignInResolver<TAuthResult>;\n optionsJsonSchema?: JsonObject;\n}\n\n/** @public */\nexport interface SignInResolverFactoryOptions<\n TAuthResult,\n TOptionsOutput,\n TOptionsInput,\n> {\n optionsSchema?: ZodSchema<TOptionsOutput, ZodTypeDef, TOptionsInput>;\n create(options: TOptionsOutput): SignInResolver<TAuthResult>;\n}\n\n/** @public */\nexport function createSignInResolverFactory<\n TAuthResult,\n TOptionsOutput,\n TOptionsInput,\n>(\n options: SignInResolverFactoryOptions<\n TAuthResult,\n TOptionsOutput,\n TOptionsInput\n >,\n): SignInResolverFactory<TAuthResult, TOptionsInput> {\n const { optionsSchema } = options;\n if (!optionsSchema) {\n return (resolverOptions?: TOptionsInput) => {\n if (resolverOptions) {\n throw new InputError('sign-in resolver does not accept options');\n }\n return options.create(undefined as TOptionsOutput);\n };\n }\n const factory = (\n ...[resolverOptions]: undefined extends TOptionsInput\n ? [options?: TOptionsInput]\n : [options: TOptionsInput]\n ) => {\n let parsedOptions;\n try {\n parsedOptions = optionsSchema.parse(resolverOptions);\n } catch (error) {\n throw new InputError(\n `Invalid sign-in resolver options, ${fromError(error)}`,\n );\n }\n return options.create(parsedOptions);\n };\n\n factory.optionsJsonSchema = zodToJsonSchema(optionsSchema) as JsonObject;\n return factory;\n}\n"],"names":["InputError","fromError","zodToJsonSchema"],"mappings":";;;;;;;;;;AA4CO,SAAS,4BAKd,OAKmD,EAAA;AACnD,EAAM,MAAA,EAAE,eAAkB,GAAA,OAAA,CAAA;AAC1B,EAAA,IAAI,CAAC,aAAe,EAAA;AAClB,IAAA,OAAO,CAAC,eAAoC,KAAA;AAC1C,MAAA,IAAI,eAAiB,EAAA;AACnB,QAAM,MAAA,IAAIA,kBAAW,0CAA0C,CAAA,CAAA;AAAA,OACjE;AACA,MAAO,OAAA,OAAA,CAAQ,OAAO,KAA2B,CAAA,CAAA,CAAA;AAAA,KACnD,CAAA;AAAA,GACF;AACA,EAAA,MAAM,OAAU,GAAA,CAAA,GACX,CAAC,eAAe,CAGhB,KAAA;AACH,IAAI,IAAA,aAAA,CAAA;AACJ,IAAI,IAAA;AACF,MAAgB,aAAA,GAAA,aAAA,CAAc,MAAM,eAAe,CAAA,CAAA;AAAA,aAC5C,KAAO,EAAA;AACd,MAAA,MAAM,IAAIA,iBAAA;AAAA,QACR,CAAA,kCAAA,EAAqCC,4BAAU,CAAA,KAAK,CAAC,CAAA,CAAA;AAAA,OACvD,CAAA;AAAA,KACF;AACA,IAAO,OAAA,OAAA,CAAQ,OAAO,aAAa,CAAA,CAAA;AAAA,GACrC,CAAA;AAEA,EAAQ,OAAA,CAAA,iBAAA,GAAoBC,iCAAgB,aAAa,CAAA,CAAA;AACzD,EAAO,OAAA,OAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function readDeclarativeSignInResolver(options) {
|
|
4
|
+
const resolvers = options.config.getOptionalConfigArray("signIn.resolvers")?.map((resolverConfig) => {
|
|
5
|
+
const resolverName = resolverConfig.getString("resolver");
|
|
6
|
+
if (!Object.hasOwn(options.signInResolverFactories, resolverName)) {
|
|
7
|
+
throw new Error(
|
|
8
|
+
`Sign-in resolver '${resolverName}' is not available`
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
const resolver = options.signInResolverFactories[resolverName];
|
|
12
|
+
const { resolver: _ignored, ...resolverOptions } = resolverConfig.get();
|
|
13
|
+
return resolver(
|
|
14
|
+
Object.keys(resolverOptions).length > 0 ? resolverOptions : void 0
|
|
15
|
+
);
|
|
16
|
+
}) ?? [];
|
|
17
|
+
if (resolvers.length === 0) {
|
|
18
|
+
return void 0;
|
|
19
|
+
}
|
|
20
|
+
return async (profile, context) => {
|
|
21
|
+
for (const resolver of resolvers) {
|
|
22
|
+
try {
|
|
23
|
+
return await resolver(profile, context);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (error?.name === "NotFoundError") {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
throw new Error(
|
|
32
|
+
"Failed to sign-in, unable to resolve user identity. Please verify that your catalog contains the expected User entities that would match your configured sign-in resolver."
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
exports.readDeclarativeSignInResolver = readDeclarativeSignInResolver;
|
|
38
|
+
//# sourceMappingURL=readDeclarativeSignInResolver.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readDeclarativeSignInResolver.cjs.js","sources":["../../src/sign-in/readDeclarativeSignInResolver.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { SignInResolver } from '../types';\nimport { SignInResolverFactory } from './createSignInResolverFactory';\n\n/** @public */\nexport interface ReadDeclarativeSignInResolverOptions<TAuthResult> {\n config: Config;\n signInResolverFactories: {\n [name in string]: SignInResolverFactory<TAuthResult, unknown>;\n };\n}\n\n/** @public */\nexport function readDeclarativeSignInResolver<TAuthResult>(\n options: ReadDeclarativeSignInResolverOptions<TAuthResult>,\n): SignInResolver<TAuthResult> | undefined {\n const resolvers =\n options.config\n .getOptionalConfigArray('signIn.resolvers')\n ?.map(resolverConfig => {\n const resolverName = resolverConfig.getString('resolver');\n if (!Object.hasOwn(options.signInResolverFactories, resolverName)) {\n throw new Error(\n `Sign-in resolver '${resolverName}' is not available`,\n );\n }\n const resolver = options.signInResolverFactories[resolverName];\n const { resolver: _ignored, ...resolverOptions } =\n resolverConfig.get<JsonObject>();\n\n return resolver(\n Object.keys(resolverOptions).length > 0 ? resolverOptions : undefined,\n );\n }) ?? [];\n\n if (resolvers.length === 0) {\n return undefined;\n }\n\n return async (profile, context) => {\n for (const resolver of resolvers) {\n try {\n return await resolver(profile, context);\n } catch (error) {\n if (error?.name === 'NotFoundError') {\n continue;\n }\n throw error;\n }\n }\n\n throw new Error(\n 'Failed to sign-in, unable to resolve user identity. Please verify that your catalog contains the expected User entities that would match your configured sign-in resolver.',\n );\n };\n}\n"],"names":[],"mappings":";;AA8BO,SAAS,8BACd,OACyC,EAAA;AACzC,EAAA,MAAM,YACJ,OAAQ,CAAA,MAAA,CACL,uBAAuB,kBAAkB,CAAA,EACxC,IAAI,CAAkB,cAAA,KAAA;AACtB,IAAM,MAAA,YAAA,GAAe,cAAe,CAAA,SAAA,CAAU,UAAU,CAAA,CAAA;AACxD,IAAA,IAAI,CAAC,MAAO,CAAA,MAAA,CAAO,OAAQ,CAAA,uBAAA,EAAyB,YAAY,CAAG,EAAA;AACjE,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,qBAAqB,YAAY,CAAA,kBAAA,CAAA;AAAA,OACnC,CAAA;AAAA,KACF;AACA,IAAM,MAAA,QAAA,GAAW,OAAQ,CAAA,uBAAA,CAAwB,YAAY,CAAA,CAAA;AAC7D,IAAA,MAAM,EAAE,QAAU,EAAA,QAAA,EAAU,GAAG,eAAgB,EAAA,GAC7C,eAAe,GAAgB,EAAA,CAAA;AAEjC,IAAO,OAAA,QAAA;AAAA,MACL,OAAO,IAAK,CAAA,eAAe,CAAE,CAAA,MAAA,GAAS,IAAI,eAAkB,GAAA,KAAA,CAAA;AAAA,KAC9D,CAAA;AAAA,GACD,KAAK,EAAC,CAAA;AAEX,EAAI,IAAA,SAAA,CAAU,WAAW,CAAG,EAAA;AAC1B,IAAO,OAAA,KAAA,CAAA,CAAA;AAAA,GACT;AAEA,EAAO,OAAA,OAAO,SAAS,OAAY,KAAA;AACjC,IAAA,KAAA,MAAW,YAAY,SAAW,EAAA;AAChC,MAAI,IAAA;AACF,QAAO,OAAA,MAAM,QAAS,CAAA,OAAA,EAAS,OAAO,CAAA,CAAA;AAAA,eAC/B,KAAO,EAAA;AACd,QAAI,IAAA,KAAA,EAAO,SAAS,eAAiB,EAAA;AACnC,UAAA,SAAA;AAAA,SACF;AACA,QAAM,MAAA,KAAA,CAAA;AAAA,OACR;AAAA,KACF;AAEA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,4KAAA;AAAA,KACF,CAAA;AAAA,GACF,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const tokenTypes = Object.freeze({
|
|
4
|
+
user: Object.freeze({
|
|
5
|
+
typParam: "vnd.backstage.user",
|
|
6
|
+
audClaim: "backstage"
|
|
7
|
+
}),
|
|
8
|
+
limitedUser: Object.freeze({
|
|
9
|
+
typParam: "vnd.backstage.limited-user"
|
|
10
|
+
}),
|
|
11
|
+
plugin: Object.freeze({
|
|
12
|
+
typParam: "vnd.backstage.plugin"
|
|
13
|
+
})
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
exports.tokenTypes = tokenTypes;
|
|
17
|
+
//# sourceMappingURL=types.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.cjs.js","sources":["../src/types.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { EntityFilterQuery } from '@backstage/catalog-client';\nimport { Entity } from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport { JsonValue } from '@backstage/types';\nimport { Request, Response } from 'express';\n\n/**\n * A representation of a successful Backstage sign-in.\n *\n * Compared to the {@link BackstageIdentityResponse} this type omits\n * the decoded identity information embedded in the token.\n *\n * @public\n */\nexport interface BackstageSignInResult {\n /**\n * The token used to authenticate the user within Backstage.\n */\n token: string;\n}\n\n/**\n * Response object containing the {@link BackstageUserIdentity} and the token\n * from the authentication provider.\n *\n * @public\n */\nexport interface BackstageIdentityResponse extends BackstageSignInResult {\n /**\n * The number of seconds until the token expires. If not set, it can be assumed that the token does not expire.\n */\n expiresInSeconds?: number;\n\n /**\n * A plaintext description of the identity that is encapsulated within the token.\n */\n identity: BackstageUserIdentity;\n}\n\n/**\n * User identity information within Backstage.\n *\n * @public\n */\nexport type BackstageUserIdentity = {\n /**\n * The type of identity that this structure represents. In the frontend app\n * this will currently always be 'user'.\n */\n type: 'user';\n\n /**\n * The entityRef of the user in the catalog.\n * For example User:default/sandra\n */\n userEntityRef: string;\n\n /**\n * The user and group entities that the user claims ownership through\n */\n ownershipEntityRefs: string[];\n};\n\n/**\n * A query for a single user in the catalog.\n *\n * If `entityRef` is used, the default kind is `'User'`.\n *\n * If `annotations` are used, all annotations must be present and\n * match the provided value exactly. Only entities of kind `'User'` will be considered.\n *\n * If `filter` are used, only entities of kind `'User'` will be considered unless it is explicitly specified differently in the filter.\n *\n * Regardless of the query method, the query must match exactly one entity\n * in the catalog, or an error will be thrown.\n *\n * @public\n */\nexport type AuthResolverCatalogUserQuery =\n | {\n entityRef:\n | string\n | {\n kind?: string;\n namespace?: string;\n name: string;\n };\n }\n | {\n annotations: Record<string, string>;\n }\n | {\n filter: EntityFilterQuery;\n };\n\n/**\n * Parameters used to issue new Backstage Tokens\n *\n * @public\n */\nexport type TokenParams = {\n /**\n * The claims that will be embedded within the token. At a minimum, this should include\n * the subject claim, `sub`. It is common to also list entity ownership relations in the\n * `ent` list. Additional claims may also be added at the developer's discretion except\n * for the following list, which will be overwritten by the TokenIssuer: `iss`, `aud`,\n * `iat`, and `exp`. The Backstage team also maintains the right add new claims in the future\n * without listing the change as a \"breaking change\".\n */\n claims: {\n /** The token subject, i.e. User ID */\n sub: string;\n /** A list of entity references that the user claims ownership through */\n ent?: string[];\n } & Record<string, JsonValue>;\n};\n\n/**\n * The context that is used for auth processing.\n *\n * @public\n */\nexport type AuthResolverContext = {\n /**\n * Issues a Backstage token using the provided parameters.\n */\n issueToken(params: TokenParams): Promise<{ token: string }>;\n\n /**\n * Finds a single user in the catalog using the provided query.\n *\n * See {@link AuthResolverCatalogUserQuery} for details.\n */\n findCatalogUser(\n query: AuthResolverCatalogUserQuery,\n ): Promise<{ entity: Entity }>;\n\n /**\n * Finds a single user in the catalog using the provided query, and then\n * issues an identity for that user using default ownership resolution.\n *\n * See {@link AuthResolverCatalogUserQuery} for details.\n */\n signInWithCatalogUser(\n query: AuthResolverCatalogUserQuery,\n ): Promise<BackstageSignInResult>;\n};\n\n/**\n * Resolver interface for resolving the ownership entity references for entity\n *\n * @public\n */\nexport interface AuthOwnershipResolver {\n resolveOwnershipEntityRefs(\n entity: Entity,\n ): Promise<{ ownershipEntityRefs: string[] }>;\n}\n\n/**\n * Any Auth provider needs to implement this interface which handles the routes in the\n * auth backend. Any auth API requests from the frontend reaches these methods.\n *\n * The routes in the auth backend API are tied to these methods like below\n *\n * `/auth/[provider]/start -> start`\n * `/auth/[provider]/handler/frame -> frameHandler`\n * `/auth/[provider]/refresh -> refresh`\n * `/auth/[provider]/logout -> logout`\n *\n * @public\n */\nexport interface AuthProviderRouteHandlers {\n /**\n * Handles the start route of the API. This initiates a sign in request with an auth provider.\n *\n * Request\n * - scopes for the auth request (Optional)\n * Response\n * - redirect to the auth provider for the user to sign in or consent.\n * - sets a nonce cookie and also pass the nonce as 'state' query parameter in the redirect request\n */\n start(req: Request, res: Response): Promise<void>;\n\n /**\n * Once the user signs in or consents in the OAuth screen, the auth provider redirects to the\n * callbackURL which is handled by this method.\n *\n * Request\n * - to contain a nonce cookie and a 'state' query parameter\n * Response\n * - postMessage to the window with a payload that contains accessToken, expiryInSeconds?, idToken? and scope.\n * - sets a refresh token cookie if the auth provider supports refresh tokens\n */\n frameHandler(req: Request, res: Response): Promise<void>;\n\n /**\n * (Optional) If the auth provider supports refresh tokens then this method handles\n * requests to get a new access token.\n *\n * Other types of providers may also use this method to implement its own logic to create new sessions\n * upon request. For example, this can be used to create a new session for a provider that handles requests\n * from an authenticating proxy.\n *\n * Request\n * - to contain a refresh token cookie and scope (Optional) query parameter.\n * Response\n * - payload with accessToken, expiryInSeconds?, idToken?, scope and user profile information.\n */\n refresh?(req: Request, res: Response): Promise<void>;\n\n /**\n * (Optional) Handles sign out requests\n *\n * Response\n * - removes the refresh token cookie\n */\n logout?(req: Request, res: Response): Promise<void>;\n}\n\n/**\n * @public\n * @deprecated Use top-level properties passed to `AuthProviderFactory` instead\n */\nexport type AuthProviderConfig = {\n /**\n * The protocol://domain[:port] where the app is hosted. This is used to construct the\n * callbackURL to redirect to once the user signs in to the auth provider.\n */\n baseUrl: string;\n\n /**\n * The base URL of the app as provided by app.baseUrl\n */\n appUrl: string;\n\n /**\n * A function that is called to check whether an origin is allowed to receive the authentication result.\n */\n isOriginAllowed: (origin: string) => boolean;\n\n /**\n * The function used to resolve cookie configuration based on the auth provider options.\n */\n cookieConfigurer?: CookieConfigurer;\n};\n\n/** @public */\nexport type AuthProviderFactory = (options: {\n providerId: string;\n /** @deprecated Use top-level properties instead */\n globalConfig: AuthProviderConfig;\n config: Config;\n logger: LoggerService;\n resolverContext: AuthResolverContext;\n /**\n * The protocol://domain[:port] where the app is hosted. This is used to construct the\n * callbackURL to redirect to once the user signs in to the auth provider.\n */\n baseUrl: string;\n\n /**\n * The base URL of the app as provided by app.baseUrl\n */\n appUrl: string;\n\n /**\n * A function that is called to check whether an origin is allowed to receive the authentication result.\n */\n isOriginAllowed: (origin: string) => boolean;\n\n /**\n * The function used to resolve cookie configuration based on the auth provider options.\n */\n cookieConfigurer?: CookieConfigurer;\n}) => AuthProviderRouteHandlers;\n\n/** @public */\nexport type ClientAuthResponse<TProviderInfo> = {\n providerInfo: TProviderInfo;\n profile: ProfileInfo;\n backstageIdentity?: BackstageIdentityResponse;\n};\n\n/**\n * Type of sign in information context. Includes the profile information and\n * authentication result which contains auth related information.\n *\n * @public\n */\nexport type SignInInfo<TAuthResult> = {\n /**\n * The simple profile passed down for use in the frontend.\n */\n profile: ProfileInfo;\n\n /**\n * The authentication result that was received from the authentication\n * provider.\n */\n result: TAuthResult;\n};\n\n/**\n * Describes the function which handles the result of a successful\n * authentication. Must return a valid {@link @backstage/plugin-auth-node#BackstageSignInResult}.\n *\n * @public\n */\nexport type SignInResolver<TAuthResult> = (\n info: SignInInfo<TAuthResult>,\n context: AuthResolverContext,\n) => Promise<BackstageSignInResult>;\n\n/**\n * Describes the function that transforms the result of a successful\n * authentication into a {@link ProfileInfo} object.\n *\n * This function may optionally throw an error in order to reject authentication.\n *\n * @public\n */\nexport type ProfileTransform<TResult> = (\n result: TResult,\n context: AuthResolverContext,\n) => Promise<{ profile: ProfileInfo }>;\n\n/**\n * Used to display login information to user, i.e. sidebar popup.\n *\n * It is also temporarily used as the profile of the signed-in user's Backstage\n * identity, but we want to replace that with data from identity and/org catalog\n * service\n *\n * @public\n */\nexport type ProfileInfo = {\n /**\n * Email ID of the signed in user.\n */\n email?: string;\n /**\n * Display name that can be presented to the signed in user.\n */\n displayName?: string;\n /**\n * URL to an image that can be used as the display image or avatar of the\n * signed in user.\n */\n picture?: string;\n};\n\n/**\n * The callback used to resolve the cookie configuration for auth providers that use cookies.\n * @public\n */\nexport type CookieConfigurer = (ctx: {\n /** ID of the auth provider that this configuration applies to */\n providerId: string;\n /** The externally reachable base URL of the auth-backend plugin */\n baseUrl: string;\n /** The configured callback URL of the auth provider */\n callbackUrl: string;\n /** The origin URL of the app */\n appOrigin: string;\n}) => {\n domain: string;\n path: string;\n secure: boolean;\n sameSite?: 'none' | 'lax' | 'strict';\n};\n\n/**\n * Core properties of various token types.\n *\n * @public\n */\nexport const tokenTypes = Object.freeze({\n user: Object.freeze({\n typParam: 'vnd.backstage.user',\n audClaim: 'backstage',\n }),\n limitedUser: Object.freeze({\n typParam: 'vnd.backstage.limited-user',\n }),\n plugin: Object.freeze({\n typParam: 'vnd.backstage.plugin',\n }),\n});\n"],"names":[],"mappings":";;AA0Ya,MAAA,UAAA,GAAa,OAAO,MAAO,CAAA;AAAA,EACtC,IAAA,EAAM,OAAO,MAAO,CAAA;AAAA,IAClB,QAAU,EAAA,oBAAA;AAAA,IACV,QAAU,EAAA,WAAA;AAAA,GACX,CAAA;AAAA,EACD,WAAA,EAAa,OAAO,MAAO,CAAA;AAAA,IACzB,QAAU,EAAA,4BAAA;AAAA,GACX,CAAA;AAAA,EACD,MAAA,EAAQ,OAAO,MAAO,CAAA;AAAA,IACpB,QAAU,EAAA,sBAAA;AAAA,GACX,CAAA;AACH,CAAC;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-auth-node",
|
|
3
|
-
"version": "0.5.3
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "node-library",
|
|
6
6
|
"pluginId": "auth",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@backstage/backend-common": "^0.25.0",
|
|
41
|
-
"@backstage/backend-plugin-api": "^1.0.1
|
|
42
|
-
"@backstage/catalog-client": "^1.7.
|
|
41
|
+
"@backstage/backend-plugin-api": "^1.0.1",
|
|
42
|
+
"@backstage/catalog-client": "^1.7.1",
|
|
43
43
|
"@backstage/catalog-model": "^1.7.0",
|
|
44
44
|
"@backstage/config": "^1.2.0",
|
|
45
45
|
"@backstage/errors": "^1.2.4",
|
|
@@ -53,11 +53,12 @@
|
|
|
53
53
|
"passport": "^0.7.0",
|
|
54
54
|
"winston": "^3.2.1",
|
|
55
55
|
"zod": "^3.22.4",
|
|
56
|
-
"zod-to-json-schema": "^3.21.4"
|
|
56
|
+
"zod-to-json-schema": "^3.21.4",
|
|
57
|
+
"zod-validation-error": "^3.4.0"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
|
-
"@backstage/backend-test-utils": "^1.0.1
|
|
60
|
-
"@backstage/cli": "^0.28.0
|
|
60
|
+
"@backstage/backend-test-utils": "^1.0.1",
|
|
61
|
+
"@backstage/cli": "^0.28.0",
|
|
61
62
|
"cookie-parser": "^1.4.6",
|
|
62
63
|
"express-promise-router": "^4.1.1",
|
|
63
64
|
"lodash": "^4.17.21",
|