security: add helmet, rate limiting, webhook auth, fix token storage, restrict hard deletes

- Add helmet for HTTP security headers (CSP, HSTS, X-Frame-Options, etc.)
- Add @nestjs/throttler for rate limiting (100 req/60s per IP)
- Add shared secret validation on Signal webhook endpoint
- Remove JWT token from localStorage, use Auth0 SDK memory cache
  with async getAccessTokenSilently() in API interceptor
- Restrict hard delete (?hard=true) to ADMINISTRATOR role in service layer
- Replace exposed Anthropic API key with placeholder in .env

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 18:30:14 +01:00
parent 8e88880838
commit 934464bf8e
18 changed files with 132 additions and 55 deletions

View File

@@ -20,11 +20,22 @@ export const copilotApi = axios.create({
timeout: 120000, // 2 minute timeout for AI requests
});
// Shared request interceptor function
const requestInterceptor = (config: any) => {
const token = localStorage.getItem('auth0_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
// Token getter function - set by AuthContext when authenticated
let getToken: (() => Promise<string>) | null = null;
export function setTokenGetter(getter: (() => Promise<string>) | null) {
getToken = getter;
}
// Shared request interceptor function (async to support token refresh)
const requestInterceptor = async (config: any) => {
if (getToken) {
try {
const token = await getToken();
config.headers.Authorization = `Bearer ${token}`;
} catch {
// Token fetch failed - request goes without auth header
}
}
if (DEBUG_MODE) {
@@ -69,7 +80,6 @@ const responseErrorInterceptor = (error: any) => {
status: response.status,
statusText: response.statusText,
data: response.data,
requestData: config?.data,
}
);