Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Authentication

Rockfish MCP supports multiple authentication mechanisms.

Overview

MethodTransportDescription
API Key (JSON)Raw TLSJSON frame before MCP session
Bearer TokenHTTP/WSStandard Authorization header
Mutual TLS (mTLS)Any TLSClient certificate verification

These can be combined for defense-in-depth.

Bearer Token Authentication (HTTP Mode)

Standard HTTP authentication using Authorization: Bearer <token> header.

Setup

  1. 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)"
    
  2. 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

  1. Client connects via TLS
  2. Client sends: {"api_key": "your-secret-key"}\n
  3. Server responds: {"success": true/false, "message": "..."}\n
  4. 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

ErrorSolution
“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\""