mudauth
Sign in to your MUD with Discord, GitHub, Google, Microsoft, Apple, Twitch, Facebook, or Steam.
mudauth is a small, stateless OAuth/OIDC broker for games that implement the
GMCP Authentication standard — supported today by Mudlet 5 and LociTerm.
- No database. It verifies a provider identity and hands
{provider, provider_id, username}to your game once. Your game stays the source of truth for accounts and characters. - No dependencies. Python 3.11+ standard library only. One process, one env file.
- No inbound port on the game. The game polls
mudauthover loopback; onlymudauthsits behind your TLS proxy. - Eight providers, each enabled by environment variables — a client id and secret for the seven OAuth/OIDC providers, a single Web API key for Steam.
Install
pipx install mudauth # or: pip install mudauth
brew install stickmud/tap/mudauth
Run
mudauth serve --env-file .env # listens on 127.0.0.1:7700
mudauth check --env-file .env # validates config and reaches the running service
.env is yours to write: AUTH_PUBLIC_BASE and one provider's id and secret are
enough to start. pip/pipx install only the Python code and the mudauth
command, so the annotated template lives in the source rather than on your PATH —
take it from a checkout, from the sdist, or straight from the repository:
curl -fsSLO https://raw.githubusercontent.com/StickMUD/mudauth/main/.env.example
cp .env.example .env
Put a TLS reverse proxy in front of AUTH_PUBLIC_BASE and forward /auth/ to the
loopback listener. See docs/deploy.md for systemd, nginx, and Apache.
Integrate your game
Your game starts a login with GET /auth/login/<provider>/<nonce>, hands the player
the returned URL over Char.Login.URL, and polls GET /auth/token-poll?nonce= until
the identity arrives. Full contract: docs/protocol.md.
Driver-specific notes (LDMud efun, Evennia, Node): docs/integrating.md.
LDMud games get a ready-made efun: pip install "mudauth[ldmud]" registers
auth_service_request(method, path, body).
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /auth/providers |
List configured providers and the public base |
| GET | /auth/login/<provider>/<nonce> |
Begin a login (302 to the provider) |
| GET | /auth/callback?code=&state= |
OAuth redirect target |
| GET | /auth/token-poll?nonce= |
Poll for the verified identity (returned once) |
| POST | /auth/login-cancel {nonce} |
Drop a pending login |
| GET | /auth/healthz |
Liveness check |
Configuration
All settings are environment variables; --env-file loads a KEY=VALUE file.
| Variable | Default | Meaning |
|---|---|---|
AUTH_BIND |
127.0.0.1:7700 |
Loopback listener. Never expose it. |
AUTH_PUBLIC_BASE |
http://localhost:7700 |
Browser-facing prefix before /auth/* |
AUTH_CALLBACK_URL |
$AUTH_PUBLIC_BASE/auth/callback |
Redirect URI registered with each provider |
AUTH_BRAND_NAME |
mudauth |
Name on the "you may close this tab" page |
AUTH_TRUSTED_PROXY_HOPS |
1 |
Proxies that append to X-Forwarded-For between the browser and the service |
AUTH_SERVICE_TOKEN |
unset | Shared secret identifying the game to the loopback exemption; set the same value in the game's environment. Recommended — see docs/deploy.md for the migration order. |
AUTH_USER_AGENT |
mudauth/<version> |
Outbound User-Agent; set it to name your game |
<PROVIDER>_CLIENT_ID / _CLIENT_SECRET |
— | Enables that provider |
<PROVIDER>_CALLBACK_URL |
$AUTH_CALLBACK_URL |
Per-provider override |
STEAM_API_KEY |
— | Steam uses OpenID 2.0; the key is only for the persona lookup |
One more variable belongs to the game side, not the service: AUTH_SERVICE_URL
(default http://127.0.0.1:7700) names the loopback listener the game talks to.
Provider registration walkthroughs: docs/providers.md.
Security model
Random per-flow state (CSRF); client-generated nonce with a 10-minute TTL; the
identity is returned exactly once and forgotten; non-loopback pollers must come from
the IP that started the flow; provider secrets never leave the service. Loopback
callers are trusted — the listener must stay on loopback. X-Forwarded-For and
X-Real-IP are believed only from a loopback peer (your reverse proxy), and only
the rightmost X-Forwarded-For element — the hop your proxy appended — is read, so
a caller cannot name its own origin. If two proxies append to the header, set
AUTH_TRUSTED_PROXY_HOPS=2.
Count the appending proxies exactly. Reading too few hops back binds every login to one
of your own proxies' addresses instead of the player's; reading too many reads an
element the client wrote whenever a client pads the header. The value is validated at
startup — a non-integer or anything below 1 stops the service with a message rather
than being clamped — and the effective count is printed in the startup banner. When a
request's forwarding header is not the shape that count promises, or carries something
that is not an IP address, the service logs an [auth][security] line and refuses the
request; it never falls back to the loopback peer, which would make every origin match.
That "loopback caller" test is itself worth strengthening: by default it rests on the
absence of X-Forwarded-For/X-Real-IP, which a proxy that stops adding them (a
misconfiguration, not an attack) can erase for every internet caller at once. Set
AUTH_SERVICE_TOKEN to the same value in the service's environment and the game's, and
the exemption instead requires a loopback peer, a matching X-Auth-Service-Token
header, and that same header absence — the token tightens the legacy rule, it does
not replace it, so a caller who learns the token still cannot claim the exemption
through the proxy. Unset is a supported, backward-compatible default — the service warns
at startup — but see docs/deploy.md for the order to turn it on without
taking logins down.
Both shipped proxy configs turn access logging off for /auth/, because the request
line carries the nonce and the authorization code. Report vulnerabilities per
SECURITY.md.
Test
python -m unittest discover -s tests -v
Credits and license
Originally built as the auth service for StickMUD, following the pattern proven by MUDdown. MIT licensed — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mudauth-0.1.1.tar.gz.
File metadata
- Download URL: mudauth-0.1.1.tar.gz
- Upload date:
- Size: 75.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d713c59a009e42ee8c47d249105dad443591f1bf1927eb1338d6451c52b03732
|
|
| MD5 |
8061682fa8eea975ab6c2b062ff60d65
|
|
| BLAKE2b-256 |
edec287d3d93c2865b1fd23e43ab8f46a1ee16cf5a23e6b9a4abce89c21b44ad
|
Provenance
The following attestation bundles were made for mudauth-0.1.1.tar.gz:
Publisher:
release.yml on StickMUD/mudauth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mudauth-0.1.1.tar.gz -
Subject digest:
d713c59a009e42ee8c47d249105dad443591f1bf1927eb1338d6451c52b03732 - Sigstore transparency entry: 2656470857
- Sigstore integration time:
-
Permalink:
StickMUD/mudauth@0a2c83b6661badf10a95eee5d8f79d2a247c784c -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/StickMUD
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0a2c83b6661badf10a95eee5d8f79d2a247c784c -
Trigger Event:
push
-
Statement type:
File details
Details for the file mudauth-0.1.1-py3-none-any.whl.
File metadata
- Download URL: mudauth-0.1.1-py3-none-any.whl
- Upload date:
- Size: 31.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c05ca6fd38655b1d03defba9d306df2f979e170ca9672a9008757d882c4cb4e1
|
|
| MD5 |
1f97198e317254aebc14d487b598545e
|
|
| BLAKE2b-256 |
0e5f71cc46e77c4bd0d0af1791323e02e55d736b53dd5a281f65fae9cecc88a4
|
Provenance
The following attestation bundles were made for mudauth-0.1.1-py3-none-any.whl:
Publisher:
release.yml on StickMUD/mudauth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mudauth-0.1.1-py3-none-any.whl -
Subject digest:
c05ca6fd38655b1d03defba9d306df2f979e170ca9672a9008757d882c4cb4e1 - Sigstore transparency entry: 2656470936
- Sigstore integration time:
-
Permalink:
StickMUD/mudauth@0a2c83b6661badf10a95eee5d8f79d2a247c784c -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/StickMUD
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0a2c83b6661badf10a95eee5d8f79d2a247c784c -
Trigger Event:
push
-
Statement type: