Files
IRC-kosmi-relay/AUTH_DISCOVERY.md
cottongin dd398c9a8c sync
2025-11-01 21:00:16 -04:00

180 lines
5.5 KiB
Markdown

# 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