DEV Community

Daniel Ioni
Daniel Ioni

Posted on

Building the MyZubster Metaverse: Secure Sessions, Verified Identities and the Road to Realtime

Building the MyZubster Metaverse: Secure Sessions, Verified Identities and the Road to Realtime

The MyZubster Metaverse is evolving from a visual experiment into a real, testable multiplayer environment.

Our objective is not simply to render avatars on a page. We are building an open-source world where guest users, verified contributors and independent communities can interact through a shared identity and knowledge layer.

The public entry point is now available here:

πŸ‘‰ https://www.myzubster.com/metaverse

This article explains what we have implemented, the security work completed in our latest development cycle, the current architecture and what still needs to be built before the platform can be considered production-ready at scale.


What the MyZubster Metaverse is

The MyZubster Metaverse is intended to connect several parts of the ecosystem:

  • public and verified user profiles;
  • GitHub contributor identities;
  • Zorgax characters;
  • Verified Knowledge;
  • community spaces;
  • Development Requests;
  • open-source contributions;
  • optional rewards and bounties;
  • future immersive WebXR experiences.

The current version focuses on the foundations: identity, presence, sessions and authenticated world actions.

Users can currently enter the world as guests without requiring:

  • a cryptocurrency wallet;
  • identity documents;
  • a GitHub account;
  • an installed application.

Verified MyZubster explorers can also be displayed with their associated public GitHub identity.

This gives us two different identity levels:

  1. Guest explorers, who can enter quickly using a public display name.
  2. Verified explorers, whose public character is linked to an authorized account or GitHub identity.

Verification here does not mean KYC or legal identity verification. It only represents a confirmed connection with the declared public account.


What we have implemented

1. Public Metaverse entry point

The production interface now provides a dedicated Metaverse route:


text
https://www.myzubster.com/metaverse
The entry interface includes:
- guest onboarding;
- public display-name selection;
- automatic character creation;
- verified explorer discovery;
- multilingual UI support;
- links to account-based authentication.
The guest path is intentionally lightweight. A user can explore the world without being forced to create a permanent account first.
2. World presence model
The backend maintains a presence record for each active Metaverse participant.
A presence can contain information such as:
{
  sessionId,
  displayName,
  characterId,
  accountId,
  githubLogin,
  position,
  status,
  lastSeenAt
}
The public representation deliberately excludes private credentials and internal security fields.
Presence data is used by the world API to support operations such as:
- joining the world;
- synchronizing visible participants;
- moving a character;
- sending chat messages;
- publishing emotes;
- leaving the world;
- retrieving world events.
Before our latest security work, knowing a public session identifier could potentially be sufficient to target mutable session routes. That is not an acceptable trust boundary for a multiplayer environment.
A public identifier must identify a session, but it must never prove ownership of it.
The latest milestone: possession-bound sessions
Our latest merged pull request introduces possession-based session credentials.
Pull request:
πŸ‘‰ MyZubster PR #34 β€” Bind world actions to session credentials
Production commit:
148a798
This work creates a security boundary between:
- the public session identifier;
- the private credential required to control that session.
How session creation now works
When a player joins the world, the backend creates:
1. a public sessionId;
2. a cryptographically random private session token.
The token is generated from 32 random bytes, providing 256 bits of entropy.
Conceptually:
const sessionToken = crypto.randomBytes(32).toString("base64url");
The raw token is returned to the client only when the session is created.
It is never included in public player data.
3. Only the token digest is stored
The backend does not persist the raw session token.
Instead, it calculates a SHA-256 digest:
const tokenHash = crypto
  .createHash("sha256")
  .update(sessionToken)
  .digest("hex");
