@friggframework/core 2.0.0--canary.540.c5ef83f.0 → 2.0.0--canary.540.d07ab53.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.
|
@@ -19,6 +19,11 @@ const createApp = (applyMiddleware) => {
|
|
|
19
19
|
})
|
|
20
20
|
);
|
|
21
21
|
|
|
22
|
+
app.use((req, res, next) => {
|
|
23
|
+
console.log(`[Frigg] ${req.method} ${req.path}`);
|
|
24
|
+
next();
|
|
25
|
+
});
|
|
26
|
+
|
|
22
27
|
if (applyMiddleware) applyMiddleware(app);
|
|
23
28
|
|
|
24
29
|
// Handle sending error response and logging server errors to console
|
|
@@ -29,22 +34,12 @@ const createApp = (applyMiddleware) => {
|
|
|
29
34
|
} = boomError;
|
|
30
35
|
|
|
31
36
|
if (statusCode >= 500) {
|
|
37
|
+
console.error(`[Frigg] ${req.method} ${req.path} -> ${statusCode}: ${err.message}`);
|
|
38
|
+
console.error(err.stack);
|
|
32
39
|
flushDebugLog(boomError);
|
|
33
40
|
res.status(statusCode).json({ error: 'Internal Server Error' });
|
|
34
41
|
} else {
|
|
35
|
-
|
|
36
|
-
const allHeaders = Object.entries(req.headers).reduce((acc, [key, value]) => {
|
|
37
|
-
if (key === 'x-frigg-api-key' || key === 'authorization') {
|
|
38
|
-
acc[key] = `${String(value).substring(0, 6)}...(redacted)`;
|
|
39
|
-
} else {
|
|
40
|
-
acc[key] = value;
|
|
41
|
-
}
|
|
42
|
-
return acc;
|
|
43
|
-
}, {});
|
|
44
|
-
console.warn(`[Frigg] ${req.method} ${req.path} -> ${statusCode}: ${err.message}`, JSON.stringify({ headers: allHeaders }));
|
|
45
|
-
} catch (logErr) {
|
|
46
|
-
console.warn(`[Frigg] ${req.method} ${req.path} -> ${statusCode}: ${err.message} (header logging failed: ${logErr.message})`);
|
|
47
|
-
}
|
|
42
|
+
console.warn(`[Frigg] ${req.method} ${req.path} -> ${statusCode}: ${err.message}`);
|
|
48
43
|
res.status(statusCode).json({ error: err.message });
|
|
49
44
|
}
|
|
50
45
|
});
|
package/modules/module.js
CHANGED
|
@@ -15,6 +15,8 @@ class ProcessAuthorizationCallback {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
async execute(userId, entityType, params) {
|
|
18
|
+
console.log(`[Frigg][OAuth] Starting callback for entityType=${entityType}, userId=${userId}`);
|
|
19
|
+
|
|
18
20
|
const moduleDefinition = this.moduleDefinitions.find((def) => {
|
|
19
21
|
return entityType === def.moduleName;
|
|
20
22
|
});
|
|
@@ -34,26 +36,37 @@ class ProcessAuthorizationCallback {
|
|
|
34
36
|
definition: moduleDefinition,
|
|
35
37
|
});
|
|
36
38
|
|
|
39
|
+
const authType = module.apiClass.requesterType;
|
|
40
|
+
console.log(`[Frigg][OAuth] Module created: name=${module.getName()}, authType=${authType}`);
|
|
41
|
+
|
|
37
42
|
let tokenResponse;
|
|
38
|
-
if (
|
|
43
|
+
if (authType === ModuleConstants.authType.oauth2) {
|
|
44
|
+
console.log(`[Frigg][OAuth] Exchanging authorization code for token...`);
|
|
39
45
|
tokenResponse = await moduleDefinition.requiredAuthMethods.getToken(
|
|
40
46
|
module.api,
|
|
41
47
|
params
|
|
42
48
|
);
|
|
49
|
+
console.log(`[Frigg][OAuth] Token exchange successful, keys: ${Object.keys(tokenResponse || {}).join(', ')}`);
|
|
43
50
|
} else {
|
|
51
|
+
console.log(`[Frigg][OAuth] Setting auth params (non-OAuth2)...`);
|
|
44
52
|
tokenResponse =
|
|
45
53
|
await moduleDefinition.requiredAuthMethods.setAuthParams(
|
|
46
54
|
module.api,
|
|
47
55
|
params
|
|
48
56
|
);
|
|
49
57
|
await this.onTokenUpdate(module, moduleDefinition, userId);
|
|
58
|
+
console.log(`[Frigg][OAuth] Auth params set and credential persisted`);
|
|
50
59
|
}
|
|
51
60
|
|
|
61
|
+
console.log(`[Frigg][OAuth] Testing auth...`);
|
|
52
62
|
const authRes = await module.testAuth();
|
|
53
63
|
if (!authRes) {
|
|
64
|
+
console.error(`[Frigg][OAuth] testAuth() returned false — authorization failed`);
|
|
54
65
|
throw new Error('Authorization failed');
|
|
55
66
|
}
|
|
67
|
+
console.log(`[Frigg][OAuth] Auth test passed`);
|
|
56
68
|
|
|
69
|
+
console.log(`[Frigg][OAuth] Fetching entity details...`);
|
|
57
70
|
const entityDetails =
|
|
58
71
|
await moduleDefinition.requiredAuthMethods.getEntityDetails(
|
|
59
72
|
module.api,
|
|
@@ -61,17 +74,20 @@ class ProcessAuthorizationCallback {
|
|
|
61
74
|
tokenResponse,
|
|
62
75
|
userId
|
|
63
76
|
);
|
|
77
|
+
console.log(`[Frigg][OAuth] Entity details received: identifiers=${JSON.stringify(entityDetails.identifiers)}`);
|
|
64
78
|
|
|
65
79
|
Object.assign(
|
|
66
80
|
entityDetails.details,
|
|
67
81
|
module.apiParamsFromEntity(module.api)
|
|
68
82
|
);
|
|
69
83
|
|
|
84
|
+
console.log(`[Frigg][OAuth] Finding or creating entity...`);
|
|
70
85
|
const persistedEntity = await this.findOrCreateEntity(
|
|
71
86
|
entityDetails,
|
|
72
87
|
entityType,
|
|
73
88
|
module.credential.id
|
|
74
89
|
);
|
|
90
|
+
console.log(`[Frigg][OAuth] Done — entity_id=${persistedEntity.id}, credential_id=${module.credential.id}`);
|
|
75
91
|
|
|
76
92
|
return {
|
|
77
93
|
credential_id: module.credential.id,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/core",
|
|
3
3
|
"prettier": "@friggframework/prettier-config",
|
|
4
|
-
"version": "2.0.0--canary.540.
|
|
4
|
+
"version": "2.0.0--canary.540.d07ab53.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
|
|
7
7
|
"@aws-sdk/client-kms": "^3.588.0",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@friggframework/eslint-config": "2.0.0--canary.540.
|
|
42
|
-
"@friggframework/prettier-config": "2.0.0--canary.540.
|
|
43
|
-
"@friggframework/test": "2.0.0--canary.540.
|
|
41
|
+
"@friggframework/eslint-config": "2.0.0--canary.540.d07ab53.0",
|
|
42
|
+
"@friggframework/prettier-config": "2.0.0--canary.540.d07ab53.0",
|
|
43
|
+
"@friggframework/test": "2.0.0--canary.540.d07ab53.0",
|
|
44
44
|
"@prisma/client": "^6.17.0",
|
|
45
45
|
"@types/lodash": "4.17.15",
|
|
46
46
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
@@ -80,5 +80,5 @@
|
|
|
80
80
|
"publishConfig": {
|
|
81
81
|
"access": "public"
|
|
82
82
|
},
|
|
83
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "d07ab5322a5e9110834139ff9efd53b2350cf266"
|
|
84
84
|
}
|
|
@@ -2,12 +2,12 @@ const Boom = require('@hapi/boom');
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Use case for authenticating a user using multiple authentication strategies.
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* Supports three authentication modes in priority order:
|
|
7
7
|
* 1. Shared Secret (backend-to-backend with x-frigg-api-key + x-frigg headers)
|
|
8
8
|
* 2. Adopter JWT (custom JWT authentication)
|
|
9
9
|
* 3. Frigg Native Token (bearer token from /user/login)
|
|
10
|
-
*
|
|
10
|
+
*
|
|
11
11
|
* x-frigg-appUserId and x-frigg-appOrgId headers are automatically supported
|
|
12
12
|
* for user identification with any auth mode. When present with JWT or Frigg
|
|
13
13
|
* tokens, they are validated to match the authenticated user.
|
|
@@ -50,29 +50,18 @@ class AuthenticateUser {
|
|
|
50
50
|
const authModes = this.userConfig.authModes || { friggToken: true };
|
|
51
51
|
const appUserId = req.headers['x-frigg-appuserid'];
|
|
52
52
|
const appOrgId = req.headers['x-frigg-apporgid'];
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (key === 'x-frigg-api-key' || key === 'authorization') {
|
|
58
|
-
acc[key] = `${String(value).substring(0, 6)}...(redacted)`;
|
|
59
|
-
} else {
|
|
60
|
-
acc[key] = value;
|
|
61
|
-
}
|
|
62
|
-
return acc;
|
|
63
|
-
}, {});
|
|
64
|
-
console.log(`[Frigg][DEBUG] ${req.method} ${req.path} - ALL headers:`, JSON.stringify(allHeaders));
|
|
65
|
-
console.log(`[Frigg][DEBUG] Parsed auth values:`, JSON.stringify({
|
|
66
|
-
appUserId: appUserId ?? '(undefined)',
|
|
67
|
-
appOrgId: appOrgId ?? '(undefined)',
|
|
68
|
-
enabledAuthModes: authModes,
|
|
69
|
-
}));
|
|
53
|
+
console.log(
|
|
54
|
+
'[Frigg] header list:',
|
|
55
|
+
JSON.stringify(Object.keys(req.headers))
|
|
56
|
+
);
|
|
70
57
|
|
|
71
58
|
// Priority 1: Shared Secret (backend-to-backend with API key)
|
|
72
59
|
if (authModes.sharedSecret !== false) {
|
|
73
60
|
const apiKey = req.headers['x-frigg-api-key'];
|
|
74
61
|
if (apiKey) {
|
|
75
|
-
console.log(
|
|
62
|
+
console.log(
|
|
63
|
+
'[Frigg] Attempting shared secret authentication with API key'
|
|
64
|
+
);
|
|
76
65
|
// Validate the API key (authentication)
|
|
77
66
|
await this.authenticateWithSharedSecret.execute(apiKey);
|
|
78
67
|
// Get user from x-frigg headers (authorization)
|
|
@@ -81,6 +70,9 @@ class AuthenticateUser {
|
|
|
81
70
|
appOrgId
|
|
82
71
|
);
|
|
83
72
|
}
|
|
73
|
+
console.log(
|
|
74
|
+
'[Frigg] No x-frigg-api-key header found, skipping shared secret authentication'
|
|
75
|
+
);
|
|
84
76
|
}
|
|
85
77
|
|
|
86
78
|
// Priority 2: Adopter JWT (if enabled)
|
|
@@ -88,10 +80,11 @@ class AuthenticateUser {
|
|
|
88
80
|
authModes.adopterJwt === true &&
|
|
89
81
|
req.headers.authorization?.startsWith('Bearer ')
|
|
90
82
|
) {
|
|
83
|
+
console.log('[Frigg] Attempting Adopter JWT authentication');
|
|
91
84
|
const token = req.headers.authorization.split(' ')[1];
|
|
92
85
|
// Detect JWT format (3 parts separated by dots)
|
|
93
86
|
if (token && token.split('.').length === 3) {
|
|
94
|
-
user = await this.getUserFromAdopterJwt.execute(token);
|
|
87
|
+
const user = await this.getUserFromAdopterJwt.execute(token);
|
|
95
88
|
// Validate x-frigg headers match JWT claims if present
|
|
96
89
|
if (appUserId || appOrgId) {
|
|
97
90
|
this.validateUserMatch(user, appUserId, appOrgId);
|
|
@@ -102,7 +95,8 @@ class AuthenticateUser {
|
|
|
102
95
|
|
|
103
96
|
// Priority 3: Frigg native token (default)
|
|
104
97
|
if (authModes.friggToken !== false && req.headers.authorization) {
|
|
105
|
-
|
|
98
|
+
console.log('[Frigg] Attempting Frigg native token authentication');
|
|
99
|
+
const user = await this.getUserFromBearerToken.execute(
|
|
106
100
|
req.headers.authorization
|
|
107
101
|
);
|
|
108
102
|
// Validate x-frigg headers match token user if present
|
|
@@ -140,5 +134,3 @@ class AuthenticateUser {
|
|
|
140
134
|
}
|
|
141
135
|
|
|
142
136
|
module.exports = { AuthenticateUser };
|
|
143
|
-
|
|
144
|
-
|
|
@@ -28,15 +28,6 @@ class GetUserFromXFriggHeaders {
|
|
|
28
28
|
* @throws {Boom} 400 Bad Request if neither ID is provided or if both IDs are provided but belong to different users.
|
|
29
29
|
*/
|
|
30
30
|
async execute(appUserId, appOrgId) {
|
|
31
|
-
console.log(`[Frigg][DEBUG] getUserFromXFriggHeaders called with:`, JSON.stringify({
|
|
32
|
-
appUserId: appUserId || '(falsy)',
|
|
33
|
-
appOrgId: appOrgId || '(falsy)',
|
|
34
|
-
appUserIdType: typeof appUserId,
|
|
35
|
-
appOrgIdType: typeof appOrgId,
|
|
36
|
-
individualUserRequired: this.userConfig.individualUserRequired,
|
|
37
|
-
organizationUserRequired: this.userConfig.organizationUserRequired,
|
|
38
|
-
}));
|
|
39
|
-
|
|
40
31
|
// At least one header must be provided
|
|
41
32
|
if (!appUserId && !appOrgId) {
|
|
42
33
|
throw Boom.badRequest(
|