# Kosmi Authentication Discovery

## Date: November 1, 2025

## Summary
Investigation into Kosmi's email/password authentication mechanism reveals a non-standard implementation that requires further reverse engineering.

## Findings

### 1. GraphQL API Analysis
**Endpoint**: `https://engine.kosmi.io/`

**Available Mutations**:
```bash
$ ./bin/test-introspection | jq '.data.__schema.mutationType.fields[] | .name'
"anonLogin"
"slackLogin"
```

**Key Discovery**: There is NO `login`, `emailLogin`, or `passwordLogin` mutation in the GraphQL API.

### 2. Anonymous Login (Working)
The `anonLogin` mutation works and is currently implemented:
```graphql
mutation {
  anonLogin {
    token
    user {
      id
      displayName
    }
  }
}
```

### 3. Email/Password Login (Mystery)
**Observations**:
- Email/password login works successfully in the browser
- After login, a JWT token appears in `localStorage` with key `"token"`
- Example token payload:
  ```json
  {
    "aud": "kosmi",
    "exp": 1793465205,
    "iat": 1762015605,
    "iss": "kosmi",
    "jti": "1c7f9db8-9a65-4909-92c0-1c646103bdee",
    "nbf": 1762015604,
    "sub": "4ec0b428-712b-49d6-8551-224295 45d29b",
    "typ": "access"
  }
  ```
- Token expires in ~1 year
- Algorithm: HS512

**REST API Endpoints Found**:
```bash
# Both return 400 with empty error message
POST https://engine.kosmi.io/auth/login
POST https://engine.kosmi.io/login

# Response format:
{
  "errors": [
    {
      "message": ""
    }
  ]
}
```

**Tested Request Formats** (all failed):
```json
{"email": "...", "password": "..."}
{"username": "...", "password": "..."}
```

### 4. Possible Authentication Mechanisms

#### Theory 1: Client-Side JWT Generation
- The browser might be generating JWTs client-side
- This would be a security concern but would explain why there's no server endpoint
- Would require extracting the signing key from the JavaScript bundle

#### Theory 2: Hidden Authentication Flow
- The password might be hashed/processed client-side before transmission
- Could be using SRP (Secure Remote Password) or similar protocol
- Would require analyzing the minified JavaScript

#### Theory 3: Separate Authentication Service
- Kosmi might use a third-party auth service (not Firebase/Auth0/Cognito - those were checked)
- The service might not be directly accessible via HTTP

#### Theory 4: WebSocket-Based Authentication
- Authentication might happen over the WebSocket connection
- The REST endpoints might be red herrings

### 5. Browser Monitoring Attempts
Multiple attempts were made to capture the authentication request:
- Playwright network interception (failed - page reloads cleared interceptors)
- JavaScript fetch() hooking (failed - page reloads)
- Browser MCP tools (successful login but couldn't capture request body)

**Successful Test**:
- Used browser MCP tools to log in with credentials: `email@email.com` / `password`
- Login succeeded
- Token appeared in localStorage
- But the actual HTTP request was not captured

## Current Implementation Status

### ✅ Working
- Anonymous authentication via `anonLogin` GraphQL mutation
- Token storage and usage for WebSocket connections
- Automatic reconnection with token refresh

### ❌ Not Working
- Email/password authentication
- Token refresh (no `refreshToken` mutation found in GraphQL API)

## Recommendations

### Option 1: Anonymous-Only (Current State)
- Document that only anonymous login is supported
- Users can still connect to rooms anonymously
- This is sufficient for basic bot functionality

### Option 2: Manual Token Provision
- Allow users to provide a pre-obtained token in the config
- Users would log in via browser, extract token from localStorage
- Bot uses the provided token directly
- **Pros**: Simple, works immediately
- **Cons**: Tokens expire (though they last ~1 year), manual process

### Option 3: Deep Reverse Engineering
- Download and deobfuscate `core.js` (~several MB)
- Find the authentication logic
- Replicate it in Go
- **Pros**: Full automation
- **Cons**: Time-consuming, fragile (breaks if Kosmi updates their code)

### Option 4: Browser Automation
- Use Playwright/Chromedp to automate browser login
- Extract token from localStorage after login
- Use token for bot connection
- **Pros**: Works with any auth changes
- **Cons**: Requires browser, more complex setup

## Next Steps

1. **Immediate**: Implement Option 2 (Manual Token Provision)
   - Add `Token` field to config
   - If provided, skip `anonLogin` and use the token directly
   - Document how users can extract their token

2. **Future**: Attempt Option 3 if user provides more information
   - User might have insights into how their own auth works
   - Could provide network HAR file from browser DevTools

3. **Alternative**: Contact Kosmi
   - Ask if they have a documented API for bots
   - Request official authentication method

## Test Credentials Used
- Email: `email@email.com`
- Password: `password`
- These credentials successfully logged in via browser

## Files Created During Investigation
- `cmd/test-login/main.go` - Test GraphQL login mutations
- `cmd/test-introspection/main.go` - GraphQL schema introspection
- `cmd/monitor-auth/main.go` - Playwright-based traffic monitoring (had issues)

## Conclusion
Kosmi's email/password authentication uses a non-standard mechanism that is not exposed through their GraphQL API. Further investigation would require either:
1. Deep analysis of their minified JavaScript
2. User providing more information about the auth flow
3. Implementing manual token provision as a workaround

