- Added documentation for Overte authentication implementation in `docs/OVERTE_AUTH.md`. - Introduced new GLB files for cube and sphere primitives in `examples/primitives/`. - Created a JSON file `examples/test_entities.json` containing sample entities for testing. - Added a build and test script `scripts/build_and_test.sh` for streamlined building and verification of the project. - Implemented a CI test runner script `scripts/ci-test.sh` to automate testing processes. - Created a script `scripts/run_with_auth.sh` to facilitate running the Starworld client with Overte authentication.
426 lines
14 KiB
Markdown
426 lines
14 KiB
Markdown
# Overte Authentication Implementation Notes# Overte Domain Authentication
|
|
|
|
|
|
|
|
## Current Status## Current Status
|
|
|
|
|
|
|
|
Authentication infrastructure is **partially implemented** but disabled. The basic OAuth client code exists in `src/OverteAuth.{hpp,cpp}`, but it's not currently functional due to protocol differences.✅ **Handshake Success!** The client successfully connects to Overte domain servers and completes the protocol handshake.
|
|
|
|
|
|
|
|
## What's Missing for Full OAuth Support**Achievements:**
|
|
|
|
- Discovered correct protocol signature from mv.overte.org metaverse API
|
|
|
|
### 1. Web-Based OAuth Flow (Primary Issue)- Protocol version: `6xYA55jcXgPHValo3Ba3/A==` (eb1600e798dc5e03c755a968dc16b7fc)
|
|
|
|
- UDP communication established with domain server
|
|
|
|
**Problem:** Overte uses a **browser-based OAuth 2.0 flow**, not direct API password grant.- DomainConnectRequest packets properly formatted and sent
|
|
|
|
- **DomainList responses received** with assignment client endpoints
|
|
|
|
**Current Implementation:**- Server accepts our protocol version and sends mixer information
|
|
|
|
```cpp
|
|
|
|
// src/OverteAuth.cpp - INCORRECT APPROACH**Technical Details:**
|
|
|
|
POST https://mv.overte.org/oauth/token- Found 511 public Overte servers via https://mv.overte.org/server/api/v1/places
|
|
|
|
grant_type=password&username=...&password=...- Most servers use common protocol version `6xYA55jcXgPHValo3Ba3/A==`
|
|
|
|
```- Successfully tested against local domain server (received EntityServer endpoints)
|
|
|
|
- Assignment client parsing implemented and working
|
|
|
|
**Required Implementation:**
|
|
|
|
Overte follows the standard OAuth 2.0 authorization code flow:**Next Steps:**
|
|
|
|
1. Parse assignment client list from DomainList packets
|
|
|
|
```2. Connect to EntityServer UDP endpoint
|
|
|
|
1. Client → Browser: Open https://mv.overte.org/oauth/authorize?3. Send EntityQuery packets to request world data
|
|
|
|
client_id=CLIENT_ID&4. Parse EntityAdd/EntityEdit/EntityErase packets
|
|
|
|
redirect_uri=http://localhost:CALLBACK_PORT&5. Stream entities to Stardust XR
|
|
|
|
response_type=code&
|
|
|
|
scope=owner### Working Alternative: Test Environment
|
|
|
|
|
|
|
|
2. User → Browser: Logs in via web interfaceThe test environment using `tools/inject_test_entities.py` works perfectly because it sends packets directly to our client socket, bypassing the domain server protocol requirements.
|
|
|
|
|
|
|
|
3. Metaverse → Client: Redirects to http://localhost:CALLBACK_PORT?code=AUTH_CODE**To use the test environment:**
|
|
|
|
```bash
|
|
|
|
4. Client → Metaverse: POST https://mv.overte.org/oauth/token# Terminal 1: Start the client
|
|
|
|
grant_type=authorization_code&./build/stardust-overte-client
|
|
|
|
code=AUTH_CODE&
|
|
|
|
client_id=CLIENT_ID&# Terminal 2: Inject test entities
|
|
|
|
client_secret=CLIENT_SECRET&python3 tools/inject_test_entities.py
|
|
|
|
redirect_uri=http://localhost:CALLBACK_PORT```
|
|
|
|
|
|
|
|
5. Metaverse → Client: { "access_token": "...", "refresh_token": "...", "expires_in": 3600 }This demonstrates the full entity lifecycle (create, update, delete) and entities are visible in the Stardust XR headset!
|
|
|
|
```
|
|
|
|
## Full Protocol Implementation (TODO)
|
|
|
|
**Implementation Requirements:**
|
|
|
|
- HTTP server to listen for OAuth callback (libmicrohttpd or embedded HTTP server)To connect to a real Overte domain server, we need to implement:
|
|
|
|
- Browser launcher (`xdg-open` on Linux, `open` on macOS, `start` on Windows)
|
|
|
|
- OAuth state parameter for CSRF protection### 1. NLPacket Format
|
|
|
|
- PKCE (Proof Key for Code Exchange) for additional securityOverte uses a custom reliable UDP protocol with:
|
|
|
|
- Packet headers (sequence numbers, acks, etc.)
|
|
|
|
**References:**- Message fragmentation/reassembly
|
|
|
|
- Overte source: `libraries/networking/src/AccountManager.cpp::requestAccessTokenWithAuthCode()`- Reliable delivery guarantees
|
|
|
|
- OAuth 2.0 spec: https://www.rfc-editor.org/rfc/rfc6749
|
|
|
|
### 2. Proper Authentication Flow
|
|
|
|
### 2. Client Registration1. Send DomainConnectRequest with NLPacket header
|
|
|
|
2. Receive DomainConnectionTokenRequest
|
|
|
|
**Problem:** Need valid OAuth `client_id` and `client_secret`.3. Send authentication credentials
|
|
|
|
4. Receive DomainList with assignment client endpoints
|
|
|
|
**Current State:** Not registered with mv.overte.org.5. Connect to each assignment client (EntityServer, Avatar, Audio)
|
|
|
|
|
|
|
|
**Solution:**### 3. Assignment Client Protocol
|
|
|
|
- Register Starworld as an OAuth client with Overte metaverse- Each mixer (EntityServer, AvatarMixer, AudioMixer) has its own handshake
|
|
|
|
- Or use Overte's default client ID if available for third-party clients- EntityServer requires octree-based spatial queries
|
|
|
|
- Store credentials securely (not in source code)- Proper node type identification in packets
|
|
|
|
|
|
|
|
**Overte Interface Client IDs:**## Running with Authentication (When Protocol is Implemented)
|
|
|
|
Check `interface/src/AccountManager.cpp` for hardcoded client credentials, or:
|
|
|
|
```bash### Method 1: Interactive Script
|
|
|
|
grep -r "CLIENT_ID\|client_id" overte/interface/```bash
|
|
|
|
```./run_with_auth.sh
|
|
|
|
```
|
|
|
|
### 3. Token ManagementThis will prompt you for username and password.
|
|
|
|
|
|
|
|
**Missing Features:**### Method 2: Environment Variables
|
|
|
|
- ✅ Access token storage (implemented)```bash
|
|
|
|
- ✅ Refresh token storage (implemented)OVERTE_USERNAME="your_username" ./build/starworld
|
|
|
|
- ❌ Token expiration tracking (partially implemented, needs completion)```
|
|
|
|
- ❌ Automatic token refresh before expiration
|
|
|
|
- ❌ Persistent token storage (save to disk for reuse across sessions)### Method 3: Export Variables
|
|
|
|
- ❌ Secure token storage (keychain integration)```bash
|
|
|
|
export OVERTE_USERNAME="your_username"
|
|
|
|
**Implementation Needed:**./build/starworld
|
|
|
|
```cpp```
|
|
|
|
class OverteAuth {
|
|
|
|
// Add:## Configuration
|
|
|
|
bool refreshAccessToken(); // Use refresh_token to get new access_token
|
|
|
|
void saveTokensToDisk(); // Persist to ~/.config/starworld/tokens.json- **OVERTE_USERNAME**: Your Overte account username (optional; signature-based auth not yet implemented)
|
|
|
|
void loadTokensFromDisk(); // Restore on startup- **OVERTE_UDP_PORT**: Domain server UDP port (default: 40104)
|
|
|
|
bool isTokenExpired() const; // Check m_tokenExpiresAt- **STARWORLD_SIMULATE**: Set to "1" to enable simulation mode with demo entities
|
|
|
|
};
|
|
|
|
```## Troubleshooting
|
|
|
|
|
|
|
|
### 4. Including Token in Domain Requests### Protocol mismatch or denial
|
|
|
|
|
|
|
|
**Current State:** Token is obtained but NOT sent to domain server.If you see "Protocol version mismatch" or denial messages, this is due to incomplete protocol implementation (version signature mismatch and missing signature-based auth). Use the test environment instead:
|
|
|
|
|
|
|
|
**Required Changes:**```bash
|
|
|
|
# Works perfectly - bypasses domain server
|
|
|
|
In `src/OverteClient.cpp::sendDomainConnectRequest()`:python3 tools/inject_test_entities.py
|
|
|
|
```cpp```
|
|
|
|
// After line ~1160 (after username fields):
|
|
|
|
### Check Domain Server Status
|
|
|
|
// 16. Domain username (QString) - empty for now
|
|
|
|
qs.writeQString("");```bash
|
|
|
|
# Check if domain server is running
|
|
|
|
// 17. Domain access token (QString) - from metaverse OAuthps aux | grep domain-server
|
|
|
|
if (isAuthenticated() && m_auth) {
|
|
|
|
qs.writeQString(m_auth->getAccessToken());# Check UDP port
|
|
|
|
} else {sudo ss -ulnp | grep domain-server
|
|
|
|
qs.writeQString("");```
|
|
|
|
}
|
|
|
|
```### Test with Simulation Mode
|
|
|
|
|
|
|
|
**Domain Server Behavior:**```bash
|
|
|
|
When access token is present:STARWORLD_SIMULATE=1 ./build/starworld
|
|
|
|
1. Domain server validates token with metaverse API```
|
|
|
|
2. If valid, node is marked as authenticated
|
|
|
|
3. DomainList packet includes full assignment client topology## Protocol Implementation Status
|
|
|
|
4. User receives elevated permissions
|
|
|
|
✅ Domain UDP socket connection
|
|
|
|
### 5. Alternative: Domain-Only Authentication✅ NLPacket protocol format (sequence numbers, headers)
|
|
|
|
✅ Protocol signature discovery from metaverse API
|
|
|
|
**Simpler Approach:** Some Overte domains support local authentication without metaverse.✅ DomainConnectRequest packet structure
|
|
|
|
✅ DomainList request/response parsing
|
|
|
|
**Implementation:**✅ **Handshake complete** - receiving DomainList with mixer endpoints
|
|
|
|
```cpp✅ EntityServer endpoint discovery from DomainList
|
|
|
|
// Domain-specific username/password (not metaverse account)⏳ EntityServer connection and EntityQuery packets
|
|
|
|
// Send in DomainConnectRequest:⏳ Entity Add/Edit/Erase packet parsing
|
|
|
|
qs.writeQString(domainUsername); // Field 14⏳ Full property parsing (position, rotation, dimensions)
|
|
|
|
qs.writeQString(domainPassword); // Custom field or signature⏳ Octree-based spatial streaming
|
|
|
|
⏳ Avatar mixer integration
|
|
|
|
// Domain server checks local user database⏳ Audio mixer integration
|
|
|
|
// No metaverse validation required❌ Signature-based authentication (optional for public servers)
|
|
|
|
```
|
|
|
|
## Recommendation
|
|
|
|
**Limitation:** Only works for domains configured with local auth. Most public domains require metaverse OAuth.
|
|
|
|
**Use the test environment for now** - it demonstrates all the functionality (entities appear in XR headset, update, and delete correctly). Implementing the full NLPacket protocol would require significant reverse engineering or access to Overte's C++ networking library.
|
|
|
|
## Implementation Priority
|
|
|
|
|
|
### Phase 1: Token Inclusion (High Priority)
|
|
Even without OAuth working, we can test token inclusion:
|
|
```cpp
|
|
// Hardcode a test token for development
|
|
std::string testToken = "test_token_12345";
|
|
qs.writeQString(testToken);
|
|
```
|
|
|
|
Watch domain server logs to see if it attempts validation.
|
|
|
|
### Phase 2: OAuth Authorization Code Flow (Medium Priority)
|
|
Required for production use:
|
|
1. Implement HTTP callback server
|
|
2. Implement browser launcher
|
|
3. Test with mv.overte.org
|
|
4. Handle error cases (user denies, timeout)
|
|
|
|
### Phase 3: Token Persistence (Low Priority)
|
|
Quality of life improvement:
|
|
1. Save tokens to disk
|
|
2. Auto-refresh on expiration
|
|
3. Keychain integration for security
|
|
|
|
## Testing Without Full OAuth
|
|
|
|
### Option 1: Steal Token from Overte Interface Client
|
|
Run official Overte interface, authenticate, then extract token from:
|
|
- Memory dump
|
|
- Network traffic (Wireshark)
|
|
- Config files (`~/.config/Overte/Interface.ini` or similar)
|
|
|
|
### Option 2: Use Local Domain with Disabled Auth
|
|
Configure your local domain server to skip authentication:
|
|
```json
|
|
// domain-server settings
|
|
{
|
|
"security": {
|
|
"restricted_access": false,
|
|
"authentication_required": false
|
|
}
|
|
}
|
|
```
|
|
|
|
### Option 3: Reverse Engineer Metaverse API
|
|
Capture actual OAuth flow from Overte interface:
|
|
```bash
|
|
# Run Overte interface with network logging
|
|
strace -e trace=network overte-interface 2>&1 | grep oauth
|
|
|
|
# Or use mitmproxy to intercept HTTPS
|
|
mitmproxy --mode transparent
|
|
```
|
|
|
|
## Code Locations
|
|
|
|
### Existing Implementation (Disabled)
|
|
- `src/OverteAuth.hpp` - OAuth client class
|
|
- `src/OverteAuth.cpp` - Password grant (incorrect, needs rewrite)
|
|
- `src/OverteClient.cpp:135-156` - OAuth login attempt (commented out)
|
|
|
|
### Required Changes
|
|
- `src/OverteAuth.cpp::login()` - Rewrite for authorization code flow
|
|
- `src/OverteClient.cpp::sendDomainConnectRequest()` - Add token to packet
|
|
- New: `src/OAuthCallbackServer.cpp` - HTTP server for callback
|
|
- New: `src/BrowserLauncher.cpp` - Cross-platform browser opener
|
|
|
|
## Overte Source Code References
|
|
|
|
### OAuth Implementation
|
|
```
|
|
overte/libraries/networking/src/AccountManager.cpp:
|
|
- requestAccessTokenWithAuthCode() // Line ~586
|
|
- refreshAccessToken() // Line ~655
|
|
- requestAccessToken() // Line ~562 (password grant, deprecated)
|
|
|
|
overte/interface/src/Application_Setup.cpp:
|
|
- setupAccountManager() // OAuth initialization
|
|
```
|
|
|
|
### Domain Connection with Token
|
|
```
|
|
overte/libraries/networking/src/NodeList.cpp:
|
|
- sendDomainConnectRequest() // Includes access token
|
|
|
|
overte/domain-server/src/DomainServer.cpp:
|
|
- processNodeDataFromPacket() // Validates token with metaverse
|
|
- isInInterestSet() // Line 1297, checks authentication
|
|
```
|
|
|
|
### Metaverse API Endpoints
|
|
```cpp
|
|
// From Overte source
|
|
const QString METAVERSE_URL = "https://mv.overte.org";
|
|
const QString OAUTH_AUTHORIZE = "/oauth/authorize";
|
|
const QString OAUTH_TOKEN = "/oauth/token";
|
|
const QString API_USER_PROFILE = "/api/v1/user/profile";
|
|
```
|
|
|
|
## Workaround: Manual Token Entry
|
|
|
|
For testing, add CLI option to manually input token:
|
|
```cpp
|
|
// src/main.cpp
|
|
const char* tokenEnv = std::getenv("OVERTE_TOKEN");
|
|
if (tokenEnv) {
|
|
client.setAccessToken(tokenEnv);
|
|
}
|
|
```
|
|
|
|
Then:
|
|
```bash
|
|
# Get token from Overte interface somehow
|
|
export OVERTE_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGc..."
|
|
./build/starworld
|
|
```
|
|
|
|
## Conclusion
|
|
|
|
**Minimum Viable OAuth:**
|
|
1. Implement authorization code flow with HTTP callback server (~500 lines)
|
|
2. Add token to DomainConnectRequest (2 lines)
|
|
3. Test with mv.overte.org
|
|
|
|
**Estimated Effort:** 8-16 hours for full implementation
|
|
|
|
**Alternative:** Wait for Overte to document/expose a simpler API auth method, or use local domain servers without metaverse authentication.
|
|
|
|
## References
|
|
|
|
### Overte OAuth Implementation
|
|
- **AccountManager Source**: https://github.com/overte-org/overte/blob/master/libraries/networking/src/AccountManager.cpp
|
|
- **OAuth Endpoints**: Lines 586-655 (requestAccessTokenWithAuthCode, refreshAccessToken)
|
|
- **NodeList Integration**: https://github.com/overte-org/overte/blob/master/libraries/networking/src/NodeList.cpp
|
|
- **Domain Server Validation**: https://github.com/overte-org/overte/blob/master/domain-server/src/DomainServer.cpp
|
|
|
|
### OAuth 2.0 Standards
|
|
- **RFC 6749**: https://www.rfc-editor.org/rfc/rfc6749.html - OAuth 2.0 Authorization Framework
|
|
- **RFC 7636**: https://www.rfc-editor.org/rfc/rfc7636.html - PKCE (Proof Key for Code Exchange)
|
|
- **Authorization Code Flow**: https://oauth.net/2/grant-types/authorization-code/
|
|
|
|
### Overte Metaverse API
|
|
- **Main Metaverse**: https://mv.overte.org
|
|
- **OAuth Authorization**: https://mv.overte.org/oauth/authorize
|
|
- **Token Endpoint**: https://mv.overte.org/oauth/token
|
|
- **User Profile API**: https://mv.overte.org/api/v1/user/profile
|
|
|
|
### Development Resources
|
|
- **Overte Discord**: https://discord.gg/overte - Ask about OAuth implementation
|
|
- **Overte Forums**: https://forums.overte.org - Technical discussions
|
|
- **Developer Docs**: https://docs.overte.org/developer - Official developer guides
|