Skip to content

[Feature]: Hydra Authentication #60

@raahulrahl

Description

@raahulrahl

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:

  1. User authenticates with Auth0
  2. Gets JWT token
  3. Sends token to Bindu API
  4. Auth0Middleware validates token
  5. 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_id

2.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) -> dict

2.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) -> list

Phase 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_requirements in 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 result

After:

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 result

4.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=true as default
  • Deprecate Auth0 endpoints
  • Remove Auth0 dependencies

5.2 User Migration Flow

For Existing Auth0 Users:

  1. User logs in with Auth0 (still works)
  2. Bindu shows migration prompt
  3. User clicks "Migrate to new auth"
  4. Creates Kratos account (email + password)
  5. Links existing agent data to new account
  6. 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.py
  • tests/unit/test_kratos_client.py
  • tests/unit/test_credential_manager.py
  • tests/unit/test_oauth_flows.py

Coverage Requirements:

  • Token validation: 100%
  • OAuth flows: 90%
  • Credential injection: 95%

6.2 Integration Tests

Test Scenarios:

  1. User registration via Kratos
  2. User login → Get Hydra token
  3. Call Bindu API with token
  4. Authorize Notion → Store credentials
  5. Call agent → Credentials injected into MCP
  6. Token refresh flow
  7. 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 section
  • docs/authentication.md - Complete rewrite
  • docs/oauth-integration.md - NEW: OAuth credential guide
  • docs/migration-guide.md - NEW: Auth0 → Hydra migration

7.2 Developer Documentation

Files to Create:

  • docs/dev/hydra-setup.md - Local development setup
  • docs/dev/oauth-providers.md - Adding new OAuth providers
  • docs/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 HydraClient class
  • Create KratosClient class
  • 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 CredentialManager class
  • Update bindufy for 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:

  1. Remove Auth0 dependencies

    • Delete bindu/server/middleware/auth/auth0.py
    • Delete bindu/server/middleware/auth/cognito.py
    • Remove Auth0 from pyproject.toml
  2. Remove compatibility layer

    • Delete compat.py
    • Remove feature flags
  3. Clean up documentation

    • Remove Auth0 references
    • Archive migration guide
  4. Database cleanup

    • Drop auth_migration table
    • Remove auth0_user_id columns

Future Enhancements

After Hydra is stable:

  1. Agent-to-Agent Auth

    • M2M client credentials flow
    • Agent identity via Hydra
    • A2A protocol integration
  2. Advanced OAuth

    • Dynamic client registration
    • Custom scopes per agent
    • Consent management UI
  3. Enterprise Features

    • SSO integration (SAML, LDAP)
    • Multi-tenancy
    • Role-based access control
  4. Developer Experience

    • OAuth provider marketplace
    • One-click provider setup
    • Credential testing tools

Questions to Resolve

  1. Hydra Deployment:

    • Self-hosted or Ory Cloud?
    • Single region or multi-region?
  2. OAuth Providers:

    • Which providers to support initially?
    • Who registers OAuth apps (Bindu or developers)?
  3. Credential Scope:

    • Per-user-per-agent or per-user-global?
    • How to handle credential conflicts?
  4. Migration:

    • Force migration or optional?
    • Timeline for Auth0 shutdown?
  5. Pricing Impact:

    • Auth0 costs vs. Hydra hosting costs?
    • Pass savings to users?

Contact & Support

Implementation Lead: [TBD]
Security Review: [TBD]
Documentation: [TBD]

Resources:


Last Updated: December 14, 2025
Status: Planning Phase
Next Review: [TBD]

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

Status

In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions