@memberjunction/auth-providers 0.0.1 → 5.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +10 -0
  3. package/dist/AuthProviderFactory.d.ts +68 -0
  4. package/dist/AuthProviderFactory.d.ts.map +1 -0
  5. package/dist/AuthProviderFactory.js +153 -0
  6. package/dist/AuthProviderFactory.js.map +1 -0
  7. package/dist/BaseAuthProvider.d.ts +41 -0
  8. package/dist/BaseAuthProvider.d.ts.map +1 -0
  9. package/dist/BaseAuthProvider.js +102 -0
  10. package/dist/BaseAuthProvider.js.map +1 -0
  11. package/dist/IAuthProvider.d.ts +46 -0
  12. package/dist/IAuthProvider.d.ts.map +1 -0
  13. package/dist/IAuthProvider.js +2 -0
  14. package/dist/IAuthProvider.js.map +1 -0
  15. package/dist/index.d.ts +6 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +4 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/providers/Auth0Provider.d.ts +18 -0
  20. package/dist/providers/Auth0Provider.d.ts.map +1 -0
  21. package/dist/providers/Auth0Provider.js +52 -0
  22. package/dist/providers/Auth0Provider.js.map +1 -0
  23. package/dist/providers/CognitoProvider.d.ts +18 -0
  24. package/dist/providers/CognitoProvider.d.ts.map +1 -0
  25. package/dist/providers/CognitoProvider.js +56 -0
  26. package/dist/providers/CognitoProvider.js.map +1 -0
  27. package/dist/providers/GoogleProvider.d.ts +18 -0
  28. package/dist/providers/GoogleProvider.d.ts.map +1 -0
  29. package/dist/providers/GoogleProvider.js +51 -0
  30. package/dist/providers/GoogleProvider.js.map +1 -0
  31. package/dist/providers/MSALProvider.d.ts +18 -0
  32. package/dist/providers/MSALProvider.d.ts.map +1 -0
  33. package/dist/providers/MSALProvider.js +52 -0
  34. package/dist/providers/MSALProvider.js.map +1 -0
  35. package/dist/providers/OktaProvider.d.ts +18 -0
  36. package/dist/providers/OktaProvider.d.ts.map +1 -0
  37. package/dist/providers/OktaProvider.js +52 -0
  38. package/dist/providers/OktaProvider.js.map +1 -0
  39. package/dist/tokenExpiredError.d.ts +5 -0
  40. package/dist/tokenExpiredError.d.ts.map +1 -0
  41. package/dist/tokenExpiredError.js +12 -0
  42. package/dist/tokenExpiredError.js.map +1 -0
  43. package/package.json +28 -7
  44. package/src/AuthProviderFactory.ts +180 -0
  45. package/src/BaseAuthProvider.ts +137 -0
  46. package/src/IAuthProvider.ts +54 -0
  47. package/src/index.ts +7 -0
  48. package/src/providers/Auth0Provider.ts +45 -0
  49. package/src/providers/CognitoProvider.ts +50 -0
  50. package/src/providers/GoogleProvider.ts +45 -0
  51. package/src/providers/MSALProvider.ts +45 -0
  52. package/src/providers/OktaProvider.ts +46 -0
  53. package/src/tokenExpiredError.ts +12 -0
  54. package/tsconfig.json +10 -0
  55. package/vitest.config.ts +11 -0
  56. package/README.md +0 -45
