This guide explains how server hosting providers can authenticate Hytale dedicated servers.
TL;DR
For Game Server Providers and server network operators wanting automatic 0-click server authentication for up-to 500 servers:
-
Obtain tokens once - Use the Device Code Flow to authenticate and get a
refresh_token -
Create sessions - Call
/my-account/get-profilesthen/game-session/newto getsessionTokenandidentityToken -
Pass tokens to servers - Start each server instance with:
java -jar HytaleServer.jar \ --session-token "<sessionToken>" \ --identity-token "<identityToken>"Or via environment variables:
HYTALE_SERVER_SESSION_TOKENandHYTALE_SERVER_IDENTITY_TOKEN - Refresh before expiry - Game sessions expire in 1 hour and are auto-refreshed 5 minutes before expiry. If game session refresh fails, the server falls back to OAuth token refresh. Each OAuth refresh issues both a new access token and a new refresh token, invalidating the previous refresh token. The server stays authenticated indefinitely as long as it remains online. Re-authentication is only required if the server is offline for longer than the refresh token TTL (30 days).
Your provisioning system handles token management centrally, so customers never see an auth prompt.
Hytale Downloader CLI
For automating server file downloads and updates, use the Hytale Downloader CLI. This tool handles OAuth2 authentication and can be integrated into your provisioning pipelines to keep server installations current.
Download: hytale-downloader.zip (Quickstart + Linux & Windows)
See Server Manual: Hytale Downloader CLI for full usage documentation.
Overview
Server authentication uses OAuth 2.0 to obtain tokens that authorize the server to:
- Create game sessions for the server operator's profile
- Validate players joining the server
- Access game assets and version information
The server uses the pre-configured hytale-server OAuth client:
Client ID: hytale-server Scopes: openid, offline, auth:server
OAuth Endpoints
All endpoints follow standard OAuth 2.0 specifications (RFC 6749, RFC 8628).
Endpoint |
URL |
|---|---|
| Authorization | https://oauth.accounts.hytale.com/oauth2/auth |
| Token | https://oauth.accounts.hytale.com/oauth2/token |
| Device Authorization | https://oauth.accounts.hytale.com/oauth2/device/auth |
Authentication Methods
Method A: Server Console Commands (Interactive)
For servers with console access, use built-in authentication commands:
Command |
Description |
|---|---|
/auth login device |
Start device code flow (recommended for headless servers) |
/auth login browser |
Start browser PKCE flow (requires desktop environment) |
/auth select <number> |
Select a game profile when multiple are available |
/auth status |
Check current authentication status |
/auth cancel |
Cancel an in-progress authentication flow |
/auth logout |
Clear authentication and terminate session |
/auth persistence |
View current credential storage method |
/auth persistence <type> |
Change credential storage method (Memory or Encrypted) |
Example workflow:
> /auth login device =================================================================== DEVICE AUTHORIZATION =================================================================== Visit: https://accounts.hytale.com/device Enter code: ABCD-1234 Or visit: https://accounts.hytale.com/device?user_code=ABCD-1234 =================================================================== Waiting for authorization (expires in 900 seconds)... [User completes authorization in browser] > Authentication successful! Mode: OAUTH_DEVICE
Method B: Device Code Flow (RFC 8628)
For automated or headless setups where you need to obtain tokens programmatically.
Step 1: Request Device Code
curl -X POST "https://oauth.accounts.hytale.com/oauth2/device/auth" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=hytale-server" \
-d "scope=openid offline auth:server"Response:
{
"device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
"user_code": "ABCD-1234",
"verification_uri": "https://accounts.hytale.com/device",
"verification_uri_complete": "https://accounts.hytale.com/device?user_code=ABCD-1234",
"expires_in": 900,
"interval": 5
}Step 2: Display Instructions to User
Show the user:
-
URL:
verification_uriorverification_uri_complete -
Code:
user_code(if usingverification_uri)
Step 3: Poll for Token
Poll the token endpoint at the specified interval (default 5 seconds):
curl -X POST "https://oauth.accounts.hytale.com/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=hytale-server" \
-d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
-d "device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS"Pending response (user hasn't authorized yet):
{
"error": "authorization_pending"
}Success response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "xreEsdDGrfIaQc...",
"scope": "openid offline auth:server"
}Step 4: Get Available Profiles
curl -X GET "https://account-data.hytale.com/my-account/get-profiles" \
-H "Authorization: Bearer <access_token>"Response:
{
"owner": "550e8400-e29b-41d4-a716-446655440000",
"profiles": [
{
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"username": "ServerOperator"
}
]
}Step 5: Create Game Session
curl -X POST "https://sessions.hytale.com/game-session/new" \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"uuid": "123e4567-e89b-12d3-a456-426614174000"}'Response:
{
"sessionToken": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"identityToken": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"expiresAt": "2026-01-07T15:00:00Z"
}The sessionToken and identityToken are what the server uses for authentication.
Method C: Token Passthrough (Environment/CLI)
For hosting providers who manage token acquisition externally and pass tokens to the server at startup.
Environment Variables
Variable |
Description |
|---|---|
HYTALE_SERVER_SESSION_TOKEN |
The session token (JWT) |
HYTALE_SERVER_IDENTITY_TOKEN |
The identity token (JWT) |
HYTALE_SERVER_AUDIENCE |
Override server audience (testing only) |
CLI Options
Option |
Description |
|---|---|
--session-token <token> |
Session token |
--identity-token <token> |
Identity token |
--owner-uuid <uuid> |
Auto-select profile by UUID |
Example:
./hytale-server \
--session-token "eyJhbGciOiJFZERTQSIs..." \
--identity-token "eyJhbGciOiJFZERTQSIs..." \
--owner-uuid "123e4567-e89b-12d3-a456-426614174000"Or via environment:
export HYTALE_SERVER_SESSION_TOKEN="eyJhbGciOiJFZERTQSIs..."
export HYTALE_SERVER_IDENTITY_TOKEN="eyJhbGciOiJFZERTQSIs..."
./hytale-serverThe server automatically refreshes game sessions 5 minutes before expiry when in EXTERNAL_SESSION mode. See Token Lifecycle for details on the refresh strategy.
Method D: Credential Store API (Plugin/Programmatic)
For hosting providers who want to programmatically manage credentials and persist tokens across server restarts via plugins.
Interface
public interface IAuthCredentialStore {
record OAuthTokens(
@Nullable String accessToken,
@Nullable String refreshToken,
@Nullable Instant accessTokenExpiresAt
) {}
void setTokens(@Nonnull OAuthTokens tokens);
@Nonnull OAuthTokens getTokens();
void setProfile(@Nullable UUID uuid);
@Nullable UUID getProfile();
void clear();
}Usage
- Implement
IAuthCredentialStoreto persist tokens (e.g., database, file, external service) - Register before authentication:
ServerAuthManager.getInstance().registerCredentialStore(store) - Server automatically retrieves and refreshes tokens via the store
- Auth mode becomes
OAUTH_STORE
Key Behaviors
- Registration timing: Store must be registered before any authentication occurs
-
Token retrieval: Server calls
getTokens()when OAuth tokens are needed -
Token persistence: Server calls
setTokens()after successful token refresh -
Profile selection: If
getProfile()returns a UUID, that profile is auto-selected
Game Session API Reference
Create Session
Creates a new game session for a specific profile.
Request:
POST /game-session/new
Host: sessions.hytale.com
Authorization: Bearer <oauth_access_token>
Content-Type: application/json
{"uuid": "123e4567-e89b-12d3-a456-426614174000"}Response (200):
{
"sessionToken": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"identityToken": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"expiresAt": "2026-01-07T15:00:00Z"
}Get Profiles
Fetches available game profiles for the authenticated account.
Request:
GET /my-account/get-profiles
Host: account-data.hytale.com
Authorization: Bearer <oauth_access_token>Response (200):
{
"owner": "550e8400-e29b-41d4-a716-446655440000",
"profiles": [
{
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"username": "ServerOperator"
}
]
}Refresh Session
Refreshes the current game session to extend its lifetime. Returns new session and identity tokens with a fresh expiry.
Request:
POST /game-session/refresh
Host: sessions.hytale.com
Authorization: Bearer <session_token>Response (200):
{
"sessionToken": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"identityToken": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"expiresAt": "2026-01-07T16:00:00Z"
}Terminate Session
Ends the current session (call on server shutdown).
Request:
DELETE /game-session
Host: sessions.hytale.com
Authorization: Bearer <session_token>Response: 204 No Content
Refresh OAuth Token
Exchange a refresh token for new OAuth tokens. Both the access token and refresh token are rotated. The response includes a new refresh token that replaces the old one.
Request:
curl -X POST "https://oauth.accounts.hytale.com/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=hytale-server" \
-d "grant_type=refresh_token" \
-d "refresh_token=<refresh_token>"Response (200):
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "xyzNewRefreshToken...",
"scope": "openid offline auth:server"
}Important: The
refresh_tokenin the response is a new refresh token. You must store it and use it for the next refresh. The previous refresh token is invalidated.
Token Lifecycle
Token Type |
TTL |
Notes |
|---|---|---|
| OAuth Access Token | 1 hour | Used to create game sessions and authenticate with service APIs |
| OAuth Refresh Token | 30 days | Rotated on each use: the old token is invalidated and a new one is returned alongside the new access token |
| Game Session | 1 hour | Auto-refreshed 5 minutes before expiry |
Refresh Strategy
The server schedules an automatic refresh 5 minutes before game session expiry. The refresh process follows this order:
-
Game session refresh: Call
POST /game-session/refreshusing the current session token. This returns new session and identity tokens with a fresh 1-hour expiry. - OAuth fallback: If game session refresh fails, the server refreshes its OAuth tokens using the refresh token, then creates a new game session.
Token Rotation
When refreshing OAuth tokens, the authorization server issues both a new access token and a new refresh token. The previous refresh token is invalidated. This means:
- A running server stays authenticated indefinitely. Each refresh extends the refresh token's 30-day TTL, so the token never expires as long as the server keeps refreshing.
-
Re-authentication is only required if the server is offline for more than 30 days. If the refresh token expires without being used (i.e., the server was down for 30+ days), a user must re-authenticate via
/auth loginor by providing new tokens.
Error Handling
Common HTTP Errors
Status |
Meaning |
|---|---|
400 Bad Request |
Invalid request format or missing required fields |
401 Unauthorized |
Missing or invalid authentication |
403 Forbidden |
Valid auth but insufficient permissions (missing entitlement, session limit) |
404 Not Found |
Resource not found (invalid profile UUID, etc.) |
Session Limit Errors
Accounts are limited to 500 concurrent server sessions. Attempting to create more returns a 403 Forbidden error. If you require additional server sessions, please reach out to our support team here
Token Validation Errors
The server validates tokens at startup. If validation fails:
Token validation failed. Server starting unauthenticated. Use /auth login to authenticate.
Common causes:
- Expired tokens
- Invalid token signature
- Missing required scope (
hytale:server)
JWKS Endpoint
Servers validate player JWTs using the public keys from:
GET /.well-known/jwks.json
Host: sessions.hytale.comResponse:
{
"keys": [
{
"kty": "OKP",
"alg": "EdDSA",
"use": "sig",
"kid": "key-id-1",
"crv": "Ed25519",
"x": "base64url-encoded-public-key"
}
]
}