Skip to main content

Overview

MCP Server with LangGraph supports pluggable authentication with two built-in providers:

InMemory Provider

Development & TestingPre-defined users for local development. Fast, zero-config.

Keycloak SSO

ProductionEnterprise OpenID Connect/OAuth2 authentication. NEW in v2.1.0 ๐Ÿ†•

Quick Start

InMemory Authentication (Development)

Perfect for local development and testing:
## .env configuration
AUTH_PROVIDER=inmemory
AUTH_MODE=token  # JWT tokens
Pre-defined users:
  • alice - Premium user, admin of organization:acme
  • bob - Standard user, member of organization:acme
  • admin - System administrator
from mcp_server_langgraph.auth.middleware import AuthMiddleware

auth = AuthMiddleware()
token = auth.create_token("alice", expires_in=3600)
print(f"Token: {token}")
Never use InMemory provider in production! It has hard-coded credentials and no real authentication.

Keycloak SSO (Production) ๐Ÿ†•

NEW in v2.1.0: Enterprise-grade authentication with Keycloak.

Features

Standards-compliant OIDC/OAuth2 flows with authorization code grant and refresh tokens.
Centralized identity management across all applications in your organization.
Public key verification without shared secrets. Token validation using Keycloakโ€™s JWKS endpoint.
Automatic refresh token rotation for long-lived sessions without re-authentication.
Flexible role and group mapping from Keycloak to OpenFGA permissions.

Setup

1

Deploy Keycloak

# Docker Compose (development)
docker compose up -d keycloak

# Or deploy to Kubernetes
helm install keycloak bitnami/keycloak \
  --namespace mcp-server-langgraph \
  --set replicaCount=2 \
  --set postgresql.enabled=true
Access Keycloak admin console:
2

Initialize Keycloak

Run the setup script to create realm and client:
python scripts/setup/setup_keycloak.py
This creates:
  • Realm: mcp-server-langgraph
  • Client: langgraph-client (confidential, OIDC)
  • Redirect URIs: Configured for your domain
Save the client secret from the output.
3

Configure Environment

# .env or Kubernetes ConfigMap
AUTH_PROVIDER=keycloak
AUTH_MODE=session  # or token

KEYCLOAK_SERVER_URL=https://sso.yourdomain.com
KEYCLOAK_REALM=mcp-server-langgraph
KEYCLOAK_CLIENT_ID=langgraph-client
KEYCLOAK_CLIENT_SECRET=your-client-secret-here
KEYCLOAK_VERIFY_SSL=true  # Required for production
4

Test Authentication

from mcp_server_langgraph.auth.keycloak import KeycloakClient

client = KeycloakClient()

# Authenticate user
result = await client.authenticate("alice", "password")
print(f"Access Token: {result['access_token']}")
print(f"Refresh Token: {result['refresh_token']}")

# Verify token
user_info = await client.get_user_info(result['access_token'])
print(f"User: {user_info}")

Authentication Modes

Token Mode (Stateless)

JWT tokens issued by Keycloak or InMemory provider.Benefits:
  • Stateless (no server-side session storage)
  • Works with Cloud Run and other serverless platforms
  • Lower infrastructure costs (no Redis required)
Trade-offs:
  • Shorter token lifetimes (refresh required)
  • No concurrent session limits
  • Cannot revoke individual tokens

Session Mode (Stateful) ๐Ÿ†•

Server-side sessions with Redis or in-memory storage.Benefits:
  • Longer session lifetimes (24+ hours)
  • Sliding expiration windows
  • Concurrent session limits per user
  • Instant session revocation
  • User session tracking
Requirements:
  • Redis instance (production)
  • Or in-memory storage (development only)

Security Best Practices

  • Use Keycloak (not InMemory)
  • Set KEYCLOAK_VERIFY_SSL=true
  • Use strong JWT secret (256-bit): openssl rand -base64 32
  • Enable session mode with Redis for sensitive applications
  • Configure appropriate token/session TTLs
  • Enable HTTPS/TLS for all endpoints
  • Store secrets in secret manager (not .env files)
  • Rotate secrets regularly
  • Monitor authentication failures
  • Set up rate limiting
JWT Tokens:
  • Use HS256 or RS256 algorithm
  • Set reasonable expiration (1-4 hours)
  • Include user ID and permissions
  • Validate signature on every request
  • Donโ€™t store sensitive data in tokens
Refresh Tokens (Keycloak):
  • Longer TTL than access tokens
  • Rotate on refresh
  • Revoke on logout
  • Secure storage (HttpOnly cookies)
Redis Sessions:
  • Use password authentication
  • Enable TLS/SSL in production
  • Set appropriate TTL (balance UX vs security)
  • Implement sliding windows carefully
  • Limit concurrent sessions per user
  • Clear sessions on password change
  • Monitor session creation rate
  • Deploy with PostgreSQL (not H2)
  • Enable SSL/TLS
  • Use strong admin password
  • Configure proper redirect URIs
  • Enable brute force protection
  • Set up backup and recovery
  • Regular security updates
  • Monitor admin console access

Troubleshooting

Symptom: 401 UnauthorizedSolutions:
# Check InMemory users
python -c "from mcp_server_langgraph.auth.middleware import InMemoryUserProvider; print(InMemoryUserProvider().users)"

# Verify Keycloak connectivity
curl https://sso.yourdomain.com/realms/mcp-server-langgraph/.well-known/openid-configuration

# Check environment variables
env | grep AUTH
env | grep KEYCLOAK
Symptom: 401 Unauthorized - Token expiredSolutions:
  • Request new token
  • Use refresh token (Keycloak)
  • Increase JWT_EXPIRATION_SECONDS
  • Enable session mode with longer TTL
Symptom: Connection refused to KeycloakSolutions:
# Check Keycloak status
docker compose ps keycloak  # Docker
kubectl get pods -l app=keycloak  # Kubernetes

# Test connectivity
curl http://keycloak:8080/health

# Check logs
docker compose logs keycloak
kubectl logs -l app=keycloak
Symptom: Session not found errorsSolutions:
  • Check Redis connectivity
  • Verify SESSION_TTL_SECONDS not too short
  • Check session was created successfully
  • Verify session ID format
  • Check Redis memory not full

Next Steps


Production Ready: With Keycloak SSO and Redis sessions, your authentication is enterprise-grade!