NeahNew/N8N_API_KEY_MISMATCH_FIX.md
2026-01-09 11:19:32 +01:00

261 lines
6.4 KiB
Markdown

# N8N API Key Mismatch - 401 Unauthorized
## 🔍 Problem Identified
**Error**: `401 - "Unauthorized"`
**Log**: `Invalid API key { received: 'present', expected: 'configured' }`
**Status**:
- ✅ Endpoint is being called (`Mission Created Webhook Received`)
- ✅ API key is being sent (`received: 'present'`)
-**API key values don't match**
---
## 🔍 Root Cause
The API key sent by N8N in the `x-api-key` header **does not match** the `N8N_API_KEY` environment variable on the server.
### How It Works
1. **Server sends to N8N** (line 420 in `app/api/missions/route.ts`):
```typescript
config: {
N8N_API_KEY: process.env.N8N_API_KEY, // From server environment
MISSION_API_URL: process.env.NEXT_PUBLIC_API_URL
}
```
2. **N8N uses this value** in "Save Mission To API" node:
```
x-api-key: {{ $node['Process Mission Data'].json.config.N8N_API_KEY }}
```
3. **Server receives and validates** (line 42 in `app/api/missions/mission-created/route.ts`):
```typescript
if (apiKey !== expectedApiKey) {
// Keys don't match → 401 error
}
```
### The Problem
**If `process.env.N8N_API_KEY` is `undefined` or empty** when sending to N8N:
- N8N receives `undefined` or empty string
- N8N sends empty string in header
- Server expects the actual key value
- **Keys don't match → 401 error**
---
## ✅ Solution
### Step 1: Verify N8N_API_KEY is Set
**Check your environment variables**:
```bash
# In your terminal (if running locally)
echo $N8N_API_KEY
# Or check in your application
# Create a test endpoint to verify
```
**Expected**: Should show the actual API key value (not empty)
### Step 2: Ensure Same Key in Both Places
**The key must be the same in**:
1. **Server environment variable**: `N8N_API_KEY=your-key-here`
2. **N8N workflow config**: The value sent in `config.N8N_API_KEY`
**If they're different**, they won't match!
### Step 3: Check What N8N is Sending
**In N8N workflow "Save Mission To API" node**, verify:
1. **Header `x-api-key` value**:
```
{{ $node['Process Mission Data'].json.config.N8N_API_KEY }}
```
2. **What this resolves to**:
- If `config.N8N_API_KEY` is `undefined` → N8N sends empty string
- If `config.N8N_API_KEY` has a value → N8N sends that value
3. **Check N8N execution logs**:
- Look at the actual request being sent
- Check the `x-api-key` header value
- Compare with your server's `N8N_API_KEY`
### Step 4: Fix the Mismatch
**Option A: If server's N8N_API_KEY is undefined**
Add to `.env.local` (or production environment):
```env
N8N_API_KEY=LwgeE1ntADD20OuWC88S3pR0EaO7FtO4
```
Restart the application.
**Option B: If N8N is sending wrong value**
Check what value N8N has in `config.N8N_API_KEY`:
- It should match the server's `N8N_API_KEY`
- If different, update one to match the other
**Option C: Hardcode in N8N (not recommended)**
If you can't sync the values, you could hardcode in N8N:
```
x-api-key: LwgeE1ntADD20OuWC88S3pR0EaO7FtO4
```
But this is less secure - better to use environment variable.
---
## 🧪 Testing
### Test 1: Check Server Environment
**Create test endpoint**:
```typescript
// app/api/test-n8n-key/route.ts
import { NextResponse } from 'next/server';
export async function GET() {
return NextResponse.json({
hasN8NApiKey: !!process.env.N8N_API_KEY,
keyLength: process.env.N8N_API_KEY?.length || 0,
keyPrefix: process.env.N8N_API_KEY ? process.env.N8N_API_KEY.substring(0, 4) + '...' : 'none'
});
}
```
**Visit**: `http://localhost:3000/api/test-n8n-key`
**Expected**:
```json
{
"hasN8NApiKey": true,
"keyLength": 32,
"keyPrefix": "Lwge..."
}
```
### Test 2: Check What N8N Sends
**In N8N execution logs**, check the "Save Mission To API" node:
- Look at the request headers
- Find `x-api-key` header
- Note the value
**Compare** with server's `N8N_API_KEY` - they must match exactly.
### Test 3: Manual Test
**Test the endpoint with the correct key**:
```bash
curl -X POST https://hub.slm-lab.net/api/missions/mission-created \
-H "Content-Type: application/json" \
-H "x-api-key: LwgeE1ntADD20OuWC88S3pR0EaO7FtO4" \
-d '{
"missionId": "test-id",
"name": "Test",
"creatorId": "user-id"
}'
```
**Expected**: 200 OK (if mission exists) or 404 (if mission doesn't exist)
**If 401**: The key in the curl command doesn't match server's `N8N_API_KEY`
---
## 🔧 Common Issues
### Issue 1: Key is undefined when sending to N8N
**Symptom**: N8N receives `undefined` or empty string in `config.N8N_API_KEY`
**Cause**: `process.env.N8N_API_KEY` is not set when creating mission
**Fix**: Add `N8N_API_KEY` to environment and restart
### Issue 2: Different keys in different environments
**Symptom**: Works in development but not production (or vice versa)
**Cause**: Different `N8N_API_KEY` values in different environments
**Fix**: Use the same key in all environments, or update N8N to use environment-specific keys
### Issue 3: Key has extra spaces or characters
**Symptom**: Keys look the same but don't match
**Cause**: Extra spaces, newlines, or special characters
**Fix**:
```env
# Correct
N8N_API_KEY=LwgeE1ntADD20OuWC88S3pR0EaO7FtO4
# Wrong (with quotes)
N8N_API_KEY="LwgeE1ntADD20OuWC88S3pR0EaO7FtO4"
# Wrong (with spaces)
N8N_API_KEY = LwgeE1ntADD20OuWC88S3pR0EaO7FtO4
```
---
## 📋 Debugging Checklist
- [ ] `N8N_API_KEY` is set in server environment
- [ ] Key value matches what N8N is sending
- [ ] No extra spaces or characters in key
- [ ] Server has been restarted after adding key
- [ ] Test endpoint shows key is loaded
- [ ] N8N execution logs show correct key in header
- [ ] Manual curl test works with the key
---
## 🎯 Expected Flow After Fix
1. **Mission created**
2. **N8N workflow triggered**
3. **Server sends `config.N8N_API_KEY` to N8N**
4. **N8N creates integrations**
5. **N8N calls `/api/missions/mission-created`**
6. **N8N sends `x-api-key` header with same value**
7. **Server validates key matches**
8. **IDs saved to database**
---
## 📝 Summary
**Problem**: 401 Unauthorized - API key mismatch
**Root Cause**: The API key sent by N8N doesn't match the server's `N8N_API_KEY`
**Solution**:
1. Ensure `N8N_API_KEY` is set in server environment
2. Ensure N8N uses the same key value
3. Verify keys match exactly (no spaces, same value)
**After Fix**: The endpoint should return 200 OK and save integration IDs.
---
**Document Created**: $(date)
**Priority**: CRITICAL - Blocks integration IDs from being saved