The presence record stores the digest:
{
  sessionId,
  sessionTokenHash: tokenHash
}
This reduces the impact of an accidental database disclosure. An attacker reading the presence collection would not immediately obtain the active bearer credentials.
A token cannot be recovered directly from its digest.
4. Constant-time credential verification
Mutable world routes verify the submitted credential against the stored digest.
The comparison uses a constant-time operation to reduce timing side-channel exposure:
crypto.timingSafeEqual(expectedBuffer, receivedBuffer);
Credential validation is centralized in an ownership middleware similar to:
requireOwnedSession
The middleware checks that:
- the session exists;
- the private token was provided;
- the submitted token produces the expected digest;
- the credential belongs to the requested session.
Missing or invalid credentials result in an unauthorized response.
HTTP 401 Unauthorized
5. Protected world actions
The following routes are now protected by session ownership verification:
/sync
/move
/chat
/emote
/leave
/events
Knowing another player’s public sessionId is no longer sufficient to:
- move that player;
- send messages as that player;
- publish their emotes;
- synchronize private session state;
- remove them from the world;
- retrieve protected session events.
This closes an important class of horizontal session-ownership vulnerabilities.
6. Tokens are sent through a dedicated header
The frontend now sends the private credential through:
X-Metaverse-Session-Token: <private-token>
Example:
const createSessionHeaders = (sessionToken) => ({
  "X-Metaverse-Session-Token": sessionToken,
});
The token is not placed inside normal public JSON payloads:
{
  "sessionId": "public-session-id",
  "x": 120,
  "y": 80
}
Separating authorization data from world-state payloads makes the security boundary clearer and reduces the risk of credentials being copied into:
- application logs;
- analytics events;
- public state;
- debugging output;
- serialized world events.
The backend temporarily supports a legacy request-body token for compatibility, but the header is the canonical client mechanism.
7. Credentials remain in memory
The browser keeps the Metaverse session credential in React runtime memory.
We deliberately avoid storing it in:
localStorage
sessionStorage
public profile objects
world event payloads
In-memory credentials disappear when the page or browser session is closed.
This does not eliminate every browser-side threat, especially an active cross-site scripting vulnerability, but it reduces long-lived credential exposure.
Privacy and identity boundaries
The Metaverse must distinguish several concepts that are often incorrectly combined:
Account identity
      ↓
Public profile
      ↓
Character identity
      ↓
Temporary world session
      ↓
Private session credential
A public GitHub profile proves control of a public contributor account only when an authorization flow verifies it.
It does not automatically prove:
- legal identity;
- employment;
- institutional affiliation;
- ownership of an organization;
- eligibility for payment;
- control of a blockchain wallet.
Similarly, the public session ID identifies an active world session, but only the private session credential authorizes mutations for that session.
These distinctions are now documented in the repository’s Metaverse privacy and security documentation.
Testing completed
The session-ownership work includes backend, frontend and static architecture tests.
Backend verification
The targeted backend suites cover:
- secure token creation;
- SHA-256 digest persistence;
- successful authorized operations;
- missing credential rejection;
- invalid credential rejection;
- attempts to mutate another player’s session;
- exclusion of credentials from public payloads;
- protected movement, chat, emote, synchronization and leave routes.
Result:
3 targeted backend suites
22 tests passed
Frontend verification
Frontend tests validate:
- token retention in application memory;
- use of X-Metaverse-Session-Token;
- authorized API requests;
- session-aware world operations;
- absence of the token from public request bodies.
Result:
1 targeted frontend suite
5 tests passed
Build and integration verification
We also completed:
Production frontend build: successful
git diff --check: clean
MYZ-164 Marketplace regression: passed
Vercel preview deployments: successful
Main deployment: successful
The implementation was squash-merged into main and deployed through the production workflow.
Current architecture
The current architecture can be summarized as:
React Metaverse Client
        |
        | HTTPS requests
        | X-Metaverse-Session-Token
        v
Node.js / Express Metaverse API
        |
        | ownership middleware
        | token hashing and verification
        v
Metaverse Presence Storage
        |
        v
