@memberjunction/server 2.90.0 → 2.91.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/AuthProviderFactory.d.ts +24 -0
- package/dist/auth/AuthProviderFactory.d.ts.map +1 -0
- package/dist/auth/AuthProviderFactory.js +82 -0
- package/dist/auth/AuthProviderFactory.js.map +1 -0
- package/dist/auth/BaseAuthProvider.d.ts +18 -0
- package/dist/auth/BaseAuthProvider.d.ts.map +1 -0
- package/dist/auth/BaseAuthProvider.js +42 -0
- package/dist/auth/BaseAuthProvider.js.map +1 -0
- package/dist/auth/IAuthProvider.d.ts +13 -0
- package/dist/auth/IAuthProvider.d.ts.map +1 -0
- package/dist/auth/IAuthProvider.js +2 -0
- package/dist/auth/IAuthProvider.js.map +1 -0
- package/dist/auth/__tests__/backward-compatibility.test.d.ts +2 -0
- package/dist/auth/__tests__/backward-compatibility.test.d.ts.map +1 -0
- package/dist/auth/__tests__/backward-compatibility.test.js +135 -0
- package/dist/auth/__tests__/backward-compatibility.test.js.map +1 -0
- package/dist/auth/index.d.ts +22 -7
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +65 -32
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.d.ts +2 -0
- package/dist/auth/initializeProviders.d.ts.map +1 -0
- package/dist/auth/initializeProviders.js +23 -0
- package/dist/auth/initializeProviders.js.map +1 -0
- package/dist/auth/providers/Auth0Provider.d.ts +9 -0
- package/dist/auth/providers/Auth0Provider.d.ts.map +1 -0
- package/dist/auth/providers/Auth0Provider.js +42 -0
- package/dist/auth/providers/Auth0Provider.js.map +1 -0
- package/dist/auth/providers/CognitoProvider.d.ts +9 -0
- package/dist/auth/providers/CognitoProvider.d.ts.map +1 -0
- package/dist/auth/providers/CognitoProvider.js +46 -0
- package/dist/auth/providers/CognitoProvider.js.map +1 -0
- package/dist/auth/providers/GoogleProvider.d.ts +9 -0
- package/dist/auth/providers/GoogleProvider.d.ts.map +1 -0
- package/dist/auth/providers/GoogleProvider.js +41 -0
- package/dist/auth/providers/GoogleProvider.js.map +1 -0
- package/dist/auth/providers/MSALProvider.d.ts +9 -0
- package/dist/auth/providers/MSALProvider.d.ts.map +1 -0
- package/dist/auth/providers/MSALProvider.js +42 -0
- package/dist/auth/providers/MSALProvider.js.map +1 -0
- package/dist/auth/providers/OktaProvider.d.ts +9 -0
- package/dist/auth/providers/OktaProvider.d.ts.map +1 -0
- package/dist/auth/providers/OktaProvider.js +42 -0
- package/dist/auth/providers/OktaProvider.js.map +1 -0
- package/dist/config.d.ts +97 -21
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -6
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +25 -17
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +3 -0
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +16 -0
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +1 -1
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +5 -4
- package/dist/generic/ResolverBase.js.map +1 -1
- package/package.json +39 -39
- package/src/auth/AuthProviderFactory.ts +152 -0
- package/src/auth/BaseAuthProvider.ts +71 -0
- package/src/auth/IAuthProvider.ts +49 -0
- package/src/auth/__tests__/backward-compatibility.test.ts +183 -0
- package/src/auth/index.ts +104 -36
- package/src/auth/initializeProviders.ts +31 -0
- package/src/auth/providers/Auth0Provider.ts +45 -0
- package/src/auth/providers/CognitoProvider.ts +50 -0
- package/src/auth/providers/GoogleProvider.ts +45 -0
- package/src/auth/providers/MSALProvider.ts +45 -0
- package/src/auth/providers/OktaProvider.ts +46 -0
- package/src/config.ts +14 -10
- package/src/context.ts +40 -17
- package/src/generated/generated.ts +10 -0
- package/src/generic/ResolverBase.ts +9 -4
package/src/config.ts
CHANGED
|
@@ -102,6 +102,18 @@ const sqlLoggingSchema = z.object({
|
|
|
102
102
|
sessionTimeout: z.number().optional().default(3600000), // 1 hour
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
+
const authProviderSchema = z.object({
|
|
106
|
+
name: z.string(),
|
|
107
|
+
type: z.string(),
|
|
108
|
+
issuer: z.string(),
|
|
109
|
+
audience: z.string(),
|
|
110
|
+
jwksUri: z.string(),
|
|
111
|
+
clientId: z.string().optional(),
|
|
112
|
+
clientSecret: z.string().optional(),
|
|
113
|
+
tenantId: z.string().optional(),
|
|
114
|
+
domain: z.string().optional(),
|
|
115
|
+
}).passthrough(); // Allow additional provider-specific fields
|
|
116
|
+
|
|
105
117
|
const configInfoSchema = z.object({
|
|
106
118
|
userHandling: userHandlingInfoSchema,
|
|
107
119
|
databaseSettings: databaseSettingsInfoSchema,
|
|
@@ -109,6 +121,7 @@ const configInfoSchema = z.object({
|
|
|
109
121
|
restApiOptions: restApiOptionsSchema.optional().default({}),
|
|
110
122
|
askSkip: askSkipInfoSchema.optional(),
|
|
111
123
|
sqlLogging: sqlLoggingSchema.optional(),
|
|
124
|
+
authProviders: z.array(authProviderSchema).optional(),
|
|
112
125
|
|
|
113
126
|
apiKey: z.string().optional(),
|
|
114
127
|
baseUrl: z.string().default('http://localhost'),
|
|
@@ -131,17 +144,12 @@ const configInfoSchema = z.object({
|
|
|
131
144
|
___codeGenAPIPort: z.coerce.number().optional().default(3999),
|
|
132
145
|
___codeGenAPISubmissionDelay: z.coerce.number().optional().default(5000),
|
|
133
146
|
graphqlRootPath: z.string().optional().default('/'),
|
|
134
|
-
webClientID: z.string().optional(),
|
|
135
|
-
tenantID: z.string().optional(),
|
|
136
147
|
enableIntrospection: z.coerce.boolean().optional().default(false),
|
|
137
148
|
websiteRunFromPackage: z.coerce.number().optional(),
|
|
138
149
|
userEmailMap: z
|
|
139
150
|
.string()
|
|
140
151
|
.transform((val) => z.record(z.string()).parse(JSON.parse(val)))
|
|
141
152
|
.optional(),
|
|
142
|
-
auth0Domain: z.string().optional(),
|
|
143
|
-
auth0WebClientID: z.string().optional(),
|
|
144
|
-
auth0ClientSecret: z.string().optional(),
|
|
145
153
|
mjCoreSchema: z.string(),
|
|
146
154
|
});
|
|
147
155
|
|
|
@@ -152,6 +160,7 @@ export type RESTApiOptions = z.infer<typeof restApiOptionsSchema>;
|
|
|
152
160
|
export type AskSkipInfo = z.infer<typeof askSkipInfoSchema>;
|
|
153
161
|
export type SqlLoggingOptions = z.infer<typeof sqlLoggingOptionsSchema>;
|
|
154
162
|
export type SqlLoggingInfo = z.infer<typeof sqlLoggingSchema>;
|
|
163
|
+
export type AuthProviderConfig = z.infer<typeof authProviderSchema>;
|
|
155
164
|
export type ConfigInfo = z.infer<typeof configInfoSchema>;
|
|
156
165
|
|
|
157
166
|
export const configInfo: ConfigInfo = loadConfig();
|
|
@@ -169,14 +178,9 @@ export const {
|
|
|
169
178
|
___codeGenAPIPort,
|
|
170
179
|
___codeGenAPISubmissionDelay,
|
|
171
180
|
graphqlRootPath,
|
|
172
|
-
webClientID,
|
|
173
|
-
tenantID,
|
|
174
181
|
enableIntrospection,
|
|
175
182
|
websiteRunFromPackage,
|
|
176
183
|
userEmailMap,
|
|
177
|
-
auth0Domain,
|
|
178
|
-
auth0WebClientID,
|
|
179
|
-
auth0ClientSecret,
|
|
180
184
|
apiKey,
|
|
181
185
|
baseUrl,
|
|
182
186
|
mjCoreSchema: mj_core_schema,
|
package/src/context.ts
CHANGED
|
@@ -5,24 +5,33 @@ import 'reflect-metadata';
|
|
|
5
5
|
import { Subject, firstValueFrom } from 'rxjs';
|
|
6
6
|
import { AuthenticationError, AuthorizationError } from 'type-graphql';
|
|
7
7
|
import sql from 'mssql';
|
|
8
|
-
import { getSigningKeys, getSystemUser,
|
|
8
|
+
import { getSigningKeys, getSystemUser, getValidationOptions, verifyUserRecord, extractUserInfoFromPayload, TokenExpiredError } from './auth/index.js';
|
|
9
9
|
import { authCache } from './cache.js';
|
|
10
10
|
import { userEmailMap, apiKey, mj_core_schema } from './config.js';
|
|
11
11
|
import { DataSourceInfo, UserPayload } from './types.js';
|
|
12
|
-
import { TokenExpiredError } from './auth/index.js';
|
|
13
12
|
import { GetReadOnlyDataSource, GetReadWriteDataSource } from './util.js';
|
|
14
13
|
import { v4 as uuidv4 } from 'uuid';
|
|
15
14
|
import e from 'express';
|
|
16
15
|
import { DatabaseProviderBase } from '@memberjunction/core';
|
|
17
16
|
import { SQLServerDataProvider, SQLServerProviderConfigData } from '@memberjunction/sqlserver-dataprovider';
|
|
17
|
+
import { AuthProviderFactory } from './auth/AuthProviderFactory.js';
|
|
18
18
|
|
|
19
|
-
const verifyAsync = async (issuer: string,
|
|
19
|
+
const verifyAsync = async (issuer: string, token: string): Promise<jwt.JwtPayload> =>
|
|
20
20
|
new Promise((resolve, reject) => {
|
|
21
|
+
const options = getValidationOptions(issuer);
|
|
22
|
+
|
|
23
|
+
if (!options) {
|
|
24
|
+
reject(new Error(`No validation options found for issuer ${issuer}`));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
jwt.verify(token, getSigningKeys(issuer), options, (err, jwt) => {
|
|
22
29
|
if (jwt && typeof jwt !== 'string' && !err) {
|
|
23
30
|
const payload = jwt.payload ?? jwt;
|
|
24
31
|
|
|
25
|
-
|
|
32
|
+
// Use provider to extract user info for logging
|
|
33
|
+
const userInfo = extractUserInfoFromPayload(payload);
|
|
34
|
+
console.log(`Valid token: ${userInfo.fullName || 'Unknown'} (${userInfo.email || userInfo.preferredUsername || 'Unknown'})`);
|
|
26
35
|
resolve(payload);
|
|
27
36
|
} else {
|
|
28
37
|
console.warn('Invalid token');
|
|
@@ -81,15 +90,28 @@ export const getUserPayload = async (
|
|
|
81
90
|
throw new AuthenticationError('Missing issuer claim on token');
|
|
82
91
|
}
|
|
83
92
|
|
|
84
|
-
|
|
93
|
+
// Verify issuer is supported
|
|
94
|
+
const factory = AuthProviderFactory.getInstance();
|
|
95
|
+
if (!factory.getByIssuer(issuer)) {
|
|
96
|
+
console.warn(`Unsupported issuer: ${issuer}`);
|
|
97
|
+
throw new AuthenticationError(`Unsupported authentication provider: ${issuer}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
await verifyAsync(issuer, token);
|
|
85
101
|
authCache.set(token, true);
|
|
86
102
|
}
|
|
87
103
|
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
const userRecord = await verifyUserRecord(
|
|
104
|
+
// Use provider to extract user information
|
|
105
|
+
const userInfo = extractUserInfoFromPayload(payload);
|
|
106
|
+
const email = userInfo.email ? ((userEmailMap ?? {})[userInfo.email] ?? userInfo.email) : userInfo.preferredUsername;
|
|
107
|
+
|
|
108
|
+
const userRecord = await verifyUserRecord(
|
|
109
|
+
email,
|
|
110
|
+
userInfo.firstName,
|
|
111
|
+
userInfo.lastName,
|
|
112
|
+
requestDomain,
|
|
113
|
+
readWriteDataSource
|
|
114
|
+
);
|
|
93
115
|
|
|
94
116
|
if (!userRecord) {
|
|
95
117
|
console.error(`User ${email} not found`);
|
|
@@ -99,12 +121,13 @@ export const getUserPayload = async (
|
|
|
99
121
|
throw new AuthorizationError();
|
|
100
122
|
}
|
|
101
123
|
|
|
102
|
-
return { userRecord, email, sessionId };
|
|
103
|
-
} catch (
|
|
104
|
-
console.error(
|
|
105
|
-
if (
|
|
106
|
-
throw
|
|
107
|
-
}
|
|
124
|
+
return { userRecord, email: userRecord.Email, sessionId };
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error(error);
|
|
127
|
+
if (error instanceof TokenExpiredError) {
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
throw new AuthenticationError('Unable to authenticate user');
|
|
108
131
|
}
|
|
109
132
|
};
|
|
110
133
|
|
|
@@ -171,4 +194,4 @@ export const contextFunction =
|
|
|
171
194
|
};
|
|
172
195
|
|
|
173
196
|
return contextResult;
|
|
174
|
-
};
|
|
197
|
+
};
|
|
@@ -39135,6 +39135,10 @@ export class ComponentLibrary_ {
|
|
|
39135
39135
|
@MaxLength(10)
|
|
39136
39136
|
_mj__UpdatedAt: Date;
|
|
39137
39137
|
|
|
39138
|
+
@Field({description: `Status of the component library. Active: fully supported; Deprecated: works but shows console warning; Disabled: throws error if used`})
|
|
39139
|
+
@MaxLength(40)
|
|
39140
|
+
Status: string;
|
|
39141
|
+
|
|
39138
39142
|
@Field(() => [ComponentLibraryLink_])
|
|
39139
39143
|
MJ_ComponentLibraryLinks_LibraryIDArray: ComponentLibraryLink_[]; // Link to MJ_ComponentLibraryLinks
|
|
39140
39144
|
|
|
@@ -39171,6 +39175,9 @@ export class CreateComponentLibraryInput {
|
|
|
39171
39175
|
|
|
39172
39176
|
@Field({ nullable: true })
|
|
39173
39177
|
Description: string | null;
|
|
39178
|
+
|
|
39179
|
+
@Field({ nullable: true })
|
|
39180
|
+
Status?: string;
|
|
39174
39181
|
}
|
|
39175
39182
|
|
|
39176
39183
|
|
|
@@ -39206,6 +39213,9 @@ export class UpdateComponentLibraryInput {
|
|
|
39206
39213
|
@Field({ nullable: true })
|
|
39207
39214
|
Description?: string | null;
|
|
39208
39215
|
|
|
39216
|
+
@Field({ nullable: true })
|
|
39217
|
+
Status?: string;
|
|
39218
|
+
|
|
39209
39219
|
@Field(() => [KeyValuePairInput], { nullable: true })
|
|
39210
39220
|
OldValues___?: KeyValuePairInput[];
|
|
39211
39221
|
}
|
|
@@ -139,7 +139,8 @@ export class ResolverBase {
|
|
|
139
139
|
viewInput.AuditLogDescription,
|
|
140
140
|
viewInput.ResultType,
|
|
141
141
|
userPayload,
|
|
142
|
-
viewInput.MaxRows
|
|
142
|
+
viewInput.MaxRows,
|
|
143
|
+
viewInput.StartRow
|
|
143
144
|
);
|
|
144
145
|
}
|
|
145
146
|
else {
|
|
@@ -173,7 +174,8 @@ export class ResolverBase {
|
|
|
173
174
|
viewInput.AuditLogDescription,
|
|
174
175
|
viewInput.ResultType,
|
|
175
176
|
userPayload,
|
|
176
|
-
viewInput.MaxRows
|
|
177
|
+
viewInput.MaxRows,
|
|
178
|
+
viewInput.StartRow
|
|
177
179
|
);
|
|
178
180
|
} catch (err) {
|
|
179
181
|
console.log(err);
|
|
@@ -210,7 +212,8 @@ export class ResolverBase {
|
|
|
210
212
|
viewInput.AuditLogDescription,
|
|
211
213
|
viewInput.ResultType,
|
|
212
214
|
userPayload,
|
|
213
|
-
viewInput.MaxRows
|
|
215
|
+
viewInput.MaxRows,
|
|
216
|
+
viewInput.StartRow
|
|
214
217
|
);
|
|
215
218
|
} catch (err) {
|
|
216
219
|
console.log(err);
|
|
@@ -370,7 +373,8 @@ export class ResolverBase {
|
|
|
370
373
|
auditLogDescription: string | undefined,
|
|
371
374
|
resultType: string | undefined,
|
|
372
375
|
userPayload: UserPayload | null,
|
|
373
|
-
maxRows: number | undefined
|
|
376
|
+
maxRows: number | undefined,
|
|
377
|
+
startRow: number | undefined
|
|
374
378
|
) {
|
|
375
379
|
try {
|
|
376
380
|
if (!viewInfo || !userPayload) return null;
|
|
@@ -420,6 +424,7 @@ export class ResolverBase {
|
|
|
420
424
|
ExcludeDataFromAllPriorViewRuns: excludeDataFromAllPriorViewRuns,
|
|
421
425
|
IgnoreMaxRows: ignoreMaxRows,
|
|
422
426
|
MaxRows: maxRows,
|
|
427
|
+
StartRow: startRow,
|
|
423
428
|
ForceAuditLog: forceAuditLog,
|
|
424
429
|
AuditLogDescription: auditLogDescription,
|
|
425
430
|
ResultType: rt,
|