Implement Overte Authentication and Add Test Entities
- 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.
This commit is contained in:
425
docs/OVERTE_AUTH.md
Normal file
425
docs/OVERTE_AUTH.md
Normal file
@@ -0,0 +1,425 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user