VERIFY_GAME_CREDENTIALS
Linking a game account to a master account
How a player proves the game account they are linking is theirs. Nothing can be delivered to a player who has not linked one, which is why this is a required capability.
| Result | Meaning |
|---|---|
VALID | Account exists, is enabled, and the password matches |
INVALID_CREDENTIALS | The account exists but the password does not match |
NO_SUCH_ACCOUNT | No account of that name — optional, see below |
ACCOUNT_DISABLED | Account exists but is banned or disabled |
TEMPORARY_FAILURE | The operation could not be completed |
Read the account through a parameterised query. Never log, store or return the supplied password.
The column does not hold a password
On every pack, that column holds a transform of what the player typed. Comparing it as text cannot verify anyone — and on a pack where the column was once edited by hand it does something worse: it accepts a password the game itself refuses, so the portal and the login screen disagree about the same account.
Implementing it
String verifyCredentials(String accountName, String password) throws Exception;Apply the hash your login server applies, then compare. The two reference implementations differ:
- aCis 409 — bcrypt, through
BCrypt.checkPw. - Mobius — SHA-1 over the UTF-8 bytes, Base64 encoded. It is worth reading
LoginController#retriveAccountInfoin your own source rather than trusting this line, because it is the only place the real answer lives.
Treat a negative access level as ACCOUNT_DISABLED rather than a wrong password: a banned player
retyping their password forever is a support ticket you do not need.
Telling a missing account apart
NO_SUCH_ACCOUNT is optional — answering INVALID_CREDENTIALS for both is always correct. It
exists so an owner can see that their query is pointed at the wrong database.
Players are never told which one it was
Forgeport collapses NO_SUCH_ACCOUNT into INVALID_CREDENTIALS on every player-facing response.
A login form that answers the two differently is a way to discover which account names exist on
the server, so the distinction is visible only in Connector check, which an owner runs against
their own server. If you surface credential outcomes anywhere else yourself, collapse them the
same way.
Verification
Connector check submits an account that cannot exist and expects a clean rejection. If you
supply a test account name it repeats the call with a password that cannot be right, which answers
a different question: whether the query is reading a database where your accounts actually are.
Nothing is written and your auth daemon is never involved — it is the same SELECT the connector
already runs, so no login counter moves.
Neither proves the transform is right. Only a real login does; see
CREATE_GAME_ACCOUNT for the one test that covers the
whole chain.