Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/core/handlers/app-handler-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ const createApp = (applyMiddleware) => {
})
);

app.use((req, res, next) => {
console.log(`[Frigg] ${req.method} ${req.path}`);
next();
});

if (applyMiddleware) applyMiddleware(app);

// Handle sending error response and logging server errors to console
Expand All @@ -29,6 +34,8 @@ const createApp = (applyMiddleware) => {
} = boomError;

if (statusCode >= 500) {
console.error(`[Frigg] ${req.method} ${req.path} -> ${statusCode}: ${err.message}`);
console.error(err.stack);
flushDebugLog(boomError);
res.status(statusCode).json({ error: 'Internal Server Error' });
} else {
Expand Down
1 change: 1 addition & 0 deletions packages/core/modules/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class Module extends Delegate {
try {
if (await this.testAuthRequest(this.api)) validAuth = true;
} catch (e) {
console.error(`[Frigg][testAuth] Failed for module ${this.name}: ${e.message}`);
flushDebugLog(e);
}
return validAuth;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class ProcessAuthorizationCallback {
}

async execute(userId, entityType, params) {
console.log(`[Frigg][OAuth] Starting callback for entityType=${entityType}, userId=${userId}`);

const moduleDefinition = this.moduleDefinitions.find((def) => {
return entityType === def.moduleName;
});
Expand All @@ -34,44 +36,58 @@ class ProcessAuthorizationCallback {
definition: moduleDefinition,
});

const authType = module.apiClass.requesterType;
console.log(`[Frigg][OAuth] Module created: name=${module.getName()}, authType=${authType}`);

let tokenResponse;
if (module.apiClass.requesterType === ModuleConstants.authType.oauth2) {
if (authType === ModuleConstants.authType.oauth2) {
console.log(`[Frigg][OAuth] Exchanging authorization code for token...`);
tokenResponse = await moduleDefinition.requiredAuthMethods.getToken(
module.api,
params
);
console.log(`[Frigg][OAuth] Token exchange successful, keys: ${Object.keys(tokenResponse || {}).join(', ')}`);
} else {
console.log(`[Frigg][OAuth] Setting auth params (non-OAuth2)...`);
tokenResponse =
await moduleDefinition.requiredAuthMethods.setAuthParams(
module.api,
params
);
await this.onTokenUpdate(module, moduleDefinition, userId);
console.log(`[Frigg][OAuth] Auth params set and credential persisted`);
}

console.log(`[Frigg][OAuth] Testing auth...`);
const authRes = await module.testAuth();
if (!authRes) {
console.error(`[Frigg][OAuth] testAuth() returned false — authorization failed`);
throw new Error('Authorization failed');
}
console.log(`[Frigg][OAuth] Auth test passed`);

console.log(`[Frigg][OAuth] Fetching entity details...`);
const entityDetails =
await moduleDefinition.requiredAuthMethods.getEntityDetails(
module.api,
params,
tokenResponse,
userId
);
console.log(`[Frigg][OAuth] Entity details received: identifiers=${JSON.stringify(entityDetails.identifiers)}`);

Object.assign(
entityDetails.details,
module.apiParamsFromEntity(module.api)
);

console.log(`[Frigg][OAuth] Finding or creating entity...`);
const persistedEntity = await this.findOrCreateEntity(
entityDetails,
entityType,
module.credential.id
);
console.log(`[Frigg][OAuth] Done — entity_id=${persistedEntity.id}, credential_id=${module.credential.id}`);

return {
credential_id: module.credential.id,
Expand Down
23 changes: 16 additions & 7 deletions packages/core/user/use-cases/authenticate-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ const Boom = require('@hapi/boom');

/**
* Use case for authenticating a user using multiple authentication strategies.
*
*
* Supports three authentication modes in priority order:
* 1. Shared Secret (backend-to-backend with x-frigg-api-key + x-frigg headers)
* 2. Adopter JWT (custom JWT authentication)
* 3. Frigg Native Token (bearer token from /user/login)
*
*
* x-frigg-appUserId and x-frigg-appOrgId headers are automatically supported
* for user identification with any auth mode. When present with JWT or Frigg
* tokens, they are validated to match the authenticated user.
Expand Down Expand Up @@ -50,12 +50,18 @@ class AuthenticateUser {
const authModes = this.userConfig.authModes || { friggToken: true };
const appUserId = req.headers['x-frigg-appuserid'];
const appOrgId = req.headers['x-frigg-apporgid'];
let user = null;
console.log(
'[Frigg] header list:',
JSON.stringify(Object.keys(req.headers))
);

// Priority 1: Shared Secret (backend-to-backend with API key)
if (authModes.sharedSecret !== false) {
const apiKey = req.headers['x-frigg-api-key'];
if (apiKey) {
console.log(
'[Frigg] Attempting shared secret authentication with API key'
);
// Validate the API key (authentication)
await this.authenticateWithSharedSecret.execute(apiKey);
// Get user from x-frigg headers (authorization)
Expand All @@ -64,17 +70,21 @@ class AuthenticateUser {
appOrgId
);
}
console.log(
'[Frigg] No x-frigg-api-key header found, skipping shared secret authentication'
);
Comment on lines +73 to +75
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This console.log is incorrectly placed outside the if (apiKey) block. It will execute unconditionally after the shared secret check, logging "No x-frigg-api-key header found" even when an API key is present and authentication succeeds.

To fix, move this log inside an else block:

if (apiKey) {
    // ... authentication logic
} else {
    console.log('[Frigg] No x-frigg-api-key header found, skipping shared secret authentication');
}
Suggested change
console.log(
'[Frigg] No x-frigg-api-key header found, skipping shared secret authentication'
);
if (apiKey) {
// Authentication logic (existing code)
} else {
console.log(
'[Frigg] No x-frigg-api-key header found, skipping shared secret authentication'
);
}

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

}

// Priority 2: Adopter JWT (if enabled)
if (
authModes.adopterJwt === true &&
req.headers.authorization?.startsWith('Bearer ')
) {
console.log('[Frigg] Attempting Adopter JWT authentication');
const token = req.headers.authorization.split(' ')[1];
// Detect JWT format (3 parts separated by dots)
if (token && token.split('.').length === 3) {
user = await this.getUserFromAdopterJwt.execute(token);
const user = await this.getUserFromAdopterJwt.execute(token);
// Validate x-frigg headers match JWT claims if present
if (appUserId || appOrgId) {
this.validateUserMatch(user, appUserId, appOrgId);
Expand All @@ -85,7 +95,8 @@ class AuthenticateUser {

// Priority 3: Frigg native token (default)
if (authModes.friggToken !== false && req.headers.authorization) {
user = await this.getUserFromBearerToken.execute(
console.log('[Frigg] Attempting Frigg native token authentication');
const user = await this.getUserFromBearerToken.execute(
req.headers.authorization
);
// Validate x-frigg headers match token user if present
Expand Down Expand Up @@ -123,5 +134,3 @@ class AuthenticateUser {
}

module.exports = { AuthenticateUser };


Loading