@flink-app/oidc-plugin 0.13.0
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 +13 -0
- package/LICENSE +21 -0
- package/README.md +846 -0
- package/dist/OidcInternalContext.d.ts +15 -0
- package/dist/OidcInternalContext.d.ts.map +1 -0
- package/dist/OidcInternalContext.js +2 -0
- package/dist/OidcPlugin.d.ts +77 -0
- package/dist/OidcPlugin.d.ts.map +1 -0
- package/dist/OidcPlugin.js +274 -0
- package/dist/OidcPluginContext.d.ts +73 -0
- package/dist/OidcPluginContext.d.ts.map +1 -0
- package/dist/OidcPluginContext.js +2 -0
- package/dist/OidcPluginOptions.d.ts +267 -0
- package/dist/OidcPluginOptions.d.ts.map +1 -0
- package/dist/OidcPluginOptions.js +2 -0
- package/dist/OidcProviderConfig.d.ts +77 -0
- package/dist/OidcProviderConfig.d.ts.map +1 -0
- package/dist/OidcProviderConfig.js +2 -0
- package/dist/handlers/CallbackOidc.d.ts +38 -0
- package/dist/handlers/CallbackOidc.d.ts.map +1 -0
- package/dist/handlers/CallbackOidc.js +219 -0
- package/dist/handlers/InitiateOidc.d.ts +35 -0
- package/dist/handlers/InitiateOidc.d.ts.map +1 -0
- package/dist/handlers/InitiateOidc.js +91 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/providers/OidcProvider.d.ts +90 -0
- package/dist/providers/OidcProvider.d.ts.map +1 -0
- package/dist/providers/OidcProvider.js +208 -0
- package/dist/providers/ProviderRegistry.d.ts +55 -0
- package/dist/providers/ProviderRegistry.d.ts.map +1 -0
- package/dist/providers/ProviderRegistry.js +94 -0
- package/dist/repos/OidcConnectionRepo.d.ts +75 -0
- package/dist/repos/OidcConnectionRepo.d.ts.map +1 -0
- package/dist/repos/OidcConnectionRepo.js +122 -0
- package/dist/repos/OidcSessionRepo.d.ts +57 -0
- package/dist/repos/OidcSessionRepo.d.ts.map +1 -0
- package/dist/repos/OidcSessionRepo.js +91 -0
- package/dist/schemas/CallbackRequest.d.ts +37 -0
- package/dist/schemas/CallbackRequest.d.ts.map +1 -0
- package/dist/schemas/CallbackRequest.js +2 -0
- package/dist/schemas/InitiateRequest.d.ts +17 -0
- package/dist/schemas/InitiateRequest.d.ts.map +1 -0
- package/dist/schemas/InitiateRequest.js +2 -0
- package/dist/schemas/OidcConnection.d.ts +69 -0
- package/dist/schemas/OidcConnection.d.ts.map +1 -0
- package/dist/schemas/OidcConnection.js +2 -0
- package/dist/schemas/OidcProfile.d.ts +69 -0
- package/dist/schemas/OidcProfile.d.ts.map +1 -0
- package/dist/schemas/OidcProfile.js +2 -0
- package/dist/schemas/OidcSession.d.ts +46 -0
- package/dist/schemas/OidcSession.d.ts.map +1 -0
- package/dist/schemas/OidcSession.js +2 -0
- package/dist/schemas/OidcTokenSet.d.ts +42 -0
- package/dist/schemas/OidcTokenSet.d.ts.map +1 -0
- package/dist/schemas/OidcTokenSet.js +2 -0
- package/dist/utils/claims-mapper.d.ts +46 -0
- package/dist/utils/claims-mapper.d.ts.map +1 -0
- package/dist/utils/claims-mapper.js +104 -0
- package/dist/utils/encryption-utils.d.ts +32 -0
- package/dist/utils/encryption-utils.d.ts.map +1 -0
- package/dist/utils/encryption-utils.js +82 -0
- package/dist/utils/error-utils.d.ts +65 -0
- package/dist/utils/error-utils.d.ts.map +1 -0
- package/dist/utils/error-utils.js +150 -0
- package/dist/utils/response-utils.d.ts +18 -0
- package/dist/utils/response-utils.d.ts.map +1 -0
- package/dist/utils/response-utils.js +42 -0
- package/dist/utils/state-utils.d.ts +36 -0
- package/dist/utils/state-utils.d.ts.map +1 -0
- package/dist/utils/state-utils.js +66 -0
- package/examples/basic-oidc.ts +151 -0
- package/examples/multi-provider.ts +146 -0
- package/package.json +44 -0
- package/spec/handlers/InitiateOidc.spec.ts +62 -0
- package/spec/helpers/reporter.ts +34 -0
- package/spec/helpers/test-helpers.ts +108 -0
- package/spec/plugin/OidcPlugin.spec.ts +126 -0
- package/spec/providers/ProviderRegistry.spec.ts +197 -0
- package/spec/repos/OidcConnectionRepo.spec.ts +257 -0
- package/spec/repos/OidcSessionRepo.spec.ts +196 -0
- package/spec/support/jasmine.json +7 -0
- package/spec/utils/claims-mapper.spec.ts +257 -0
- package/spec/utils/encryption-utils.spec.ts +126 -0
- package/spec/utils/error-utils.spec.ts +107 -0
- package/spec/utils/state-utils.spec.ts +102 -0
- package/src/OidcInternalContext.ts +15 -0
- package/src/OidcPlugin.ts +290 -0
- package/src/OidcPluginContext.ts +76 -0
- package/src/OidcPluginOptions.ts +286 -0
- package/src/OidcProviderConfig.ts +87 -0
- package/src/handlers/CallbackOidc.ts +257 -0
- package/src/handlers/InitiateOidc.ts +110 -0
- package/src/index.ts +38 -0
- package/src/providers/OidcProvider.ts +237 -0
- package/src/providers/ProviderRegistry.ts +107 -0
- package/src/repos/OidcConnectionRepo.ts +132 -0
- package/src/repos/OidcSessionRepo.ts +99 -0
- package/src/schemas/CallbackRequest.ts +41 -0
- package/src/schemas/InitiateRequest.ts +17 -0
- package/src/schemas/OidcConnection.ts +80 -0
- package/src/schemas/OidcProfile.ts +79 -0
- package/src/schemas/OidcSession.ts +52 -0
- package/src/schemas/OidcTokenSet.ts +47 -0
- package/src/utils/claims-mapper.ts +114 -0
- package/src/utils/encryption-utils.ts +92 -0
- package/src/utils/error-utils.ts +167 -0
- package/src/utils/response-utils.ts +41 -0
- package/src/utils/state-utils.ts +66 -0
- package/tsconfig.dist.json +9 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OIDC Initiate Handler
|
|
4
|
+
*
|
|
5
|
+
* Initiates the OIDC authorization code flow by:
|
|
6
|
+
* 1. Validating the provider is supported and configured
|
|
7
|
+
* 2. Generating cryptographically secure state, code_verifier, and nonce
|
|
8
|
+
* 3. Creating an OIDC session to track the flow
|
|
9
|
+
* 4. Building the provider's authorization URL with PKCE
|
|
10
|
+
* 5. Redirecting the user to the provider for authorization
|
|
11
|
+
*
|
|
12
|
+
* Route: GET /oidc/:provider/initiate?redirectUri={optional_redirect_url}
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.Route = void 0;
|
|
16
|
+
const flink_1 = require("@flink-app/flink");
|
|
17
|
+
const state_utils_1 = require("../utils/state-utils");
|
|
18
|
+
const error_utils_1 = require("../utils/error-utils");
|
|
19
|
+
const openid_client_1 = require("openid-client");
|
|
20
|
+
/**
|
|
21
|
+
* Route configuration
|
|
22
|
+
* This handler is registered programmatically by the plugin
|
|
23
|
+
*/
|
|
24
|
+
exports.Route = {
|
|
25
|
+
path: "/oidc/:provider/initiate",
|
|
26
|
+
method: flink_1.HttpMethod.get,
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* OIDC Initiate Handler
|
|
30
|
+
*
|
|
31
|
+
* Starts the OIDC flow by generating security parameters, creating a session,
|
|
32
|
+
* and redirecting to the OIDC provider's authorization URL.
|
|
33
|
+
*/
|
|
34
|
+
const InitiateOidc = async ({ ctx, req }) => {
|
|
35
|
+
const { provider } = req.params;
|
|
36
|
+
const { redirectUri } = req.query;
|
|
37
|
+
try {
|
|
38
|
+
// Validate provider name format
|
|
39
|
+
(0, error_utils_1.validateProvider)(provider);
|
|
40
|
+
// Get provider registry from context
|
|
41
|
+
const providerRegistry = ctx.oidcProviderRegistry;
|
|
42
|
+
if (!providerRegistry) {
|
|
43
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.PROVIDER_NOT_CONFIGURED, "OIDC plugin not properly initialized");
|
|
44
|
+
}
|
|
45
|
+
// Get OIDC provider instance (loads dynamically if needed)
|
|
46
|
+
const oidcProvider = await providerRegistry.getProvider(provider);
|
|
47
|
+
// Get plugin options
|
|
48
|
+
const { options } = ctx.plugins.oidc;
|
|
49
|
+
// Determine redirect URI (use provided or default to callback URL)
|
|
50
|
+
const staticProviderConfig = options.providers[provider];
|
|
51
|
+
const finalRedirectUri = redirectUri || staticProviderConfig?.callbackUrl || `${req.protocol}://${req.get("host")}/oidc/${provider}/callback`;
|
|
52
|
+
// Generate cryptographically secure parameters
|
|
53
|
+
const state = (0, state_utils_1.generateState)();
|
|
54
|
+
const sessionId = (0, state_utils_1.generateSessionId)();
|
|
55
|
+
const nonce = (0, state_utils_1.generateNonce)();
|
|
56
|
+
const codeVerifier = openid_client_1.generators.codeVerifier();
|
|
57
|
+
// Store session for state validation in callback
|
|
58
|
+
await ctx.repos.oidcSessionRepo.create({
|
|
59
|
+
sessionId,
|
|
60
|
+
state,
|
|
61
|
+
codeVerifier,
|
|
62
|
+
nonce,
|
|
63
|
+
provider,
|
|
64
|
+
redirectUri: finalRedirectUri,
|
|
65
|
+
createdAt: new Date(),
|
|
66
|
+
});
|
|
67
|
+
// Build authorization URL with PKCE and nonce
|
|
68
|
+
const authorizationUrl = await oidcProvider.getAuthorizationUrl({
|
|
69
|
+
state,
|
|
70
|
+
codeVerifier,
|
|
71
|
+
nonce,
|
|
72
|
+
});
|
|
73
|
+
// Redirect user to provider's authorization page
|
|
74
|
+
return {
|
|
75
|
+
status: 302,
|
|
76
|
+
headers: {
|
|
77
|
+
Location: authorizationUrl,
|
|
78
|
+
},
|
|
79
|
+
data: {},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
// Handle validation errors
|
|
84
|
+
if (error.code && Object.values(error_utils_1.OidcErrorCodes).includes(error.code)) {
|
|
85
|
+
return (0, flink_1.badRequest)(error.message);
|
|
86
|
+
}
|
|
87
|
+
// Handle unexpected errors
|
|
88
|
+
return (0, flink_1.internalServerError)(error.message || "Failed to initiate OIDC flow");
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
exports.default = InitiateOidc;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @flink-app/oidc-plugin
|
|
3
|
+
*
|
|
4
|
+
* OIDC authentication plugin for Flink Framework
|
|
5
|
+
*
|
|
6
|
+
* Provides OpenID Connect authentication with generic IdP support,
|
|
7
|
+
* JWT integration via jwt-auth-plugin, JIT user provisioning,
|
|
8
|
+
* and optional token storage for API access.
|
|
9
|
+
*/
|
|
10
|
+
export { oidcPlugin } from "./OidcPlugin";
|
|
11
|
+
export { OidcPluginOptions, OidcError, AuthSuccessCallbackResponse, AuthErrorCallbackResponse } from "./OidcPluginOptions";
|
|
12
|
+
export { OidcProviderConfig } from "./OidcProviderConfig";
|
|
13
|
+
export { OidcPluginContext } from "./OidcPluginContext";
|
|
14
|
+
export { default as OidcProfile } from "./schemas/OidcProfile";
|
|
15
|
+
export { default as OidcTokenSet } from "./schemas/OidcTokenSet";
|
|
16
|
+
export { default as OidcSession } from "./schemas/OidcSession";
|
|
17
|
+
export { default as OidcConnection } from "./schemas/OidcConnection";
|
|
18
|
+
export { default as InitiateRequest } from "./schemas/InitiateRequest";
|
|
19
|
+
export { default as CallbackRequest } from "./schemas/CallbackRequest";
|
|
20
|
+
export { OidcProvider } from "./providers/OidcProvider";
|
|
21
|
+
export { ProviderRegistry } from "./providers/ProviderRegistry";
|
|
22
|
+
export { generateState, generateSessionId, generateNonce, validateState } from "./utils/state-utils";
|
|
23
|
+
export { encryptToken, decryptToken, validateEncryptionSecret } from "./utils/encryption-utils";
|
|
24
|
+
export { mapClaimsToProfile, extractCustomClaims } from "./utils/claims-mapper";
|
|
25
|
+
export { formatTokenResponse } from "./utils/response-utils";
|
|
26
|
+
export { createOidcError, validateProvider, handleProviderError, OidcErrorCodes } from "./utils/error-utils";
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAC3H,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGvE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGhE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACrG,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAChG,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @flink-app/oidc-plugin
|
|
4
|
+
*
|
|
5
|
+
* OIDC authentication plugin for Flink Framework
|
|
6
|
+
*
|
|
7
|
+
* Provides OpenID Connect authentication with generic IdP support,
|
|
8
|
+
* JWT integration via jwt-auth-plugin, JIT user provisioning,
|
|
9
|
+
* and optional token storage for API access.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.OidcErrorCodes = exports.handleProviderError = exports.validateProvider = exports.createOidcError = exports.formatTokenResponse = exports.extractCustomClaims = exports.mapClaimsToProfile = exports.validateEncryptionSecret = exports.decryptToken = exports.encryptToken = exports.validateState = exports.generateNonce = exports.generateSessionId = exports.generateState = exports.ProviderRegistry = exports.OidcProvider = exports.oidcPlugin = void 0;
|
|
13
|
+
// Main plugin factory
|
|
14
|
+
var OidcPlugin_1 = require("./OidcPlugin");
|
|
15
|
+
Object.defineProperty(exports, "oidcPlugin", { enumerable: true, get: function () { return OidcPlugin_1.oidcPlugin; } });
|
|
16
|
+
// Provider classes (for advanced usage)
|
|
17
|
+
var OidcProvider_1 = require("./providers/OidcProvider");
|
|
18
|
+
Object.defineProperty(exports, "OidcProvider", { enumerable: true, get: function () { return OidcProvider_1.OidcProvider; } });
|
|
19
|
+
var ProviderRegistry_1 = require("./providers/ProviderRegistry");
|
|
20
|
+
Object.defineProperty(exports, "ProviderRegistry", { enumerable: true, get: function () { return ProviderRegistry_1.ProviderRegistry; } });
|
|
21
|
+
// Utility functions (for custom implementations)
|
|
22
|
+
var state_utils_1 = require("./utils/state-utils");
|
|
23
|
+
Object.defineProperty(exports, "generateState", { enumerable: true, get: function () { return state_utils_1.generateState; } });
|
|
24
|
+
Object.defineProperty(exports, "generateSessionId", { enumerable: true, get: function () { return state_utils_1.generateSessionId; } });
|
|
25
|
+
Object.defineProperty(exports, "generateNonce", { enumerable: true, get: function () { return state_utils_1.generateNonce; } });
|
|
26
|
+
Object.defineProperty(exports, "validateState", { enumerable: true, get: function () { return state_utils_1.validateState; } });
|
|
27
|
+
var encryption_utils_1 = require("./utils/encryption-utils");
|
|
28
|
+
Object.defineProperty(exports, "encryptToken", { enumerable: true, get: function () { return encryption_utils_1.encryptToken; } });
|
|
29
|
+
Object.defineProperty(exports, "decryptToken", { enumerable: true, get: function () { return encryption_utils_1.decryptToken; } });
|
|
30
|
+
Object.defineProperty(exports, "validateEncryptionSecret", { enumerable: true, get: function () { return encryption_utils_1.validateEncryptionSecret; } });
|
|
31
|
+
var claims_mapper_1 = require("./utils/claims-mapper");
|
|
32
|
+
Object.defineProperty(exports, "mapClaimsToProfile", { enumerable: true, get: function () { return claims_mapper_1.mapClaimsToProfile; } });
|
|
33
|
+
Object.defineProperty(exports, "extractCustomClaims", { enumerable: true, get: function () { return claims_mapper_1.extractCustomClaims; } });
|
|
34
|
+
var response_utils_1 = require("./utils/response-utils");
|
|
35
|
+
Object.defineProperty(exports, "formatTokenResponse", { enumerable: true, get: function () { return response_utils_1.formatTokenResponse; } });
|
|
36
|
+
var error_utils_1 = require("./utils/error-utils");
|
|
37
|
+
Object.defineProperty(exports, "createOidcError", { enumerable: true, get: function () { return error_utils_1.createOidcError; } });
|
|
38
|
+
Object.defineProperty(exports, "validateProvider", { enumerable: true, get: function () { return error_utils_1.validateProvider; } });
|
|
39
|
+
Object.defineProperty(exports, "handleProviderError", { enumerable: true, get: function () { return error_utils_1.handleProviderError; } });
|
|
40
|
+
Object.defineProperty(exports, "OidcErrorCodes", { enumerable: true, get: function () { return error_utils_1.OidcErrorCodes; } });
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { UserinfoResponse } from "openid-client";
|
|
2
|
+
import { OidcProviderConfig } from "../OidcProviderConfig";
|
|
3
|
+
import OidcProfile from "../schemas/OidcProfile";
|
|
4
|
+
import OidcTokenSet from "../schemas/OidcTokenSet";
|
|
5
|
+
/**
|
|
6
|
+
* Generic OIDC Provider implementation using openid-client
|
|
7
|
+
*
|
|
8
|
+
* Supports both OIDC discovery and manual configuration.
|
|
9
|
+
* Handles the complete OIDC flow including:
|
|
10
|
+
* - Authorization URL generation with PKCE
|
|
11
|
+
* - Token exchange (code → tokens)
|
|
12
|
+
* - ID token validation
|
|
13
|
+
* - UserInfo endpoint fetching
|
|
14
|
+
* - Claims mapping to profile
|
|
15
|
+
*/
|
|
16
|
+
export declare class OidcProvider {
|
|
17
|
+
private config;
|
|
18
|
+
private issuer;
|
|
19
|
+
private client;
|
|
20
|
+
private initialized;
|
|
21
|
+
constructor(config: OidcProviderConfig);
|
|
22
|
+
/**
|
|
23
|
+
* Initialize the provider by discovering or creating the OIDC client
|
|
24
|
+
*
|
|
25
|
+
* Uses OIDC discovery if discoveryUrl is provided, otherwise uses
|
|
26
|
+
* manual endpoint configuration.
|
|
27
|
+
*
|
|
28
|
+
* This is async and should be called before using the provider.
|
|
29
|
+
*/
|
|
30
|
+
initialize(): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Generate authorization URL with PKCE and nonce
|
|
33
|
+
*
|
|
34
|
+
* @param params - Authorization parameters
|
|
35
|
+
* @returns Authorization URL to redirect user to
|
|
36
|
+
*/
|
|
37
|
+
getAuthorizationUrl(params: {
|
|
38
|
+
state: string;
|
|
39
|
+
codeVerifier: string;
|
|
40
|
+
nonce: string;
|
|
41
|
+
}): Promise<string>;
|
|
42
|
+
/**
|
|
43
|
+
* Exchange authorization code for tokens
|
|
44
|
+
*
|
|
45
|
+
* Performs the OAuth 2.0 token exchange and validates the ID token.
|
|
46
|
+
*
|
|
47
|
+
* @param params - Token exchange parameters
|
|
48
|
+
* @returns Token set with access token, ID token, and claims
|
|
49
|
+
*/
|
|
50
|
+
exchangeCodeForToken(params: {
|
|
51
|
+
code: string;
|
|
52
|
+
codeVerifier: string;
|
|
53
|
+
state: string;
|
|
54
|
+
nonce: string;
|
|
55
|
+
}): Promise<OidcTokenSet>;
|
|
56
|
+
/**
|
|
57
|
+
* Get user profile from UserInfo endpoint
|
|
58
|
+
*
|
|
59
|
+
* Fetches additional user claims from the UserInfo endpoint.
|
|
60
|
+
* Merges with claims from ID token.
|
|
61
|
+
*
|
|
62
|
+
* @param accessToken - Access token from token exchange
|
|
63
|
+
* @returns UserInfo response
|
|
64
|
+
*/
|
|
65
|
+
getUserInfo(accessToken: string): Promise<UserinfoResponse>;
|
|
66
|
+
/**
|
|
67
|
+
* Build complete user profile from tokens
|
|
68
|
+
*
|
|
69
|
+
* Combines claims from ID token and UserInfo endpoint,
|
|
70
|
+
* applies custom claim mapping, and returns normalized profile.
|
|
71
|
+
*
|
|
72
|
+
* @param tokenSet - Token set from exchange
|
|
73
|
+
* @param includeUserInfo - Whether to fetch UserInfo endpoint
|
|
74
|
+
* @returns Normalized user profile
|
|
75
|
+
*/
|
|
76
|
+
buildProfile(tokenSet: OidcTokenSet, includeUserInfo?: boolean): Promise<OidcProfile>;
|
|
77
|
+
/**
|
|
78
|
+
* Ensure provider is initialized before use
|
|
79
|
+
*
|
|
80
|
+
* @throws Error if not initialized
|
|
81
|
+
*/
|
|
82
|
+
private ensureInitialized;
|
|
83
|
+
/**
|
|
84
|
+
* Get issuer metadata (after initialization)
|
|
85
|
+
*
|
|
86
|
+
* @returns Issuer metadata
|
|
87
|
+
*/
|
|
88
|
+
getIssuerMetadata(): any;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=OidcProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OidcProvider.d.ts","sourceRoot":"","sources":["../../src/providers/OidcProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwC,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,WAAW,MAAM,wBAAwB,CAAC;AACjD,OAAO,YAAY,MAAM,yBAAyB,CAAC;AAInD;;;;;;;;;;GAUG;AACH,qBAAa,YAAY;IACrB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,WAAW,CAAkB;gBAEzB,MAAM,EAAE,kBAAkB;IAItC;;;;;;;OAOG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA+CjC;;;;;OAKG;IACG,mBAAmB,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAiB1G;;;;;;;OAOG;IACG,oBAAoB,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAqC/H;;;;;;;;OAQG;IACG,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAajE;;;;;;;;;OASG;IACG,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,eAAe,GAAE,OAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IA2BjG;;;;OAIG;YACW,iBAAiB;IAU/B;;;;OAIG;IACH,iBAAiB,IAAI,GAAG;CAM3B"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OidcProvider = void 0;
|
|
4
|
+
const openid_client_1 = require("openid-client");
|
|
5
|
+
const claims_mapper_1 = require("../utils/claims-mapper");
|
|
6
|
+
const error_utils_1 = require("../utils/error-utils");
|
|
7
|
+
/**
|
|
8
|
+
* Generic OIDC Provider implementation using openid-client
|
|
9
|
+
*
|
|
10
|
+
* Supports both OIDC discovery and manual configuration.
|
|
11
|
+
* Handles the complete OIDC flow including:
|
|
12
|
+
* - Authorization URL generation with PKCE
|
|
13
|
+
* - Token exchange (code → tokens)
|
|
14
|
+
* - ID token validation
|
|
15
|
+
* - UserInfo endpoint fetching
|
|
16
|
+
* - Claims mapping to profile
|
|
17
|
+
*/
|
|
18
|
+
class OidcProvider {
|
|
19
|
+
constructor(config) {
|
|
20
|
+
this.issuer = null;
|
|
21
|
+
this.client = null;
|
|
22
|
+
this.initialized = false;
|
|
23
|
+
this.config = config;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Initialize the provider by discovering or creating the OIDC client
|
|
27
|
+
*
|
|
28
|
+
* Uses OIDC discovery if discoveryUrl is provided, otherwise uses
|
|
29
|
+
* manual endpoint configuration.
|
|
30
|
+
*
|
|
31
|
+
* This is async and should be called before using the provider.
|
|
32
|
+
*/
|
|
33
|
+
async initialize() {
|
|
34
|
+
if (this.initialized) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
// Option 1: OIDC Discovery
|
|
39
|
+
if (this.config.discoveryUrl) {
|
|
40
|
+
this.issuer = await openid_client_1.Issuer.discover(this.config.discoveryUrl);
|
|
41
|
+
}
|
|
42
|
+
// Option 2: Manual configuration
|
|
43
|
+
else {
|
|
44
|
+
// Validate required endpoints for manual config
|
|
45
|
+
if (!this.config.authorizationEndpoint || !this.config.tokenEndpoint || !this.config.jwksUri) {
|
|
46
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.PROVIDER_NOT_CONFIGURED, "Provider must have either discoveryUrl or manual endpoints (authorizationEndpoint, tokenEndpoint, jwksUri)", { provider: this.config.issuer });
|
|
47
|
+
}
|
|
48
|
+
this.issuer = new openid_client_1.Issuer({
|
|
49
|
+
issuer: this.config.issuer,
|
|
50
|
+
authorization_endpoint: this.config.authorizationEndpoint,
|
|
51
|
+
token_endpoint: this.config.tokenEndpoint,
|
|
52
|
+
userinfo_endpoint: this.config.userinfoEndpoint,
|
|
53
|
+
jwks_uri: this.config.jwksUri,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// Create OIDC client
|
|
57
|
+
this.client = new this.issuer.Client({
|
|
58
|
+
client_id: this.config.clientId,
|
|
59
|
+
client_secret: this.config.clientSecret,
|
|
60
|
+
redirect_uris: [this.config.callbackUrl],
|
|
61
|
+
response_types: ["code"],
|
|
62
|
+
});
|
|
63
|
+
this.initialized = true;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.DISCOVERY_FAILED, `Failed to initialize OIDC provider: ${error.message}`, {
|
|
67
|
+
issuer: this.config.issuer,
|
|
68
|
+
originalError: error.message,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Generate authorization URL with PKCE and nonce
|
|
74
|
+
*
|
|
75
|
+
* @param params - Authorization parameters
|
|
76
|
+
* @returns Authorization URL to redirect user to
|
|
77
|
+
*/
|
|
78
|
+
async getAuthorizationUrl(params) {
|
|
79
|
+
await this.ensureInitialized();
|
|
80
|
+
const codeChallenge = openid_client_1.generators.codeChallenge(params.codeVerifier);
|
|
81
|
+
const scope = this.config.scope?.join(" ") || "openid email profile";
|
|
82
|
+
const authUrl = this.client.authorizationUrl({
|
|
83
|
+
scope,
|
|
84
|
+
state: params.state,
|
|
85
|
+
code_challenge: codeChallenge,
|
|
86
|
+
code_challenge_method: "S256",
|
|
87
|
+
nonce: params.nonce,
|
|
88
|
+
});
|
|
89
|
+
return authUrl;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Exchange authorization code for tokens
|
|
93
|
+
*
|
|
94
|
+
* Performs the OAuth 2.0 token exchange and validates the ID token.
|
|
95
|
+
*
|
|
96
|
+
* @param params - Token exchange parameters
|
|
97
|
+
* @returns Token set with access token, ID token, and claims
|
|
98
|
+
*/
|
|
99
|
+
async exchangeCodeForToken(params) {
|
|
100
|
+
await this.ensureInitialized();
|
|
101
|
+
try {
|
|
102
|
+
const tokenSet = await this.client.callback(this.config.callbackUrl, {
|
|
103
|
+
code: params.code,
|
|
104
|
+
state: params.state,
|
|
105
|
+
}, {
|
|
106
|
+
code_verifier: params.codeVerifier,
|
|
107
|
+
state: params.state,
|
|
108
|
+
nonce: params.nonce,
|
|
109
|
+
});
|
|
110
|
+
// Extract claims from ID token (already validated by openid-client)
|
|
111
|
+
const claims = tokenSet.claims();
|
|
112
|
+
return {
|
|
113
|
+
accessToken: tokenSet.access_token,
|
|
114
|
+
idToken: tokenSet.id_token,
|
|
115
|
+
refreshToken: tokenSet.refresh_token,
|
|
116
|
+
tokenType: tokenSet.token_type || "Bearer",
|
|
117
|
+
expiresIn: tokenSet.expires_in,
|
|
118
|
+
scope: tokenSet.scope,
|
|
119
|
+
claims,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.TOKEN_EXCHANGE_FAILED, `Token exchange failed: ${error.message}`, {
|
|
124
|
+
originalError: error.message,
|
|
125
|
+
errorCode: error.error,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get user profile from UserInfo endpoint
|
|
131
|
+
*
|
|
132
|
+
* Fetches additional user claims from the UserInfo endpoint.
|
|
133
|
+
* Merges with claims from ID token.
|
|
134
|
+
*
|
|
135
|
+
* @param accessToken - Access token from token exchange
|
|
136
|
+
* @returns UserInfo response
|
|
137
|
+
*/
|
|
138
|
+
async getUserInfo(accessToken) {
|
|
139
|
+
await this.ensureInitialized();
|
|
140
|
+
try {
|
|
141
|
+
const userinfo = await this.client.userinfo(accessToken);
|
|
142
|
+
return userinfo;
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.USERINFO_FAILED, `UserInfo request failed: ${error.message}`, {
|
|
146
|
+
originalError: error.message,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Build complete user profile from tokens
|
|
152
|
+
*
|
|
153
|
+
* Combines claims from ID token and UserInfo endpoint,
|
|
154
|
+
* applies custom claim mapping, and returns normalized profile.
|
|
155
|
+
*
|
|
156
|
+
* @param tokenSet - Token set from exchange
|
|
157
|
+
* @param includeUserInfo - Whether to fetch UserInfo endpoint
|
|
158
|
+
* @returns Normalized user profile
|
|
159
|
+
*/
|
|
160
|
+
async buildProfile(tokenSet, includeUserInfo = true) {
|
|
161
|
+
let claims = { ...tokenSet.claims };
|
|
162
|
+
// Optionally fetch additional claims from UserInfo endpoint
|
|
163
|
+
if (includeUserInfo && this.config.userinfoEndpoint) {
|
|
164
|
+
try {
|
|
165
|
+
const userinfo = await this.getUserInfo(tokenSet.accessToken);
|
|
166
|
+
// Merge UserInfo claims with ID token claims
|
|
167
|
+
claims = { ...claims, ...userinfo };
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
// UserInfo is optional - continue with ID token claims only
|
|
171
|
+
console.warn("Failed to fetch UserInfo, using ID token claims only:", error);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Apply custom claim mapping if configured
|
|
175
|
+
if (this.config.claimMapping) {
|
|
176
|
+
const customClaims = (0, claims_mapper_1.extractCustomClaims)(claims, this.config.claimMapping);
|
|
177
|
+
claims = { ...claims, ...customClaims };
|
|
178
|
+
}
|
|
179
|
+
// Map to normalized profile
|
|
180
|
+
const profile = (0, claims_mapper_1.mapClaimsToProfile)(claims);
|
|
181
|
+
return profile;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Ensure provider is initialized before use
|
|
185
|
+
*
|
|
186
|
+
* @throws Error if not initialized
|
|
187
|
+
*/
|
|
188
|
+
async ensureInitialized() {
|
|
189
|
+
if (!this.initialized) {
|
|
190
|
+
await this.initialize();
|
|
191
|
+
}
|
|
192
|
+
if (!this.client) {
|
|
193
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.PROVIDER_NOT_CONFIGURED, "OIDC client not initialized");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get issuer metadata (after initialization)
|
|
198
|
+
*
|
|
199
|
+
* @returns Issuer metadata
|
|
200
|
+
*/
|
|
201
|
+
getIssuerMetadata() {
|
|
202
|
+
if (!this.issuer) {
|
|
203
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.PROVIDER_NOT_CONFIGURED, "Provider not initialized");
|
|
204
|
+
}
|
|
205
|
+
return this.issuer.metadata;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
exports.OidcProvider = OidcProvider;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { OidcProvider } from "./OidcProvider";
|
|
2
|
+
import { OidcProviderConfig } from "../OidcProviderConfig";
|
|
3
|
+
/**
|
|
4
|
+
* Provider registry for managing OIDC provider instances
|
|
5
|
+
*
|
|
6
|
+
* Handles:
|
|
7
|
+
* - Static provider configuration
|
|
8
|
+
* - Dynamic provider loading from database
|
|
9
|
+
* - Provider instance caching
|
|
10
|
+
* - Lazy initialization
|
|
11
|
+
*/
|
|
12
|
+
export declare class ProviderRegistry {
|
|
13
|
+
private staticProviders;
|
|
14
|
+
private providerInstances;
|
|
15
|
+
private providerLoader?;
|
|
16
|
+
constructor(staticProviders: Record<string, OidcProviderConfig>, providerLoader?: (providerName: string) => Promise<OidcProviderConfig | null>);
|
|
17
|
+
/**
|
|
18
|
+
* Get provider instance by name
|
|
19
|
+
*
|
|
20
|
+
* Looks up provider in the following order:
|
|
21
|
+
* 1. Cached instance
|
|
22
|
+
* 2. Static configuration
|
|
23
|
+
* 3. Dynamic loader (if configured)
|
|
24
|
+
*
|
|
25
|
+
* Providers are lazy-initialized on first use and cached.
|
|
26
|
+
*
|
|
27
|
+
* @param providerName - Provider identifier
|
|
28
|
+
* @returns Initialized OIDC provider instance
|
|
29
|
+
* @throws Error if provider not found or initialization fails
|
|
30
|
+
*/
|
|
31
|
+
getProvider(providerName: string): Promise<OidcProvider>;
|
|
32
|
+
/**
|
|
33
|
+
* Check if provider exists in static configuration or can be loaded dynamically
|
|
34
|
+
*
|
|
35
|
+
* @param providerName - Provider identifier
|
|
36
|
+
* @returns true if provider exists, false otherwise
|
|
37
|
+
*/
|
|
38
|
+
hasProvider(providerName: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Clear provider cache
|
|
41
|
+
*
|
|
42
|
+
* Forces re-initialization of providers on next access.
|
|
43
|
+
* Useful when provider configurations change.
|
|
44
|
+
*
|
|
45
|
+
* @param providerName - Optional provider to clear (clears all if not specified)
|
|
46
|
+
*/
|
|
47
|
+
clearCache(providerName?: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Get list of configured provider names
|
|
50
|
+
*
|
|
51
|
+
* @returns Array of provider names from static configuration
|
|
52
|
+
*/
|
|
53
|
+
getProviderNames(): string[];
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=ProviderRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProviderRegistry.d.ts","sourceRoot":"","sources":["../../src/providers/ProviderRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IACzB,OAAO,CAAC,eAAe,CAAqC;IAC5D,OAAO,CAAC,iBAAiB,CAAwC;IACjE,OAAO,CAAC,cAAc,CAAC,CAA+D;gBAGlF,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACnD,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAMjF;;;;;;;;;;;;;OAaG;IACG,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAgC9D;;;;;OAKG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI1C;;;;;;;OAOG;IACH,UAAU,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;IAQvC;;;;OAIG;IACH,gBAAgB,IAAI,MAAM,EAAE;CAG/B"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProviderRegistry = void 0;
|
|
4
|
+
const OidcProvider_1 = require("./OidcProvider");
|
|
5
|
+
const error_utils_1 = require("../utils/error-utils");
|
|
6
|
+
/**
|
|
7
|
+
* Provider registry for managing OIDC provider instances
|
|
8
|
+
*
|
|
9
|
+
* Handles:
|
|
10
|
+
* - Static provider configuration
|
|
11
|
+
* - Dynamic provider loading from database
|
|
12
|
+
* - Provider instance caching
|
|
13
|
+
* - Lazy initialization
|
|
14
|
+
*/
|
|
15
|
+
class ProviderRegistry {
|
|
16
|
+
constructor(staticProviders, providerLoader) {
|
|
17
|
+
this.providerInstances = new Map();
|
|
18
|
+
this.staticProviders = staticProviders;
|
|
19
|
+
this.providerLoader = providerLoader;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get provider instance by name
|
|
23
|
+
*
|
|
24
|
+
* Looks up provider in the following order:
|
|
25
|
+
* 1. Cached instance
|
|
26
|
+
* 2. Static configuration
|
|
27
|
+
* 3. Dynamic loader (if configured)
|
|
28
|
+
*
|
|
29
|
+
* Providers are lazy-initialized on first use and cached.
|
|
30
|
+
*
|
|
31
|
+
* @param providerName - Provider identifier
|
|
32
|
+
* @returns Initialized OIDC provider instance
|
|
33
|
+
* @throws Error if provider not found or initialization fails
|
|
34
|
+
*/
|
|
35
|
+
async getProvider(providerName) {
|
|
36
|
+
// Check cache first
|
|
37
|
+
const cachedProvider = this.providerInstances.get(providerName);
|
|
38
|
+
if (cachedProvider) {
|
|
39
|
+
return cachedProvider;
|
|
40
|
+
}
|
|
41
|
+
// Try static configuration
|
|
42
|
+
let config = this.staticProviders[providerName] || null;
|
|
43
|
+
// Try dynamic loader if not in static config
|
|
44
|
+
if (!config && this.providerLoader) {
|
|
45
|
+
config = await this.providerLoader(providerName);
|
|
46
|
+
}
|
|
47
|
+
if (!config) {
|
|
48
|
+
throw (0, error_utils_1.createOidcError)(error_utils_1.OidcErrorCodes.PROVIDER_NOT_CONFIGURED, `OIDC provider '${providerName}' is not configured`, {
|
|
49
|
+
providerName,
|
|
50
|
+
availableProviders: Object.keys(this.staticProviders),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// Create and initialize provider
|
|
54
|
+
const provider = new OidcProvider_1.OidcProvider(config);
|
|
55
|
+
await provider.initialize();
|
|
56
|
+
// Cache the instance
|
|
57
|
+
this.providerInstances.set(providerName, provider);
|
|
58
|
+
return provider;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Check if provider exists in static configuration or can be loaded dynamically
|
|
62
|
+
*
|
|
63
|
+
* @param providerName - Provider identifier
|
|
64
|
+
* @returns true if provider exists, false otherwise
|
|
65
|
+
*/
|
|
66
|
+
hasProvider(providerName) {
|
|
67
|
+
return providerName in this.staticProviders || !!this.providerLoader;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Clear provider cache
|
|
71
|
+
*
|
|
72
|
+
* Forces re-initialization of providers on next access.
|
|
73
|
+
* Useful when provider configurations change.
|
|
74
|
+
*
|
|
75
|
+
* @param providerName - Optional provider to clear (clears all if not specified)
|
|
76
|
+
*/
|
|
77
|
+
clearCache(providerName) {
|
|
78
|
+
if (providerName) {
|
|
79
|
+
this.providerInstances.delete(providerName);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
this.providerInstances.clear();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get list of configured provider names
|
|
87
|
+
*
|
|
88
|
+
* @returns Array of provider names from static configuration
|
|
89
|
+
*/
|
|
90
|
+
getProviderNames() {
|
|
91
|
+
return Object.keys(this.staticProviders);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.ProviderRegistry = ProviderRegistry;
|