Authentication hooks
PlasmaJohn
Member Posts: 31
Hi folks. Some may remember me from back in the day. I was pretty active on the old BW NWN forums and I spent almost a decade working on the Avlis PW.
I'd like to re-raise an issue that's been plaguing NWN PW's for a long time and that's the dependence on the Master Server as the sole arbiter of player authentication. Towards the end of its support lifetime there were several outages which usually happened during a weekend. Evenings and weekends of course are our Prime Time and the studio's downtime. To not have the game available during those outages were extremely frustrating. And then, without warning, it went away completely.
For the love of little green goblins please don't inflict that situation on the NWN PW community again. Please add hooks into password authentication that allows a PW to manage their own player base without having to pray that the MS is online. This community has proven that it will outlast the studios behind the product please don't insult us with claims that the new MS will last forever.
Possible implementation. A server may override the following function:
struct authResults {
bool approved;
String errorMessage:
};
authResults clientAuthCallback(String accountId, String hmac);
This function is called when a client logs into a server if the approved val is false then the text of the errorMessage is displayed to the user. Please be a string and not an index of canned messages because you'll never cover all possible messages. If the approved value is true then the login process proceeds as normal.
The accountId should be obvious. The hmac argument should be an irreversible hash of the password the player has typed into the password field. Cleartext passwords are wholly unnecessary and extremely dangerous.
I'd like to re-raise an issue that's been plaguing NWN PW's for a long time and that's the dependence on the Master Server as the sole arbiter of player authentication. Towards the end of its support lifetime there were several outages which usually happened during a weekend. Evenings and weekends of course are our Prime Time and the studio's downtime. To not have the game available during those outages were extremely frustrating. And then, without warning, it went away completely.
For the love of little green goblins please don't inflict that situation on the NWN PW community again. Please add hooks into password authentication that allows a PW to manage their own player base without having to pray that the MS is online. This community has proven that it will outlast the studios behind the product please don't insult us with claims that the new MS will last forever.
Possible implementation. A server may override the following function:
struct authResults {
bool approved;
String errorMessage:
};
authResults clientAuthCallback(String accountId, String hmac);
This function is called when a client logs into a server if the approved val is false then the text of the errorMessage is displayed to the user. Please be a string and not an index of canned messages because you'll never cover all possible messages. If the approved value is true then the login process proceeds as normal.
The accountId should be obvious. The hmac argument should be an irreversible hash of the password the player has typed into the password field. Cleartext passwords are wholly unnecessary and extremely dangerous.
8
Comments
https://forums.beamdog.com/discussion/67008/custom-players-authentifications#latest
Actually, how dependent on the Master Server Redux will NWN:EE be? Classic NWN had a switch to ignore it when it failed. Will NWN:EE server have the same freedom? If a server can't ignore a MS outage then NWN:EE is unsuitable for PW usage.
Yes I know there was some discussion on one of the livestreams. I have better things to do with my life than watch TV.
I hope I can address some concerns.
Password authentication is not possible. The server never sees the player password - as we don't have passwords anymore! All that has been removed, including the UI for it.
Specifically, as far as authentication factors go, the server sees:
* The players' IP address (obviously).
* The player name.
* The public CD key.
* A salted hash of the private key, and the salt.
* The response from the masterserver if public, private and salt are a match.
* The old public keys tuple, if present.
Now, what you could easily do with NWNX is hook into this and add another layer of checks to it; maybe to compare it against your local database. However, keep in mind:
* You'll still have to authenticate against the masterserver in order to be sure a public key is actually a valid player and not a fake/griefer. Also, for obvious business reasons, we can't possibly support evading the key check.
* That the servervault key/account migration helpers already do much of the same.
Going forward, we're looking at getting a fallback in place should the worst happen; i.e. the masterservers going AWOL. We don't have a decision or plan for this yet; but it is VERY early public beta, so there's a lot of "need/want/have to do" and very little "have done".
If you know me from the nwnx days, then you'll be sure to realise that this is a important topic to me, and I'll want to make sure the past will not repeat itself.
Hope that helps!
Edit: There were two points where you had to enter a password: To authenticate against the MS and then another one when logging into a server, one for players and one for DM's. Are those going away or just the one to authenticate against the MS?
It's the latter two that I'd like to see some hooks exposed. If those are going away how the heck are servers going to control access? (is actually an approved DM, has read the rules and agreed, has sworn they're 18+ etc.)
IIRC the protocol passes those in cleartext or base64'd cleartext. If they're staying and that's the case then that needs to be fixed.
Because they have to do it manually it's too much of a pain to be used for piracy, but it gives a good fallback.
Regardless it made startup even more painful than necessary and IIRC it rolls over and dies after a few thousand entries. I think it lasted a day before we disabled it. Certainly no more than a week.
But that's the great thing about a hook. You can implement whatever algorithm works best for your needs and talent. The default already covers "none" and "one password rules them all". A hook can be used to support per player or even Google Auth style codes.
If those will remain intact then can we get the hooks requested in the OP?
yes. I missed that message after seeing the initial post.
Of course player/DM passwords are still in! Would be incredibly silly to remove. Just the GameSpy authentication was purged, since that is defunct anyways.
You can hook those via nwnx easily. I don't think there's a plugin for it yet, but then again, I don't really do much nwnx stuff now.
The existing and known account->pubkey mapping already exists as part of the servervault migration code. If that file doesn't suit your purposes, then I'm sure nwnx can help there too.
Er, GameSpy or Master Server? Those were two completely different services. GS was the lobbying service and I don't think it had its own login. Sorry, people conflating MS and GS is pet peeve. I forget the exact reason why I didn't pursue that. Might have been time pressure to get something working after the old MS died. OTOH I remember one of the authentication exchanges was trivially insecure. Unfortunately I don't have access to my wire protocol notes and I can't find the site that used to host a wiki documenting it.
If somebody can verify that the player/dm passwords are appropriately hashed before being sent from the client to the server I can then let some folks know there's a better solution than the Rube Goldberg I shackled them with
They may or may not have the resources to write that sort of hook themselves.
If that was possible in the past it's no longer functional.
I spent the weekend trying to hook various methods within CNetLayer, notably StartConnectToSession I went so far as to try hooking CServerExoAppInternal CServerExoApp::ValidatePlayerLogin. All of them had a trace message sent to LOG_DEBUG right before handing off the args to the original call and none got a hit.
Any clues on which method to target would be appreciated.
edit: Just noticed that hooking CServerExoAppInternal caused an assertion error, hooking the CServerExoApp method was happier but just as fruitless.
yet another edit: Just to stave off the inevitable, yes, the log level is set to 7. I even threw in some std::cout traces just in case the logs were getting swallowed.