@memberjunction/server 6.1.0-edge.2 → 6.1.0-edge.4
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/LICENSE +180 -4
- package/dist/agentSessions/SessionManager.d.ts +19 -5
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +27 -9
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/auth/AuthProviderCatalogRouter.d.ts +31 -0
- package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -0
- package/dist/auth/AuthProviderCatalogRouter.js +69 -0
- package/dist/auth/AuthProviderCatalogRouter.js.map +1 -0
- package/dist/auth/AuthProviderEngine.d.ts +96 -0
- package/dist/auth/AuthProviderEngine.d.ts.map +1 -0
- package/dist/auth/AuthProviderEngine.js +245 -0
- package/dist/auth/AuthProviderEngine.js.map +1 -0
- package/dist/auth/index.d.ts +12 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +57 -13
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +64 -1
- package/dist/auth/initializeProviders.d.ts.map +1 -1
- package/dist/auth/initializeProviders.js +117 -5
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/scopeLimitedPrincipal.d.ts +39 -0
- package/dist/auth/scopeLimitedPrincipal.d.ts.map +1 -0
- package/dist/auth/scopeLimitedPrincipal.js +49 -0
- package/dist/auth/scopeLimitedPrincipal.js.map +1 -0
- package/dist/config.d.ts +89 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +52 -35
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +21 -1
- package/dist/context.js.map +1 -1
- package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.d.ts.map +1 -1
- package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.js +8 -7
- package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.js.map +1 -1
- package/dist/generated/generated.d.ts +619 -1597
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +3341 -17021
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +28 -1
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +57 -8
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +4 -0
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +31 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +147 -14
- package/dist/index.js.map +1 -1
- package/dist/integration/CustomColumnPromoter.d.ts +79 -15
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +472 -97
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/integration/InactiveRowWarnings.d.ts +48 -0
- package/dist/integration/InactiveRowWarnings.d.ts.map +1 -0
- package/dist/integration/InactiveRowWarnings.js +57 -0
- package/dist/integration/InactiveRowWarnings.js.map +1 -0
- package/dist/integration/RSUProgressBridge.d.ts +83 -0
- package/dist/integration/RSUProgressBridge.d.ts.map +1 -0
- package/dist/integration/RSUProgressBridge.js +230 -0
- package/dist/integration/RSUProgressBridge.js.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts +62 -0
- package/dist/integration/SchemaRefreshLaunch.d.ts.map +1 -0
- package/dist/integration/SchemaRefreshLaunch.js +67 -0
- package/dist/integration/SchemaRefreshLaunch.js.map +1 -0
- package/dist/providerConfigUnits.d.ts +20 -0
- package/dist/providerConfigUnits.d.ts.map +1 -0
- package/dist/providerConfigUnits.js +22 -0
- package/dist/providerConfigUnits.js.map +1 -0
- package/dist/resolvers/AdhocQueryResolver.d.ts +4 -0
- package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/AdhocQueryResolver.js +20 -6
- package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts +34 -4
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +218 -28
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/IdentityClaimRedemptionResolver.d.ts +37 -0
- package/dist/resolvers/IdentityClaimRedemptionResolver.d.ts.map +1 -0
- package/dist/resolvers/IdentityClaimRedemptionResolver.js +220 -0
- package/dist/resolvers/IdentityClaimRedemptionResolver.js.map +1 -0
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +108 -3
- package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
- package/dist/resolvers/IntegrationDiscoveryResolver.js +374 -87
- package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts +5 -4
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +29 -14
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +12 -3
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +33 -14
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +3 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +20 -7
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.d.ts +18 -0
- package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskGraphFrameResolver.js +75 -0
- package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
- package/dist/resolvers/UserResolver.d.ts +19 -17
- package/dist/resolvers/UserResolver.d.ts.map +1 -1
- package/dist/resolvers/UserResolver.js +66 -67
- package/dist/resolvers/UserResolver.js.map +1 -1
- package/dist/resolvers/currentUserRoles.d.ts +19 -0
- package/dist/resolvers/currentUserRoles.d.ts.map +1 -0
- package/dist/resolvers/currentUserRoles.js +36 -0
- package/dist/resolvers/currentUserRoles.js.map +1 -0
- package/dist/resolvers/meetingRecordingRegistration.d.ts.map +1 -1
- package/dist/resolvers/meetingRecordingRegistration.js +3 -6
- package/dist/resolvers/meetingRecordingRegistration.js.map +1 -1
- package/dist/rest/MediaAccessKeys.d.ts +17 -0
- package/dist/rest/MediaAccessKeys.d.ts.map +1 -1
- package/dist/rest/MediaAccessKeys.js +42 -1
- package/dist/rest/MediaAccessKeys.js.map +1 -1
- package/dist/rest/MediaStreamHandler.d.ts +3 -2
- package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
- package/dist/rest/MediaStreamHandler.js +83 -2
- package/dist/rest/MediaStreamHandler.js.map +1 -1
- package/dist/rest/OAuthCallbackHandler.d.ts +49 -1
- package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
- package/dist/rest/OAuthCallbackHandler.js +129 -43
- package/dist/rest/OAuthCallbackHandler.js.map +1 -1
- package/dist/rest/UploadTokenManager.d.ts +90 -0
- package/dist/rest/UploadTokenManager.d.ts.map +1 -0
- package/dist/rest/UploadTokenManager.js +156 -0
- package/dist/rest/UploadTokenManager.js.map +1 -0
- package/dist/services/IntegrationSyncWorkerService.d.ts +48 -0
- package/dist/services/IntegrationSyncWorkerService.d.ts.map +1 -0
- package/dist/services/IntegrationSyncWorkerService.js +132 -0
- package/dist/services/IntegrationSyncWorkerService.js.map +1 -0
- package/dist/services/StartTaskGraphDispatcher.d.ts +0 -10
- package/dist/services/StartTaskGraphDispatcher.d.ts.map +1 -1
- package/dist/services/StartTaskGraphDispatcher.js +21 -1
- package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
- package/dist/services/TaskGraphAgentRunner.d.ts +7 -0
- package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
- package/dist/services/TaskGraphAgentRunner.js +23 -0
- package/dist/services/TaskGraphAgentRunner.js.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
- package/dist/services/TaskGraphContinuationDeliverer.js +12 -1
- package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +92 -92
- package/src/__tests__/APIKeyScopeAuth.test.ts +475 -0
- package/src/__tests__/AdhocQueryResolver.scopeGuard.test.ts +84 -0
- package/src/__tests__/AuthProviderEngine.test.ts +278 -0
- package/src/__tests__/CustomColumnPromoterOnePass.test.ts +387 -0
- package/src/__tests__/EntityCRUDHandler.test.ts +378 -0
- package/src/__tests__/InactiveRowWarnings.test.ts +87 -0
- package/src/__tests__/IntegrationSyncWorkerService.test.ts +275 -0
- package/src/__tests__/OAuthCallbackHandler.openRedirect.test.ts +117 -0
- package/src/__tests__/OAuthCallbackHandler.xss.test.ts +4 -1
- package/src/__tests__/RESTEndpointHandler.test.ts +672 -0
- package/src/__tests__/RSUProgressBridge.test.ts +250 -0
- package/src/__tests__/ReactivateRefreshMessage.test.ts +85 -0
- package/src/__tests__/RealtimeBridgeResolver.test.ts +10 -2
- package/src/__tests__/ResolverBase.filterEscaping.test.ts +147 -0
- package/src/__tests__/SchemaRefreshLaunch.test.ts +114 -0
- package/src/__tests__/SessionManager.test.ts +55 -0
- package/src/__tests__/UserResolver.currentUser.test.ts +87 -0
- package/src/__tests__/ViewOperationsHandler.test.ts +277 -0
- package/src/__tests__/config-units.test.ts +74 -0
- package/src/__tests__/initializeProviders.refresh.test.ts +146 -0
- package/src/__tests__/mjapi-bootstrap.test.ts +0 -6
- package/src/__tests__/newUsers.test.ts +726 -0
- package/src/__tests__/uploadTokenManager.test.ts +159 -0
- package/src/agentSessions/SessionManager.ts +27 -9
- package/src/auth/AuthProviderCatalogRouter.ts +76 -0
- package/src/auth/AuthProviderEngine.ts +253 -0
- package/src/auth/index.ts +60 -15
- package/src/auth/initializeProviders.ts +128 -7
- package/src/auth/scopeLimitedPrincipal.ts +50 -0
- package/src/config.ts +55 -36
- package/src/context.ts +26 -2
- package/src/entitySubclasses/MJEntityPermissionEntityServer.server.ts +8 -7
- package/src/generated/generated.ts +2347 -10551
- package/src/generic/ResolverBase.ts +67 -8
- package/src/generic/RunViewResolver.ts +31 -0
- package/src/index.ts +165 -16
- package/src/integration/CustomColumnPromoter.ts +520 -98
- package/src/integration/InactiveRowWarnings.ts +85 -0
- package/src/integration/RSUProgressBridge.ts +248 -0
- package/src/integration/SchemaRefreshLaunch.ts +93 -0
- package/src/providerConfigUnits.ts +21 -0
- package/src/resolvers/AdhocQueryResolver.ts +21 -6
- package/src/resolvers/FileResolver.ts +200 -40
- package/src/resolvers/IdentityClaimRedemptionResolver.ts +184 -0
- package/src/resolvers/IntegrationDiscoveryResolver.ts +390 -71
- package/src/resolvers/QueryResolver.ts +25 -11
- package/src/resolvers/QuerySystemUserResolver.ts +28 -13
- package/src/resolvers/RunAIAgentResolver.ts +21 -6
- package/src/resolvers/TaskGraphFrameResolver.ts +67 -0
- package/src/resolvers/UserResolver.ts +99 -60
- package/src/resolvers/currentUserRoles.ts +47 -0
- package/src/resolvers/meetingRecordingRegistration.ts +3 -7
- package/src/rest/MediaAccessKeys.ts +47 -1
- package/src/rest/MediaStreamHandler.ts +98 -3
- package/src/rest/OAuthCallbackHandler.ts +149 -41
- package/src/rest/UploadTokenManager.ts +211 -0
- package/src/services/IntegrationSyncWorkerService.ts +141 -0
- package/src/services/StartTaskGraphDispatcher.ts +21 -1
- package/src/services/TaskGraphAgentRunner.ts +23 -0
- package/src/services/TaskGraphContinuationDeliverer.ts +11 -1
- package/src/types.ts +14 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Metadata-driven authentication provider catalog.
|
|
3
|
+
*
|
|
4
|
+
* Loads `MJ: Authentication Providers` rows and registers each one with the runtime
|
|
5
|
+
* `AuthProviderFactory`, resolving the concrete driver through `ClassFactory` by `DriverClass`.
|
|
6
|
+
* This is the auth subsystem's equivalent of the File Storage `ServerDriverKey` pattern:
|
|
7
|
+
* adding a provider is a subclass plus a row, never an edit to core code.
|
|
8
|
+
*
|
|
9
|
+
* @module @memberjunction/server/auth
|
|
10
|
+
*/
|
|
11
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
12
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
13
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
14
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
15
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
16
|
+
};
|
|
17
|
+
import { BaseEngine, LogError, LogStatusEx, RegisterForStartup } from '@memberjunction/core';
|
|
18
|
+
import { AuthProviderFactory } from '@memberjunction/auth-providers';
|
|
19
|
+
import { CredentialEngine } from '@memberjunction/credentials';
|
|
20
|
+
/**
|
|
21
|
+
* Subsystem label used when this engine asks CredentialEngine to decrypt secret material,
|
|
22
|
+
* so credential-access auditing attributes the read to authentication.
|
|
23
|
+
*/
|
|
24
|
+
const CREDENTIAL_SUBSYSTEM = 'Authentication';
|
|
25
|
+
/**
|
|
26
|
+
* Loads the authentication-provider catalog from metadata and registers it with the
|
|
27
|
+
* {@link AuthProviderFactory}.
|
|
28
|
+
*
|
|
29
|
+
* **Not `deferred`**: no authenticated request may be served before the catalog is registered,
|
|
30
|
+
* or tokens from a metadata-defined provider would be rejected during the startup window.
|
|
31
|
+
*
|
|
32
|
+
* **Severity is `warn`, not `fatal`**, and that is deliberate. This engine is one of two possible
|
|
33
|
+
* sources of providers — `initializeAuthProviders` also registers whatever `mj.config.cjs`
|
|
34
|
+
* declares. Making a catalog load failure fatal would turn a transient metadata problem into a
|
|
35
|
+
* total authentication outage for deployments that never adopted the table. The failure is
|
|
36
|
+
* logged loudly and the config-declared providers still stand.
|
|
37
|
+
*/
|
|
38
|
+
let AuthProviderEngine = class AuthProviderEngine extends BaseEngine {
|
|
39
|
+
constructor() {
|
|
40
|
+
super(...arguments);
|
|
41
|
+
this._providers = [];
|
|
42
|
+
}
|
|
43
|
+
static get Instance() {
|
|
44
|
+
return super.getInstance();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Loads Active providers only. Inactive rows are excluded at the query rather than filtered
|
|
48
|
+
* later, so a disabled provider is never even instantiated.
|
|
49
|
+
*/
|
|
50
|
+
async Config(forceRefresh, contextUser, provider) {
|
|
51
|
+
const configs = [
|
|
52
|
+
{
|
|
53
|
+
PropertyName: '_providers',
|
|
54
|
+
EntityName: 'MJ: Authentication Providers',
|
|
55
|
+
Filter: `Status='Active'`,
|
|
56
|
+
OrderBy: 'Sequence ASC, Name ASC',
|
|
57
|
+
CacheLocal: true
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
await this.Load(configs, provider, forceRefresh, contextUser);
|
|
61
|
+
}
|
|
62
|
+
/** Active providers from metadata, ordered for presentation. */
|
|
63
|
+
get Providers() {
|
|
64
|
+
return this.GetConfigData('_providers');
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Startup hook: load the catalog, then register every row with the factory.
|
|
68
|
+
*/
|
|
69
|
+
async HandleStartup(contextUser, provider) {
|
|
70
|
+
await this.Config(false, contextUser, provider);
|
|
71
|
+
await this.RegisterAll(contextUser);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Instantiates and registers every catalog row with the {@link AuthProviderFactory}.
|
|
75
|
+
*
|
|
76
|
+
* One bad row must not cost the deployment its other providers, so each registration is
|
|
77
|
+
* isolated: a failure is logged with the offending provider's name and the loop continues.
|
|
78
|
+
*
|
|
79
|
+
* @returns the number of providers successfully registered.
|
|
80
|
+
*/
|
|
81
|
+
async RegisterAll(contextUser) {
|
|
82
|
+
const factory = AuthProviderFactory.Instance;
|
|
83
|
+
let registered = 0;
|
|
84
|
+
for (const row of this.Providers) {
|
|
85
|
+
try {
|
|
86
|
+
const config = await this.buildProviderConfig(row, contextUser);
|
|
87
|
+
factory.register(AuthProviderFactory.createProvider(config));
|
|
88
|
+
registered++;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
92
|
+
LogError(`[Auth] Could not register metadata provider '${row.Name}' (DriverClass '${row.DriverClass}'): ${message}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (registered > 0) {
|
|
96
|
+
LogStatusEx({ message: `[Auth] Registered ${registered} provider(s) from metadata.`, verboseOnly: true });
|
|
97
|
+
}
|
|
98
|
+
return registered;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Projects a catalog row onto the runtime {@link AuthProviderConfig} the driver expects.
|
|
102
|
+
*
|
|
103
|
+
* `AdditionalConfiguration` is spread FIRST so that the modelled columns win over anything a
|
|
104
|
+
* driver-specific blob happens to repeat — the columns are the reviewable, described surface,
|
|
105
|
+
* and a JSON blob must not be able to silently redefine the issuer a token is validated against.
|
|
106
|
+
*/
|
|
107
|
+
async buildProviderConfig(row, contextUser) {
|
|
108
|
+
const additional = this.parseJsonColumn(row.AdditionalConfiguration, row.Name, 'AdditionalConfiguration');
|
|
109
|
+
const secrets = await this.resolveCredential(row, contextUser);
|
|
110
|
+
const config = {
|
|
111
|
+
...additional,
|
|
112
|
+
...secrets,
|
|
113
|
+
name: row.Name,
|
|
114
|
+
type: row.DriverClass
|
|
115
|
+
};
|
|
116
|
+
if (row.ClientID)
|
|
117
|
+
config.clientId = row.ClientID;
|
|
118
|
+
if (row.Domain)
|
|
119
|
+
config.domain = row.Domain;
|
|
120
|
+
if (row.Issuer)
|
|
121
|
+
config.issuer = row.Issuer;
|
|
122
|
+
if (row.Audience)
|
|
123
|
+
config.audience = row.Audience;
|
|
124
|
+
if (row.JWKSUri)
|
|
125
|
+
config.jwksUri = row.JWKSUri;
|
|
126
|
+
if (row.Scopes)
|
|
127
|
+
config.scopes = this.parseScopes(row.Scopes);
|
|
128
|
+
return config;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Splits the delimited `Scopes` column into the parsed list both projections publish.
|
|
132
|
+
*
|
|
133
|
+
* This is the single home of the delimiter convention: `buildProviderConfig` and
|
|
134
|
+
* `GetPublicCatalog` must agree on it, or the server would validate tokens against one scope
|
|
135
|
+
* set while telling the browser to request another.
|
|
136
|
+
*/
|
|
137
|
+
parseScopes(raw) {
|
|
138
|
+
return raw ? raw.split(/[\s,]+/).filter((s) => s.length > 0) : [];
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Decrypts the row's linked credential, when it has one.
|
|
142
|
+
*
|
|
143
|
+
* Almost every provider validates tokens against a public JWKS and needs no secret at all, so
|
|
144
|
+
* this is the uncommon path — present for confidential-client flows, management APIs, and SCIM.
|
|
145
|
+
*/
|
|
146
|
+
async resolveCredential(row, contextUser) {
|
|
147
|
+
if (!row.CredentialID || !row.Credential) {
|
|
148
|
+
return {};
|
|
149
|
+
}
|
|
150
|
+
await CredentialEngine.Instance.Config(false, contextUser);
|
|
151
|
+
const resolved = await CredentialEngine.Instance.getCredential(row.Credential, {
|
|
152
|
+
contextUser,
|
|
153
|
+
subsystem: CREDENTIAL_SUBSYSTEM
|
|
154
|
+
});
|
|
155
|
+
return resolved.values;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Parses a JSON configuration column, treating malformed content as absent.
|
|
159
|
+
*
|
|
160
|
+
* Throwing here would take down an otherwise-valid provider over a stray character in an
|
|
161
|
+
* optional extras blob, so the row is registered without the extras and the problem is logged.
|
|
162
|
+
*/
|
|
163
|
+
parseJsonColumn(raw, providerName, columnName) {
|
|
164
|
+
if (!raw?.trim()) {
|
|
165
|
+
return {};
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
const parsed = JSON.parse(raw);
|
|
169
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
170
|
+
return parsed;
|
|
171
|
+
}
|
|
172
|
+
LogError(`[Auth] ${columnName} on provider '${providerName}' is not a JSON object; ignoring it.`);
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
176
|
+
LogError(`[Auth] ${columnName} on provider '${providerName}' is not valid JSON (${message}); ignoring it.`);
|
|
177
|
+
}
|
|
178
|
+
return {};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Projects the catalog to the PUBLIC shape served by the unauthenticated catalog endpoint.
|
|
182
|
+
*
|
|
183
|
+
* The projection is an explicit allow-list rather than a redaction of the full row: a column
|
|
184
|
+
* added to this entity later is invisible to anonymous callers until someone deliberately adds
|
|
185
|
+
* it here. `AdditionalConfiguration` and `CredentialID` are structurally absent, never merely
|
|
186
|
+
* omitted at serialization time.
|
|
187
|
+
*/
|
|
188
|
+
GetPublicCatalog() {
|
|
189
|
+
return this.Providers.filter((row) => row.ClientVisible).map((row) => {
|
|
190
|
+
const info = {
|
|
191
|
+
name: row.Name,
|
|
192
|
+
driverClass: row.DriverClass,
|
|
193
|
+
displayName: row.DisplayName ?? row.Name,
|
|
194
|
+
sequence: row.Sequence,
|
|
195
|
+
isDefault: row.IsDefault
|
|
196
|
+
};
|
|
197
|
+
if (row.Icon)
|
|
198
|
+
info.icon = row.Icon;
|
|
199
|
+
if (row.ClientID)
|
|
200
|
+
info.clientId = row.ClientID;
|
|
201
|
+
if (row.Issuer)
|
|
202
|
+
info.issuer = row.Issuer;
|
|
203
|
+
if (row.Domain)
|
|
204
|
+
info.domain = row.Domain;
|
|
205
|
+
// Published pre-parsed so the browser never re-derives the delimiter convention —
|
|
206
|
+
// the drivers hand this straight to SDK config typed string[].
|
|
207
|
+
const scopes = this.parseScopes(row.Scopes);
|
|
208
|
+
if (scopes.length > 0)
|
|
209
|
+
info.scopes = scopes;
|
|
210
|
+
const clientConfig = this.parseJsonColumn(row.ClientConfiguration, row.Name, 'ClientConfiguration');
|
|
211
|
+
if (Object.keys(clientConfig).length > 0) {
|
|
212
|
+
info.clientConfiguration = this.toPublicClientConfig(clientConfig, row.Name);
|
|
213
|
+
}
|
|
214
|
+
return info;
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Flattens a parsed `ClientConfiguration` blob to the primitive key/value shape the browser
|
|
219
|
+
* contract declares. Nested objects and arrays are dropped with a warning rather than passed
|
|
220
|
+
* through, so a structured blob (the shape a credential would take) cannot ride along to an
|
|
221
|
+
* anonymous caller.
|
|
222
|
+
*/
|
|
223
|
+
toPublicClientConfig(parsed, providerName) {
|
|
224
|
+
const result = {};
|
|
225
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
226
|
+
if (value === null || ['string', 'number', 'boolean'].includes(typeof value)) {
|
|
227
|
+
result[key] = value;
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
LogError(`[Auth] ClientConfiguration key '${key}' on provider '${providerName}' is not a primitive value; it was NOT published to the public catalog.`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
AuthProviderEngine = __decorate([
|
|
237
|
+
RegisterForStartup({
|
|
238
|
+
priority: 20,
|
|
239
|
+
severity: 'warn',
|
|
240
|
+
deferred: false,
|
|
241
|
+
description: 'Loads the metadata authentication-provider catalog and registers it with AuthProviderFactory'
|
|
242
|
+
})
|
|
243
|
+
], AuthProviderEngine);
|
|
244
|
+
export { AuthProviderEngine };
|
|
245
|
+
//# sourceMappingURL=AuthProviderEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthProviderEngine.js","sourceRoot":"","sources":["../../src/auth/AuthProviderEngine.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -2,7 +2,11 @@ import { JwtHeader, SigningKeyCallback, JwtPayload } from 'jsonwebtoken';
|
|
|
2
2
|
import sql from 'mssql';
|
|
3
3
|
import { UserInfo } from '@memberjunction/core';
|
|
4
4
|
export * from './APIKeyScopeAuth.js';
|
|
5
|
+
export * from './scopeLimitedPrincipal.js';
|
|
5
6
|
export * from './actingContextResolver.js';
|
|
7
|
+
export * from './AuthProviderEngine.js';
|
|
8
|
+
export * from './AuthProviderCatalogRouter.js';
|
|
9
|
+
export { initializeAuthProviders, initializeAuthProvidersFromMetadata, refreshAuthProviders, validateAuthProvidersRegistered } from './initializeProviders.js';
|
|
6
10
|
/**
|
|
7
11
|
* Gets validation options for a specific issuer.
|
|
8
12
|
* When multiple providers share the same issuer (e.g. two Auth0 apps on
|
|
@@ -57,5 +61,13 @@ export declare const extractUserInfoFromPayload: (payload: JwtPayload) => {
|
|
|
57
61
|
preferredUsername?: string;
|
|
58
62
|
};
|
|
59
63
|
export declare const getSystemUser: (dataSource?: sql.ConnectionPool, attemptCacheUpdateIfNeeded?: boolean) => Promise<UserInfo>;
|
|
64
|
+
/**
|
|
65
|
+
* Resolves a verified identity to an MJ `UserInfo`, optionally auto-provisioning a new user.
|
|
66
|
+
*
|
|
67
|
+
* @param requestDomain the hostname parsed from the request's `Origin` header. **Not used for any
|
|
68
|
+
* authorization decision** — it is spoofable on non-browser requests, and new-user domain
|
|
69
|
+
* authorization runs against the verified JWT's email domain instead. Retained for audit
|
|
70
|
+
* logging and for the recursive retry call.
|
|
71
|
+
*/
|
|
60
72
|
export declare const verifyUserRecord: (email?: string, firstName?: string, lastName?: string, requestDomain?: string, dataSource?: sql.ConnectionPool, attemptCacheUpdateIfNeeded?: boolean) => Promise<UserInfo | undefined>;
|
|
61
73
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/auth/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAGzE,OAAO,GAAG,MAAM,OAAO,CAAC;AACxB,OAAO,EAA4C,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAO1F,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAGzE,OAAO,GAAG,MAAM,OAAO,CAAC;AACxB,OAAO,EAA4C,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAO1F,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAE,mCAAmC,EAAE,oBAAoB,EAAE,+BAA+B,EAAE,MAAM,0BAA0B,CAAC;AAsC/J;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,KAAG;IAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,SAexG,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAW7F,CAAC;AAEH,qBAAa,WAAW;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,MAAM,QAAQ,SAAS,EAAE,IAAI,kBAAkB,SAmB3F,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,GAAI,SAAS,UAAU,KAAG;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAiC5B,CAAC;AAEF,eAAO,MAAM,aAAa,GAAU,aAAa,GAAG,CAAC,cAAc,EAAE,6BAA4B,OAAc,KAAG,OAAO,CAAC,QAAQ,CAYjI,CAAC;AA8BF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,MAAM,EACd,YAAY,MAAM,EAClB,WAAW,MAAM,EACjB,gBAAgB,MAAM,EACtB,aAAa,GAAG,CAAC,cAAc,EAC/B,6BAA4B,OAAc,KACzC,OAAO,CAAC,QAAQ,GAAG,SAAS,CA8E9B,CAAC"}
|
package/dist/auth/index.js
CHANGED
|
@@ -6,7 +6,11 @@ import { MJGlobal } from '@memberjunction/global';
|
|
|
6
6
|
import { AuthProviderFactory } from '@memberjunction/auth-providers';
|
|
7
7
|
import { initializeAuthProviders } from './initializeProviders.js';
|
|
8
8
|
export * from './APIKeyScopeAuth.js';
|
|
9
|
+
export * from './scopeLimitedPrincipal.js';
|
|
9
10
|
export * from './actingContextResolver.js';
|
|
11
|
+
export * from './AuthProviderEngine.js';
|
|
12
|
+
export * from './AuthProviderCatalogRouter.js';
|
|
13
|
+
export { initializeAuthProviders, initializeAuthProvidersFromMetadata, refreshAuthProviders, validateAuthProvidersRegistered } from './initializeProviders.js';
|
|
10
14
|
// This is a hard-coded forever constant due to internal migrations
|
|
11
15
|
class MissingAuthError extends Error {
|
|
12
16
|
constructor() {
|
|
@@ -136,6 +140,40 @@ export const getSystemUser = async (dataSource, attemptCacheUpdateIfNeeded = tru
|
|
|
136
140
|
}
|
|
137
141
|
return systemUser;
|
|
138
142
|
};
|
|
143
|
+
/**
|
|
144
|
+
* Extracts the lowercased domain portion of an email address.
|
|
145
|
+
*
|
|
146
|
+
* @returns the domain, or an empty string when the value is not an email address (e.g. an IdP that
|
|
147
|
+
* issues a bare username). Callers MUST treat an empty result as "cannot be authorized"
|
|
148
|
+
* rather than as a wildcard.
|
|
149
|
+
*/
|
|
150
|
+
const extractEmailDomain = (email) => {
|
|
151
|
+
const parts = email.split('@');
|
|
152
|
+
// Reject anything that isn't exactly local@domain — a value with 0 or 2+ '@' is not an address we
|
|
153
|
+
// can make a trust decision about.
|
|
154
|
+
if (parts.length !== 2)
|
|
155
|
+
return '';
|
|
156
|
+
return parts[1].toLowerCase().trim();
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Tests a domain against `userHandling.newUserAuthorizedDomains`, honoring `*` wildcards.
|
|
160
|
+
*
|
|
161
|
+
* Note that a pattern is matched in full, so `*.example.com` matches `mail.example.com` but NOT
|
|
162
|
+
* `example.com` — list both if you need both.
|
|
163
|
+
*/
|
|
164
|
+
const isDomainAuthorized = (domain) => configInfo.userHandling.newUserAuthorizedDomains.some((pattern) => {
|
|
165
|
+
// Convert wildcard domain patterns to regular expressions
|
|
166
|
+
const regex = new RegExp('^' + pattern.toLowerCase().trim().replace(/\./g, '\\.').replace(/\*/g, '.*') + '$');
|
|
167
|
+
return regex.test(domain);
|
|
168
|
+
});
|
|
169
|
+
/**
|
|
170
|
+
* Resolves a verified identity to an MJ `UserInfo`, optionally auto-provisioning a new user.
|
|
171
|
+
*
|
|
172
|
+
* @param requestDomain the hostname parsed from the request's `Origin` header. **Not used for any
|
|
173
|
+
* authorization decision** — it is spoofable on non-browser requests, and new-user domain
|
|
174
|
+
* authorization runs against the verified JWT's email domain instead. Retained for audit
|
|
175
|
+
* logging and for the recursive retry call.
|
|
176
|
+
*/
|
|
139
177
|
export const verifyUserRecord = async (email, firstName, lastName, requestDomain, dataSource, attemptCacheUpdateIfNeeded = true) => {
|
|
140
178
|
if (!email)
|
|
141
179
|
return undefined;
|
|
@@ -150,20 +188,20 @@ export const verifyUserRecord = async (email, firstName, lastName, requestDomain
|
|
|
150
188
|
return u.Email.toLowerCase().trim() === email.toLowerCase().trim();
|
|
151
189
|
});
|
|
152
190
|
if (!user) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
191
|
+
// NOTE: `requestDomain` (parsed from the spoofable `Origin` header) is deliberately NOT part of
|
|
192
|
+
// this condition. It was previously required here, which meant a non-browser client sending no
|
|
193
|
+
// Origin could never auto-provision while an attacker simply forged one — it gated entry without
|
|
194
|
+
// authorizing anything. Authorization happens below, against the verified identity's email domain.
|
|
195
|
+
if (configInfo.userHandling.autoCreateNewUsers && firstName && lastName) {
|
|
196
|
+
// SECURITY: authorize against the EMAIL DOMAIN of the cryptographically-verified identity,
|
|
197
|
+
// NOT the request `Origin` header. Origin is trivially spoofable on non-browser / bearer-token
|
|
198
|
+
// requests, so gating on it let a holder of any valid IdP token auto-provision an account under
|
|
199
|
+
// an authorized domain by sending a forged Origin. The email comes from the verified JWT.
|
|
200
|
+
const emailDomain = extractEmailDomain(email);
|
|
158
201
|
let passesDomainCheck = configInfo.userHandling.newUserLimitedToAuthorizedDomains ===
|
|
159
202
|
false; /*in this first condition, we are set up to NOT care about domain */
|
|
160
|
-
if (!passesDomainCheck
|
|
161
|
-
|
|
162
|
-
passesDomainCheck = configInfo.userHandling.newUserAuthorizedDomains.some((pattern) => {
|
|
163
|
-
// Convert wildcard domain patterns to regular expressions
|
|
164
|
-
const regex = new RegExp('^' + pattern.toLowerCase().trim().replace(/\./g, '\\.').replace(/\*/g, '.*') + '$');
|
|
165
|
-
return regex.test(requestDomain?.toLowerCase().trim());
|
|
166
|
-
});
|
|
203
|
+
if (!passesDomainCheck) {
|
|
204
|
+
passesDomainCheck = emailDomain.length > 0 && isDomainAuthorized(emailDomain);
|
|
167
205
|
}
|
|
168
206
|
if (passesDomainCheck) {
|
|
169
207
|
// we have a domain from the request that matches one of the domains provided by the configuration, so we will create a new user
|
|
@@ -185,8 +223,14 @@ export const verifyUserRecord = async (email, firstName, lastName, requestDomain
|
|
|
185
223
|
console.warn(` >>> New user ${email} created successfully!`);
|
|
186
224
|
}
|
|
187
225
|
}
|
|
226
|
+
else if (emailDomain.length === 0) {
|
|
227
|
+
// The verified identity carries no email domain at all — typically an IdP that issues a bare
|
|
228
|
+
// `preferred_username` with no `email` claim. There is nothing to match against, so the gate
|
|
229
|
+
// denies rather than falling back to anything spoofable.
|
|
230
|
+
console.warn(`User ${email} not found in cache and will NOT be auto-created: the verified identity has no email domain (no '@'), so it cannot be matched against newUserAuthorizedDomains. This usually means the identity provider issues a username rather than an email address — configure it to emit an 'email' claim, or set newUserLimitedToAuthorizedDomains to false to disable domain checking.`);
|
|
231
|
+
}
|
|
188
232
|
else {
|
|
189
|
-
console.warn(`User ${email} not found in cache.
|
|
233
|
+
console.warn(`User ${email} not found in cache. Email domain '${emailDomain}' does not match any of the domains in the newUserAuthorizedDomains setting. NOTE: this check is against the EMAIL DOMAIN of the verified identity, NOT the browser Origin — if newUserAuthorizedDomains lists frontend hostnames (e.g. 'app.example.com'), replace them with email domains (e.g. 'example.com'). To ignore domain, make sure you set the newUserLimitedToAuthorizedDomains setting to false. In this case we are NOT creating a new user.`);
|
|
190
234
|
}
|
|
191
235
|
}
|
|
192
236
|
if (!user && configInfo.userHandling.updateCacheWhenNotFound && dataSource && attemptCacheUpdateIfNeeded) {
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,2CAA2C,CAAC;AAEtE,OAAO,EAAwB,QAAQ,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,68 @@
|
|
|
1
|
+
import { UserInfo, type IMetadataProvider } from '@memberjunction/core';
|
|
1
2
|
/**
|
|
2
|
-
* Initialize authentication providers from configuration
|
|
3
|
+
* Initialize authentication providers from configuration.
|
|
4
|
+
*
|
|
5
|
+
* Registers everything declared in `mj.config.cjs`'s `authProviders` array. This remains the
|
|
6
|
+
* baseline path and runs on every boot: it needs no database, so it is what lets the server
|
|
7
|
+
* authenticate even when metadata is unreachable.
|
|
8
|
+
*
|
|
9
|
+
* Providers defined in the `MJ: Authentication Providers` catalog are layered on top by
|
|
10
|
+
* {@link initializeAuthProvidersFromMetadata}, which runs later in startup once a database
|
|
11
|
+
* connection and a system user exist.
|
|
3
12
|
*/
|
|
4
13
|
export declare function initializeAuthProviders(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Layers the metadata provider catalog on top of the config-declared providers.
|
|
16
|
+
*
|
|
17
|
+
* Called after the data provider and system user are available. Metadata rows are registered in
|
|
18
|
+
* addition to — not instead of — the config-declared ones: a deployment mid-migration may
|
|
19
|
+
* legitimately have both, and a name collision resolves to the metadata row because it registers
|
|
20
|
+
* last and `AuthProviderFactory.register` keys by provider name.
|
|
21
|
+
*
|
|
22
|
+
* Never throws. An unreachable or empty catalog leaves the config-declared providers exactly as
|
|
23
|
+
* they were, which is what makes adopting this feature a no-op for existing deployments and keeps
|
|
24
|
+
* a metadata problem from turning into a lockout.
|
|
25
|
+
*
|
|
26
|
+
* @returns the number of providers registered from metadata.
|
|
27
|
+
*/
|
|
28
|
+
export declare function initializeAuthProvidersFromMetadata(contextUser?: UserInfo, provider?: IMetadataProvider): Promise<number>;
|
|
29
|
+
/**
|
|
30
|
+
* Rebuilds the provider registry from scratch: config-declared providers first, then the
|
|
31
|
+
* metadata catalog layered on top — the same two-source order as startup.
|
|
32
|
+
*
|
|
33
|
+
* This is THE entry point for reacting to a catalog edit at runtime (an admin page's Save
|
|
34
|
+
* button, a future invalidation hook). A full rebuild is required because the factory caches
|
|
35
|
+
* issuer→provider resolutions, so an edited row would otherwise keep serving its old
|
|
36
|
+
* configuration until the process restarted. It lives here rather than on `AuthProviderEngine`
|
|
37
|
+
* because a bare `factory.clear()` + metadata re-registration would silently drop everything
|
|
38
|
+
* the config path registered — magic-link included — and no caller should have to know to put
|
|
39
|
+
* those back. `initializeAuthProviders()` clears the factory itself, so no separate clear step
|
|
40
|
+
* exists for a caller to forget.
|
|
41
|
+
*
|
|
42
|
+
* **Failure policy: abort-before-mutate.** Everything that can throw — the catalog reload and
|
|
43
|
+
* the permission probe on its result — runs BEFORE the factory is touched, so a failed refresh
|
|
44
|
+
* leaves the registry serving the previous (stale but complete) provider set and surfaces the
|
|
45
|
+
* error to the caller. This is deliberately the opposite of `initializeAuthProvidersFromMetadata`,
|
|
46
|
+
* which swallows metadata failures: at boot there is no previous registry to preserve and a
|
|
47
|
+
* metadata problem must not become a lockout, while at refresh time there is one and the caller
|
|
48
|
+
* (an admin UI) wants the error. That difference in failure policy is why this function does not
|
|
49
|
+
* simply delegate to its sibling.
|
|
50
|
+
*
|
|
51
|
+
* Known limitation, acceptable for an admin-triggered operation: metadata providers are absent
|
|
52
|
+
* from the registry for the duration of `RegisterAll`'s per-row config builds (config-declared
|
|
53
|
+
* providers are restored synchronously). A request bearing a metadata-declared IdP's token in
|
|
54
|
+
* that window is rejected. If a caller ever needs an atomic swap, build the configs first and
|
|
55
|
+
* register them in one synchronous pass.
|
|
56
|
+
*
|
|
57
|
+
* @returns the number of providers registered from metadata after the refresh.
|
|
58
|
+
*/
|
|
59
|
+
export declare function refreshAuthProviders(contextUser?: UserInfo, provider?: IMetadataProvider): Promise<number>;
|
|
60
|
+
/**
|
|
61
|
+
* Reports whether any provider is registered, from either source, and logs a diagnostic when none
|
|
62
|
+
* is.
|
|
63
|
+
*
|
|
64
|
+
* Split out from {@link initializeAuthProviders} because "no providers" is only genuinely wrong
|
|
65
|
+
* once BOTH sources have had their turn.
|
|
66
|
+
*/
|
|
67
|
+
export declare function validateAuthProvidersRegistered(): boolean;
|
|
5
68
|
//# sourceMappingURL=initializeProviders.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initializeProviders.d.ts","sourceRoot":"","sources":["../../src/auth/initializeProviders.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"initializeProviders.d.ts","sourceRoot":"","sources":["../../src/auth/initializeProviders.ts"],"names":[],"mappings":"AACA,OAAO,EAAwD,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAI9H;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CA4C9C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mCAAmC,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAa/H;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAchH;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,IAAI,OAAO,CASzD"}
|