5.5 KiB
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:
$ ./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:
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
localStoragewith key"token" - Example token payload:
{ "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:
# 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):
{"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
anonLoginGraphQL mutation - Token storage and usage for WebSocket connections
- Automatic reconnection with token refresh
❌ Not Working
- Email/password authentication
- Token refresh (no
refreshTokenmutation 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
-
Immediate: Implement Option 2 (Manual Token Provision)
- Add
Tokenfield to config - If provided, skip
anonLoginand use the token directly - Document how users can extract their token
- Add
-
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
-
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 mutationscmd/test-introspection/main.go- GraphQL schema introspectioncmd/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:
- Deep analysis of their minified JavaScript
- User providing more information about the auth flow
- Implementing manual token provision as a workaround