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)

  • Overview
  • Configuration
  • Usage
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) 🆕

  • Overview
  • Configuration
  • Usage
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!