@@ -0,0 +1,18 @@
1
+ import { JwtPayload } from 'jsonwebtoken';
2
+ import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
3
+ import { BaseAuthProvider } from '../BaseAuthProvider.js';
4
+ /**
5
+ * Google Identity Platform authentication provider implementation
6
+ */
7
+ export declare class GoogleProvider extends BaseAuthProvider {
8
+ constructor(config: AuthProviderConfig);
9
+ /**
10
+ * Extracts user information from Google JWT payload
11
+ */
12
+ extractUserInfo(payload: JwtPayload): AuthUserInfo;
13
+ /**
14
+ * Validates Google-specific configuration
15
+ */
16
+ validateConfig(): boolean;
17
+ }
18
+ //# sourceMappingURL=GoogleProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GoogleProvider.d.ts","sourceRoot":"","sources":["../../src/providers/GoogleProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D;;GAEG;AACH,qBACa,cAAe,SAAQ,gBAAgB;gBACtC,MAAM,EAAE,kBAAkB;IAItC;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,YAAY;IAiBlD;;OAEG;IACH,cAAc,IAAI,OAAO;CAM1B"}
@@ -0,0 +1,51 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { RegisterClass } from '@memberjunction/global';
11
+ import { BaseAuthProvider } from '../BaseAuthProvider.js';
12
+ /**
13
+ * Google Identity Platform authentication provider implementation
14
+ */
15
+ let GoogleProvider = class GoogleProvider extends BaseAuthProvider {
16
+ constructor(config) {
17
+ super(config);
18
+ }
19
+ /**
20
+ * Extracts user information from Google JWT payload
21
+ */
22
+ extractUserInfo(payload) {
23
+ // Google uses standard OIDC claims
24
+ const email = payload.email;
25
+ const fullName = payload.name;
26
+ const firstName = payload.given_name;
27
+ const lastName = payload.family_name;
28
+ const preferredUsername = email; // Google typically uses email as username
29
+ return {
30
+ email,
31
+ firstName: firstName || fullName?.split(' ')[0],
32
+ lastName: lastName || fullName?.split(' ')[1] || fullName?.split(' ')[0],
33
+ fullName,
34
+ preferredUsername
35
+ };
36
+ }
37
+ /**
38
+ * Validates Google-specific configuration
39
+ */
40
+ validateConfig() {
41
+ const baseValid = super.validateConfig();
42
+ const hasClientId = !!this.config.clientId;
43
+ return baseValid && hasClientId;
44
+ }
45
+ };
46
+ GoogleProvider = __decorate([
47
+ RegisterClass(BaseAuthProvider, 'google'),
48
+ __metadata("design:paramtypes", [Object])
49
+ ], GoogleProvider);
50
+ export { GoogleProvider };
51
+ //# sourceMappingURL=GoogleProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GoogleProvider.js","sourceRoot":"","sources":["../../src/providers/GoogleProvider.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D;;GAEG;AAEI,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,gBAAgB;IAClD,YAAY,MAA0B;QACpC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,OAAmB;QACjC,mCAAmC;QACnC,MAAM,KAAK,GAAG,OAAO,CAAC,KAA2B,CAAC;QAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAA0B,CAAC;QACpD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAgC,CAAC;QAC3D,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAiC,CAAC;QAC3D,MAAM,iBAAiB,GAAG,KAAK,CAAC,CAAC,0CAA0C;QAE3E,OAAO;YACL,KAAK;YACL,SAAS,EAAE,SAAS,IAAI,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC/C,QAAQ,EAAE,QAAQ,IAAI,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACxE,QAAQ;YACR,iBAAiB;SAClB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;QACzC,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QAE3C,OAAO,SAAS,IAAI,WAAW,CAAC;IAClC,CAAC;CACF,CAAA;AAlCY,cAAc;IAD1B,aAAa,CAAC,gBAAgB,EAAE,QAAQ,CAAC;;GAC7B,cAAc,CAkC1B"}
@@ -0,0 +1,18 @@
1
+ import { JwtPayload } from 'jsonwebtoken';
2
+ import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
3
+ import { BaseAuthProvider } from '../BaseAuthProvider.js';
4
+ /**
5
+ * Microsoft Authentication Library (MSAL) provider implementation
6
+ */
7
+ export declare class MSALProvider extends BaseAuthProvider {
8
+ constructor(config: AuthProviderConfig);
9
+ /**
10
+ * Extracts user information from MSAL/Azure AD JWT payload
11
+ */
12
+ extractUserInfo(payload: JwtPayload): AuthUserInfo;
13
+ /**
14
+ * Validates MSAL-specific configuration
15
+ */
16
+ validateConfig(): boolean;
17
+ }
18
+ //# sourceMappingURL=MSALProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MSALProvider.d.ts","sourceRoot":"","sources":["../../src/providers/MSALProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D;;GAEG;AACH,qBACa,YAAa,SAAQ,gBAAgB;gBACpC,MAAM,EAAE,kBAAkB;IAItC;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,YAAY;IAiBlD;;OAEG;IACH,cAAc,IAAI,OAAO;CAO1B"}
@@ -0,0 +1,52 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { RegisterClass } from '@memberjunction/global';
11
+ import { BaseAuthProvider } from '../BaseAuthProvider.js';
12
+ /**
13
+ * Microsoft Authentication Library (MSAL) provider implementation
14
+ */
15
+ let MSALProvider = class MSALProvider extends BaseAuthProvider {
16
+ constructor(config) {
17
+ super(config);
18
+ }
19
+ /**
20
+ * Extracts user information from MSAL/Azure AD JWT payload
21
+ */
22
+ extractUserInfo(payload) {
23
+ // MSAL/Azure AD uses some custom claims
24
+ const email = payload.email || payload.preferred_username;
25
+ const fullName = payload.name;
26
+ const firstName = payload.given_name;
27
+ const lastName = payload.family_name;
28
+ const preferredUsername = payload.preferred_username;
29
+ return {
30
+ email,
31
+ firstName: firstName || fullName?.split(' ')[0],
32
+ lastName: lastName || fullName?.split(' ')[1] || fullName?.split(' ')[0],
33
+ fullName,
34
+ preferredUsername
35
+ };
36
+ }
37
+ /**
38
+ * Validates MSAL-specific configuration
39
+ */
40
+ validateConfig() {
41
+ const baseValid = super.validateConfig();
42
+ const hasClientId = !!this.config.clientId;
43
+ const hasTenantId = !!this.config.tenantId;
44
+ return baseValid && hasClientId && hasTenantId;
45
+ }
46
+ };
47
+ MSALProvider = __decorate([
48
+ RegisterClass(BaseAuthProvider, 'msal'),
49
+ __metadata("design:paramtypes", [Object])
50
+ ], MSALProvider);
51
+ export { MSALProvider };
52
+ //# sourceMappingURL=MSALProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MSALProvider.js","sourceRoot":"","sources":["../../src/providers/MSALProvider.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D;;GAEG;AAEI,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,gBAAgB;IAChD,YAAY,MAA0B;QACpC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,OAAmB;QACjC,wCAAwC;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,KAA2B,IAAI,OAAO,CAAC,kBAAwC,CAAC;QACtG,MAAM,QAAQ,GAAG,OAAO,CAAC,IAA0B,CAAC;QACpD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAgC,CAAC;QAC3D,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAiC,CAAC;QAC3D,MAAM,iBAAiB,GAAG,OAAO,CAAC,kBAAwC,CAAC;QAE3E,OAAO;YACL,KAAK;YACL,SAAS,EAAE,SAAS,IAAI,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC/C,QAAQ,EAAE,QAAQ,IAAI,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACxE,QAAQ;YACR,iBAAiB;SAClB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;QACzC,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC3C,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QAE3C,OAAO,SAAS,IAAI,WAAW,IAAI,WAAW,CAAC;IACjD,CAAC;CACF,CAAA;AAnCY,YAAY;IADxB,aAAa,CAAC,gBAAgB,EAAE,MAAM,CAAC;;GAC3B,YAAY,CAmCxB"}
@@ -0,0 +1,18 @@
1
+ import { JwtPayload } from 'jsonwebtoken';
2
+ import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
3
+ import { BaseAuthProvider } from '../BaseAuthProvider.js';
4
+ /**
5
+ * Okta authentication provider implementation
6
+ */
7
+ export declare class OktaProvider extends BaseAuthProvider {
8
+ constructor(config: AuthProviderConfig);
9
+ /**
10
+ * Extracts user information from Okta JWT payload
11
+ */
12
+ extractUserInfo(payload: JwtPayload): AuthUserInfo;
13
+ /**
14
+ * Validates Okta-specific configuration
15
+ */
16
+ validateConfig(): boolean;
17
+ }
18
+ //# sourceMappingURL=OktaProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OktaProvider.d.ts","sourceRoot":"","sources":["../../src/providers/OktaProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D;;GAEG;AACH,qBACa,YAAa,SAAQ,gBAAgB;gBACpC,MAAM,EAAE,kBAAkB;IAItC;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,YAAY;IAiBlD;;OAEG;IACH,cAAc,IAAI,OAAO;CAO1B"}
@@ -0,0 +1,52 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { RegisterClass } from '@memberjunction/global';
11
+ import { BaseAuthProvider } from '../BaseAuthProvider.js';
12
+ /**
13
+ * Okta authentication provider implementation
14
+ */
15
+ let OktaProvider = class OktaProvider extends BaseAuthProvider {
16
+ constructor(config) {
17
+ super(config);
18
+ }
19
+ /**
20
+ * Extracts user information from Okta JWT payload
21
+ */
22
+ extractUserInfo(payload) {
23
+ // Okta uses standard OIDC claims plus some custom ones
24
+ const email = payload.email || payload.preferred_username;
25
+ const fullName = payload.name;
26
+ const firstName = payload.given_name;
27
+ const lastName = payload.family_name;
28
+ const preferredUsername = payload.preferred_username || email;
29
+ return {
30
+ email,
31
+ firstName: firstName || fullName?.split(' ')[0],
32
+ lastName: lastName || fullName?.split(' ')[1] || fullName?.split(' ')[0],
33
+ fullName,
34
+ preferredUsername
35
+ };
36
+ }
37
+ /**
38
+ * Validates Okta-specific configuration
39
+ */
40
+ validateConfig() {
41
+ const baseValid = super.validateConfig();
42
+ const hasClientId = !!this.config.clientId;
43
+ const hasDomain = !!this.config.domain;
44
+ return baseValid && hasClientId && hasDomain;
45
+ }
46
+ };
47
+ OktaProvider = __decorate([
48
+ RegisterClass(BaseAuthProvider, 'okta'),
49
+ __metadata("design:paramtypes", [Object])
50
+ ], OktaProvider);
51
+ export { OktaProvider };
52
+ //# sourceMappingURL=OktaProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OktaProvider.js","sourceRoot":"","sources":["../../src/providers/OktaProvider.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D;;GAEG;AAEI,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,gBAAgB;IAChD,YAAY,MAA0B;QACpC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,OAAmB;QACjC,uDAAuD;QACvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAA2B,IAAI,OAAO,CAAC,kBAAwC,CAAC;QACtG,MAAM,QAAQ,GAAG,OAAO,CAAC,IAA0B,CAAC;QACpD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAgC,CAAC;QAC3D,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAiC,CAAC;QAC3D,MAAM,iBAAiB,GAAG,OAAO,CAAC,kBAAwC,IAAI,KAAK,CAAC;QAEpF,OAAO;YACL,KAAK;YACL,SAAS,EAAE,SAAS,IAAI,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC/C,QAAQ,EAAE,QAAQ,IAAI,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACxE,QAAQ;YACR,iBAAiB;SAClB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;QACzC,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC3C,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAEvC,OAAO,SAAS,IAAI,WAAW,IAAI,SAAS,CAAC;IAC/C,CAAC;CACF,CAAA;AAnCY,YAAY;IADxB,aAAa,CAAC,gBAAgB,EAAE,MAAM,CAAC;;GAC3B,YAAY,CAmCxB"}
@@ -0,0 +1,5 @@
1
+ import { GraphQLError } from 'graphql';
2
+ export declare class TokenExpiredError extends GraphQLError {
3
+ constructor(expiryDate: Date, message?: string);
4
+ }
5
+ //# sourceMappingURL=tokenExpiredError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenExpiredError.d.ts","sourceRoot":"","sources":["../src/tokenExpiredError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,qBAAa,iBAAkB,SAAQ,YAAY;gBACrC,UAAU,EAAE,IAAI,EAAE,OAAO,SAA+D;CAQrG"}
@@ -0,0 +1,12 @@
1
+ import { GraphQLError } from 'graphql';
2
+ export class TokenExpiredError extends GraphQLError {
3
+ constructor(expiryDate, message = 'The provided token has expired. Please authenticate again.') {
4
+ super(message, {
5
+ extensions: {
6
+ code: 'JWT_EXPIRED',
7
+ expiryDate: expiryDate.toISOString(),
8
+ },
9
+ });
10
+ }
11
+ }
12
+ //# sourceMappingURL=tokenExpiredError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenExpiredError.js","sourceRoot":"","sources":["../src/tokenExpiredError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,OAAO,iBAAkB,SAAQ,YAAY;IACjD,YAAY,UAAgB,EAAE,OAAO,GAAG,4DAA4D;QAClG,KAAK,CAAC,OAAO,EAAE;YACb,UAAU,EAAE;gBACV,IAAI,EAAE,aAAa;gBACnB,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE;aACrC;SACF,CAAC,CAAC;IACL,CAAC;CACF"}
package/package.json CHANGED
@@ -1,10 +1,31 @@
1
1
  {
2
2
  "name": "@memberjunction/auth-providers",
3
- "version": "0.0.1",
4
- "description": "OIDC trusted publishing setup package for @memberjunction/auth-providers",
5
- "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
9
- ]
3
+ "version": "5.16.0",
4
+ "description": "Authentication provider interfaces, base classes, and implementations for MemberJunction",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsc && tsc-alias -f",
10
+ "test": "vitest run --passWithNoTests",
11
+ "test:watch": "vitest"
12
+ },
13
+ "dependencies": {
14
+ "@memberjunction/core": "5.16.0",
15
+ "@memberjunction/global": "5.16.0",
16
+ "graphql": "^16.12.0",
17
+ "jsonwebtoken": "9.0.3",
18
+ "jwks-rsa": "^3.2.2"
19
+ },
20
+ "devDependencies": {
21
+ "@types/jsonwebtoken": "9.0.10",
22
+ "@types/node": "24.10.11",
23
+ "tsc-alias": "^1.8.15",
24
+ "typescript": "^5.9.3",
25
+ "vitest": "^4.0.18"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/MemberJunction/MJ"
30
+ }
10
31
  }
