This project enables running a complete free-to-play Hytale setup with custom authentication, bypassing the official Hytale authentication servers. It consists of three interconnected repositories that work together.
| Repository | Description | Status |
|---|---|---|
| hytale-auth-server | Authentication server handling JWT signing | Ready for GitHub |
| hytale-server-docker | Dedicated game server Docker image | Updated |
| Hytale-F2P | Game launcher with binary patching | Updated |
Problem: Hytale client and server binaries hardcode hytale.com for authentication.
Solution: Binary patching to replace domain at runtime.
- Patches
HytaleClient.dll(.NET binary) - Uses UTF-16LE encoding (Windows .NET strings)
- Handles two string formats:
- Standard null-terminated:
h\x00y\x00t\x00a\x00l\x00e\x00.\x00c\x00o\x00m\x00 - Length-prefixed:
h\x00y\x00t\x00a\x00l\x00e\x00.\x00c\x00o\x00m\x89(metadata byte instead of null)
- Standard null-terminated:
- Finds 4 occurrences in the binary
- Critical fix: macOS code signing must happen AFTER patching (not before)
- Patches
HytaleServer.jar(Java binary) - Uses UTF-8 encoding (Java strings)
- Bash script using
unzip,perl,zip - Creates
.patched_customflag file to avoid re-patching
Purpose: Handle all authentication requests from game client and dedicated servers.
- Ed25519 JWT signing with persisted key pairs
- JWKS endpoint (
/.well-known/jwks.json) for signature verification - mTLS certificate binding (
cnf.x5t#S256claim) - Cosmetics extraction from
Assets.zip - User data persistence (skins saved by username)
| Endpoint | Purpose |
|---|---|
/.well-known/jwks.json |
JWT public key for verification |
/game-session/new |
Create new session (launcher/server) |
/game-session/child |
Create child session |
/game-session/refresh |
Refresh existing session |
/server-join/auth-grant |
Authorization grant for server connection |
/server-join/auth-token |
Token exchange with cert binding |
/my-account/game-profile |
Get user profile |
/my-account/cosmetics |
Get unlocked cosmetics |
/my-account/skin |
Save skin preferences |
/my-account/get-profiles |
Get all profiles |
server.js- Main server codeDockerfile- Docker build configurationpackage.json- Node.js dependenciescompose.yaml- Production config with Traefik (HTTPS)compose.simple.yaml- Local development (HTTP)README.md- DocumentationLICENSE- MIT License.gitignore- Git ignore rulesassets/.gitkeep- Placeholder for Assets.zip
Problem: Domain sanasol.ws was hardcoded in multiple places.
Solution: Centralized configuration with environment variable support.
const DEFAULT_AUTH_DOMAIN = 'sanasol.ws';
function getAuthDomain() {
// Priority: env var > config file > default
if (process.env.HYTALE_AUTH_DOMAIN) return process.env.HYTALE_AUTH_DOMAIN;
const config = loadConfig();
if (config.authDomain) return config.authDomain;
return DEFAULT_AUTH_DOMAIN;
}| Variable | Default | Used By |
|---|---|---|
HYTALE_AUTH_DOMAIN |
sanasol.ws |
All components |
HYTALE_PATCH_SERVER |
false |
Docker server |
HYTALE_AUTO_FETCH_TOKENS |
false |
Docker server |
HYTALE_AUTH_SERVER |
https://sessions.sanasol.ws |
Docker server |
Requirement: Custom domain must be exactly 10 characters (same as hytale.com).
Reason: Binary patching replaces bytes in-place. Different length would corrupt the binary.
Examples: sanasol.ws, example.co, myserver.x
- Domain:
sanasol.ws - Endpoints:
sessions.sanasol.ws,account-data.sanasol.ws,telemetry.sanasol.ws - All cosmetics unlocked
- Cosmetics saved by username
- Address:
ht.vboro.de:5720 - Uses
sanasol.wsauth server
- v2.0.4-auth-sanasol.ws
- Ready to use, no setup required
- Public test server section
- Quick test instructions (download + connect)
- Requirements for own server
- Complete setup guide
- Troubleshooting section
- Cross-links to related projects
- Custom Auth Server Support section
- Public Test Server (Default) section
- Quick Start (Using Public Test Server)
- Complete Setup (Own Auth Server)
- Cross-links to related projects
Problem: Game crashed after patching, then reverted to hytale.com on restart.
Root Cause: macOS was re-signing the binary BEFORE patching, then the patched binary had an invalid signature.
Fix (gameLauncher.js):
// Order: fetch tokens → patch → sign (macOS) → launch
const authDomain = getAuthDomain();
if (clientPatcher) {
await clientPatcher.ensureClientPatched(gameLatest, ...);
}
// macOS: Sign binaries AFTER patching
if (process.platform === 'darwin') {
// codesign --force --deep --sign - <binary>
}Problem: Patcher found 3 occurrences but game still used hytale.com.
Investigation: Hex dump revealed 4th occurrence had different format:
Standard: h 00 y 00 t 00 a 00 l 00 e 00 . 00 c 00 o 00 m 00
Length-prefixed: h 00 y 00 t 00 a 00 l 00 e 00 . 00 c 00 o 00 m 89
Fix: Check only first byte of last character, preserve metadata byte:
const lastCharFirstByte = result[lastCharPos];
if (lastCharFirstByte === oldLastCharByte) {
newUtf16NoLast.copy(result, pos);
result[lastCharPos] = newLastCharByte;
// Preserves 0x00 or 0x89 in second byte position
}- No password authentication - anyone can use any username
- Shared profiles - same username = same cosmetic profile
- For testing purposes only
- First login → server generates secret claim token
- Token stored locally on client
- Future skin saves require token
- Without token → fresh profile (can't modify existing)
Not yet implemented - would require changes to both server and launcher.
cd /Users/sanasol/code/pterodactyl-hytale/hytale-auth-server
git remote -v
# origin git@github.com:sanasol/hytale-auth-server.git
git log --oneline
# 24535e5 Add disclaimer about shared usernames
# ca9a5f5 Add cosmetics info to public test server section
# 8405907 Add pre-built release and public game server links
# f70c5d9 Add public test server documentation
# 3b94462 Initial commit: Hytale Auth Server
# To push:
git push -u origin mastercd /Users/sanasol/code/pterodactyl-hytale/hytale-server-docker
git remote -v
# origin git@github.com:sanasol/hytale-server-docker.git
# Recent commits ready to push:
git push- Download Hytale-F2P v2.0.4-auth-sanasol.ws
- Launch and connect to
ht.vboro.de:5720
git clone https://github.com/sanasol/hytale-server-docker.git
cd hytale-server-docker
docker compose build
docker compose up -d- Set up auth server with custom 10-char domain
- Configure DNS records
- Start auth server with Traefik
- Start game server with custom domain
- Build launcher with custom domain
| Path | Description |
|---|---|
/f2p/backend/core/config.js |
Centralized auth domain configuration |
/f2p/backend/utils/clientPatcher.js |
Client binary patcher (UTF-16LE) |
/f2p/backend/managers/gameLauncher.js |
Game launch with proper patch→sign order |
/hytale-server-docker/scripts/patch-server.sh |
Server JAR patcher (UTF-8) |
/hytale-server-docker/README.md |
Updated with custom auth docs |
/hytale-auth-server/* |
Complete auth server package |
Successfully created a complete Hytale F2P infrastructure:
- Binary patching for both client (.NET/UTF-16LE) and server (Java/UTF-8)
- Custom auth server with Ed25519 JWT signing and all required endpoints
- Centralized configuration with environment variable support
- Public test infrastructure at
sanasol.wswith game server atht.vboro.de:5720 - Pre-built releases for immediate testing
- Comprehensive documentation with cross-links between all repositories
All components are designed to work together out of the box with default sanasol.ws configuration, while supporting custom domains for self-hosted setups.