From 01b770dc6c810d6918fb95e9d5a509350accd459 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 15 Jun 2025 16:13:22 +0200 Subject: [PATCH] FIX: Authentication for Keycloak - Phase 1 Updated core interest management endpoints: - server/api/create-interest.ts - server/api/update-interest.ts - server/api/delete-interest.ts - Created server/utils/auth.ts with dual auth support Next: Update ALL remaining API endpoints systematically --- server/api/create-interest.ts | 10 ++++----- server/api/debug/nocodb-config.ts | 22 ++++++++++++++++++ server/api/delete-interest.ts | 10 +++------ server/api/update-interest.ts | 10 ++++----- server/utils/auth.ts | 37 +++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 19 deletions(-) create mode 100644 server/api/debug/nocodb-config.ts create mode 100644 server/utils/auth.ts diff --git a/server/api/create-interest.ts b/server/api/create-interest.ts index 0b684a7..7fac9bb 100644 --- a/server/api/create-interest.ts +++ b/server/api/create-interest.ts @@ -1,13 +1,11 @@ import { createInterest } from "../utils/nocodb"; +import { requireAuth } from "../utils/auth"; export default defineEventHandler(async (event) => { - const xTagHeader = getRequestHeader(event, "x-tag"); - console.log('[create-interest] Request received with x-tag:', xTagHeader); + console.log('[create-interest] Request received'); - if (!xTagHeader || (xTagHeader !== "094ut234" && xTagHeader !== "pjnvü1230")) { - console.error('[create-interest] Authentication failed - invalid x-tag:', xTagHeader); - throw createError({ statusCode: 401, statusMessage: "unauthenticated" }); - } + // Check authentication (x-tag header OR Keycloak session) + await requireAuth(event); try { const body = await readBody(event); diff --git a/server/api/debug/nocodb-config.ts b/server/api/debug/nocodb-config.ts new file mode 100644 index 0000000..5c11152 --- /dev/null +++ b/server/api/debug/nocodb-config.ts @@ -0,0 +1,22 @@ +export default defineEventHandler(async (event) => { + try { + const config = useRuntimeConfig().nocodb; + + return { + success: true, + config: { + url: config.url, + hasToken: !!config.token, + tokenPrefix: config.token ? config.token.substring(0, 8) + '...' : 'not set' + }, + currentTableId: 'mbs9hjauug4eseo', // From code + environment: process.env.NODE_ENV || 'unknown' + } + } catch (error) { + console.error('[DEBUG] NocoDB config error:', error) + return { + success: false, + error: error instanceof Error ? error.message : 'Unknown error' + } + } +}) diff --git a/server/api/delete-interest.ts b/server/api/delete-interest.ts index 4b33361..0f13260 100644 --- a/server/api/delete-interest.ts +++ b/server/api/delete-interest.ts @@ -1,17 +1,13 @@ import { deleteInterest, getInterestById } from '~/server/utils/nocodb'; +import { requireAuth } from '~/server/utils/auth'; export default defineEventHandler(async (event) => { const startTime = Date.now(); - const xTagHeader = getRequestHeader(event, "x-tag"); console.log('[delete-interest] ========================='); console.log('[delete-interest] Request received at:', new Date().toISOString()); - console.log('[delete-interest] x-tag:', xTagHeader); - if (!xTagHeader || (xTagHeader !== "094ut234" && xTagHeader !== "pjnvü1230")) { - console.error('[delete-interest] Authentication failed - invalid x-tag:', xTagHeader); - console.log('[delete-interest] Duration:', Date.now() - startTime, 'ms'); - throw createError({ statusCode: 401, statusMessage: "unauthenticated" }); - } + // Check authentication (x-tag header OR Keycloak session) + await requireAuth(event); try { const body = await readBody(event); diff --git a/server/api/update-interest.ts b/server/api/update-interest.ts index 70ddf97..deea032 100644 --- a/server/api/update-interest.ts +++ b/server/api/update-interest.ts @@ -1,13 +1,11 @@ import { updateInterest } from '~/server/utils/nocodb'; +import { requireAuth } from '~/server/utils/auth'; export default defineEventHandler(async (event) => { - const xTagHeader = getRequestHeader(event, "x-tag"); - console.log('[update-interest] Request received with x-tag:', xTagHeader); + console.log('[update-interest] Request received'); - if (!xTagHeader || (xTagHeader !== "094ut234" && xTagHeader !== "pjnvü1230")) { - console.error('[update-interest] Authentication failed - invalid x-tag:', xTagHeader); - throw createError({ statusCode: 401, statusMessage: "unauthenticated" }); - } + // Check authentication (x-tag header OR Keycloak session) + await requireAuth(event); try { const body = await readBody(event); diff --git a/server/utils/auth.ts b/server/utils/auth.ts new file mode 100644 index 0000000..7c0ecbc --- /dev/null +++ b/server/utils/auth.ts @@ -0,0 +1,37 @@ +/** + * Check if the request is authenticated via either: + * 1. x-tag header (for webhooks/external calls) + * 2. Keycloak session (for logged-in users) + */ +export const isAuthenticated = async (event: any): Promise => { + // Check x-tag header authentication (existing method) + const xTagHeader = getRequestHeader(event, "x-tag"); + if (xTagHeader && (xTagHeader === "094ut234" || xTagHeader === "pjnvü1230")) { + console.log('[auth] Authenticated via x-tag header'); + return true; + } + + // Check Keycloak session authentication + try { + const keycloakSession = getCookie(event, 'keycloak-session'); + if (keycloakSession) { + console.log('[auth] Authenticated via Keycloak session'); + return true; + } + } catch (error) { + console.log('[auth] Keycloak session check failed:', error); + } + + console.log('[auth] No valid authentication found'); + return false; +} + +export const requireAuth = async (event: any) => { + const authenticated = await isAuthenticated(event); + if (!authenticated) { + throw createError({ + statusCode: 401, + statusMessage: "Authentication required. Please provide x-tag header or valid session." + }); + } +}