- 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.
14 KiB
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 SupportAchievements:
- 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
// 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-openon Linux,openon macOS,starton 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
- Receive DomainConnectionTokenRequest
Problem: Need valid OAuth client_id and client_secret.3. Send authentication credentials
- 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:
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
};
### 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:
// 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:
- Implement HTTP callback server
- Implement browser launcher
- Test with mv.overte.org
- Handle error cases (user denies, timeout)
Phase 3: Token Persistence (Low Priority)
Quality of life improvement:
- Save tokens to disk
- Auto-refresh on expiration
- 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.inior similar)
Option 2: Use Local Domain with Disabled Auth
Configure your local domain server to skip authentication:
// domain-server settings
{
"security": {
"restricted_access": false,
"authentication_required": false
}
}
Option 3: Reverse Engineer Metaverse API
Capture actual OAuth flow from Overte interface:
# 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 classsrc/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 flowsrc/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
// 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:
// src/main.cpp
const char* tokenEnv = std::getenv("OVERTE_TOKEN");
if (tokenEnv) {
client.setAccessToken(tokenEnv);
}
Then:
# Get token from Overte interface somehow
export OVERTE_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGc..."
./build/starworld
Conclusion
Minimum Viable OAuth:
- Implement authorization code flow with HTTP callback server (~500 lines)
- Add token to DomainConnectRequest (2 lines)
- 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