Description
Replace the current hardcoded backend credential system with proper user authentication. The backend should act on behalf of authenticated users using their identity/permissions, rather than requiring manual configuration of API keys and tokens in environment variables.
Current Issues
Backend Credential Management Problems
- Hardcoded Credentials: Backend requires manual configuration of Google credentials and Jira tokens in .env files
- Single Identity: All users share the same backend service account - no per-user permissions
- No Multi-tenancy: Can't support multiple users with different Google/Jira accounts
- Manual Setup: Each deployment requires manual credential configuration
- Security Risk: Backend credentials give broad access to all resources
- No User Context: Can't track which user performed which action
🚨 Claude Proposed Solution (Read/Implement with caution) 🚨
Current Flow (Single Backend Identity)
┌─────────────┐ ┌──────────────────┐
│ Client │ ─────────────────> │ Backend Server │ Backend credentials (.env)
│ (Any User) │ │ (Service Acct) │ ────────────────────────────> Google/Jira
└─────────────┘ └──────────────────┘ (Acts as single user)
Proposed Flow (User Identity-Based)
Option 1: User OAuth Flow
┌─────────────┐ ┌──────────────────┐
│ Client │ 1. Login/Auth │ Backend Server │ User's OAuth token
│ (User A) │ ─────────────────>│ (Authenticates │ ────────────────────> Google/Jira
│ │ 2. User token │ User A) │ (Acts as User A)
└─────────────┘ <─────────────────└──────────────────┘
Option 2: Service Account with Domain-Wide Delegation
┌─────────────┐ ┌──────────────────┐
│ Client │ User email │ Backend Server │ Impersonate user@domain.com
│ (user@ │ ─────────────────>│ (Service Acct │ ─────────────────────────────> Google
│ domain) │ │ with DWD) │ (Acts as user@domain.com)
└─────────────┘ └──────────────────┘
Implementation
Option 1: User OAuth Flow (Recommended for Multi-User Deployments)
1. User Authentication Endpoints
# src/auth/oauth_handler.py
from fastapi import FastAPI, Depends, HTTPException
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import Flow
import jwt
app = FastAPI()
class UserAuthManager:
"""Manage user OAuth authentication."""
def __init__(self):
self.sessions = {} # In production, use Redis/database
async def initiate_google_oauth(self, user_id: str):
"""Start Google OAuth flow for user."""
flow = Flow.from_client_secrets_file(
'client_secrets.json',
scopes=[
'https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/documents',
'https://www.googleapis.com/auth/drive.readonly'
],
redirect_uri='http://localhost:8000/auth/google/callback'
)
auth_url, state = flow.authorization_url(
access_type='offline',
include_granted_scopes='true'
)
self.sessions[state] = user_id
return auth_url
async def handle_oauth_callback(self, code: str, state: str):
"""Handle OAuth callback and store user credentials."""
flow = Flow.from_client_secrets_file(
'client_secrets.json',
scopes=None,
state=state,
redirect_uri='http://localhost:8000/auth/google/callback'
)
flow.fetch_token(code=code)
credentials = flow.credentials
user_id = self.sessions.pop(state)
# Store credentials securely (encrypt in production)
await self.store_user_credentials(user_id, {
'token': credentials.token,
'refresh_token': credentials.refresh_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret,
'scopes': credentials.scopes
})
return user_id
@app.get("/auth/google/login")
async def google_login(user_id: str):
"""Initiate Google OAuth login."""
auth_url = await auth_manager.initiate_google_oauth(user_id)
return {"auth_url": auth_url}
@app.get("/auth/google/callback")
async def google_callback(code: str, state: str):
"""Handle Google OAuth callback."""
user_id = await auth_manager.handle_oauth_callback(code, state)
return {"status": "authenticated", "user_id": user_id}
2. User-Context API Calls
# src/services/user_google_tools.py
class UserGoogleTools:
"""Google API calls using user's credentials."""
async def get_user_credentials(self, user_id: str) -> Credentials:
"""Retrieve user's stored credentials."""
creds_data = await credentials_store.get(user_id)
credentials = Credentials(
token=creds_data['token'],
refresh_token=creds_data['refresh_token'],
token_uri=creds_data['token_uri'],
client_id=creds_data['client_id'],
client_secret=creds_data['client_secret'],
scopes=creds_data['scopes']
)
# Refresh if expired
if credentials.expired and credentials.refresh_token:
credentials.refresh(Request())
await self.update_stored_credentials(user_id, credentials)
return credentials
async def create_calendar_event(
self,
user_id: str,
title: str,
description: str,
start_time: str,
duration_minutes: int,
attendees: List[str]
):
"""Create calendar event using user's credentials."""
credentials = await self.get_user_credentials(user_id)
service = build('calendar', 'v3', credentials=credentials)
# Create event on user's calendar
event = service.events().insert(
calendarId='primary',
body={
'summary': title,
'description': description,
# ... rest of event details
}
).execute()
return event['id']
Option 2: Service Account with Domain-Wide Delegation (Google Workspace)
1. Service Account Setup
# src/auth/service_account_delegated.py
from google.oauth2 import service_account
from googleapiclient.discovery import build
class DelegatedServiceAccount:
"""Service account with domain-wide delegation."""
def __init__(self, service_account_file: str):
self.service_account_file = service_account_file
self.scopes = [
'https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/documents',
'https://www.googleapis.com/auth/drive.readonly'
]
def get_delegated_credentials(self, user_email: str):
"""Get credentials impersonating a specific user."""
credentials = service_account.Credentials.from_service_account_file(
self.service_account_file,
scopes=self.scopes,
subject=user_email # Impersonate this user
)
return credentials
async def create_calendar_event_for_user(
self,
user_email: str,
title: str,
description: str,
start_time: str,
duration_minutes: int
):
"""Create calendar event as specific user."""
credentials = self.get_delegated_credentials(user_email)
service = build('calendar', 'v3', credentials=credentials)
# Create event on user's calendar
event = service.events().insert(
calendarId='primary',
body={
'summary': title,
'description': description,
# ... event details
}
).execute()
return event['id']
2. Updated Workflow Integration
# src/core/workflow_servers/action_items_server.py
class ActionItemsRequest(BaseModel):
user_email: str # NEW: User's email for identity
meeting_notes: str
date: str
@app.post("/generate")
async def generate_action_items(request: ActionItemsRequest):
"""Generate action items for specific user."""
# Use user's identity for all operations
google_tools = DelegatedServiceAccount('service_account.json')
# Read meeting notes from user's Drive
notes_content = await google_tools.read_document_for_user(
user_email=request.user_email,
document_id=request.notes_doc_id
)
# Generate action items...
# Dispatch to agents with user context...
3. CLI Client Changes
# src/clients/meeting_actions_client.py
class MeetingActionsClient:
def run(self):
# Get user's email (they must be in the Google Workspace domain)
user_email = self.get_input("Your email", default=os.getenv("USER_EMAIL"))
# All backend calls include user email
response = requests.post(
f"{self.url}/generate",
json={
"user_email": user_email, # Backend impersonates this user
"meeting_notes": notes,
"date": date
}
)
Benefits
1. User-Based Permissions
- ✅ Each user operates with their own Google/Jira permissions
- ✅ Users can only access their own resources
- ✅ No need for backend to have broad access to all resources
- ✅ Respects existing Google Workspace/Jira permissions
2. Multi-Tenancy Support
- ✅ Multiple users can use the same backend deployment
- ✅ Each user has isolated access to their own data
- ✅ No credential configuration needed per user
- ✅ Scalable to organization-wide deployment
3. Security
- ✅ No hardcoded credentials in .env files
- ✅ Principle of least privilege - users have only their own permissions
- ✅ Token refresh handled automatically
- ✅ Audit trail shows which user performed which action
4. Simplified Deployment
- ✅ No manual credential setup for each backend instance
- ✅ OAuth flow guides users through authentication
- ✅ Service account option for Google Workspace deployments
- ✅ Single setup for entire organization
Implementation Comparison
| Feature |
Option 1: User OAuth |
Option 2: Service Account DWD |
| Best For |
Multi-user SaaS, public deployment |
Google Workspace organizations |
| User Experience |
One-time OAuth login per user |
Just provide email address |
| Setup Complexity |
Medium (OAuth app setup) |
High (requires Workspace admin) |
| Google Workspace |
Not required |
Required |
| Jira Support |
Yes (user OAuth) |
Limited (needs equivalent) |
| Token Storage |
Backend stores per-user tokens |
Service account only |
| Permissions |
User's own permissions |
User's permissions (via delegation) |
Recommended Approach
Start with Option 1 (User OAuth) because:
- Works for both Google Workspace and personal Google accounts
- Easier to set up initially
- Better for Jira integration
- Can add Option 2 later for Workspace-specific deployments
Acceptance Criteria
Option 1 (User OAuth) - Recommended
Option 2 (Service Account DWD) - Optional
Priority: 🔴 High
Effort: 12-16 hours (Option 1), 8-10 hours (Option 2 if Workspace-only)
Difficulty: High
Security Impact: High - Eliminates hardcoded credentials, enables multi-user support
Description
Replace the current hardcoded backend credential system with proper user authentication. The backend should act on behalf of authenticated users using their identity/permissions, rather than requiring manual configuration of API keys and tokens in environment variables.
Current Issues
Backend Credential Management Problems
🚨 Claude Proposed Solution (Read/Implement with caution) 🚨
Current Flow (Single Backend Identity)
Proposed Flow (User Identity-Based)
Option 1: User OAuth Flow
Option 2: Service Account with Domain-Wide Delegation
Implementation
Option 1: User OAuth Flow (Recommended for Multi-User Deployments)
1. User Authentication Endpoints
2. User-Context API Calls
Option 2: Service Account with Domain-Wide Delegation (Google Workspace)
1. Service Account Setup
2. Updated Workflow Integration
3. CLI Client Changes
Benefits
1. User-Based Permissions
2. Multi-Tenancy Support
3. Security
4. Simplified Deployment
Implementation Comparison
Recommended Approach
Start with Option 1 (User OAuth) because:
Acceptance Criteria
Option 1 (User OAuth) - Recommended
Option 2 (Service Account DWD) - Optional
Priority: 🔴 High
Effort: 12-16 hours (Option 1), 8-10 hours (Option 2 if Workspace-only)
Difficulty: High
Security Impact: High - Eliminates hardcoded credentials, enables multi-user support