@memberjunction/auth-providers 6.2.0-edge.0 → 6.2.0-edge.1
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +59 -0
- package/dist/AuthProviderFactory.d.ts +24 -1
- package/dist/AuthProviderFactory.d.ts.map +1 -1
- package/dist/AuthProviderFactory.js +66 -13
- package/dist/AuthProviderFactory.js.map +1 -1
- package/dist/BaseAuthProvider.d.ts +11 -0
- package/dist/BaseAuthProvider.d.ts.map +1 -1
- package/dist/BaseAuthProvider.js +9 -2
- package/dist/BaseAuthProvider.js.map +1 -1
- package/dist/IAuthProvider.d.ts +8 -0
- package/dist/IAuthProvider.d.ts.map +1 -1
- package/dist/IEnvironmentConfigurableProvider.d.ts +2 -0
- package/dist/IEnvironmentConfigurableProvider.d.ts.map +1 -1
- package/dist/IEnvironmentConfigurableProvider.js +5 -1
- package/dist/IEnvironmentConfigurableProvider.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/AuthProviderFactory.ts +78 -13
- package/src/BaseAuthProvider.ts +16 -2
- package/src/IAuthProvider.ts +19 -10
- package/src/IEnvironmentConfigurableProvider.ts +6 -1
- package/src/__tests__/AuthProviderFactory.test.ts +74 -0
- package/src/__tests__/BaseAuthProvider.test.ts +81 -0
- package/src/index.ts +1 -1
package/.turbo/turbo-build.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# @memberjunction/auth-providers
|
|
2
2
|
|
|
3
|
+
## 6.2.0-edge.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 9d4a28a: fix: cache/dispose provider and driver instances that were being silently rebuilt or leaked on every call
|
|
8
|
+
|
|
9
|
+
Memory-leak audit findings (Round 15, 2026-09-19):
|
|
10
|
+
- **`CommunicationEngine.GetProvider()`** constructed a brand-new provider instance (Twilio/Gmail/MSGraph/etc.) via `ClassFactory.CreateInstance` on every single send — including once per recipient during a bulk `SendMessages()` call. Because each provider's own SDK-client cache (`MJLruCache`) lives on the instance, this silently defeated the earlier fix that added those caches: they were rebuilt empty and thrown away on every call in production, causing sawtooth GC pressure and SDK-client/socket churn on every bulk send. `GetProvider()` now caches resolved provider instances by name, bounded by the small, admin-managed number of registered communication providers.
|
|
11
|
+
- **`FileStorageEngine.RefreshDriverCache()`** dropped every cached storage driver — including live SDK clients (S3Client, BlobServiceClient, etc.) — with no disposal, and is reachable from ordinary end-user activity (`UploadFile()` force-refreshes the whole driver cache any time a requested `storageAccountId` isn't found). `FileStorageBase` gains a `Dispose()` hook (no-op by default, since most of the storage SDKs used here expose no explicit teardown API); `AWSFileStorage` overrides it to destroy its `S3Client`, mirroring the destroy-before-reassign it already does internally on re-init. `FileStorageEngine` now disposes every cached driver before clearing the cache.
|
|
12
|
+
- **`AuthProviderFactory.register()`/`clear()`** dropped the previous `BaseAuthProvider` instance — each holding a live `https.Agent` keep-alive socket pool and `jwksClient` — with no cleanup, on every admin-triggered auth-catalog refresh. `BaseAuthProvider` now retains its HTTP agent and exposes `Dispose()` to destroy it; `IAuthProvider.Dispose()` is optional. `register()` disposes the provider it's replacing (but not when the same instance re-registers itself); `clear()` disposes every provider first.
|
|
13
|
+
|
|
14
|
+
No behavior changes to any success path. 19 new unit tests cover the caching/disposal semantics, including edge cases (failed lookups aren't cached, throwing `Dispose()` doesn't block disposing sibling drivers, same-instance re-registration isn't disposed, providers with no `Dispose()` method are tolerated).
|
|
15
|
+
|
|
16
|
+
- 80905a1: Rename public class members and exported functions to PascalCase, per MJ's naming convention,
|
|
17
|
+
**without breaking a single consumer**.
|
|
18
|
+
|
|
19
|
+
Every renamed symbol keeps its old name beside the new one as a `@deprecated` stub that forwards to
|
|
20
|
+
it — a delegating method or function, a getter/setter pair for a property, and for Angular a
|
|
21
|
+
readable accessor pair for an `@Input` and a second `@Output` sharing the same `EventEmitter`, so a
|
|
22
|
+
template still binding the old name keeps receiving events. Old names still compile, still resolve,
|
|
23
|
+
and still behave identically; the deprecation tag rides through to the published `.d.ts`, so editors
|
|
24
|
+
point callers at the replacement. Where a package re-exports through an explicit `export { … }`
|
|
25
|
+
list, the new name is added alongside the old, so the correct name is actually on the public surface
|
|
26
|
+
rather than merely declared.
|
|
27
|
+
|
|
28
|
+
The rename is deliberately refused wherever a mechanical stub would not be equivalent, because
|
|
29
|
+
several of those shapes change a type contract while still compiling in the package that declares
|
|
30
|
+
them:
|
|
31
|
+
- an **optional** property or parameter property — TypeScript has no optional accessor, so a stub
|
|
32
|
+
would promote `foo?` to a required member and break every object literal that omits it;
|
|
33
|
+
- a class that is a **data shape** (no methods, or `@ObjectType`/`@InputType`) — object literals are
|
|
34
|
+
assigned to it, and an accessor stub changes what they must supply;
|
|
35
|
+
- a property whose **subclass redeclares it**, since TypeScript forbids a property overriding an
|
|
36
|
+
accessor (TS2610);
|
|
37
|
+
- a name whose PascalCase form is **already bound** in that file or class;
|
|
38
|
+
- decorated members, `get`/`set` pairs behind a decorator, generators, destructured parameters,
|
|
39
|
+
overload sets and abstract members.
|
|
40
|
+
|
|
41
|
+
**One wire-visible consequence, for version skew only.** `BaseInfo.toJSON` walks `_`-prefixed
|
|
42
|
+
backing fields and emits them through their public getter, preferring the PascalCase one. Renaming
|
|
43
|
+
the 23 field aliases in `MJCore/src/generic` therefore changes what `AllMetadata` carries:
|
|
44
|
+
`EntityInfo.spCreate` and friends now serialize as `SpCreate`. A same-version client is unaffected —
|
|
45
|
+
`copyInitData` accepts a value through a settable accessor, so either spelling lands on the right
|
|
46
|
+
field. An OLDER client against a newer server has no such path in its `copyInitData` and drops those
|
|
47
|
+
fields silently. Same-version deployments, which is the supported configuration, see no change.
|
|
48
|
+
|
|
49
|
+
Each package was verified against its own pre-change baseline rather than against zero, because
|
|
50
|
+
several packages in this repo do not typecheck cleanly to begin with. Angular packages were verified
|
|
51
|
+
with `ngc`, not `tsc`: a plain typecheck does not compile templates, and an earlier write-only
|
|
52
|
+
`@Input` alias passed `tsc` while breaking six template reads.
|
|
53
|
+
|
|
54
|
+
- Updated dependencies [a3539d2]
|
|
55
|
+
- Updated dependencies [41274aa]
|
|
56
|
+
- Updated dependencies [a7da50b]
|
|
57
|
+
- Updated dependencies [17cc774]
|
|
58
|
+
- Updated dependencies [80905a1]
|
|
59
|
+
- @memberjunction/core@6.2.0-edge.1
|
|
60
|
+
- @memberjunction/global@6.2.0-edge.1
|
|
61
|
+
|
|
3
62
|
## 6.2.0-edge.0
|
|
4
63
|
|
|
5
64
|
### Patch Changes
|
|
@@ -28,14 +28,20 @@ export declare class AuthProviderFactory extends BaseSingleton<AuthProviderFacto
|
|
|
28
28
|
* Creates an authentication provider instance based on configuration
|
|
29
29
|
* Uses MJGlobal ClassFactory to instantiate the correct provider class
|
|
30
30
|
*/
|
|
31
|
+
static CreateProvider(config: AuthProviderConfig): IAuthProvider;
|
|
32
|
+
/** @deprecated Use {@link CreateProvider}. */
|
|
31
33
|
static createProvider(config: AuthProviderConfig): IAuthProvider;
|
|
32
34
|
/**
|
|
33
35
|
* Registers a new authentication provider
|
|
34
36
|
*/
|
|
37
|
+
Register(provider: IAuthProvider): void;
|
|
38
|
+
/** @deprecated Use {@link Register}. */
|
|
35
39
|
register(provider: IAuthProvider): void;
|
|
36
40
|
/**
|
|
37
41
|
* Gets a provider by its issuer URL
|
|
38
42
|
*/
|
|
43
|
+
GetByIssuer(issuer: string): IAuthProvider | undefined;
|
|
44
|
+
/** @deprecated Use {@link GetByIssuer}. */
|
|
39
45
|
getByIssuer(issuer: string): IAuthProvider | undefined;
|
|
40
46
|
/**
|
|
41
47
|
* Gets all providers matching an issuer URL.
|
|
@@ -44,26 +50,41 @@ export declare class AuthProviderFactory extends BaseSingleton<AuthProviderFacto
|
|
|
44
50
|
* (e.g. MJExplorer + MJCentral) share the same Auth0 domain but have
|
|
45
51
|
* different audiences (client IDs).
|
|
46
52
|
*/
|
|
53
|
+
GetAllByIssuer(issuer: string): IAuthProvider[];
|
|
54
|
+
/** @deprecated Use {@link GetAllByIssuer}. */
|
|
47
55
|
getAllByIssuer(issuer: string): IAuthProvider[];
|
|
48
56
|
/**
|
|
49
57
|
* Gets a provider by its name
|
|
50
58
|
*/
|
|
59
|
+
GetByName(name: string): IAuthProvider | undefined;
|
|
60
|
+
/** @deprecated Use {@link GetByName}. */
|
|
51
61
|
getByName(name: string): IAuthProvider | undefined;
|
|
52
62
|
/**
|
|
53
63
|
* Gets all registered providers
|
|
54
64
|
*/
|
|
65
|
+
GetAllProviders(): IAuthProvider[];
|
|
66
|
+
/** @deprecated Use {@link GetAllProviders}. */
|
|
55
67
|
getAllProviders(): IAuthProvider[];
|
|
56
68
|
/**
|
|
57
69
|
* Checks if any providers are registered
|
|
58
70
|
*/
|
|
71
|
+
HasProviders(): boolean;
|
|
72
|
+
/** @deprecated Use {@link HasProviders}. */
|
|
59
73
|
hasProviders(): boolean;
|
|
60
74
|
/**
|
|
61
|
-
* Clears all registered providers (useful for testing
|
|
75
|
+
* Clears all registered providers (useful for testing, and called on every server boot /
|
|
76
|
+
* runtime catalog refresh — see `initializeProviders.ts`). Disposes each provider first so its
|
|
77
|
+
* HTTP agent/JWKS client's socket pool is released immediately rather than leaking until its
|
|
78
|
+
* own idle timeout.
|
|
62
79
|
*/
|
|
80
|
+
Clear(): void;
|
|
81
|
+
/** @deprecated Use {@link Clear}. */
|
|
63
82
|
clear(): void;
|
|
64
83
|
/**
|
|
65
84
|
* Gets all registered provider types from the ClassFactory
|
|
66
85
|
*/
|
|
86
|
+
static GetRegisteredProviderTypes(): string[];
|
|
87
|
+
/** @deprecated Use {@link GetRegisteredProviderTypes}. */
|
|
67
88
|
static getRegisteredProviderTypes(): string[];
|
|
68
89
|
/**
|
|
69
90
|
* Collects provider configurations from environment variables by asking every registered
|
|
@@ -85,6 +106,8 @@ export declare class AuthProviderFactory extends BaseSingleton<AuthProviderFacto
|
|
|
85
106
|
/**
|
|
86
107
|
* Checks if a provider type is registered
|
|
87
108
|
*/
|
|
109
|
+
static IsProviderTypeRegistered(type: string): boolean;
|
|
110
|
+
/** @deprecated Use {@link IsProviderTypeRegistered}. */
|
|
88
111
|
static isProviderTypeRegistered(type: string): boolean;
|
|
89
112
|
}
|
|
90
113
|
//# sourceMappingURL=AuthProviderFactory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProviderFactory.d.ts","sourceRoot":"","sources":["../src/AuthProviderFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAe,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAY,aAAa,EAAc,MAAM,wBAAwB,CAAC;AAgB7E;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,aAAa,CAAC,mBAAmB,CAAC;IACzE,OAAO,CAAC,SAAS,CAAyC;IAC1D;;;;;;OAMG;IACH,OAAO,CAAC,WAAW,CAA6F;IAChH;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAAiG;;IAMzH;;OAEG;IACH,WAAkB,QAAQ,IAAI,mBAAmB,CAEhD;IAED;;;OAGG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,aAAa;IAsBhE;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"AuthProviderFactory.d.ts","sourceRoot":"","sources":["../src/AuthProviderFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAe,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAY,aAAa,EAAc,MAAM,wBAAwB,CAAC;AAgB7E;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,aAAa,CAAC,mBAAmB,CAAC;IACzE,OAAO,CAAC,SAAS,CAAyC;IAC1D;;;;;;OAMG;IACH,OAAO,CAAC,WAAW,CAA6F;IAChH;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAAiG;;IAMzH;;OAEG;IACH,WAAkB,QAAQ,IAAI,mBAAmB,CAEhD;IAED;;;OAGG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,aAAa;IAsBhE,8CAA8C;IAC9C,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,aAAa;IAIhE;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAyBvC,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAIvC;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAmBtD,2CAA2C;IAC3C,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAItD;;;;;;OAMG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE;IAqB/C,8CAA8C;IAC9C,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE;IAI/C;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIlD,yCAAyC;IACzC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIlD;;OAEG;IACH,eAAe,IAAI,aAAa,EAAE;IAIlC,+CAA+C;IAC/C,eAAe,IAAI,aAAa,EAAE;IAIlC;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB,4CAA4C;IAC5C,YAAY,IAAI,OAAO;IAIvB;;;;;OAKG;IACH,KAAK,IAAI,IAAI;IAUb,qCAAqC;IACrC,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,MAAM,CAAC,0BAA0B,IAAI,MAAM,EAAE;IAW7C,0DAA0D;IAC1D,MAAM,CAAC,0BAA0B,IAAI,MAAM,EAAE;IAI7C;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,kBAAkB,EAAE;IA0B1F;;OAEG;IACH,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAUtD,wDAAwD;IACxD,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAGvD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LogStatusEx } from '@memberjunction/core';
|
|
2
2
|
import { BaseAuthProvider } from './BaseAuthProvider.js';
|
|
3
|
-
import {
|
|
3
|
+
import { IsEnvironmentConfigurable } from './IEnvironmentConfigurableProvider.js';
|
|
4
4
|
import { MJGlobal, BaseSingleton, MJLruCache } from '@memberjunction/global';
|
|
5
5
|
// NOTE: this file deliberately contains NO list of concrete providers.
|
|
6
6
|
//
|
|
@@ -46,7 +46,7 @@ export class AuthProviderFactory extends BaseSingleton {
|
|
|
46
46
|
* Creates an authentication provider instance based on configuration
|
|
47
47
|
* Uses MJGlobal ClassFactory to instantiate the correct provider class
|
|
48
48
|
*/
|
|
49
|
-
static
|
|
49
|
+
static CreateProvider(config) {
|
|
50
50
|
try {
|
|
51
51
|
// Use MJGlobal ClassFactory to create the provider instance
|
|
52
52
|
// The provider type in config should match the key used in @RegisterClass
|
|
@@ -62,13 +62,24 @@ export class AuthProviderFactory extends BaseSingleton {
|
|
|
62
62
|
throw new Error(`Failed to create authentication provider for type '${config.type}': ${message}`);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
/** @deprecated Use {@link CreateProvider}. */
|
|
66
|
+
static createProvider(config) {
|
|
67
|
+
return this.CreateProvider(config);
|
|
68
|
+
}
|
|
65
69
|
/**
|
|
66
70
|
* Registers a new authentication provider
|
|
67
71
|
*/
|
|
68
|
-
|
|
72
|
+
Register(provider) {
|
|
69
73
|
if (!provider.validateConfig()) {
|
|
70
74
|
throw new Error(`Invalid configuration for provider: ${provider.name}`);
|
|
71
75
|
}
|
|
76
|
+
// Dispose the provider being replaced (if any) so its HTTP agent/JWKS client's socket pool
|
|
77
|
+
// is released immediately rather than leaking until its own idle timeout. Re-registering the
|
|
78
|
+
// SAME instance (e.g. an idempotent re-register) must not dispose it out from under itself.
|
|
79
|
+
const existing = this.providers.get(provider.name);
|
|
80
|
+
if (existing && existing !== provider) {
|
|
81
|
+
existing.Dispose?.();
|
|
82
|
+
}
|
|
72
83
|
this.providers.set(provider.name, provider);
|
|
73
84
|
// Clear issuer caches when registering new provider
|
|
74
85
|
this.issuerCache.Clear();
|
|
@@ -78,10 +89,14 @@ export class AuthProviderFactory extends BaseSingleton {
|
|
|
78
89
|
// server's telemetry.level) so it's reusable by any consumer of this generic package.
|
|
79
90
|
LogStatusEx({ message: `Registered auth provider: ${provider.name} with issuer: ${provider.issuer}`, verboseOnly: true });
|
|
80
91
|
}
|
|
92
|
+
/** @deprecated Use {@link Register}. */
|
|
93
|
+
register(provider) {
|
|
94
|
+
return this.Register(provider);
|
|
95
|
+
}
|
|
81
96
|
/**
|
|
82
97
|
* Gets a provider by its issuer URL
|
|
83
98
|
*/
|
|
84
|
-
|
|
99
|
+
GetByIssuer(issuer) {
|
|
85
100
|
// Check cache first
|
|
86
101
|
const cached = this.issuerCache.Get(issuer);
|
|
87
102
|
if (cached) {
|
|
@@ -97,6 +112,10 @@ export class AuthProviderFactory extends BaseSingleton {
|
|
|
97
112
|
}
|
|
98
113
|
return undefined;
|
|
99
114
|
}
|
|
115
|
+
/** @deprecated Use {@link GetByIssuer}. */
|
|
116
|
+
getByIssuer(issuer) {
|
|
117
|
+
return this.GetByIssuer(issuer);
|
|
118
|
+
}
|
|
100
119
|
/**
|
|
101
120
|
* Gets all providers matching an issuer URL.
|
|
102
121
|
* Unlike getByIssuer() which returns only the first match, this returns
|
|
@@ -104,7 +123,7 @@ export class AuthProviderFactory extends BaseSingleton {
|
|
|
104
123
|
* (e.g. MJExplorer + MJCentral) share the same Auth0 domain but have
|
|
105
124
|
* different audiences (client IDs).
|
|
106
125
|
*/
|
|
107
|
-
|
|
126
|
+
GetAllByIssuer(issuer) {
|
|
108
127
|
// Check multi-provider cache first
|
|
109
128
|
const cached = this.issuerMultiCache.Get(issuer);
|
|
110
129
|
if (cached) {
|
|
@@ -121,36 +140,62 @@ export class AuthProviderFactory extends BaseSingleton {
|
|
|
121
140
|
}
|
|
122
141
|
return matches;
|
|
123
142
|
}
|
|
143
|
+
/** @deprecated Use {@link GetAllByIssuer}. */
|
|
144
|
+
getAllByIssuer(issuer) {
|
|
145
|
+
return this.GetAllByIssuer(issuer);
|
|
146
|
+
}
|
|
124
147
|
/**
|
|
125
148
|
* Gets a provider by its name
|
|
126
149
|
*/
|
|
127
|
-
|
|
150
|
+
GetByName(name) {
|
|
128
151
|
return this.providers.get(name);
|
|
129
152
|
}
|
|
153
|
+
/** @deprecated Use {@link GetByName}. */
|
|
154
|
+
getByName(name) {
|
|
155
|
+
return this.GetByName(name);
|
|
156
|
+
}
|
|
130
157
|
/**
|
|
131
158
|
* Gets all registered providers
|
|
132
159
|
*/
|
|
133
|
-
|
|
160
|
+
GetAllProviders() {
|
|
134
161
|
return Array.from(this.providers.values());
|
|
135
162
|
}
|
|
163
|
+
/** @deprecated Use {@link GetAllProviders}. */
|
|
164
|
+
getAllProviders() {
|
|
165
|
+
return this.GetAllProviders();
|
|
166
|
+
}
|
|
136
167
|
/**
|
|
137
168
|
* Checks if any providers are registered
|
|
138
169
|
*/
|
|
139
|
-
|
|
170
|
+
HasProviders() {
|
|
140
171
|
return this.providers.size > 0;
|
|
141
172
|
}
|
|
173
|
+
/** @deprecated Use {@link HasProviders}. */
|
|
174
|
+
hasProviders() {
|
|
175
|
+
return this.HasProviders();
|
|
176
|
+
}
|
|
142
177
|
/**
|
|
143
|
-
* Clears all registered providers (useful for testing
|
|
178
|
+
* Clears all registered providers (useful for testing, and called on every server boot /
|
|
179
|
+
* runtime catalog refresh — see `initializeProviders.ts`). Disposes each provider first so its
|
|
180
|
+
* HTTP agent/JWKS client's socket pool is released immediately rather than leaking until its
|
|
181
|
+
* own idle timeout.
|
|
144
182
|
*/
|
|
145
|
-
|
|
183
|
+
Clear() {
|
|
184
|
+
for (const provider of this.providers.values()) {
|
|
185
|
+
provider.Dispose?.();
|
|
186
|
+
}
|
|
146
187
|
this.providers.clear();
|
|
147
188
|
this.issuerCache.Clear();
|
|
148
189
|
this.issuerMultiCache.Clear();
|
|
149
190
|
}
|
|
191
|
+
/** @deprecated Use {@link Clear}. */
|
|
192
|
+
clear() {
|
|
193
|
+
return this.Clear();
|
|
194
|
+
}
|
|
150
195
|
/**
|
|
151
196
|
* Gets all registered provider types from the ClassFactory
|
|
152
197
|
*/
|
|
153
|
-
static
|
|
198
|
+
static GetRegisteredProviderTypes() {
|
|
154
199
|
// Get all registrations for BaseAuthProvider from ClassFactory
|
|
155
200
|
const registrations = MJGlobal.Instance.ClassFactory.GetAllRegistrations(BaseAuthProvider);
|
|
156
201
|
// Extract unique keys (provider types) from registrations
|
|
@@ -160,6 +205,10 @@ export class AuthProviderFactory extends BaseSingleton {
|
|
|
160
205
|
// Return unique provider types
|
|
161
206
|
return Array.from(new Set(providerTypes));
|
|
162
207
|
}
|
|
208
|
+
/** @deprecated Use {@link GetRegisteredProviderTypes}. */
|
|
209
|
+
static getRegisteredProviderTypes() {
|
|
210
|
+
return this.GetRegisteredProviderTypes();
|
|
211
|
+
}
|
|
163
212
|
/**
|
|
164
213
|
* Collects provider configurations from environment variables by asking every registered
|
|
165
214
|
* provider class to configure itself.
|
|
@@ -181,7 +230,7 @@ export class AuthProviderFactory extends BaseSingleton {
|
|
|
181
230
|
const configs = new Map();
|
|
182
231
|
for (const registration of registrations) {
|
|
183
232
|
const providerClass = registration.SubClass;
|
|
184
|
-
if (!
|
|
233
|
+
if (!IsEnvironmentConfigurable(providerClass)) {
|
|
185
234
|
continue;
|
|
186
235
|
}
|
|
187
236
|
try {
|
|
@@ -203,7 +252,7 @@ export class AuthProviderFactory extends BaseSingleton {
|
|
|
203
252
|
/**
|
|
204
253
|
* Checks if a provider type is registered
|
|
205
254
|
*/
|
|
206
|
-
static
|
|
255
|
+
static IsProviderTypeRegistered(type) {
|
|
207
256
|
try {
|
|
208
257
|
// Try to get the registration for this specific type
|
|
209
258
|
const registration = MJGlobal.Instance.ClassFactory.GetRegistration(BaseAuthProvider, type.toLowerCase());
|
|
@@ -213,5 +262,9 @@ export class AuthProviderFactory extends BaseSingleton {
|
|
|
213
262
|
return false;
|
|
214
263
|
}
|
|
215
264
|
}
|
|
265
|
+
/** @deprecated Use {@link IsProviderTypeRegistered}. */
|
|
266
|
+
static isProviderTypeRegistered(type) {
|
|
267
|
+
return this.IsProviderTypeRegistered(type);
|
|
268
|
+
}
|
|
216
269
|
}
|
|
217
270
|
//# sourceMappingURL=AuthProviderFactory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProviderFactory.js","sourceRoot":"","sources":["../src/AuthProviderFactory.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"AuthProviderFactory.js","sourceRoot":"","sources":["../src/AuthProviderFactory.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,18 @@ export declare abstract class BaseAuthProvider implements IAuthProvider {
|
|
|
18
18
|
domain?: string;
|
|
19
19
|
protected config: AuthProviderConfig;
|
|
20
20
|
protected jwksClient: jwksClient.JwksClient;
|
|
21
|
+
/**
|
|
22
|
+
* The keep-alive HTTP agent backing `jwksClient`'s requests. Retained (rather than left as a
|
|
23
|
+
* constructor-local) so {@link Dispose} can release its socket pool when this provider instance
|
|
24
|
+
* is replaced or the registry is torn down — see `AuthProviderFactory.register()`/`clear()`.
|
|
25
|
+
*/
|
|
26
|
+
private readonly requestAgent;
|
|
21
27
|
constructor(config: AuthProviderConfig);
|
|
28
|
+
/**
|
|
29
|
+
* Destroys this provider's keep-alive HTTP agent, closing any open/idle sockets immediately
|
|
30
|
+
* instead of waiting for their own idle timeout. Safe to call more than once.
|
|
31
|
+
*/
|
|
32
|
+
Dispose(): void;
|
|
22
33
|
/**
|
|
23
34
|
* Validates that required configuration is present
|
|
24
35
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseAuthProvider.d.ts","sourceRoot":"","sources":["../src/BaseAuthProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,UAAU,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAInD;;;;GAIG;AACH,8BAAsB,gBAAiB,YAAW,aAAa;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uGAAuG;IACvG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACrC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"BaseAuthProvider.d.ts","sourceRoot":"","sources":["../src/BaseAuthProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,UAAU,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAInD;;;;GAIG;AACH,8BAAsB,gBAAiB,YAAW,aAAa;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uGAAuG;IACvG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACrC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;IAC5C;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA2B;gBAE5C,MAAM,EAAE,kBAAkB;IAqCtC;;;OAGG;IACH,OAAO,IAAI,IAAI;IAIf;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAYpE;;OAEG;YACW,sBAAsB;IAuCpC;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAOtC;;OAEG;IACH,QAAQ,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,YAAY;CAC5D"}
|
package/dist/BaseAuthProvider.js
CHANGED
|
@@ -16,7 +16,7 @@ export class BaseAuthProvider {
|
|
|
16
16
|
this.clientId = config.clientId;
|
|
17
17
|
this.domain = config.domain;
|
|
18
18
|
// Create HTTP agent with keep-alive to prevent socket hangups
|
|
19
|
-
|
|
19
|
+
this.requestAgent = this.jwksUri.startsWith('https')
|
|
20
20
|
? new https.Agent({
|
|
21
21
|
keepAlive: true,
|
|
22
22
|
keepAliveMsecs: 30000,
|
|
@@ -38,9 +38,16 @@ export class BaseAuthProvider {
|
|
|
38
38
|
cacheMaxEntries: 5,
|
|
39
39
|
cacheMaxAge: 600000, // 10 minutes
|
|
40
40
|
timeout: 60000, // 60 seconds (increased from default 30s)
|
|
41
|
-
requestAgent:
|
|
41
|
+
requestAgent: this.requestAgent
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Destroys this provider's keep-alive HTTP agent, closing any open/idle sockets immediately
|
|
46
|
+
* instead of waiting for their own idle timeout. Safe to call more than once.
|
|
47
|
+
*/
|
|
48
|
+
Dispose() {
|
|
49
|
+
this.requestAgent.destroy();
|
|
50
|
+
}
|
|
44
51
|
/**
|
|
45
52
|
* Validates that required configuration is present
|
|
46
53
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseAuthProvider.js","sourceRoot":"","sources":["../src/BaseAuthProvider.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,MAAM,UAAU,CAAC;AAGlC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;GAIG;AACH,MAAM,OAAgB,gBAAgB;
|
|
1
|
+
{"version":3,"file":"BaseAuthProvider.js","sourceRoot":"","sources":["../src/BaseAuthProvider.ts"],"names":[],"mappings":"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"}
|
package/dist/IAuthProvider.d.ts
CHANGED
|
@@ -44,6 +44,14 @@ export interface IAuthProvider {
|
|
|
44
44
|
* Different providers use different claim names
|
|
45
45
|
*/
|
|
46
46
|
extractUserInfo(payload: JwtPayload): AuthUserInfo;
|
|
47
|
+
/**
|
|
48
|
+
* Releases any resources (keep-alive HTTP agent, JWKS client) this provider instance holds.
|
|
49
|
+
* Optional so implementations with nothing to release don't need a no-op override. Called by
|
|
50
|
+
* {@link AuthProviderFactory} before an existing provider is replaced (`register()`) or the
|
|
51
|
+
* registry is torn down (`clear()`), so a discarded provider's socket pool doesn't stay open
|
|
52
|
+
* until its own idle timeout.
|
|
53
|
+
*/
|
|
54
|
+
Dispose?(): void;
|
|
47
55
|
/**
|
|
48
56
|
* Checks if a given issuer URL belongs to this provider
|
|
49
57
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IAuthProvider.d.ts","sourceRoot":"","sources":["../src/IAuthProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAsB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAExE;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,cAAc,IAAI,OAAO,CAAC;IAE1B;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAErE;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,YAAY,CAAC;IAEnD;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;CACxC"}
|
|
1
|
+
{"version":3,"file":"IAuthProvider.d.ts","sourceRoot":"","sources":["../src/IAuthProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAsB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAExE;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,cAAc,IAAI,OAAO,CAAC;IAE1B;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAErE;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,YAAY,CAAC;IAEnD;;;;;;OAMG;IACH,OAAO,CAAC,IAAI,IAAI,CAAC;IAEjB;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;CACxC"}
|
|
@@ -47,5 +47,7 @@ export interface IEnvironmentConfigurableProvider {
|
|
|
47
47
|
/**
|
|
48
48
|
* Narrows an unknown provider class to one that offers env-var configuration.
|
|
49
49
|
*/
|
|
50
|
+
export declare function IsEnvironmentConfigurable(subject: unknown): subject is IEnvironmentConfigurableProvider;
|
|
51
|
+
/** @deprecated Use {@link IsEnvironmentConfigurable}. */
|
|
50
52
|
export declare function isEnvironmentConfigurable(subject: unknown): subject is IEnvironmentConfigurableProvider;
|
|
51
53
|
//# sourceMappingURL=IEnvironmentConfigurableProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IEnvironmentConfigurableProvider.d.ts","sourceRoot":"","sources":["../src/IEnvironmentConfigurableProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,WAAW,gCAAgC;IAC/C;;;;;;;;;OASG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,kBAAkB,GAAG,IAAI,CAAC;CAC1E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gCAAgC,CAEvG"}
|
|
1
|
+
{"version":3,"file":"IEnvironmentConfigurableProvider.d.ts","sourceRoot":"","sources":["../src/IEnvironmentConfigurableProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,WAAW,gCAAgC;IAC/C;;;;;;;;;OASG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,kBAAkB,GAAG,IAAI,CAAC;CAC1E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gCAAgC,CAEvG;AAED,yDAAyD;AACzD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gCAAgC,CAEvG"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Narrows an unknown provider class to one that offers env-var configuration.
|
|
3
3
|
*/
|
|
4
|
-
export function
|
|
4
|
+
export function IsEnvironmentConfigurable(subject) {
|
|
5
5
|
return typeof subject?.ConfigFromEnvironment === 'function';
|
|
6
6
|
}
|
|
7
|
+
/** @deprecated Use {@link IsEnvironmentConfigurable}. */
|
|
8
|
+
export function isEnvironmentConfigurable(subject) {
|
|
9
|
+
return IsEnvironmentConfigurable(subject);
|
|
10
|
+
}
|
|
7
11
|
//# sourceMappingURL=IEnvironmentConfigurableProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IEnvironmentConfigurableProvider.js","sourceRoot":"","sources":["../src/IEnvironmentConfigurableProvider.ts"],"names":[],"mappings":"AAgDA;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,OAAO,OAAQ,OAAwD,EAAE,qBAAqB,KAAK,UAAU,CAAC;AAChH,CAAC"}
|
|
1
|
+
{"version":3,"file":"IEnvironmentConfigurableProvider.js","sourceRoot":"","sources":["../src/IEnvironmentConfigurableProvider.ts"],"names":[],"mappings":"AAgDA;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,OAAO,OAAQ,OAAwD,EAAE,qBAAqB,KAAK,UAAU,CAAC;AAChH,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,OAAO,yBAAyB,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { IAuthProvider } from './IAuthProvider.js';
|
|
|
2
2
|
export { BaseAuthProvider } from './BaseAuthProvider.js';
|
|
3
3
|
export { AuthProviderFactory } from './AuthProviderFactory.js';
|
|
4
4
|
export { TokenExpiredError } from './tokenExpiredError.js';
|
|
5
|
-
export { type IEnvironmentConfigurableProvider, isEnvironmentConfigurable } from './IEnvironmentConfigurableProvider.js';
|
|
5
|
+
export { type IEnvironmentConfigurableProvider, IsEnvironmentConfigurable, isEnvironmentConfigurable } from './IEnvironmentConfigurableProvider.js';
|
|
6
6
|
export { MagicLinkProvider } from './providers/MagicLinkProvider.js';
|
|
7
7
|
export { HostIdentityProvider, type HostAssertionVerifyResult, type HostAssertionError, } from './providers/HostIdentityProvider.js';
|
|
8
8
|
export type { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,KAAK,gCAAgC,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,KAAK,gCAAgC,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AACpJ,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EACL,oBAAoB,EACpB,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,GACxB,MAAM,qCAAqC,CAAC;AAG7C,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAM7E,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { BaseAuthProvider } from './BaseAuthProvider.js';
|
|
2
2
|
export { AuthProviderFactory } from './AuthProviderFactory.js';
|
|
3
3
|
export { TokenExpiredError } from './tokenExpiredError.js';
|
|
4
|
-
export { isEnvironmentConfigurable } from './IEnvironmentConfigurableProvider.js';
|
|
4
|
+
export { IsEnvironmentConfigurable, isEnvironmentConfigurable } from './IEnvironmentConfigurableProvider.js';
|
|
5
5
|
export { MagicLinkProvider } from './providers/MagicLinkProvider.js';
|
|
6
6
|
export { HostIdentityProvider, } from './providers/HostIdentityProvider.js';
|
|
7
7
|
// Concrete auth providers. These are @RegisterClass plugins resolved by key at runtime, so
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAyC,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAyC,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AACpJ,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EACL,oBAAoB,GAGrB,MAAM,qCAAqC,CAAC;AAK7C,2FAA2F;AAC3F,sFAAsF;AACtF,yFAAyF;AACzF,6DAA6D;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/auth-providers",
|
|
3
3
|
"license": "BUSL-1.1",
|
|
4
|
-
"version": "6.2.0-edge.
|
|
4
|
+
"version": "6.2.0-edge.1",
|
|
5
5
|
"description": "Authentication provider interfaces, base classes, and implementations for MemberJunction",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@memberjunction/core": "6.2.0-edge.
|
|
11
|
-
"@memberjunction/global": "6.2.0-edge.
|
|
10
|
+
"@memberjunction/core": "6.2.0-edge.1",
|
|
11
|
+
"@memberjunction/global": "6.2.0-edge.1",
|
|
12
12
|
"graphql": "^16.12.0",
|
|
13
13
|
"jsonwebtoken": "9.0.3",
|
|
14
14
|
"jwks-rsa": "^3.2.2"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AuthProviderConfig, LogStatusEx } from '@memberjunction/core';
|
|
2
2
|
import { IAuthProvider } from './IAuthProvider.js';
|
|
3
3
|
import { BaseAuthProvider } from './BaseAuthProvider.js';
|
|
4
|
-
import {
|
|
4
|
+
import { IsEnvironmentConfigurable } from './IEnvironmentConfigurableProvider.js';
|
|
5
5
|
import { MJGlobal, BaseSingleton, MJLruCache } from '@memberjunction/global';
|
|
6
6
|
|
|
7
7
|
// NOTE: this file deliberately contains NO list of concrete providers.
|
|
@@ -52,7 +52,7 @@ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
|
|
|
52
52
|
* Creates an authentication provider instance based on configuration
|
|
53
53
|
* Uses MJGlobal ClassFactory to instantiate the correct provider class
|
|
54
54
|
*/
|
|
55
|
-
static
|
|
55
|
+
static CreateProvider(config: AuthProviderConfig): IAuthProvider {
|
|
56
56
|
try {
|
|
57
57
|
// Use MJGlobal ClassFactory to create the provider instance
|
|
58
58
|
// The provider type in config should match the key used in @RegisterClass
|
|
@@ -74,14 +74,27 @@ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/** @deprecated Use {@link CreateProvider}. */
|
|
78
|
+
static createProvider(config: AuthProviderConfig): IAuthProvider {
|
|
79
|
+
return this.CreateProvider(config);
|
|
80
|
+
}
|
|
81
|
+
|
|
77
82
|
/**
|
|
78
83
|
* Registers a new authentication provider
|
|
79
84
|
*/
|
|
80
|
-
|
|
85
|
+
Register(provider: IAuthProvider): void {
|
|
81
86
|
if (!provider.validateConfig()) {
|
|
82
87
|
throw new Error(`Invalid configuration for provider: ${provider.name}`);
|
|
83
88
|
}
|
|
84
89
|
|
|
90
|
+
// Dispose the provider being replaced (if any) so its HTTP agent/JWKS client's socket pool
|
|
91
|
+
// is released immediately rather than leaking until its own idle timeout. Re-registering the
|
|
92
|
+
// SAME instance (e.g. an idempotent re-register) must not dispose it out from under itself.
|
|
93
|
+
const existing = this.providers.get(provider.name);
|
|
94
|
+
if (existing && existing !== provider) {
|
|
95
|
+
existing.Dispose?.();
|
|
96
|
+
}
|
|
97
|
+
|
|
85
98
|
this.providers.set(provider.name, provider);
|
|
86
99
|
|
|
87
100
|
// Clear issuer caches when registering new provider
|
|
@@ -94,10 +107,15 @@ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
|
|
|
94
107
|
LogStatusEx({ message: `Registered auth provider: ${provider.name} with issuer: ${provider.issuer}`, verboseOnly: true });
|
|
95
108
|
}
|
|
96
109
|
|
|
110
|
+
/** @deprecated Use {@link Register}. */
|
|
111
|
+
register(provider: IAuthProvider): void {
|
|
112
|
+
return this.Register(provider);
|
|
113
|
+
}
|
|
114
|
+
|
|
97
115
|
/**
|
|
98
116
|
* Gets a provider by its issuer URL
|
|
99
117
|
*/
|
|
100
|
-
|
|
118
|
+
GetByIssuer(issuer: string): IAuthProvider | undefined {
|
|
101
119
|
// Check cache first
|
|
102
120
|
const cached = this.issuerCache.Get(issuer);
|
|
103
121
|
if (cached) {
|
|
@@ -116,6 +134,11 @@ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
|
|
|
116
134
|
return undefined;
|
|
117
135
|
}
|
|
118
136
|
|
|
137
|
+
/** @deprecated Use {@link GetByIssuer}. */
|
|
138
|
+
getByIssuer(issuer: string): IAuthProvider | undefined {
|
|
139
|
+
return this.GetByIssuer(issuer);
|
|
140
|
+
}
|
|
141
|
+
|
|
119
142
|
/**
|
|
120
143
|
* Gets all providers matching an issuer URL.
|
|
121
144
|
* Unlike getByIssuer() which returns only the first match, this returns
|
|
@@ -123,7 +146,7 @@ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
|
|
|
123
146
|
* (e.g. MJExplorer + MJCentral) share the same Auth0 domain but have
|
|
124
147
|
* different audiences (client IDs).
|
|
125
148
|
*/
|
|
126
|
-
|
|
149
|
+
GetAllByIssuer(issuer: string): IAuthProvider[] {
|
|
127
150
|
// Check multi-provider cache first
|
|
128
151
|
const cached = this.issuerMultiCache.Get(issuer);
|
|
129
152
|
if (cached) {
|
|
@@ -144,40 +167,72 @@ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
|
|
|
144
167
|
return matches;
|
|
145
168
|
}
|
|
146
169
|
|
|
170
|
+
/** @deprecated Use {@link GetAllByIssuer}. */
|
|
171
|
+
getAllByIssuer(issuer: string): IAuthProvider[] {
|
|
172
|
+
return this.GetAllByIssuer(issuer);
|
|
173
|
+
}
|
|
174
|
+
|
|
147
175
|
/**
|
|
148
176
|
* Gets a provider by its name
|
|
149
177
|
*/
|
|
150
|
-
|
|
178
|
+
GetByName(name: string): IAuthProvider | undefined {
|
|
151
179
|
return this.providers.get(name);
|
|
152
180
|
}
|
|
153
181
|
|
|
182
|
+
/** @deprecated Use {@link GetByName}. */
|
|
183
|
+
getByName(name: string): IAuthProvider | undefined {
|
|
184
|
+
return this.GetByName(name);
|
|
185
|
+
}
|
|
186
|
+
|
|
154
187
|
/**
|
|
155
188
|
* Gets all registered providers
|
|
156
189
|
*/
|
|
157
|
-
|
|
190
|
+
GetAllProviders(): IAuthProvider[] {
|
|
158
191
|
return Array.from(this.providers.values());
|
|
159
192
|
}
|
|
160
193
|
|
|
194
|
+
/** @deprecated Use {@link GetAllProviders}. */
|
|
195
|
+
getAllProviders(): IAuthProvider[] {
|
|
196
|
+
return this.GetAllProviders();
|
|
197
|
+
}
|
|
198
|
+
|
|
161
199
|
/**
|
|
162
200
|
* Checks if any providers are registered
|
|
163
201
|
*/
|
|
164
|
-
|
|
202
|
+
HasProviders(): boolean {
|
|
165
203
|
return this.providers.size > 0;
|
|
166
204
|
}
|
|
167
205
|
|
|
206
|
+
/** @deprecated Use {@link HasProviders}. */
|
|
207
|
+
hasProviders(): boolean {
|
|
208
|
+
return this.HasProviders();
|
|
209
|
+
}
|
|
210
|
+
|
|
168
211
|
/**
|
|
169
|
-
* Clears all registered providers (useful for testing
|
|
212
|
+
* Clears all registered providers (useful for testing, and called on every server boot /
|
|
213
|
+
* runtime catalog refresh — see `initializeProviders.ts`). Disposes each provider first so its
|
|
214
|
+
* HTTP agent/JWKS client's socket pool is released immediately rather than leaking until its
|
|
215
|
+
* own idle timeout.
|
|
170
216
|
*/
|
|
171
|
-
|
|
217
|
+
Clear(): void {
|
|
218
|
+
for (const provider of this.providers.values()) {
|
|
219
|
+
provider.Dispose?.();
|
|
220
|
+
}
|
|
221
|
+
|
|
172
222
|
this.providers.clear();
|
|
173
223
|
this.issuerCache.Clear();
|
|
174
224
|
this.issuerMultiCache.Clear();
|
|
175
225
|
}
|
|
176
226
|
|
|
227
|
+
/** @deprecated Use {@link Clear}. */
|
|
228
|
+
clear(): void {
|
|
229
|
+
return this.Clear();
|
|
230
|
+
}
|
|
231
|
+
|
|
177
232
|
/**
|
|
178
233
|
* Gets all registered provider types from the ClassFactory
|
|
179
234
|
*/
|
|
180
|
-
static
|
|
235
|
+
static GetRegisteredProviderTypes(): string[] {
|
|
181
236
|
// Get all registrations for BaseAuthProvider from ClassFactory
|
|
182
237
|
const registrations = MJGlobal.Instance.ClassFactory.GetAllRegistrations(BaseAuthProvider);
|
|
183
238
|
// Extract unique keys (provider types) from registrations
|
|
@@ -188,6 +243,11 @@ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
|
|
|
188
243
|
return Array.from(new Set(providerTypes));
|
|
189
244
|
}
|
|
190
245
|
|
|
246
|
+
/** @deprecated Use {@link GetRegisteredProviderTypes}. */
|
|
247
|
+
static getRegisteredProviderTypes(): string[] {
|
|
248
|
+
return this.GetRegisteredProviderTypes();
|
|
249
|
+
}
|
|
250
|
+
|
|
191
251
|
/**
|
|
192
252
|
* Collects provider configurations from environment variables by asking every registered
|
|
193
253
|
* provider class to configure itself.
|
|
@@ -210,7 +270,7 @@ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
|
|
|
210
270
|
|
|
211
271
|
for (const registration of registrations) {
|
|
212
272
|
const providerClass: unknown = registration.SubClass;
|
|
213
|
-
if (!
|
|
273
|
+
if (!IsEnvironmentConfigurable(providerClass)) {
|
|
214
274
|
continue;
|
|
215
275
|
}
|
|
216
276
|
try {
|
|
@@ -233,7 +293,7 @@ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
|
|
|
233
293
|
/**
|
|
234
294
|
* Checks if a provider type is registered
|
|
235
295
|
*/
|
|
236
|
-
static
|
|
296
|
+
static IsProviderTypeRegistered(type: string): boolean {
|
|
237
297
|
try {
|
|
238
298
|
// Try to get the registration for this specific type
|
|
239
299
|
const registration = MJGlobal.Instance.ClassFactory.GetRegistration(BaseAuthProvider, type.toLowerCase());
|
|
@@ -242,4 +302,9 @@ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
|
|
|
242
302
|
return false;
|
|
243
303
|
}
|
|
244
304
|
}
|
|
305
|
+
|
|
306
|
+
/** @deprecated Use {@link IsProviderTypeRegistered}. */
|
|
307
|
+
static isProviderTypeRegistered(type: string): boolean {
|
|
308
|
+
return this.IsProviderTypeRegistered(type);
|
|
309
|
+
}
|
|
245
310
|
}
|
package/src/BaseAuthProvider.ts
CHANGED
|
@@ -21,6 +21,12 @@ export abstract class BaseAuthProvider implements IAuthProvider {
|
|
|
21
21
|
domain?: string;
|
|
22
22
|
protected config: AuthProviderConfig;
|
|
23
23
|
protected jwksClient: jwksClient.JwksClient;
|
|
24
|
+
/**
|
|
25
|
+
* The keep-alive HTTP agent backing `jwksClient`'s requests. Retained (rather than left as a
|
|
26
|
+
* constructor-local) so {@link Dispose} can release its socket pool when this provider instance
|
|
27
|
+
* is replaced or the registry is torn down — see `AuthProviderFactory.register()`/`clear()`.
|
|
28
|
+
*/
|
|
29
|
+
private readonly requestAgent: https.Agent | http.Agent;
|
|
24
30
|
|
|
25
31
|
constructor(config: AuthProviderConfig) {
|
|
26
32
|
this.config = config;
|
|
@@ -32,7 +38,7 @@ export abstract class BaseAuthProvider implements IAuthProvider {
|
|
|
32
38
|
this.domain = config.domain;
|
|
33
39
|
|
|
34
40
|
// Create HTTP agent with keep-alive to prevent socket hangups
|
|
35
|
-
|
|
41
|
+
this.requestAgent = this.jwksUri.startsWith('https')
|
|
36
42
|
? new https.Agent({
|
|
37
43
|
keepAlive: true,
|
|
38
44
|
keepAliveMsecs: 30000,
|
|
@@ -55,10 +61,18 @@ export abstract class BaseAuthProvider implements IAuthProvider {
|
|
|
55
61
|
cacheMaxEntries: 5,
|
|
56
62
|
cacheMaxAge: 600000, // 10 minutes
|
|
57
63
|
timeout: 60000, // 60 seconds (increased from default 30s)
|
|
58
|
-
requestAgent:
|
|
64
|
+
requestAgent: this.requestAgent
|
|
59
65
|
});
|
|
60
66
|
}
|
|
61
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Destroys this provider's keep-alive HTTP agent, closing any open/idle sockets immediately
|
|
70
|
+
* instead of waiting for their own idle timeout. Safe to call more than once.
|
|
71
|
+
*/
|
|
72
|
+
Dispose(): void {
|
|
73
|
+
this.requestAgent.destroy();
|
|
74
|
+
}
|
|
75
|
+
|
|
62
76
|
/**
|
|
63
77
|
* Validates that required configuration is present
|
|
64
78
|
*/
|
package/src/IAuthProvider.ts
CHANGED
|
@@ -9,53 +9,62 @@ export interface IAuthProvider {
|
|
|
9
9
|
/**
|
|
10
10
|
* Unique name identifier for this provider
|
|
11
11
|
*/
|
|
12
|
-
name: string;
|
|
12
|
+
name: string; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* The issuer URL for this provider (must match the 'iss' claim in tokens)
|
|
16
16
|
*/
|
|
17
|
-
issuer: string;
|
|
17
|
+
issuer: string; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* The expected audience for tokens from this provider
|
|
21
21
|
*/
|
|
22
|
-
audience: string;
|
|
22
|
+
audience: string; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* The JWKS endpoint URL for retrieving signing keys
|
|
26
26
|
*/
|
|
27
|
-
jwksUri: string;
|
|
27
|
+
jwksUri: string; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* OAuth client ID for this provider (optional, used by OAuth proxy for upstream authentication)
|
|
31
31
|
*/
|
|
32
|
-
clientId?: string;
|
|
32
|
+
clientId?: string; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Provider domain, where the provider hosts its OAuth endpoints somewhere other than its
|
|
36
36
|
* issuer (optional, used by the OAuth proxy). Cognito is the case that needs it: its issuer
|
|
37
37
|
* is the user-pool URL, but /authorize and /token live on the hosted-UI domain.
|
|
38
38
|
*/
|
|
39
|
-
domain?: string;
|
|
39
|
+
domain?: string; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Validates that the provider configuration is complete and valid
|
|
43
43
|
*/
|
|
44
|
-
validateConfig(): boolean;
|
|
44
|
+
validateConfig(): boolean; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* Gets the signing key for token verification
|
|
48
48
|
*/
|
|
49
|
-
getSigningKey(header: JwtHeader, callback: SigningKeyCallback): void;
|
|
49
|
+
getSigningKey(header: JwtHeader, callback: SigningKeyCallback): void; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Extracts user information from the JWT payload
|
|
53
53
|
* Different providers use different claim names
|
|
54
54
|
*/
|
|
55
|
-
extractUserInfo(payload: JwtPayload): AuthUserInfo;
|
|
55
|
+
extractUserInfo(payload: JwtPayload): AuthUserInfo; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Releases any resources (keep-alive HTTP agent, JWKS client) this provider instance holds.
|
|
59
|
+
* Optional so implementations with nothing to release don't need a no-op override. Called by
|
|
60
|
+
* {@link AuthProviderFactory} before an existing provider is replaced (`register()`) or the
|
|
61
|
+
* registry is torn down (`clear()`), so a discarded provider's socket pool doesn't stay open
|
|
62
|
+
* until its own idle timeout.
|
|
63
|
+
*/
|
|
64
|
+
Dispose?(): void;
|
|
56
65
|
|
|
57
66
|
/**
|
|
58
67
|
* Checks if a given issuer URL belongs to this provider
|
|
59
68
|
*/
|
|
60
|
-
matchesIssuer(issuer: string): boolean;
|
|
69
|
+
matchesIssuer(issuer: string): boolean; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub
|
|
61
70
|
}
|
|
@@ -49,6 +49,11 @@ export interface IEnvironmentConfigurableProvider {
|
|
|
49
49
|
/**
|
|
50
50
|
* Narrows an unknown provider class to one that offers env-var configuration.
|
|
51
51
|
*/
|
|
52
|
-
export function
|
|
52
|
+
export function IsEnvironmentConfigurable(subject: unknown): subject is IEnvironmentConfigurableProvider {
|
|
53
53
|
return typeof (subject as IEnvironmentConfigurableProvider | undefined)?.ConfigFromEnvironment === 'function';
|
|
54
54
|
}
|
|
55
|
+
|
|
56
|
+
/** @deprecated Use {@link IsEnvironmentConfigurable}. */
|
|
57
|
+
export function isEnvironmentConfigurable(subject: unknown): subject is IEnvironmentConfigurableProvider {
|
|
58
|
+
return IsEnvironmentConfigurable(subject);
|
|
59
|
+
}
|
|
@@ -103,3 +103,77 @@ describe('AuthProviderFactory cache (memory-leak fix R2-C4)', () => {
|
|
|
103
103
|
expect(issuerMultiCache.Size).toBe(0);
|
|
104
104
|
});
|
|
105
105
|
});
|
|
106
|
+
|
|
107
|
+
describe('AuthProviderFactory provider disposal (memory-leak audit 2026-09-19)', () => {
|
|
108
|
+
// `register()`/`clear()` used to drop the old IAuthProvider value with no disposal call.
|
|
109
|
+
// Each BaseAuthProvider instance owns a keep-alive https.Agent + jwksClient; discarding it
|
|
110
|
+
// without disposing left its socket pool open until its own 60s idle timeout, on every
|
|
111
|
+
// admin-triggered auth-catalog refresh (`refreshAuthProviders()`).
|
|
112
|
+
let factory: AuthProviderFactory;
|
|
113
|
+
|
|
114
|
+
beforeEach(() => {
|
|
115
|
+
factory = AuthProviderFactory.Instance;
|
|
116
|
+
factory.clear();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('does not call Dispose when registering a brand-new provider name', () => {
|
|
120
|
+
const provider = makeProvider('p1', 'auth0.com');
|
|
121
|
+
const disposeSpy = vi.fn();
|
|
122
|
+
provider.Dispose = disposeSpy;
|
|
123
|
+
|
|
124
|
+
factory.register(provider);
|
|
125
|
+
|
|
126
|
+
expect(disposeSpy).not.toHaveBeenCalled();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('disposes the outgoing provider when register() replaces an existing name', () => {
|
|
130
|
+
const oldProvider = makeProvider('p1', 'auth0.com');
|
|
131
|
+
const oldDispose = vi.fn();
|
|
132
|
+
oldProvider.Dispose = oldDispose;
|
|
133
|
+
factory.register(oldProvider);
|
|
134
|
+
|
|
135
|
+
const newProvider = makeProvider('p1', 'auth0.com');
|
|
136
|
+
const newDispose = vi.fn();
|
|
137
|
+
newProvider.Dispose = newDispose;
|
|
138
|
+
factory.register(newProvider);
|
|
139
|
+
|
|
140
|
+
expect(oldDispose).toHaveBeenCalledTimes(1);
|
|
141
|
+
expect(newDispose).not.toHaveBeenCalled();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('does not dispose a provider that re-registers itself (same instance)', () => {
|
|
145
|
+
const provider = makeProvider('p1', 'auth0.com');
|
|
146
|
+
const disposeSpy = vi.fn();
|
|
147
|
+
provider.Dispose = disposeSpy;
|
|
148
|
+
|
|
149
|
+
factory.register(provider);
|
|
150
|
+
factory.register(provider); // idempotent re-register of the SAME instance
|
|
151
|
+
|
|
152
|
+
expect(disposeSpy).not.toHaveBeenCalled();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('disposes every registered provider on clear()', () => {
|
|
156
|
+
const p1 = makeProvider('p1', 'auth0.com');
|
|
157
|
+
const p2 = makeProvider('p2', 'okta.com');
|
|
158
|
+
const dispose1 = vi.fn();
|
|
159
|
+
const dispose2 = vi.fn();
|
|
160
|
+
p1.Dispose = dispose1;
|
|
161
|
+
p2.Dispose = dispose2;
|
|
162
|
+
factory.register(p1);
|
|
163
|
+
factory.register(p2);
|
|
164
|
+
|
|
165
|
+
factory.clear();
|
|
166
|
+
|
|
167
|
+
expect(dispose1).toHaveBeenCalledTimes(1);
|
|
168
|
+
expect(dispose2).toHaveBeenCalledTimes(1);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('tolerates providers with no Dispose method (optional on IAuthProvider)', () => {
|
|
172
|
+
// makeProvider() intentionally does not set Dispose - most of this file's fixtures don't.
|
|
173
|
+
expect(() => {
|
|
174
|
+
factory.register(makeProvider('p1', 'auth0.com'));
|
|
175
|
+
factory.register(makeProvider('p1', 'auth0.com')); // replaces p1, old has no Dispose
|
|
176
|
+
factory.clear();
|
|
177
|
+
}).not.toThrow();
|
|
178
|
+
});
|
|
179
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for BaseAuthProvider.Dispose() (memory-leak audit 2026-09-19, High finding #3).
|
|
3
|
+
*
|
|
4
|
+
* Each BaseAuthProvider instance owns a keep-alive https.Agent/http.Agent backing its
|
|
5
|
+
* jwksClient. Before this fix, that agent was a constructor-local variable with no way for a
|
|
6
|
+
* caller to release it, so `AuthProviderFactory.register()`/`clear()` replacing or dropping a
|
|
7
|
+
* provider left its socket pool open until the agent's own 60s idle timeout.
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
10
|
+
import type { JwtPayload } from 'jsonwebtoken';
|
|
11
|
+
import https from 'https';
|
|
12
|
+
import http from 'http';
|
|
13
|
+
import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
|
|
14
|
+
import { BaseAuthProvider } from '../BaseAuthProvider';
|
|
15
|
+
|
|
16
|
+
class TestAuthProvider extends BaseAuthProvider {
|
|
17
|
+
extractUserInfo(payload: JwtPayload): AuthUserInfo {
|
|
18
|
+
return { userId: payload.sub ?? '', email: '', firstName: '', lastName: '', preferredUsername: '' };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function makeConfig(overrides: Partial<AuthProviderConfig> = {}): AuthProviderConfig {
|
|
23
|
+
return {
|
|
24
|
+
name: 'test-provider',
|
|
25
|
+
type: 'test',
|
|
26
|
+
issuer: 'https://example.com/',
|
|
27
|
+
audience: 'test-aud',
|
|
28
|
+
jwksUri: 'https://example.com/.well-known/jwks.json',
|
|
29
|
+
...overrides,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe('BaseAuthProvider.Dispose', () => {
|
|
34
|
+
it('destroys the https.Agent backing the jwksClient when jwksUri is https', () => {
|
|
35
|
+
const destroySpy = vi.spyOn(https.Agent.prototype, 'destroy');
|
|
36
|
+
const provider = new TestAuthProvider(makeConfig());
|
|
37
|
+
const agent = (provider as unknown as { requestAgent: https.Agent }).requestAgent;
|
|
38
|
+
expect(agent).toBeInstanceOf(https.Agent);
|
|
39
|
+
|
|
40
|
+
provider.Dispose();
|
|
41
|
+
|
|
42
|
+
expect(destroySpy).toHaveBeenCalledTimes(1);
|
|
43
|
+
expect(destroySpy.mock.instances[0]).toBe(agent);
|
|
44
|
+
destroySpy.mockRestore();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('destroys the http.Agent when jwksUri is plain http (non-TLS test/dev endpoints)', () => {
|
|
48
|
+
const destroySpy = vi.spyOn(http.Agent.prototype, 'destroy');
|
|
49
|
+
const provider = new TestAuthProvider(makeConfig({ jwksUri: 'http://localhost:4000/.well-known/jwks.json' }));
|
|
50
|
+
const agent = (provider as unknown as { requestAgent: http.Agent }).requestAgent;
|
|
51
|
+
expect(agent).toBeInstanceOf(http.Agent);
|
|
52
|
+
|
|
53
|
+
provider.Dispose();
|
|
54
|
+
|
|
55
|
+
expect(destroySpy).toHaveBeenCalledTimes(1);
|
|
56
|
+
expect(destroySpy.mock.instances[0]).toBe(agent);
|
|
57
|
+
destroySpy.mockRestore();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('is safe to call more than once', () => {
|
|
61
|
+
const provider = new TestAuthProvider(makeConfig());
|
|
62
|
+
|
|
63
|
+
expect(() => {
|
|
64
|
+
provider.Dispose();
|
|
65
|
+
provider.Dispose();
|
|
66
|
+
}).not.toThrow();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("does not affect a different provider instance's agent", () => {
|
|
70
|
+
const destroySpy = vi.spyOn(https.Agent.prototype, 'destroy');
|
|
71
|
+
const providerA = new TestAuthProvider(makeConfig({ name: 'a' }));
|
|
72
|
+
const providerB = new TestAuthProvider(makeConfig({ name: 'b' }));
|
|
73
|
+
const agentB = (providerB as unknown as { requestAgent: https.Agent }).requestAgent;
|
|
74
|
+
|
|
75
|
+
providerA.Dispose();
|
|
76
|
+
|
|
77
|
+
expect(destroySpy).toHaveBeenCalledTimes(1);
|
|
78
|
+
expect(destroySpy.mock.instances[0]).not.toBe(agentB);
|
|
79
|
+
destroySpy.mockRestore();
|
|
80
|
+
});
|
|
81
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { IAuthProvider } from './IAuthProvider.js';
|
|
|
2
2
|
export { BaseAuthProvider } from './BaseAuthProvider.js';
|
|
3
3
|
export { AuthProviderFactory } from './AuthProviderFactory.js';
|
|
4
4
|
export { TokenExpiredError } from './tokenExpiredError.js';
|
|
5
|
-
export { type IEnvironmentConfigurableProvider, isEnvironmentConfigurable } from './IEnvironmentConfigurableProvider.js';
|
|
5
|
+
export { type IEnvironmentConfigurableProvider, IsEnvironmentConfigurable, isEnvironmentConfigurable } from './IEnvironmentConfigurableProvider.js';
|
|
6
6
|
export { MagicLinkProvider } from './providers/MagicLinkProvider.js';
|
|
7
7
|
export {
|
|
8
8
|
HostIdentityProvider,
|