Shared world polling and event synchronization
The current system provides a practical foundation, but it is not yet the final realtime architecture.
What still needs to be completed
1. Realtime transport
The current shared-world model still relies on polling-based synchronization in important areas.
The next architectural step is to introduce a proper realtime transport, most likely based on:
- WebSockets;
- Socket.IO;
- Server-Sent Events for selected read-only streams;
- a message broker when horizontal scaling becomes necessary.
Realtime transport must include:
- authenticated connection establishment;
- session-token validation;
- connection-to-session binding;
- reconnect handling;
- event ordering;
- duplicate-event protection;
- backpressure controls;
- presence expiry.
We should not simply move the existing endpoints to WebSockets. The event protocol must be explicitly designed and versioned.
2. Distributed rate limiting
In-memory rate limiting is insufficient when multiple backend instances process requests.
We still need a distributed limiter for:
- session creation;
- movement events;
- chat messages;
- emotes;
- authentication attempts;
- reconnect operations.
Possible storage layers include Redis or another shared atomic counter service.
The limiter should support dimensions such as:
IP address
account ID
session ID
route
world or room ID
time window
Movement events should have different limits from chat or authentication attempts.
3. Session lifecycle and revocation
Possession-bound credentials are now implemented, but lifecycle management needs additional work.
Remaining tasks include:
- explicit session expiration;
- server-side revocation;
- automatic removal of abandoned sessions;
- token rotation;
- reconnect-safe credential renewal;
- maximum active sessions per account;
- logout across devices;
- suspicious-session invalidation.
We also need clear rules for temporary guest sessions versus authenticated persistent characters.
4. Stronger account authentication
Verified characters need a canonical authentication path.
The roadmap includes:
- stable GitHub OAuth integration;
- verified account-to-character linking;
- protection against account-link substitution;
- clear reauthorization flows;
- audit trails for identity changes;
- recovery procedures.
The Metaverse must never trust a GitHub username supplied directly by the browser without verifying control of that account.
5. Privacy-safe analytics
We need operational visibility without building invasive tracking.
Metrics should focus on system health:
- active anonymous sessions;
- session duration ranges;
- API latency;
- reconnect frequency;
- rate-limit events;
- server errors;
- world capacity;
- event throughput.
We should avoid collecting unnecessary personal identifiers.
Analytics data needs:
- documented retention;
- aggregation;
- access restrictions;
- deletion rules;
- explicit separation from public profile data.
6. Reliability and load testing
The next reliability milestone must test realistic concurrent behavior.
Scenarios should include:
- many simultaneous joins;
- movement bursts;
- reconnect storms;
- inactive sessions;
- malformed events;
- duplicate events;
- slow clients;
- backend restarts;
- database latency;
- multiple application instances.
The system needs measurable targets for:
maximum concurrent participants
p95 and p99 API latency
event delivery delay
error rate
recovery time
presence consistency
7. Complete end-to-end acceptance tests
Unit and integration tests are not sufficient for the entire world flow.
We still need automated E2E tests covering:
Guest joins
β†’ session credential is issued
β†’ character becomes visible
β†’ movement is synchronized
β†’ chat and emotes are authorized
β†’ another session cannot impersonate the guest
β†’ reconnect behavior is correct
β†’ session leaves or expires
Equivalent tests are required for verified characters.
8. WebXR and immersive clients
WebXR remains a later-stage objective.
Before adding immersive rendering, we need to stabilize:
- authentication;
- world protocol;
- realtime synchronization;
- abuse prevention;
- accessibility;
- performance;
- mobile behavior.
The WebXR client should consume the same documented world protocol rather than implementing an independent backend.
This will allow multiple compatible clients:
2D web client
3D browser client
WebXR client
mobile client
community-built client
9. Dependency security debt
The current repository still reports dependency vulnerabilities during npm audit.
The latest Metaverse pull request did not modify package or lock files, so these findings were not introduced by the session-security work.
However, they remain real technical debt.
They must be handled in a separate dependency-hardening cycle involving:
1. vulnerability classification;
2. identification of production versus development exposure;
3. safe direct dependency updates;
4. transitive dependency analysis;
5. regression testing;
6. replacement of abandoned packages;
7. lockfile regeneration;
8. SBOM and audit evidence updates.
We should not hide or disable the audit simply to obtain a green badge.
Proposed next development sequence
The recommended order is:
1. Stabilize session expiration and revocation
2. Implement distributed rate limiting
3. Complete canonical account authentication
4. Design the versioned realtime event protocol
5. Introduce authenticated WebSocket connections
6. Add privacy-safe operational metrics
7. Execute reliability and load testing
8. Complete full guest and verified-user E2E tests
9. Resolve dependency security debt
10. Start the WebXR client milestone
Security and reliability must come before graphical complexity.
Open-source collaboration
We are looking for developers and independent testers interested in:
- Node.js and Express;
- React;
- realtime systems;
- WebSockets;
- MongoDB;
- Redis;
- application security;
- abuse prevention;
- privacy engineering;
- load testing;
- WebXR;
- open-source documentation.
Repository:
πŸ‘‰ https://github.com/danieldirimini-myzubster/myzubster
Public Metaverse:
πŸ‘‰ https://www.myzubster.com/metaverse
Recent security implementation:
πŸ‘‰ https://github.com/danieldirimini-myzubster/myzubster/pull/34
Conclusion
The MyZubster Metaverse now has a stronger technical foundation.
We have moved from trusting public session identifiers to enforcing private possession-bound credentials for mutable world actions.
The platform now includes:
- public guest access;
- verified explorer discovery;
- character presence;
- protected world operations;
- 256-bit session credentials;
- SHA-256 token digests;
- constant-time verification;
- header-based authorization;
- memory-only client credentials;
- backend and frontend tests;
- automated production deployment.
The next challenge is no longer simply creating more visual features.
It is building a secure, realtime, distributed and independently testable world protocol that can support different clients and communities without sacrificing privacy or transparency.
That is the direction of the next MyZubster Metaverse milestones.

Enter fullscreen mode Exit fullscreen mode

Top comments (0)