@@ -0,0 +1,180 @@
1
+ import { AuthProviderConfig } from '@memberjunction/core';
2
+ import { IAuthProvider } from './IAuthProvider.js';
3
+ import { BaseAuthProvider } from './BaseAuthProvider.js';
4
+ import { MJGlobal, BaseSingleton } from '@memberjunction/global';
5
+
6
+ // Import providers to ensure they're registered
7
+ import './providers/Auth0Provider.js';
8
+ import './providers/MSALProvider.js';
9
+ import './providers/OktaProvider.js';
10
+ import './providers/CognitoProvider.js';
11
+ import './providers/GoogleProvider.js';
12
+
13
+ /**
14
+ * Factory and registry for managing authentication providers
15
+ * Combines provider creation and lifecycle management in a single class
16
+ */
17
+ export class AuthProviderFactory extends BaseSingleton<AuthProviderFactory> {
18
+ private providers: Map<string, IAuthProvider> = new Map();
19
+ private issuerCache: Map<string, IAuthProvider> = new Map();
20
+ private issuerMultiCache: Map<string, IAuthProvider[]> = new Map();
21
+
22
+ public constructor() {
23
+ super();
24
+ }
25
+
26
+ /**
27
+ * Gets the singleton instance of the factory
28
+ */
29
+ public static get Instance(): AuthProviderFactory {
30
+ return AuthProviderFactory.getInstance<AuthProviderFactory>();
31
+ }
32
+
33
+ /**
34
+ * Creates an authentication provider instance based on configuration
35
+ * Uses MJGlobal ClassFactory to instantiate the correct provider class
36
+ */
37
+ static createProvider(config: AuthProviderConfig): IAuthProvider {
38
+ try {
39
+ // Use MJGlobal ClassFactory to create the provider instance
40
+ // The provider type in config should match the key used in @RegisterClass
41
+ // The config is passed as a constructor parameter via the spread operator
42
+ const provider = MJGlobal.Instance.ClassFactory.CreateInstance<BaseAuthProvider>(
43
+ BaseAuthProvider,
44
+ config.type.toLowerCase(),
45
+ config
46
+ );
47
+
48
+ if (!provider) {
49
+ throw new Error(`No provider registered for type: ${config.type}`);
50
+ }
51
+
52
+ return provider;
53
+ } catch (error) {
54
+ const message = error instanceof Error ? error.message : String(error);
55
+ throw new Error(`Failed to create authentication provider for type '${config.type}': ${message}`);
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Registers a new authentication provider
61
+ */
62
+ register(provider: IAuthProvider): void {
63
+ if (!provider.validateConfig()) {
64
+ throw new Error(`Invalid configuration for provider: ${provider.name}`);
65
+ }
66
+
67
+ this.providers.set(provider.name, provider);
68
+
69
+ // Clear issuer caches when registering new provider
70
+ this.issuerCache.clear();
71
+ this.issuerMultiCache.clear();
72
+
73
+ console.log(`Registered auth provider: ${provider.name} with issuer: ${provider.issuer}`);
74
+ }
75
+
76
+ /**
77
+ * Gets a provider by its issuer URL
78
+ */
79
+ getByIssuer(issuer: string): IAuthProvider | undefined {
80
+ // Check cache first
81
+ if (this.issuerCache.has(issuer)) {
82
+ return this.issuerCache.get(issuer);
83
+ }
84
+
85
+ // Search through providers
86
+ for (const provider of this.providers.values()) {
87
+ if (provider.matchesIssuer(issuer)) {
88
+ // Cache for future lookups
89
+ this.issuerCache.set(issuer, provider);
90
+ return provider;
91
+ }
92
+ }
93
+
94
+ return undefined;
95
+ }
96
+
97
+ /**
98
+ * Gets all providers matching an issuer URL.
99
+ * Unlike getByIssuer() which returns only the first match, this returns
100
+ * all providers for a given issuer. This is needed when multiple apps
101
+ * (e.g. MJExplorer + MJCentral) share the same Auth0 domain but have
102
+ * different audiences (client IDs).
103
+ */
104
+ getAllByIssuer(issuer: string): IAuthProvider[] {
105
+ // Check multi-provider cache first
106
+ if (this.issuerMultiCache.has(issuer)) {
107
+ return this.issuerMultiCache.get(issuer)!;
108
+ }
109
+
110
+ const matches: IAuthProvider[] = [];
111
+ for (const provider of this.providers.values()) {
112
+ if (provider.matchesIssuer(issuer)) {
113
+ matches.push(provider);
114
+ }
115
+ }
116
+
117
+ if (matches.length > 0) {
118
+ this.issuerMultiCache.set(issuer, matches);
119
+ }
120
+
121
+ return matches;
122
+ }
123
+
124
+ /**
125
+ * Gets a provider by its name
126
+ */
127
+ getByName(name: string): IAuthProvider | undefined {
128
+ return this.providers.get(name);
129
+ }
130
+
131
+ /**
132
+ * Gets all registered providers
133
+ */
134
+ getAllProviders(): IAuthProvider[] {
135
+ return Array.from(this.providers.values());
136
+ }
137
+
138
+ /**
139
+ * Checks if any providers are registered
140
+ */
141
+ hasProviders(): boolean {
142
+ return this.providers.size > 0;
143
+ }
144
+
145
+ /**
146
+ * Clears all registered providers (useful for testing)
147
+ */
148
+ clear(): void {
149
+ this.providers.clear();
150
+ this.issuerCache.clear();
151
+ this.issuerMultiCache.clear();
152
+ }
153
+
154
+ /**
155
+ * Gets all registered provider types from the ClassFactory
156
+ */
157
+ static getRegisteredProviderTypes(): string[] {
158
+ // Get all registrations for BaseAuthProvider from ClassFactory
159
+ const registrations = MJGlobal.Instance.ClassFactory.GetAllRegistrations(BaseAuthProvider);
160
+ // Extract unique keys (provider types) from registrations
161
+ const providerTypes = registrations
162
+ .map(reg => reg.Key)
163
+ .filter((key): key is string => key !== null && key !== undefined);
164
+ // Return unique provider types
165
+ return Array.from(new Set(providerTypes));
166
+ }
167
+
168
+ /**
169
+ * Checks if a provider type is registered
170
+ */
171
+ static isProviderTypeRegistered(type: string): boolean {
172
+ try {
173
+ // Try to get the registration for this specific type
174
+ const registration = MJGlobal.Instance.ClassFactory.GetRegistration(BaseAuthProvider, type.toLowerCase());
175
+ return registration !== null && registration !== undefined;
176
+ } catch {
177
+ return false;
178
+ }
179
+ }
180
+ }
@@ -0,0 +1,137 @@
1
+ import { JwtHeader, JwtPayload, SigningKeyCallback } from 'jsonwebtoken';
2
+ import jwksClient from 'jwks-rsa';
3
+ import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
4
+ import { IAuthProvider } from './IAuthProvider.js';
5
+ import https from 'https';
6
+ import http from 'http';
7
+
8
+ /**
9
+ * Base implementation of IAuthProvider with common functionality
10
+ * Concrete providers should extend this class and use @RegisterClass decorator
11
+ * with BaseAuthProvider as the base class
12
+ */
13
+ export abstract class BaseAuthProvider implements IAuthProvider {
14
+ name: string;
15
+ issuer: string;
16
+ audience: string;
17
+ jwksUri: string;
18
+ /** OAuth client ID for this provider (used by OAuth proxy for upstream auth) */
19
+ clientId?: string;
20
+ protected config: AuthProviderConfig;
21
+ protected jwksClient: jwksClient.JwksClient;
22
+
23
+ constructor(config: AuthProviderConfig) {
24
+ this.config = config;
25
+ this.name = config.name;
26
+ this.issuer = config.issuer;
27
+ this.audience = config.audience;
28
+ this.jwksUri = config.jwksUri;
29
+ this.clientId = config.clientId;
30
+
31
+ // Create HTTP agent with keep-alive to prevent socket hangups
32
+ const agent = this.jwksUri.startsWith('https')
33
+ ? new https.Agent({
34
+ keepAlive: true,
35
+ keepAliveMsecs: 30000,
36
+ maxSockets: 50,
37
+ maxFreeSockets: 10,
38
+ timeout: 60000
39
+ })
40
+ : new http.Agent({
41
+ keepAlive: true,
42
+ keepAliveMsecs: 30000,
43
+ maxSockets: 50,
44
+ maxFreeSockets: 10,
45
+ timeout: 60000
46
+ });
47
+
48
+ // Initialize JWKS client with connection pooling and extended timeout
49
+ this.jwksClient = jwksClient({
50
+ jwksUri: this.jwksUri,
51
+ cache: true,
52
+ cacheMaxEntries: 5,
53
+ cacheMaxAge: 600000, // 10 minutes
54
+ timeout: 60000, // 60 seconds (increased from default 30s)
55
+ requestAgent: agent
56
+ });
57
+ }
58
+
59
+ /**
60
+ * Validates that required configuration is present
61
+ */
62
+ validateConfig(): boolean {
63
+ return !!(this.name && this.issuer && this.audience && this.jwksUri);
64
+ }
65
+
66
+ /**
67
+ * Gets the signing key for token verification with retry logic
68
+ */
69
+ getSigningKey(header: JwtHeader, callback: SigningKeyCallback): void {
70
+ this.getSigningKeyWithRetry(header, 3, 1000)
71
+ .then((key) => {
72
+ const signingKey = 'publicKey' in key ? key.publicKey : key.rsaPublicKey;
73
+ callback(null, signingKey);
74
+ })
75
+ .catch((err) => {
76
+ console.error(`Error getting signing key for provider ${this.name} after retries:`, err);
77
+ callback(err);
78
+ });
79
+ }
80
+
81
+ /**
82
+ * Retrieves signing key with exponential backoff retry logic
83
+ */
84
+ private async getSigningKeyWithRetry(
85
+ header: JwtHeader,
86
+ maxRetries: number,
87
+ initialDelayMs: number
88
+ ): Promise<jwksClient.SigningKey> {
89
+ let lastError: Error | undefined;
90
+
91
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
92
+ try {
93
+ return await this.jwksClient.getSigningKey(header.kid);
94
+ } catch (err) {
95
+ lastError = err instanceof Error ? err : new Error(String(err));
96
+
97
+ // Check if this is a connection error that's worth retrying
98
+ const isRetryableError =
99
+ lastError.message.includes('socket hang up') ||
100
+ lastError.message.includes('ECONNRESET') ||
101
+ lastError.message.includes('ETIMEDOUT') ||
102
+ lastError.message.includes('ENOTFOUND') ||
103
+ lastError.message.includes('EAI_AGAIN');
104
+
105
+ if (!isRetryableError || attempt === maxRetries) {
106
+ throw lastError;
107
+ }
108
+
109
+ // Exponential backoff: wait longer between each retry
110
+ const delayMs = initialDelayMs * Math.pow(2, attempt);
111
+ console.warn(
112
+ `Attempt ${attempt + 1}/${maxRetries + 1} failed for provider ${this.name}. ` +
113
+ `Retrying in ${delayMs}ms... Error: ${lastError.message}`
114
+ );
115
+
116
+ await new Promise(resolve => setTimeout(resolve, delayMs));
117
+ }
118
+ }
119
+
120
+ throw lastError || new Error('Failed to retrieve signing key');
121
+ }
122
+
123
+ /**
124
+ * Checks if a given issuer URL belongs to this provider
125
+ */
126
+ matchesIssuer(issuer: string): boolean {
127
+ // Handle trailing slashes and case sensitivity
128
+ const normalizedIssuer = issuer.toLowerCase().replace(/\/$/, '');
129
+ const normalizedProviderIssuer = this.issuer.toLowerCase().replace(/\/$/, '');
130
+ return normalizedIssuer === normalizedProviderIssuer;
131
+ }
132
+
133
+ /**
134
+ * Abstract method for extracting user info - must be implemented by each provider
135
+ */
136
+ abstract extractUserInfo(payload: JwtPayload): AuthUserInfo;
137
+ }