-
Notifications
You must be signed in to change notification settings - Fork 56
Description
Hydra Migration Plan: Complete Auth System Replacement
Executive Summary
Goal: Replace Auth0/Cognito authentication with Ory Hydra + Kratos for unified OAuth2-based authentication and credential management.
Why:
- Single auth system for both user authentication AND external service credentials (Notion, Google Maps, etc.)
- Self-hosted, open-source, no vendor lock-in
- Built for OAuth2 flows needed for MCP server credential injection
- Supports agent-to-agent authentication (future A2A protocol needs)
Timeline: 2-3 weeks
- Week 1: Infrastructure setup + basic auth
- Week 2: OAuth flows + credential management
- Week 3: Migration + testing
Current State Analysis
What We Have
bindu/server/middleware/auth/
├── __init__.py # Exports Auth0Middleware, CognitoMiddleware
├── base.py # Abstract AuthMiddleware base class
├── auth0.py # Auth0 JWT validation (production)
└── cognito.py # Cognito template (not implemented)
Current Flow:
- User authenticates with Auth0
- Gets JWT token
- Sends token to Bindu API
- Auth0Middleware validates token
- Extracts user info, attaches to
request.state.user
Problem: No way to manage user's OAuth credentials for external services (Notion, Google, etc.)
Target Architecture
What We'll Build
┌─────────────────────────────────────────────────────────┐
│ Ory Hydra │
│ - OAuth2 Authorization Server │
│ - Issues tokens for Bindu API access │
│ - Manages OAuth flows for external services │
│ - Token introspection & validation │
│ - Client credentials for M2M (agent-to-agent) │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Ory Kratos │
│ - Identity management (user accounts) │
│ - Password/credential storage │
│ - Social login (Google, GitHub, etc.) │
│ - User profile management │
│ - Links users to their OAuth tokens │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ External OAuth Providers │
│ - Notion API │
│ - Google Maps API │
│ - Slack, GitHub, Linear, etc. │
└─────────────────────────────────────────────────────────┘
Phase 1: Infrastructure Setup
1.1 Docker Compose Setup
File: docker-compose.hydra.yml
Services:
- PostgreSQL (shared database)
- Ory Hydra (OAuth2 server)
- Ory Kratos (Identity management)
- Hydra/Kratos migrations
Ports:
- Hydra Public API: 4444
- Hydra Admin API: 4445
- Kratos Public API: 4433
- Kratos Admin API: 4434
1.2 Hydra Configuration
File: config/hydra/hydra.yml
Key Settings:
- Database DSN
- Token lifetimes (access: 1h, refresh: 30d)
- CORS settings
- Consent/login URLs
- JWKS rotation
- OAuth2 clients (Notion, Google, etc.)
1.3 Kratos Configuration
File: config/kratos/kratos.yml
Key Settings:
- Identity schema
- Self-service flows (login, registration, recovery)
- OIDC providers (Notion, Google, etc.)
- Session management
- CORS settings
1.4 Identity Schema
File: config/kratos/identity.schema.json
Fields:
- Email (primary identifier)
- Name
- OAuth connections (Notion, Google, etc.)
- Metadata (agent preferences, etc.)
Phase 2: Core Authentication Implementation
2.1 New Middleware Structure
bindu/server/middleware/auth/
├── __init__.py # Export HydraMiddleware only
├── base.py # Keep abstract base (minimal changes)
├── hydra.py # NEW: Hydra token validation
├── auth0.py # DEPRECATED: Mark for removal
└── cognito.py # DEPRECATED: Mark for removal
2.2 HydraMiddleware Implementation
File: bindu/server/middleware/auth/hydra.py
Responsibilities:
- Extract Bearer token from Authorization header
- Introspect token with Hydra Admin API
- Validate token is active
- Extract user_id (sub claim)
- Attach user context to request.state
- Handle token expiration errors
Key Methods:
class HydraMiddleware(AuthMiddleware):
def _initialize_provider(self):
# Setup Hydra client
def _validate_token(self, token: str) -> dict:
# POST to /admin/oauth2/introspect
def _extract_user_info(self, token_payload: dict) -> dict:
# Extract sub, scope, client_id2.3 Hydra Client Library
File: bindu/auth/hydra_client.py
Responsibilities:
- Token introspection
- OAuth2 client management
- Token refresh
- Authorization URL generation
Key Methods:
class HydraClient:
async def introspect_token(token: str) -> dict
async def refresh_token(refresh_token: str) -> dict
async def revoke_token(token: str) -> bool
async def create_oauth_client(name: str, redirect_uris: list) -> dict2.4 Kratos Client Library
File: bindu/auth/kratos_client.py
Responsibilities:
- User identity management
- OAuth credential storage/retrieval
- Token refresh for external services
- User profile management
Key Methods:
class KratosClient:
async def get_identity(user_id: str) -> dict
async def get_oauth_token(user_id: str, provider: str) -> dict
async def store_oauth_token(user_id: str, provider: str, tokens: dict)
async def refresh_oauth_token(user_id: str, provider: str) -> dict
async def list_user_connections(user_id: str) -> listPhase 3: OAuth Credential Management
3.1 Credential Requirements in Agent Config
Update: agent_config.json schema
{
"author": "[email protected]",
"name": "research_agent",
"description": "Research assistant with Notion integration",
"deployment": {
"url": "http://localhost:3773",
"expose": true
},
"credential_requirements": {
"notion": {
"type": "oauth2",
"provider": "notion",
"scopes": ["read_content", "search"],
"required": true,
"description": "Access your Notion workspace to search documents"
},
"google_maps": {
"type": "oauth2",
"provider": "google",
"scopes": ["https://www.googleapis.com/auth/maps.readonly"],
"required": false,
"description": "Get location data for enhanced search results"
}
}
}3.2 OAuth Flow Endpoints
File: bindu/server/routes/oauth.py
Endpoints:
GET /oauth/authorize/{provider}
- Initiates OAuth flow for external service
- Parameters:
provider(notion, google, etc.) - Returns: Authorization URL
- Stores state for CSRF protection
GET /oauth/callback/{provider}
- Receives OAuth callback from provider
- Exchanges authorization code for tokens
- Stores tokens in Kratos (linked to user_id)
- Redirects user back to app
GET /oauth/connections
- Lists user's connected services
- Returns: List of providers with connection status
DELETE /oauth/connections/{provider}
- Revokes OAuth connection
- Removes stored tokens from Kratos
3.3 Credential Injection System
File: bindu/penguin/credential_manager.py
Responsibilities:
- Check if user has required credentials
- Fetch credentials from Kratos
- Refresh expired tokens
- Inject credentials into agent context
Key Methods:
class CredentialManager:
async def check_requirements(user_id: str, agent_config: dict) -> dict
async def get_credentials(user_id: str, providers: list) -> dict
async def inject_into_context(context: dict, credentials: dict)3.4 Modified Bindufy
File: bindu/penguin/bindufy.py
Changes:
- Accept
credential_requirementsin config - Wrap handler with credential check
- Return authorization URLs if credentials missing
- Inject credentials into handler context
New Flow:
async def execute_with_credentials(handler, messages, request, config):
user_id = request.state.user["sub"]
# Check credential requirements
credential_manager = CredentialManager()
check_result = await credential_manager.check_requirements(
user_id,
config.get("credential_requirements", {})
)
if not check_result["satisfied"]:
return {
"error": "authorization_required",
"missing_providers": check_result["missing"],
"authorization_urls": check_result["auth_urls"]
}
# Get credentials
credentials = await credential_manager.get_credentials(
user_id,
list(config["credential_requirements"].keys())
)
# Inject into context
context = {
"messages": messages,
"credentials": credentials,
"user": request.state.user
}
return await handler(context)Phase 4: MCP Integration
4.1 MCP Server Credential Injection
Update: Agent handler pattern
Before:
async def handler(messages):
# No access to user credentials
result = agent.run(messages)
return resultAfter:
async def handler(context):
messages = context["messages"]
credentials = context["credentials"]
# Start MCP server with user's credentials
server_params = StdioServerParameters(
command="npx",
args=["-y", "@modelcontextprotocol/server-notion"],
env={
"NOTION_TOKEN": credentials["notion"]["access_token"]
}
)
async with ClientSession(server_params) as session:
await session.initialize()
result = await session.call_tool("notion_search", {...})
return result4.2 MCP Server Configuration
File: bindu/mcp/server_config.py
Responsibilities:
- Map providers to MCP server packages
- Define environment variable names
- Handle server initialization
Example:
MCP_SERVER_CONFIG = {
"notion": {
"package": "@modelcontextprotocol/server-notion",
"env_vars": {
"NOTION_TOKEN": "access_token"
}
},
"google_maps": {
"package": "@modelcontextprotocol/server-google-maps",
"env_vars": {
"GOOGLE_MAPS_API_KEY": "access_token"
}
}
}Phase 5: Migration Strategy
5.1 Deprecation Timeline
Week 1-2: Parallel Operation
- Deploy Hydra alongside Auth0
- Add feature flag:
USE_HYDRA_AUTH=false - Test Hydra with internal users
Week 3: Gradual Migration
- Enable Hydra for new users
- Provide migration path for existing users
- Keep Auth0 running for existing sessions
Week 4: Full Cutover
- Set
USE_HYDRA_AUTH=trueas default - Deprecate Auth0 endpoints
- Remove Auth0 dependencies
5.2 User Migration Flow
For Existing Auth0 Users:
- User logs in with Auth0 (still works)
- Bindu shows migration prompt
- User clicks "Migrate to new auth"
- Creates Kratos account (email + password)
- Links existing agent data to new account
- Auth0 session invalidated
Database Migration:
-- Add hydra_user_id to existing tables
ALTER TABLE users ADD COLUMN hydra_user_id VARCHAR(255);
ALTER TABLE user_agents ADD COLUMN hydra_user_id VARCHAR(255);
-- Create mapping table
CREATE TABLE auth_migration (
auth0_user_id VARCHAR(255) PRIMARY KEY,
hydra_user_id VARCHAR(255) NOT NULL,
migrated_at TIMESTAMP DEFAULT NOW()
);5.3 Backward Compatibility
File: bindu/server/middleware/auth/compat.py
Temporary dual-auth support:
class CompatAuthMiddleware:
async def dispatch(self, request, call_next):
token = self._extract_token(request)
# Try Hydra first
try:
user = await hydra_middleware.validate(token)
request.state.user = user
return await call_next(request)
except:
pass
# Fall back to Auth0
try:
user = await auth0_middleware.validate(token)
request.state.user = user
return await call_next(request)
except:
return JSONResponse({"error": "unauthorized"}, 401)Phase 6: Testing & Validation
6.1 Unit Tests
New Test Files:
tests/unit/test_hydra_middleware.pytests/unit/test_kratos_client.pytests/unit/test_credential_manager.pytests/unit/test_oauth_flows.py
Coverage Requirements:
- Token validation: 100%
- OAuth flows: 90%
- Credential injection: 95%
6.2 Integration Tests
Test Scenarios:
- User registration via Kratos
- User login → Get Hydra token
- Call Bindu API with token
- Authorize Notion → Store credentials
- Call agent → Credentials injected into MCP
- Token refresh flow
- Token revocation
6.3 E2E Tests
File: tests/e2e/test_hydra_auth_flow.py
Full User Journey:
async def test_complete_auth_flow():
# 1. Register user
user = await register_user("[email protected]", "password")
# 2. Login and get token
token = await login_user("[email protected]", "password")
# 3. Call agent (should fail - no Notion creds)
response = await call_agent(token, "Search Notion")
assert response["error"] == "authorization_required"
# 4. Authorize Notion
await authorize_provider(token, "notion")
# 5. Call agent again (should succeed)
response = await call_agent(token, "Search Notion")
assert response["status"] == "success"Phase 7: Documentation Updates
7.1 User Documentation
Files to Update:
README.md- Update auth sectiondocs/authentication.md- Complete rewritedocs/oauth-integration.md- NEW: OAuth credential guidedocs/migration-guide.md- NEW: Auth0 → Hydra migration
7.2 Developer Documentation
Files to Create:
docs/dev/hydra-setup.md- Local development setupdocs/dev/oauth-providers.md- Adding new OAuth providersdocs/dev/credential-injection.md- How credentials reach MCP servers
7.3 API Documentation
Update OpenAPI Spec:
- Remove Auth0-specific endpoints
- Add Hydra OAuth endpoints
- Document credential requirements in agent config
- Add OAuth flow examples
Phase 8: Deployment & Operations
8.1 Infrastructure Requirements
Production Setup:
- PostgreSQL cluster (HA)
- Hydra instances (2+ for HA)
- Kratos instances (2+ for HA)
- Load balancer
- Redis (for session storage)
Resource Estimates:
- Hydra: 512MB RAM, 0.5 CPU per instance
- Kratos: 512MB RAM, 0.5 CPU per instance
- PostgreSQL: 2GB RAM, 1 CPU
8.2 Monitoring & Observability
Metrics to Track:
- Token validation latency
- OAuth flow success rate
- Token refresh rate
- Failed authentication attempts
- Credential fetch latency
Alerts:
- Hydra/Kratos service down
- Database connection failures
- High token validation error rate
- OAuth provider API errors
8.3 Security Considerations
Token Security:
- Short-lived access tokens (1 hour)
- Long-lived refresh tokens (30 days)
- Token rotation on refresh
- Secure token storage (encrypted at rest)
OAuth Security:
- PKCE for public clients
- State parameter for CSRF protection
- Strict redirect URI validation
- Scope validation
Credential Storage:
- Encrypt OAuth tokens in Kratos
- Use Kratos encryption keys
- Regular key rotation
- Audit logging for credential access
File Structure (Complete)
bindu/
├── auth/
│ ├── __init__.py
│ ├── hydra_client.py # NEW: Hydra API client
│ ├── kratos_client.py # NEW: Kratos API client
│ └── ory_config.py # NEW: Ory configuration
│
├── server/
│ ├── middleware/
│ │ └── auth/
│ │ ├── __init__.py # UPDATED: Export HydraMiddleware
│ │ ├── base.py # KEEP: Abstract base
│ │ ├── hydra.py # NEW: Hydra middleware
│ │ ├── auth0.py # DEPRECATED
│ │ └── cognito.py # DEPRECATED
│ │
│ └── routes/
│ ├── oauth.py # NEW: OAuth flow endpoints
│ └── auth.py # NEW: Login/register endpoints
│
├── penguin/
│ ├── bindufy.py # UPDATED: Credential injection
│ └── credential_manager.py # NEW: Credential management
│
└── mcp/
├── server_config.py # NEW: MCP server configs
└── credential_injector.py # NEW: MCP credential injection
config/
├── hydra/
│ ├── hydra.yml # NEW: Hydra configuration
│ └── clients.yml # NEW: OAuth client configs
│
└── kratos/
├── kratos.yml # NEW: Kratos configuration
├── identity.schema.json # NEW: Identity schema
└── oidc_providers.yml # NEW: OIDC provider configs
docs/
├── HYDRA_MIGRATION_PLAN.md # THIS FILE
├── authentication.md # UPDATED
├── oauth-integration.md # NEW
└── migration-guide.md # NEW
tests/
├── unit/
│ ├── test_hydra_middleware.py # NEW
│ ├── test_kratos_client.py # NEW
│ └── test_credential_manager.py # NEW
│
├── integration/
│ └── test_oauth_flows.py # NEW
│
└── e2e/
└── test_hydra_auth_flow.py # NEW
docker-compose.hydra.yml # NEW: Ory stack
.env.hydra # NEW: Hydra environment vars
Implementation Checklist
Week 1: Foundation
- Create
docker-compose.hydra.yml - Configure Hydra (
config/hydra/hydra.yml) - Configure Kratos (
config/kratos/kratos.yml) - Create identity schema
- Deploy Ory stack locally
- Create
HydraClientclass - Create
KratosClientclass - Implement
HydraMiddleware - Write unit tests for middleware
- Test token validation flow
Week 2: OAuth Integration
- Create OAuth route handlers
- Implement authorization flow
- Implement callback handler
- Configure OAuth providers (Notion, Google)
- Create
CredentialManagerclass - Update
bindufyfor credential injection - Test OAuth flow end-to-end
- Write integration tests
- Document OAuth setup
Week 3: Migration & Polish
- Create migration scripts
- Implement dual-auth compatibility layer
- Update all documentation
- Deploy to staging
- Run E2E tests
- Performance testing
- Security audit
- Create migration guide for users
- Deprecate Auth0/Cognito code
- Production deployment
Success Criteria
✅ Functional:
- Users can register/login via Hydra
- Users can authorize external services (Notion, Google)
- Credentials automatically injected into MCP servers
- Token refresh works automatically
- All existing features work with Hydra auth
✅ Performance:
- Token validation < 50ms p99
- OAuth flow completion < 5 seconds
- Credential fetch < 100ms p99
✅ Security:
- No plaintext credential storage
- All tokens encrypted at rest
- CSRF protection on OAuth flows
- Rate limiting on auth endpoints
✅ Testing:
- 80%+ code coverage
- All E2E scenarios passing
- Load testing completed
✅ Documentation:
- Migration guide published
- OAuth integration guide complete
- API docs updated
- Developer setup guide ready
Risks & Mitigations
Risk 1: Ory Learning Curve
Mitigation:
- Start with simple flows
- Use Ory documentation extensively
- Join Ory community Slack
Risk 2: OAuth Provider Quirks
Mitigation:
- Test each provider thoroughly
- Document provider-specific issues
- Create provider-specific adapters if needed
Risk 3: User Migration Complexity
Mitigation:
- Maintain dual-auth during transition
- Provide clear migration instructions
- Offer migration support
Risk 4: Performance Impact
Mitigation:
- Cache token introspection results
- Use connection pooling
- Monitor latency metrics
Risk 5: Credential Security
Mitigation:
- Use Kratos encryption
- Regular security audits
- Implement audit logging
- Follow OWASP guidelines
Post-Migration Cleanup
After 1 month of stable Hydra operation:
-
Remove Auth0 dependencies
- Delete
bindu/server/middleware/auth/auth0.py - Delete
bindu/server/middleware/auth/cognito.py - Remove Auth0 from
pyproject.toml
- Delete
-
Remove compatibility layer
- Delete
compat.py - Remove feature flags
- Delete
-
Clean up documentation
- Remove Auth0 references
- Archive migration guide
-
Database cleanup
- Drop
auth_migrationtable - Remove
auth0_user_idcolumns
- Drop
Future Enhancements
After Hydra is stable:
-
Agent-to-Agent Auth
- M2M client credentials flow
- Agent identity via Hydra
- A2A protocol integration
-
Advanced OAuth
- Dynamic client registration
- Custom scopes per agent
- Consent management UI
-
Enterprise Features
- SSO integration (SAML, LDAP)
- Multi-tenancy
- Role-based access control
-
Developer Experience
- OAuth provider marketplace
- One-click provider setup
- Credential testing tools
Questions to Resolve
-
Hydra Deployment:
- Self-hosted or Ory Cloud?
- Single region or multi-region?
-
OAuth Providers:
- Which providers to support initially?
- Who registers OAuth apps (Bindu or developers)?
-
Credential Scope:
- Per-user-per-agent or per-user-global?
- How to handle credential conflicts?
-
Migration:
- Force migration or optional?
- Timeline for Auth0 shutdown?
-
Pricing Impact:
- Auth0 costs vs. Hydra hosting costs?
- Pass savings to users?
Contact & Support
Implementation Lead: [TBD]
Security Review: [TBD]
Documentation: [TBD]
Resources:
- Ory Docs: https://www.ory.sh/docs
- Ory Community: https://slack.ory.sh
- Hydra GitHub: https://github.com/ory/hydra
- Kratos GitHub: https://github.com/ory/kratos
Last Updated: December 14, 2025
Status: Planning Phase
Next Review: [TBD]
Metadata
Metadata
Assignees
Labels
Type
Projects
Status