code security
This commit is contained in:
@@ -14,7 +14,7 @@ function getEnv(key: string): string {
|
||||
return value;
|
||||
}
|
||||
|
||||
const SECRET_KEY = new TextEncoder().encode(getEnv('OIDC_CLIENT_SECRET'));
|
||||
const SECRET_KEY = new TextEncoder().encode(getEnv('AUTH_SECRET'));
|
||||
const SESSION_DURATION = 6 * 60 * 60; // 6 hours in seconds
|
||||
|
||||
export interface SessionData {
|
||||
@@ -74,12 +74,13 @@ export function getSessionFromRequest(request: Request): string | null {
|
||||
// Create session cookie
|
||||
export function createSessionCookie(token: string): string {
|
||||
const publicBaseUrl = getEnv('PUBLIC_BASE_URL');
|
||||
const isSecure = publicBaseUrl.startsWith('https://');
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
const isSecure = publicBaseUrl.startsWith('https://') || isProduction;
|
||||
|
||||
return serialize('session', token, {
|
||||
httpOnly: true,
|
||||
secure: isSecure,
|
||||
sameSite: 'lax',
|
||||
sameSite: 'strict', // More secure than 'lax'
|
||||
maxAge: SESSION_DURATION,
|
||||
path: '/'
|
||||
});
|
||||
@@ -127,7 +128,7 @@ export async function exchangeCodeForTokens(code: string): Promise<any> {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Authorization': `Basic ${btoa(`${clientId}:${clientSecret}`)}`
|
||||
'Authorization': `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
|
||||
@@ -1,6 +1,43 @@
|
||||
import { promises as fs } from 'fs';
|
||||
import { load } from 'js-yaml';
|
||||
import path from 'path';
|
||||
import { z } from 'zod';
|
||||
|
||||
const ToolSchema = z.object({
|
||||
name: z.string(),
|
||||
description: z.string(),
|
||||
domains: z.array(z.string()).optional().nullable().default([]),
|
||||
phases: z.array(z.string()).optional().nullable().default([]),
|
||||
platforms: z.array(z.string()).default([]),
|
||||
skillLevel: z.string(),
|
||||
url: z.string(),
|
||||
license: z.string(),
|
||||
tags: z.array(z.string()).default([]),
|
||||
// Optional fields that can be null, undefined, or empty
|
||||
projectUrl: z.string().optional().nullable(),
|
||||
knowledgebase: z.boolean().optional().nullable(),
|
||||
statusUrl: z.string().optional().nullable(),
|
||||
accessType: z.string().optional(),
|
||||
'domain-agnostic-software': z.array(z.string()).optional().nullable(),
|
||||
});
|
||||
|
||||
const ToolsDataSchema = z.object({
|
||||
tools: z.array(ToolSchema),
|
||||
domains: z.array(z.object({
|
||||
id: z.string(),
|
||||
name: z.string()
|
||||
})),
|
||||
phases: z.array(z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().optional()
|
||||
})),
|
||||
'domain-agnostic-software': z.array(z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().optional()
|
||||
})).optional().default([]),
|
||||
});
|
||||
|
||||
interface ToolsData {
|
||||
tools: any[];
|
||||
@@ -49,7 +86,14 @@ async function loadRawData(): Promise<ToolsData> {
|
||||
if (!cachedData) {
|
||||
const yamlPath = path.join(process.cwd(), 'src/data/tools.yaml');
|
||||
const yamlContent = await fs.readFile(yamlPath, 'utf8');
|
||||
cachedData = load(yamlContent) as ToolsData;
|
||||
const rawData = load(yamlContent);
|
||||
|
||||
try {
|
||||
cachedData = ToolsDataSchema.parse(rawData);
|
||||
} catch (error) {
|
||||
console.error('YAML validation failed:', error);
|
||||
throw new Error('Invalid tools.yaml structure');
|
||||
}
|
||||
}
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user