Authentication
Dashboard authentication
Users log into hle.world/dashboard using one of these methods:
- Email & password: Register a new account with email and password
- GitHub SSO: OAuth 2.0 via GitHub
- Google SSO: OIDC via Google
API keys
API keys authenticate the client tunnel to the relay server. Key details:
- Format:
hle_prefix + 32 hex characters (36 chars total) - Stored as: SHA-256 hash in the database (plaintext never stored)
- Per-key tunnel limit: Each key has a
max_tunnelssetting (unlimited for all tiers). All users receive 2 GB of bandwidth free per calendar month; PAYG users pay from their credit balance beyond that. - Created in: Dashboard > Keys
- Visible once: The raw key is only shown once on creation — save it immediately
Tunnel authentication flow
- Client sends
TUNNEL_REGISTERmessage withapi_key - Server hashes the key and looks up
ApiKeyRecord - Server validates:
- Key exists and is active
- Tunnel count does not exceed
max_tunnels
- Server derives
user_codefrom key owner’sUserRecord(3-char alphanumeric) - Tunnel is registered with format:
<service_label>-<user_code>.<base_domain>
Subdomain routing
Each tunnel gets a unique public URL:
<service_label>-<user_code>.hle.worldExample: If your user code is x7k and label is ha, the URL is https://ha-x7k.hle.world
user_code: Server-allocated 3-char alphanumeric per user, derived from API key ownerservice_label: User-chosen name (e.g., “ha”, “jellyfin”, “app1”), auto-generated if omitted
Tunnel access control
The gate evaluates rules in a fixed order and the first match decides. That order is shown in the dashboard rather than being editable, because it comes from the relay:
- Public override (
--auth none) — nothing else is checked - Basic Auth, if set — checked before any cookie, with the address allow-list able to skip it
- A valid gate cookie — share link, allow-listed email, or PIN
- The address allow-list
- Otherwise: the gate page, or a refusal
Refuse unmatched visitors
By default, a visitor who matches no rule is refused. This is an account-level setting on the Access Control tab.
Turning it off restores the relay’s older behaviour, in which an endpoint with no sign-in rule and no PIN was reachable by anyone who had the address — including one whose owner had set up an address allow-list and nothing else, because step 3 above returned before the address was ever consulted.
Webhook endpoints are exempt: they cannot use the sign-in gate, so refusing would leave them permanently unreachable.
Email allow-list
For each tunnel, the owner can create an email allow-list with provider selection from the tunnel’s Access Control tab in the dashboard. Provider options:
any: Allow any auth method (native email/password, GitHub, Google)github: Require GitHub SSOgoogle: Require Google SSOhle: Require native HLE email/password login
When a user accesses the tunnel gate page, only the allowed auth methods are displayed:
provider: "github"— Only GitHub button shownprovider: "any"— All buttons (email form, GitHub, Google)
PIN protection
In addition to the email allow-list, any tunnel can be protected with a PIN. Visitors who pass the SSO gate are then prompted for the PIN before being granted access. PIN protection is available on all plans and is configured from the tunnel’s Access Control tab in the dashboard.
HTTP Basic Auth
Any tunnel can be protected with standard HTTP Basic Auth — a username and password enforced by the relay before the request ever reaches your local service. This works natively with browsers (which show a credentials dialog), curl, and any HTTP client that understands Authorization: Basic.
Configure it from the tunnel’s Access Control tab in the dashboard, or via the CLI:
hle config basic-auth set ha # prompts for username & passwordhle config basic-auth status ha # show whether activehle config basic-auth remove ha # remove credentialsCredentials are stored as PBKDF2-SHA256 hashes. The password is never returned in plaintext.
Upstream Basic Auth
Separately, you can inject Basic Auth credentials into every request forwarded to your local service. This is useful when the local service itself requires authentication (e.g., Home Assistant, Grafana, or Jupyter):
hle expose --service http://localhost:8123 --upstream-basic-auth admin:yourpasswordThis injects an Authorization: Basic header on every proxied request — independent of the tunnel-level Basic Auth above.
Share links
Share links let you grant temporary access to a tunnel without adding someone to the permanent allow-list. Each share link embeds a signed token that is validated at the gate.
They are not a paid feature — the same limits apply on every plan:
- Any number of active links per endpoint
- Any duration up to 7 days, set in hours when you create the link
- Optionally limited to a maximum number of uses
The 7-day ceiling is a security bound rather than a plan boundary: anyone holding the URL gets in, so a link that never expires becomes a credential nobody remembers issuing.
Share links appear as a rule in the tunnel’s Access Control list, alongside sign-in rules, the PIN and the address list, with the link itself on the row and its own access log.
CLI authentication
The CLI commands under hle config authenticate against the REST API using your API key sent as an Authorization: Bearer header. The key is resolved in this order:
--api-keycommand-line flagHLE_API_KEYenvironment variable~/.config/hle/config.tomlconfig file
The same API key used for tunnel connections also authenticates REST API calls for managing access rules and listing tunnels. The dashboard uses JWT cookies for the same endpoints — both auth methods are accepted.
JWT tokens
JWT tokens are issued by the server and stored in HTTP-only, SameSite=Lax cookies. The secure flag is set automatically — cookies are marked secure in production (HTTPS) and plain in local development (HTTP).
- Dashboard JWT (
hle_access_token): 24h expiry, used for all/api/*dashboard endpoints - Tunnel access JWT (
hle_tunnel_token): 24h expiry, issued after a visitor passes the SSO gate page, scoped to the specific tunnel subdomain
Password security
Passwords are hashed using PBKDF2-SHA256 with 600,000 iterations. This is OWASP-recommended and resistant to modern GPU attacks.
Rate limiting
Authentication endpoints are rate-limited to prevent brute force attacks. The limit is applied per IP address across the hle.world hosted service.