@memberjunction/server 5.15.0 → 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 (70) hide show
  1. package/dist/auth/index.d.ts +0 -3
  2. package/dist/auth/index.d.ts.map +1 -1
  3. package/dist/auth/index.js +5 -7
  4. package/dist/auth/index.js.map +1 -1
  5. package/dist/auth/initializeProviders.js +2 -2
  6. package/dist/auth/initializeProviders.js.map +1 -1
  7. package/dist/context.d.ts.map +1 -1
  8. package/dist/context.js +3 -3
  9. package/dist/context.js.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +16 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/resolvers/DatasetResolver.d.ts +5 -0
  15. package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
  16. package/dist/resolvers/DatasetResolver.js +35 -0
  17. package/dist/resolvers/DatasetResolver.js.map +1 -1
  18. package/package.json +60 -59
  19. package/src/__tests__/unifiedAuth.test.ts +3 -2
  20. package/src/auth/__tests__/backward-compatibility.test.ts +2 -3
  21. package/src/auth/index.ts +5 -8
  22. package/src/auth/initializeProviders.ts +2 -2
  23. package/src/context.ts +3 -3
  24. package/src/index.ts +21 -3
  25. package/src/resolvers/DatasetResolver.ts +36 -0
  26. package/dist/auth/AuthProviderFactory.d.ts +0 -68
  27. package/dist/auth/AuthProviderFactory.d.ts.map +0 -1
  28. package/dist/auth/AuthProviderFactory.js +0 -155
  29. package/dist/auth/AuthProviderFactory.js.map +0 -1
  30. package/dist/auth/BaseAuthProvider.d.ts +0 -41
  31. package/dist/auth/BaseAuthProvider.d.ts.map +0 -1
  32. package/dist/auth/BaseAuthProvider.js +0 -102
  33. package/dist/auth/BaseAuthProvider.js.map +0 -1
  34. package/dist/auth/IAuthProvider.d.ts +0 -46
  35. package/dist/auth/IAuthProvider.d.ts.map +0 -1
  36. package/dist/auth/IAuthProvider.js +0 -2
  37. package/dist/auth/IAuthProvider.js.map +0 -1
  38. package/dist/auth/providers/Auth0Provider.d.ts +0 -18
  39. package/dist/auth/providers/Auth0Provider.d.ts.map +0 -1
  40. package/dist/auth/providers/Auth0Provider.js +0 -52
  41. package/dist/auth/providers/Auth0Provider.js.map +0 -1
  42. package/dist/auth/providers/CognitoProvider.d.ts +0 -18
  43. package/dist/auth/providers/CognitoProvider.d.ts.map +0 -1
  44. package/dist/auth/providers/CognitoProvider.js +0 -56
  45. package/dist/auth/providers/CognitoProvider.js.map +0 -1
  46. package/dist/auth/providers/GoogleProvider.d.ts +0 -18
  47. package/dist/auth/providers/GoogleProvider.d.ts.map +0 -1
  48. package/dist/auth/providers/GoogleProvider.js +0 -51
  49. package/dist/auth/providers/GoogleProvider.js.map +0 -1
  50. package/dist/auth/providers/MSALProvider.d.ts +0 -18
  51. package/dist/auth/providers/MSALProvider.d.ts.map +0 -1
  52. package/dist/auth/providers/MSALProvider.js +0 -52
  53. package/dist/auth/providers/MSALProvider.js.map +0 -1
  54. package/dist/auth/providers/OktaProvider.d.ts +0 -18
  55. package/dist/auth/providers/OktaProvider.d.ts.map +0 -1
  56. package/dist/auth/providers/OktaProvider.js +0 -52
  57. package/dist/auth/providers/OktaProvider.js.map +0 -1
  58. package/dist/auth/tokenExpiredError.d.ts +0 -5
  59. package/dist/auth/tokenExpiredError.d.ts.map +0 -1
  60. package/dist/auth/tokenExpiredError.js +0 -12
  61. package/dist/auth/tokenExpiredError.js.map +0 -1
  62. package/src/auth/AuthProviderFactory.ts +0 -182
  63. package/src/auth/BaseAuthProvider.ts +0 -137
  64. package/src/auth/IAuthProvider.ts +0 -54
  65. package/src/auth/providers/Auth0Provider.ts +0 -45
  66. package/src/auth/providers/CognitoProvider.ts +0 -50
  67. package/src/auth/providers/GoogleProvider.ts +0 -45
  68. package/src/auth/providers/MSALProvider.ts +0 -45
  69. package/src/auth/providers/OktaProvider.ts +0 -46
  70. package/src/auth/tokenExpiredError.ts +0 -12
