feat: scope query param auth to MCP endpoints
Restrict api_key query parameter to /mcp/tools, /mcp/tool/call, and /mcp/sse only. Updated documentation to reflect query param usage for ChatGPT UI without header support.
This commit is contained in:
@@ -77,9 +77,12 @@ API key authentication ENABLED (1 key(s) configured)
|
|||||||
# Without key - should fail with 401
|
# Without key - should fail with 401
|
||||||
curl https://mcp.yourdomain.com/mcp/tools
|
curl https://mcp.yourdomain.com/mcp/tools
|
||||||
|
|
||||||
# With valid key - should succeed
|
# With valid key (header) - should succeed
|
||||||
curl -H "Authorization: Bearer YOUR_KEY_HERE" \
|
curl -H "Authorization: Bearer YOUR_KEY_HERE" \
|
||||||
https://mcp.yourdomain.com/mcp/tools
|
https://mcp.yourdomain.com/mcp/tools
|
||||||
|
|
||||||
|
# With valid key (query param) - should succeed
|
||||||
|
curl "https://mcp.yourdomain.com/mcp/tools?api_key=YOUR_KEY_HERE"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ aegis-gitea-mcp Up 0.0.0.0:8080->8080/tcp
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Replace YOUR_API_KEY with your actual key
|
# Replace YOUR_API_KEY with your actual key
|
||||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
curl "https://mcp.yourdomain.com/mcp/tools?api_key=YOUR_API_KEY"
|
||||||
https://mcp.yourdomain.com/mcp/tools
|
|
||||||
|
|
||||||
# Expected: JSON response with available tools
|
# Expected: JSON response with available tools
|
||||||
# If error: Check AUTH_SETUP.md troubleshooting
|
# If error: Check AUTH_SETUP.md troubleshooting
|
||||||
@@ -50,22 +49,12 @@ curl -H "Authorization: Bearer YOUR_API_KEY" \
|
|||||||
3. **Enter Server Details**
|
3. **Enter Server Details**
|
||||||
```
|
```
|
||||||
Name: AegisGitea MCP
|
Name: AegisGitea MCP
|
||||||
URL: https://mcp.yourdomain.com
|
URL: https://mcp.yourdomain.com?api_key=YOUR_API_KEY_HERE
|
||||||
Type: HTTP/SSE (Server-Sent Events)
|
Type: HTTP/SSE (Server-Sent Events)
|
||||||
|
Auth: None (or Mixed, leave OAuth fields empty)
|
||||||
```
|
```
|
||||||
|
|
||||||
4. **Add Custom Header**
|
4. **Save Configuration**
|
||||||
```
|
|
||||||
Header Name: Authorization
|
|
||||||
Header Value: Bearer YOUR_API_KEY_HERE
|
|
||||||
```
|
|
||||||
|
|
||||||
**Important:**
|
|
||||||
- Include the word "Bearer" followed by a space
|
|
||||||
- Then paste your full 64-character API key
|
|
||||||
- No quotes around the key
|
|
||||||
|
|
||||||
5. **Save Configuration**
|
|
||||||
|
|
||||||
### Step 4: Test Connection
|
### Step 4: Test Connection
|
||||||
|
|
||||||
@@ -168,18 +157,18 @@ curl https://mcp.yourdomain.com/health
|
|||||||
|
|
||||||
### Issue: "Authentication failed"
|
### Issue: "Authentication failed"
|
||||||
|
|
||||||
**Check 1: Authorization header format**
|
**Check 1: MCP Server URL format**
|
||||||
|
|
||||||
Correct:
|
Correct:
|
||||||
```
|
```
|
||||||
Authorization: Bearer a1b2c3d4e5f6g7h8...
|
https://mcp.yourdomain.com?api_key=YOUR_KEY
|
||||||
```
|
```
|
||||||
|
|
||||||
Wrong:
|
Wrong:
|
||||||
```
|
```
|
||||||
Authorization: a1b2c3d4... (missing "Bearer ")
|
https://mcp.yourdomain.com (missing api_key)
|
||||||
Authorization: "Bearer a1b2c3d4..." (extra quotes)
|
https://mcp.yourdomain.com?api_key= (empty key)
|
||||||
Authorization:Bearer a1b2c3d4... (missing space after colon)
|
https://mcp.yourdomain.com?api_key=short (too short)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Check 2: Key matches .env**
|
**Check 2: Key matches .env**
|
||||||
@@ -197,7 +186,7 @@ docker-compose logs aegis-mcp | tail -50
|
|||||||
|
|
||||||
Look for:
|
Look for:
|
||||||
- `invalid_api_key` → Key doesn't match
|
- `invalid_api_key` → Key doesn't match
|
||||||
- `missing_api_key` → Header not sent
|
- `missing_api_key` → api_key not provided
|
||||||
- `invalid_key_format` → Key too short
|
- `invalid_key_format` → Key too short
|
||||||
|
|
||||||
### Issue: "No repositories visible"
|
### Issue: "No repositories visible"
|
||||||
@@ -211,8 +200,7 @@ Look for:
|
|||||||
|
|
||||||
**Test manually:**
|
**Test manually:**
|
||||||
```bash
|
```bash
|
||||||
curl -H "Authorization: Bearer YOUR_KEY" \
|
curl "https://mcp.yourdomain.com/mcp/tool/call?api_key=YOUR_KEY" \
|
||||||
https://mcp.yourdomain.com/mcp/tool/call \
|
|
||||||
-X POST \
|
-X POST \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"tool": "list_repositories", "arguments": {}}'
|
-d '{"tool": "list_repositories", "arguments": {}}'
|
||||||
@@ -241,8 +229,7 @@ Too many failed authentication attempts
|
|||||||
|
|
||||||
**Verify tools are registered:**
|
**Verify tools are registered:**
|
||||||
```bash
|
```bash
|
||||||
curl -H "Authorization: Bearer YOUR_KEY" \
|
curl "https://mcp.yourdomain.com/mcp/tools?api_key=YOUR_KEY"
|
||||||
https://mcp.yourdomain.com/mcp/tools
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Should return JSON with tools array.
|
Should return JSON with tools array.
|
||||||
@@ -320,8 +307,7 @@ You can call tools directly via API:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# List repositories
|
# List repositories
|
||||||
curl -X POST https://mcp.yourdomain.com/mcp/tool/call \
|
curl -X POST "https://mcp.yourdomain.com/mcp/tool/call?api_key=YOUR_KEY" \
|
||||||
-H "Authorization: Bearer YOUR_KEY" \
|
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"tool": "list_repositories",
|
"tool": "list_repositories",
|
||||||
@@ -329,8 +315,7 @@ curl -X POST https://mcp.yourdomain.com/mcp/tool/call \
|
|||||||
}'
|
}'
|
||||||
|
|
||||||
# Get file contents
|
# Get file contents
|
||||||
curl -X POST https://mcp.yourdomain.com/mcp/tool/call \
|
curl -X POST "https://mcp.yourdomain.com/mcp/tool/call?api_key=YOUR_KEY" \
|
||||||
-H "Authorization: Bearer YOUR_KEY" \
|
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{
|
-d '{
|
||||||
"tool": "get_file_contents",
|
"tool": "get_file_contents",
|
||||||
@@ -350,8 +335,7 @@ For automated workflows, you can integrate MCP tools into CI/CD:
|
|||||||
# Example GitHub Actions (future enhancement)
|
# Example GitHub Actions (future enhancement)
|
||||||
- name: Sync to Gitea via MCP
|
- name: Sync to Gitea via MCP
|
||||||
run: |
|
run: |
|
||||||
curl -X POST https://mcp.yourdomain.com/mcp/tool/call \
|
curl -X POST "https://mcp.yourdomain.com/mcp/tool/call?api_key=${{ secrets.MCP_API_KEY }}" \
|
||||||
-H "Authorization: Bearer ${{ secrets.MCP_API_KEY }}" \
|
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{...}'
|
-d '{...}'
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ async def authenticate_request(request: Request, call_next):
|
|||||||
auth_header = request.headers.get("authorization")
|
auth_header = request.headers.get("authorization")
|
||||||
api_key = auth_validator.extract_bearer_token(auth_header)
|
api_key = auth_validator.extract_bearer_token(auth_header)
|
||||||
|
|
||||||
# Fallback: allow API key via query parameter (for ChatGPT UI without headers)
|
# Fallback: allow API key via query parameter only for MCP endpoints
|
||||||
if not api_key:
|
if not api_key and request.url.path in {"/mcp/tools", "/mcp/tool/call", "/mcp/sse"}:
|
||||||
api_key = request.query_params.get("api_key")
|
api_key = request.query_params.get("api_key")
|
||||||
|
|
||||||
# Validate API key
|
# Validate API key
|
||||||
|
|||||||
Reference in New Issue
Block a user