Authentication
Rockfish MCP supports multiple authentication mechanisms.
Overview
| Method | Transport | Description |
|---|---|---|
| API Key (JSON) | Raw TLS | JSON frame before MCP session |
| Bearer Token | HTTP/WS | Standard Authorization header |
| Mutual TLS (mTLS) | Any TLS | Client certificate verification |
These can be combined for defense-in-depth.
Bearer Token Authentication (HTTP Mode)
Standard HTTP authentication using Authorization: Bearer <token> header.
Setup
-
Generate API key and hash:
API_KEY=$(openssl rand -base64 32) echo "API Key: $API_KEY" echo "Hash: $(echo -n "$API_KEY" | sha256sum | cut -d' ' -f1)" -
Configure:
tls: enabled: true http_mode: true bind_address: "0.0.0.0:8443" cert_path: "./certs/cert.pem" key_path: "./certs/key.pem" auth: api_keys: - name: "production-client" key_hash: "a1b2c3d4e5f6..."
Client Examples
Python (websockets):
import asyncio
import websockets
import json
async def connect():
uri = "wss://localhost:8443/mcp"
headers = {"Authorization": "Bearer your-api-key"}
async with websockets.connect(uri, extra_headers=headers) as ws:
await ws.send(json.dumps({
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "python-client", "version": "1.0"}
}
}))
print(await ws.recv())
asyncio.run(connect())
JavaScript/Node.js:
const WebSocket = require('ws');
const ws = new WebSocket('wss://localhost:8443/mcp', {
headers: { 'Authorization': 'Bearer your-api-key' },
rejectUnauthorized: true // false for self-signed certs
});
ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: {
protocolVersion: '2024-11-05',
capabilities: {},
clientInfo: { name: 'nodejs-client', version: '1.0' }
}
}));
});
ws.on('message', data => console.log(data.toString()));
cURL:
curl -i -N \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Authorization: Bearer your-api-key" \
-H "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==" \
-H "Sec-WebSocket-Version: 13" \
https://localhost:8443/mcp
API Key Authentication (TLS Mode)
JSON-based authentication for raw TLS connections.
Protocol
- Client connects via TLS
- Client sends:
{"api_key": "your-secret-key"}\n - Server responds:
{"success": true/false, "message": "..."}\n - MCP session proceeds if successful
Configuration
tls:
enabled: true
http_mode: false # Raw TLS mode
bind_address: "127.0.0.1:8443"
cert_path: "./certs/cert.pem"
key_path: "./certs/key.pem"
auth:
api_keys:
- name: "production-client"
key_hash: "sha256-hash-here"
Client Example
import socket
import ssl
import json
context = ssl.create_default_context()
sock = socket.create_connection(("localhost", 8443))
tls_sock = context.wrap_socket(sock, server_hostname="localhost")
# Authenticate
auth = {"api_key": "your-secret-key"}
tls_sock.sendall((json.dumps(auth) + "\n").encode())
response = json.loads(tls_sock.recv(4096).decode().strip())
if not response["success"]:
raise Exception(f"Auth failed: {response['message']}")
# Proceed with MCP protocol...
Mutual TLS (mTLS)
Transport-level authentication using client certificates.
Create CA and Client Certificates
# Generate CA
openssl genrsa -out ca-key.pem 4096
openssl req -new -x509 -key ca-key.pem -out ca-cert.pem -days 3650 \
-subj "/CN=Rockfish MCP CA/O=Your Org"
# Generate client certificate
openssl genrsa -out client-key.pem 2048
openssl req -new -key client-key.pem -out client.csr \
-subj "/CN=client1/O=Your Org"
openssl x509 -req -in client.csr -CA ca-cert.pem -CAkey ca-key.pem \
-CAcreateserial -out client-cert.pem -days 365
Configuration
tls:
enabled: true
bind_address: "0.0.0.0:8443"
cert_path: "./certs/cert.pem"
key_path: "./certs/key.pem"
auth:
require_client_cert: true
client_ca_cert_path: "./certs/ca-cert.pem"
Client Example
import ssl
import socket
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
context.load_cert_chain(
certfile="client-cert.pem",
keyfile="client-key.pem"
)
context.load_verify_locations(cafile="server-ca-cert.pem")
sock = socket.create_connection(("localhost", 8443))
tls_sock = context.wrap_socket(sock, server_hostname="localhost")
# Connection authenticated via mTLS
Combining Authentication Methods
For maximum security, use both mTLS and API keys:
tls:
enabled: true
bind_address: "0.0.0.0:8443"
cert_path: "./certs/cert.pem"
key_path: "./certs/key.pem"
auth:
require_client_cert: true
client_ca_cert_path: "./certs/ca-cert.pem"
api_keys:
- name: "production-client"
key_hash: "a1b2c3d4e5f6..."
Both must succeed for authorization.
Security Best Practices
API Keys
- Generate with sufficient entropy:
openssl rand -base64 32 - One key per client for audit/revocation
- Rotate regularly
- Never store plain-text keys in config
mTLS
- Protect CA private key:
chmod 600 ca-key.pem - Use short certificate lifetimes (90 days)
- Implement certificate revocation
- Unique certificates per client
General
- Use TLS in production
- Implement rate limiting
- Monitor authentication logs
- Use network segmentation
Troubleshooting
| Error | Solution |
|---|---|
| “Authentication failed” | Verify key matches hash |
| “Invalid auth request format” | Check JSON format, ensure \n at end |
| “Client certificate verification failed” | Check cert signed by configured CA |
| “require_client_cert without client_ca_cert_path” | Add CA path to config |
Utility: Generate API Key
#!/bin/bash
API_KEY=$(openssl rand -base64 32)
KEY_HASH=$(echo -n "$API_KEY" | sha256sum | cut -d' ' -f1)
echo "API Key: $API_KEY"
echo "Hash: $KEY_HASH"
echo ""
echo "Config entry:"
echo " - name: \"client-name\""
echo " key_hash: \"$KEY_HASH\""