@@ -1,12 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"tokenExpiredError.js","sourceRoot":"","sources":["../../src/auth/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"}
@@ -1,182 +0,0 @@
1
- import { AuthProviderConfig } from '@memberjunction/core';
2
- import { IAuthProvider } from './IAuthProvider.js';
3
- import { BaseAuthProvider } from './BaseAuthProvider.js';
4
- import { MJGlobal } 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 {
18
- private static instance: AuthProviderFactory;
19
- private providers: Map<string, IAuthProvider> = new Map();
20
- private issuerCache: Map<string, IAuthProvider> = new Map();
21
- private issuerMultiCache: Map<string, IAuthProvider[]> = new Map();
22
-
23
- private constructor() {}
24
-
25
- /**
26
- * Gets the singleton instance of the factory
27
- */
28
- static getInstance(): AuthProviderFactory {
29
- if (!AuthProviderFactory.instance) {
30
- AuthProviderFactory.instance = new AuthProviderFactory();
31
- }
32
- return AuthProviderFactory.instance;
33
- }
34
-
35
- /**
36
- * Creates an authentication provider instance based on configuration
37
- * Uses MJGlobal ClassFactory to instantiate the correct provider class
38
- */
39
- static createProvider(config: AuthProviderConfig): IAuthProvider {
40
- try {
41
- // Use MJGlobal ClassFactory to create the provider instance
42
- // The provider type in config should match the key used in @RegisterClass
43
- // The config is passed as a constructor parameter via the spread operator
44
- const provider = MJGlobal.Instance.ClassFactory.CreateInstance<BaseAuthProvider>(
45
- BaseAuthProvider,
46
- config.type.toLowerCase(),
47
- config
48
- );
49
-
50
- if (!provider) {
51
- throw new Error(`No provider registered for type: ${config.type}`);
52
- }
53
-
54
- return provider;
55
- } catch (error) {
56
- const message = error instanceof Error ? error.message : String(error);
57
- throw new Error(`Failed to create authentication provider for type '${config.type}': ${message}`);
58
- }
59
- }
60
-
61
- /**
62
- * Registers a new authentication provider
63
- */
64
- register(provider: IAuthProvider): void {
65
- if (!provider.validateConfig()) {
66
- throw new Error(`Invalid configuration for provider: ${provider.name}`);
67
- }
68
-
69
- this.providers.set(provider.name, provider);
70
-
71
- // Clear issuer caches when registering new provider
72
- this.issuerCache.clear();
73
- this.issuerMultiCache.clear();
74
-
75
- console.log(`Registered auth provider: ${provider.name} with issuer: ${provider.issuer}`);
76
- }
77
-
78
- /**
79
- * Gets a provider by its issuer URL
80
- */
81
- getByIssuer(issuer: string): IAuthProvider | undefined {
82
- // Check cache first
83
- if (this.issuerCache.has(issuer)) {
84
- return this.issuerCache.get(issuer);
85
- }
86
-
87
- // Search through providers
88
- for (const provider of this.providers.values()) {
89
- if (provider.matchesIssuer(issuer)) {
90
- // Cache for future lookups
91
- this.issuerCache.set(issuer, provider);
92
- return provider;
93
- }
94
- }
95
-
96
- return undefined;
97
- }
98
-
99
- /**
100
- * Gets all providers matching an issuer URL.
101
- * Unlike getByIssuer() which returns only the first match, this returns
102
- * all providers for a given issuer. This is needed when multiple apps
103
- * (e.g. MJExplorer + MJCentral) share the same Auth0 domain but have
104
- * different audiences (client IDs).
105
- */
106
- getAllByIssuer(issuer: string): IAuthProvider[] {
107
- // Check multi-provider cache first
108
- if (this.issuerMultiCache.has(issuer)) {
109
- return this.issuerMultiCache.get(issuer)!;
110
- }
111
-
112
- const matches: IAuthProvider[] = [];
113
- for (const provider of this.providers.values()) {
114
- if (provider.matchesIssuer(issuer)) {
115
- matches.push(provider);
116
- }
117
- }
118
-
119
- if (matches.length > 0) {
120
- this.issuerMultiCache.set(issuer, matches);
121
- }
122
-
123
- return matches;
124
- }
125
-
126
- /**
127
- * Gets a provider by its name
128
- */
129
- getByName(name: string): IAuthProvider | undefined {
130
- return this.providers.get(name);
131
- }
132
-
133
- /**
134
- * Gets all registered providers
135
- */
136
- getAllProviders(): IAuthProvider[] {
137
- return Array.from(this.providers.values());
138
- }
139
-
140
- /**
141
- * Checks if any providers are registered
142
- */
143
- hasProviders(): boolean {
144
- return this.providers.size > 0;
145
- }
146
-
147
- /**
148
- * Clears all registered providers (useful for testing)
149
- */
150
- clear(): void {
151
- this.providers.clear();
152
- this.issuerCache.clear();
153
- this.issuerMultiCache.clear();
154
- }
155
-
156
- /**
157
- * Gets all registered provider types from the ClassFactory
158
- */
159
- static getRegisteredProviderTypes(): string[] {
160
- // Get all registrations for BaseAuthProvider from ClassFactory
161
- const registrations = MJGlobal.Instance.ClassFactory.GetAllRegistrations(BaseAuthProvider);
162
- // Extract unique keys (provider types) from registrations
163
- const providerTypes = registrations
164
- .map(reg => reg.Key)
165
- .filter((key): key is string => key !== null && key !== undefined);
166
- // Return unique provider types
167
- return Array.from(new Set(providerTypes));
168
- }
169
-
170
- /**
171
- * Checks if a provider type is registered
172
- */
173
- static isProviderTypeRegistered(type: string): boolean {
174
- try {
175
- // Try to get the registration for this specific type
176
- const registration = MJGlobal.Instance.ClassFactory.GetRegistration(BaseAuthProvider, type.toLowerCase());
177
- return registration !== null && registration !== undefined;
178
- } catch {
179
- return false;
180
- }
181
- }
182
- }
@@ -1,137 +0,0 @@
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
- }
@@ -1,54 +0,0 @@
1
- import { JwtHeader, JwtPayload, SigningKeyCallback } from 'jsonwebtoken';
2
- import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
3
-
4
- /**
5
- * Interface for authentication providers in MemberJunction
6
- * Enables support for any OAuth 2.0/OIDC compliant provider
7
- */
8
- export interface IAuthProvider {
9
- /**
10
- * Unique name identifier for this provider
11
- */
12
- name: string;
13
-
14
- /**
15
- * The issuer URL for this provider (must match the 'iss' claim in tokens)
16
- */
17
- issuer: string;
18
-
19
- /**
20
- * The expected audience for tokens from this provider
21
- */
22
- audience: string;
23
-
24
- /**
25
- * The JWKS endpoint URL for retrieving signing keys
26
- */
27
- jwksUri: string;
28
-
29
- /**
30
- * OAuth client ID for this provider (optional, used by OAuth proxy for upstream authentication)
31
- */
32
- clientId?: string;
33
-
34
- /**
35
- * Validates that the provider configuration is complete and valid
36
- */
37
- validateConfig(): boolean;
38
-
39
- /**
40
- * Gets the signing key for token verification
41
- */
42
- getSigningKey(header: JwtHeader, callback: SigningKeyCallback): void;
43
-
44
- /**
45
- * Extracts user information from the JWT payload
46
- * Different providers use different claim names
47
- */
48
- extractUserInfo(payload: JwtPayload): AuthUserInfo;
49
-
50
- /**
51
- * Checks if a given issuer URL belongs to this provider
52
- */
53
- matchesIssuer(issuer: string): boolean;
54
- }
@@ -1,45 +0,0 @@
1
- import { JwtPayload } from 'jsonwebtoken';
2
- import { RegisterClass } from '@memberjunction/global';
3
- import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
4
- import { BaseAuthProvider } from '../BaseAuthProvider.js';
5
-
6
- /**
7
- * Auth0 authentication provider implementation
8
- */
9
- @RegisterClass(BaseAuthProvider, 'auth0')
10
- export class Auth0Provider extends BaseAuthProvider {
11
- constructor(config: AuthProviderConfig) {
12
- super(config);
13
- }
14
-
15
- /**
16
- * Extracts user information from Auth0 JWT payload
17
- */
18
- extractUserInfo(payload: JwtPayload): AuthUserInfo {
19
- // Auth0 uses standard OIDC claims
20
- const email = payload.email as string | undefined;
21
- const fullName = payload.name as string | undefined;
22
- const firstName = payload.given_name as string | undefined;
23
- const lastName = payload.family_name as string | undefined;
24
- const preferredUsername = payload.preferred_username as string | undefined || email;
25
-
26
- return {
27
- email,
28
- firstName: firstName || fullName?.split(' ')[0],
29
- lastName: lastName || fullName?.split(' ')[1] || fullName?.split(' ')[0],
30
- fullName,
31
- preferredUsername
32
- };
33
- }
34
-
35
- /**
36
- * Validates Auth0-specific configuration
37
- */
38
- validateConfig(): boolean {
39
- const baseValid = super.validateConfig();
40
- const hasClientId = !!this.config.clientId;
41
- const hasDomain = !!this.config.domain;
42
-
43
- return baseValid && hasClientId && hasDomain;
44
- }
45
- }
@@ -1,50 +0,0 @@
1
- import { JwtPayload } from 'jsonwebtoken';
2
- import { RegisterClass } from '@memberjunction/global';
3
- import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
4
- import { BaseAuthProvider } from '../BaseAuthProvider.js';
5
-
6
-
7
- /**
8
- * AWS Cognito authentication provider implementation
9
- */
10
- @RegisterClass(BaseAuthProvider, 'cognito')
11
- export class CognitoProvider extends BaseAuthProvider {
12
- constructor(config: AuthProviderConfig) {
13
- super(config);
14
- }
15
-
16
- /**
17
- * Extracts user information from Cognito JWT payload
18
- */
19
- extractUserInfo(payload: JwtPayload): AuthUserInfo {
20
- // Cognito uses custom claims with 'cognito:' prefix for some fields
21
- const email = payload.email as string | undefined ||
22
- payload['cognito:username'] as string | undefined;
23
- const fullName = payload.name as string | undefined;
24
- const firstName = payload.given_name as string | undefined;
25
- const lastName = payload.family_name as string | undefined;
26
- const preferredUsername = payload['cognito:username'] as string | undefined ||
27
- payload.preferred_username as string | undefined ||
28
- email;
29
-
30
- return {
31
- email,
32
- firstName: firstName || fullName?.split(' ')[0],
33
- lastName: lastName || fullName?.split(' ')[1] || fullName?.split(' ')[0],
34
- fullName,
35
- preferredUsername
36
- };
37
- }
38
-
39
- /**
40
- * Validates Cognito-specific configuration
41
- */
42
- validateConfig(): boolean {
43
- const baseValid = super.validateConfig();
44
- const hasClientId = !!this.config.clientId;
45
- const hasRegion = !!this.config.region;
46
- const hasUserPoolId = !!this.config.userPoolId;
47
-
48
- return baseValid && hasClientId && hasRegion && hasUserPoolId;
49
- }
50
- }
@@ -1,45 +0,0 @@
1
- import { JwtPayload } from 'jsonwebtoken';
2
- import { RegisterClass } from '@memberjunction/global';
3
- import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
4
- import { BaseAuthProvider } from '../BaseAuthProvider.js';
5
-
6
-
7
- /**
8
- * Google Identity Platform authentication provider implementation
9
- */
10
- @RegisterClass(BaseAuthProvider, 'google')
11
- export class GoogleProvider extends BaseAuthProvider {
12
- constructor(config: AuthProviderConfig) {
13
- super(config);
14
- }
15
-
16
- /**
17
- * Extracts user information from Google JWT payload
18
- */
19
- extractUserInfo(payload: JwtPayload): AuthUserInfo {
20
- // Google uses standard OIDC claims
21
- const email = payload.email as string | undefined;
22
- const fullName = payload.name as string | undefined;
23
- const firstName = payload.given_name as string | undefined;
24
- const lastName = payload.family_name as string | undefined;
25
- const preferredUsername = email; // Google typically uses email as username
26
-
27
- return {
28
- email,
29
- firstName: firstName || fullName?.split(' ')[0],
30
- lastName: lastName || fullName?.split(' ')[1] || fullName?.split(' ')[0],
31
- fullName,
32
- preferredUsername
33
- };
34
- }
35
-
36
- /**
37
- * Validates Google-specific configuration
38
- */
39
- validateConfig(): boolean {
40
- const baseValid = super.validateConfig();
41
- const hasClientId = !!this.config.clientId;
42
-
43
- return baseValid && hasClientId;
44
- }
45
- }
@@ -1,45 +0,0 @@
1
- import { JwtPayload } from 'jsonwebtoken';
2
- import { RegisterClass } from '@memberjunction/global';
3
- import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
4
- import { BaseAuthProvider } from '../BaseAuthProvider.js';
5
-
6
- /**
7
- * Microsoft Authentication Library (MSAL) provider implementation
8
- */
9
- @RegisterClass(BaseAuthProvider, 'msal')
10
- export class MSALProvider extends BaseAuthProvider {
11
- constructor(config: AuthProviderConfig) {
12
- super(config);
13
- }
14
-
15
- /**
16
- * Extracts user information from MSAL/Azure AD JWT payload
17
- */
18
- extractUserInfo(payload: JwtPayload): AuthUserInfo {
19
- // MSAL/Azure AD uses some custom claims
20
- const email = payload.email as string | undefined || payload.preferred_username as string | undefined;
21
- const fullName = payload.name as string | undefined;
22
- const firstName = payload.given_name as string | undefined;
23
- const lastName = payload.family_name as string | undefined;
24
- const preferredUsername = payload.preferred_username as string | undefined;
25
-
26
- return {
27
- email,
28
- firstName: firstName || fullName?.split(' ')[0],
29
- lastName: lastName || fullName?.split(' ')[1] || fullName?.split(' ')[0],
30
- fullName,
31
- preferredUsername
32
- };
33
- }
34
-
35
- /**
36
- * Validates MSAL-specific configuration
37
- */
38
- validateConfig(): boolean {
39
- const baseValid = super.validateConfig();
40
- const hasClientId = !!this.config.clientId;
41
- const hasTenantId = !!this.config.tenantId;
42
-
43
- return baseValid && hasClientId && hasTenantId;
44
- }
45
- }
@@ -1,46 +0,0 @@
1
- import { JwtPayload } from 'jsonwebtoken';
2
- import { RegisterClass } from '@memberjunction/global';
3
- import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
4
- import { BaseAuthProvider } from '../BaseAuthProvider.js';
5
-
6
-
7
- /**
8
- * Okta authentication provider implementation
9
- */
10
- @RegisterClass(BaseAuthProvider, 'okta')
11
- export class OktaProvider extends BaseAuthProvider {
12
- constructor(config: AuthProviderConfig) {
13
- super(config);
14
- }
15
-
16
- /**
17
- * Extracts user information from Okta JWT payload
18
- */
19
- extractUserInfo(payload: JwtPayload): AuthUserInfo {
20
- // Okta uses standard OIDC claims plus some custom ones
21
- const email = payload.email as string | undefined || payload.preferred_username as string | undefined;
22
- const fullName = payload.name as string | undefined;
23
- const firstName = payload.given_name as string | undefined;
24
- const lastName = payload.family_name as string | undefined;
25
- const preferredUsername = payload.preferred_username as string | undefined || email;
26
-
27
- return {
28
- email,
29
- firstName: firstName || fullName?.split(' ')[0],
30
- lastName: lastName || fullName?.split(' ')[1] || fullName?.split(' ')[0],
31
- fullName,
32
- preferredUsername
33
- };
34
- }
35
-
36
- /**
37
- * Validates Okta-specific configuration
38
- */
39
- validateConfig(): boolean {
40
- const baseValid = super.validateConfig();
41
- const hasClientId = !!this.config.clientId;
42
- const hasDomain = !!this.config.domain;
43
-
44
- return baseValid && hasClientId && hasDomain;
45
- }
46
- }
@@ -1,12 +0,0 @@
1
- import { GraphQLError } from 'graphql';
2
-
3
- export class TokenExpiredError extends GraphQLError {
4
- constructor(expiryDate: Date, message = 'The provided token has expired. Please authenticate again.') {
5
- super(message, {
6
- extensions: {
7
- code: 'JWT_EXPIRED',
8
- expiryDate: expiryDate.toISOString(),
9
- },
10
- });
11
- }
12
- }